abaddon/abaddon.cpp

266 lines
8.2 KiB
C++
Raw Normal View History

2020-08-17 06:40:03 +00:00
#include <gtkmm.h>
#include <memory>
2020-08-19 05:07:55 +00:00
#include <string>
#include <algorithm>
2020-08-19 05:07:55 +00:00
#include "discord/discord.hpp"
#include "dialogs/token.hpp"
2020-08-31 02:55:36 +00:00
#include "dialogs/editmessage.hpp"
2020-08-17 06:40:03 +00:00
#include "abaddon.hpp"
#ifdef _WIN32
#pragma comment(lib, "crypt32.lib")
#endif
2020-08-19 05:07:55 +00:00
Abaddon::Abaddon()
: m_settings("abaddon.ini") {
LoadFromSettings();
2020-09-07 03:34:29 +00:00
m_discord.signal_gateway_ready().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReady));
m_discord.signal_channel_list_refresh().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelListRefresh));
m_discord.signal_message_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageCreate));
m_discord.signal_message_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageDelete));
m_discord.signal_message_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnMessageUpdate));
m_discord.signal_guild_member_list_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildMemberListUpdate));
2020-08-19 05:07:55 +00:00
}
Abaddon::~Abaddon() {
m_settings.Close();
m_discord.Stop();
}
int Abaddon::StartGTK() {
2020-08-17 06:40:03 +00:00
m_gtk_app = Gtk::Application::create("com.github.lorpus.abaddon");
2020-09-03 04:47:49 +00:00
// tmp css stuff
m_css_provider = Gtk::CssProvider::create();
2020-09-04 05:37:39 +00:00
m_css_provider->signal_parsing_error().connect([this](const Glib::RefPtr<const Gtk::CssSection> &section, const Glib::Error &error) {
Gtk::MessageDialog dlg(*m_main_window, "main.css failed parsing (" + error.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
dlg.run();
});
2020-09-03 04:47:49 +00:00
2020-08-19 05:07:55 +00:00
m_main_window = std::make_unique<MainWindow>();
m_main_window->SetAbaddon(this);
2020-09-03 06:32:28 +00:00
m_main_window->set_title(APP_TITLE);
2020-08-19 05:07:55 +00:00
m_main_window->show();
m_main_window->UpdateComponents();
2020-08-17 06:40:03 +00:00
2020-09-04 05:37:39 +00:00
ActionReloadCSS();
2020-08-17 06:40:03 +00:00
m_gtk_app->signal_shutdown().connect([&]() {
2020-08-19 05:07:55 +00:00
StopDiscord();
2020-08-17 06:40:03 +00:00
});
2020-08-19 05:07:55 +00:00
if (!m_settings.IsValid()) {
Gtk::MessageDialog dlg(*m_main_window, "The settings file could not be created!", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
dlg.run();
}
2020-08-17 06:40:03 +00:00
2020-08-19 05:07:55 +00:00
return m_gtk_app->run(*m_main_window);
}
2020-08-17 06:40:03 +00:00
2020-08-19 05:07:55 +00:00
void Abaddon::LoadFromSettings() {
std::string token = m_settings.GetSetting("discord", "token");
if (token.size()) {
m_discord_token = token;
m_discord.UpdateToken(m_discord_token);
2020-08-19 05:07:55 +00:00
}
2020-08-17 06:40:03 +00:00
}
2020-08-19 05:07:55 +00:00
void Abaddon::StartDiscord() {
2020-08-17 06:40:03 +00:00
m_discord.Start();
}
2020-08-19 05:07:55 +00:00
void Abaddon::StopDiscord() {
m_discord.Stop();
}
bool Abaddon::IsDiscordActive() const {
return m_discord.IsStarted();
}
std::string Abaddon::GetDiscordToken() const {
return m_discord_token;
}
const DiscordClient &Abaddon::GetDiscordClient() const {
std::scoped_lock<std::mutex> guard(m_mutex);
return m_discord;
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnReady() {
m_main_window->UpdateComponents();
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnChannelListRefresh() {
m_main_window->UpdateChannelListing();
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnMessageCreate(Snowflake id) {
2020-08-21 04:42:46 +00:00
m_main_window->UpdateChatNewMessage(id);
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnMessageDelete(Snowflake id, Snowflake channel_id) {
2020-08-29 05:14:07 +00:00
m_main_window->UpdateChatMessageDeleted(id, channel_id);
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnMessageUpdate(Snowflake id, Snowflake channel_id) {
2020-08-31 00:24:02 +00:00
m_main_window->UpdateChatMessageEditContent(id, channel_id);
}
2020-09-07 03:34:29 +00:00
void Abaddon::DiscordOnGuildMemberListUpdate(Snowflake guild_id) {
m_main_window->UpdateMembers();
}
2020-08-17 06:40:03 +00:00
void Abaddon::ActionConnect() {
if (!m_discord.IsStarted())
2020-08-19 05:07:55 +00:00
StartDiscord();
m_main_window->UpdateComponents();
2020-08-19 05:07:55 +00:00
}
void Abaddon::ActionDisconnect() {
if (m_discord.IsStarted())
StopDiscord();
2020-09-03 06:32:28 +00:00
m_main_window->set_title(APP_TITLE);
m_main_window->UpdateComponents();
2020-08-19 05:07:55 +00:00
}
void Abaddon::ActionSetToken() {
TokenDialog dlg(*m_main_window);
auto response = dlg.run();
if (response == Gtk::RESPONSE_OK) {
m_discord_token = dlg.GetToken();
m_discord.UpdateToken(m_discord_token);
m_main_window->UpdateComponents();
2020-08-19 05:07:55 +00:00
m_settings.SetSetting("discord", "token", m_discord_token);
}
2020-08-17 06:40:03 +00:00
}
void Abaddon::ActionMoveGuildUp(Snowflake id) {
auto order = m_discord.GetUserSortedGuilds();
// get iter to target
decltype(order)::iterator target_iter;
for (auto it = order.begin(); it != order.end(); it++) {
2020-09-07 01:28:07 +00:00
if (*it == id) {
target_iter = it;
break;
}
}
decltype(order)::iterator left = target_iter - 1;
std::swap(*left, *target_iter);
2020-09-07 01:28:07 +00:00
m_discord.UpdateSettingsGuildPositions(order);
}
void Abaddon::ActionMoveGuildDown(Snowflake id) {
auto order = m_discord.GetUserSortedGuilds();
// get iter to target
decltype(order)::iterator target_iter;
for (auto it = order.begin(); it != order.end(); it++) {
2020-09-07 01:28:07 +00:00
if (*it == id) {
target_iter = it;
break;
}
}
decltype(order)::iterator right = target_iter + 1;
std::swap(*right, *target_iter);
2020-09-07 01:28:07 +00:00
m_discord.UpdateSettingsGuildPositions(order);
}
void Abaddon::ActionCopyGuildID(Snowflake id) {
Gtk::Clipboard::get()->set_text(std::to_string(id));
}
2020-08-20 07:19:16 +00:00
void Abaddon::ActionListChannelItemClick(Snowflake id) {
2020-09-03 06:32:28 +00:00
auto *channel = m_discord.GetChannel(id);
2020-09-05 05:04:28 +00:00
if (channel->Type != ChannelType::DM && channel->Type != ChannelType::GROUP_DM)
m_discord.SendLazyLoad(id);
if (channel->Type == ChannelType::GUILD_TEXT)
m_main_window->set_title(std::string(APP_TITLE) + " - #" + channel->Name);
else {
std::string display;
if (channel->Recipients.size() > 1)
display = std::to_string(channel->Recipients.size()) + " users";
else
display = channel->Recipients[0].Username;
m_main_window->set_title(std::string(APP_TITLE) + " - " + display);
}
2020-08-20 07:19:16 +00:00
m_main_window->UpdateChatActiveChannel(id);
if (m_channels_requested.find(id) == m_channels_requested.end()) {
m_discord.FetchMessagesInChannel(id, [this, id](const std::vector<Snowflake> &msgs) {
2020-08-28 22:21:08 +00:00
if (msgs.size() > 0) {
m_oldest_listed_message[id] = msgs.back();
2020-08-28 22:21:08 +00:00
m_main_window->UpdateChatWindowContents();
}
2020-08-20 07:19:16 +00:00
m_channels_requested.insert(id);
});
} else {
m_main_window->UpdateChatWindowContents();
}
}
2020-08-28 22:21:08 +00:00
void Abaddon::ActionChatLoadHistory(Snowflake id) {
if (m_channels_history_loaded.find(id) != m_channels_history_loaded.end())
return;
if (m_channels_history_loading.find(id) != m_channels_history_loading.end())
return;
m_channels_history_loading.insert(id);
m_discord.FetchMessagesInChannelBefore(id, m_oldest_listed_message[id], [this, id](const std::vector<Snowflake> &msgs) {
2020-08-28 22:21:08 +00:00
m_channels_history_loading.erase(id);
if (msgs.size() == 0) {
m_channels_history_loaded.insert(id);
} else {
m_oldest_listed_message[id] = msgs.back();
2020-08-28 22:21:08 +00:00
m_main_window->UpdateChatPrependHistory(msgs);
}
});
}
2020-08-22 02:25:23 +00:00
void Abaddon::ActionChatInputSubmit(std::string msg, Snowflake channel) {
2020-09-04 05:03:43 +00:00
if (msg.substr(0, 7) == "/shrug " || msg == "/shrug")
msg = msg.substr(6) + "\xC2\xAF\x5C\x5F\x28\xE3\x83\x84\x29\x5F\x2F\xC2\xAF"; // this is important
2020-08-22 02:25:23 +00:00
m_discord.SendChatMessage(msg, channel);
}
2020-08-30 06:00:56 +00:00
void Abaddon::ActionChatDeleteMessage(Snowflake channel_id, Snowflake id) {
m_discord.DeleteMessage(channel_id, id);
}
2020-08-31 02:55:36 +00:00
void Abaddon::ActionChatEditMessage(Snowflake channel_id, Snowflake id) {
EditMessageDialog dlg(*m_main_window);
auto response = dlg.run();
if (response == Gtk::RESPONSE_OK) {
auto new_content = dlg.GetContent();
m_discord.EditMessage(channel_id, id, new_content);
}
}
void Abaddon::ActionInsertMention(Snowflake id) {
m_main_window->InsertChatInput("<@" + std::to_string(id) + ">");
}
2020-09-03 04:47:49 +00:00
void Abaddon::ActionReloadCSS() {
2020-09-04 05:37:39 +00:00
try {
Gtk::StyleContext::remove_provider_for_screen(Gdk::Screen::get_default(), m_css_provider);
m_css_provider->load_from_path("./css/main.css");
Gtk::StyleContext::add_provider_for_screen(Gdk::Screen::get_default(), m_css_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} catch (Glib::Error &e) {
Gtk::MessageDialog dlg(*m_main_window, "main.css failed to load (" + e.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
dlg.run();
}
2020-09-03 04:47:49 +00:00
}
2020-08-17 06:40:03 +00:00
int main(int argc, char **argv) {
2020-08-20 07:19:16 +00:00
Gtk::Main::init_gtkmm_internals(); // why???
2020-08-17 06:40:03 +00:00
Abaddon abaddon;
2020-08-19 05:07:55 +00:00
return abaddon.StartGTK();
2020-08-17 06:40:03 +00:00
}