diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-09-21 18:47:34 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-09-21 18:47:34 -0400 |
commit | 3b4edbfa16861b5013663396e1af827ba889e9df (patch) | |
tree | 51686baf5997c32a3e3aac0aa20368c404f6f3f1 | |
parent | 23b32f8de957204597308f2c1823d5e89f632610 (diff) | |
download | abaddon-portaudio-3b4edbfa16861b5013663396e1af827ba889e9df.tar.gz abaddon-portaudio-3b4edbfa16861b5013663396e1af827ba889e9df.zip |
join/leave guild
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | abaddon.cpp | 31 | ||||
-rw-r--r-- | abaddon.hpp | 5 | ||||
-rw-r--r-- | components/channels.cpp | 14 | ||||
-rw-r--r-- | components/channels.hpp | 5 | ||||
-rw-r--r-- | dialogs/joinguild.cpp | 98 | ||||
-rw-r--r-- | dialogs/joinguild.hpp | 31 | ||||
-rw-r--r-- | discord/discord.cpp | 97 | ||||
-rw-r--r-- | discord/discord.hpp | 14 | ||||
-rw-r--r-- | discord/http.cpp | 1 | ||||
-rw-r--r-- | discord/invite.cpp | 14 | ||||
-rw-r--r-- | discord/invite.hpp | 15 | ||||
-rw-r--r-- | discord/objects.hpp | 3 | ||||
-rw-r--r-- | discord/store.cpp | 8 | ||||
-rw-r--r-- | discord/store.hpp | 3 | ||||
-rw-r--r-- | windows/mainwindow.cpp | 13 | ||||
-rw-r--r-- | windows/mainwindow.hpp | 4 |
17 files changed, 347 insertions, 17 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 792e373..b1c9f29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,8 +128,8 @@ add_executable(abaddon abaddon.cpp filecache.hpp filecache.cpp - "imgmanager.hpp" - "imgmanager.cpp" + imgmanager.hpp + imgmanager.cpp components/channels.hpp components/channels.cpp components/chatmessage.hpp @@ -140,6 +140,8 @@ add_executable(abaddon components/memberlist.cpp dialogs/editmessage.hpp dialogs/editmessage.cpp + dialogs/joinguild.hpp + dialogs/joinguild.cpp dialogs/token.hpp dialogs/token.cpp discord/discord.hpp @@ -169,6 +171,8 @@ add_executable(abaddon discord/usersettings.cpp discord/message.hpp discord/message.cpp + discord/invite.hpp + discord/invite.cpp windows/mainwindow.hpp windows/mainwindow.cpp ) diff --git a/abaddon.cpp b/abaddon.cpp index 14fdcc0..0f8a679 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -5,6 +5,7 @@ #include "discord/discord.hpp" #include "dialogs/token.hpp" #include "dialogs/editmessage.hpp" +#include "dialogs/joinguild.hpp" #include "abaddon.hpp" #ifdef _WIN32 @@ -21,6 +22,8 @@ Abaddon::Abaddon() 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)); + m_discord.signal_guild_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildCreate)); + m_discord.signal_guild_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildDelete)); } Abaddon::~Abaddon() { @@ -52,11 +55,13 @@ int Abaddon::StartGTK() { m_main_window->signal_action_disconnect().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnect)); m_main_window->signal_action_set_token().connect(sigc::mem_fun(*this, &Abaddon::ActionSetToken)); m_main_window->signal_action_reload_css().connect(sigc::mem_fun(*this, &Abaddon::ActionReloadCSS)); + m_main_window->signal_action_join_guild().connect(sigc::mem_fun(*this, &Abaddon::ActionJoinGuildDialog)); m_main_window->GetChannelList()->signal_action_channel_item_select().connect(sigc::mem_fun(*this, &Abaddon::ActionListChannelItemClick)); m_main_window->GetChannelList()->signal_action_guild_move_up().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildUp)); m_main_window->GetChannelList()->signal_action_guild_move_down().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildDown)); m_main_window->GetChannelList()->signal_action_guild_copy_id().connect(sigc::mem_fun(*this, &Abaddon::ActionCopyGuildID)); + m_main_window->GetChannelList()->signal_action_guild_leave().connect(sigc::mem_fun(*this, &Abaddon::ActionLeaveGuild)); m_main_window->GetChatWindow()->signal_action_message_delete().connect(sigc::mem_fun(*this, &Abaddon::ActionChatDeleteMessage)); m_main_window->GetChatWindow()->signal_action_message_edit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatEditMessage)); @@ -103,6 +108,11 @@ std::string Abaddon::GetDiscordToken() const { return m_discord_token; } +DiscordClient &Abaddon::GetDiscordClient() { + std::scoped_lock<std::mutex> guard(m_mutex); + return m_discord; +} + const DiscordClient &Abaddon::GetDiscordClient() const { std::scoped_lock<std::mutex> guard(m_mutex); return m_discord; @@ -132,6 +142,14 @@ void Abaddon::DiscordOnGuildMemberListUpdate(Snowflake guild_id) { m_main_window->UpdateMembers(); } +void Abaddon::DiscordOnGuildCreate(Snowflake guild_id) { + m_main_window->UpdateChannelListing(); +} + +void Abaddon::DiscordOnGuildDelete(Snowflake guild_id) { + m_main_window->UpdateChannelListing(); +} + void Abaddon::ActionConnect() { if (!m_discord.IsStarted()) StartDiscord(); @@ -160,6 +178,15 @@ void Abaddon::ActionSetToken() { } } +void Abaddon::ActionJoinGuildDialog() { + JoinGuildDialog dlg(*m_main_window); + auto response = dlg.run(); + if (response == Gtk::RESPONSE_OK) { + auto code = dlg.GetCode(); + m_discord.JoinGuild(code); + } +} + void Abaddon::ActionMoveGuildUp(Snowflake id) { auto order = m_discord.GetUserSortedGuilds(); // get iter to target @@ -286,6 +313,10 @@ void Abaddon::ActionInsertMention(Snowflake id) { m_main_window->InsertChatInput("<@" + std::to_string(id) + ">"); } +void Abaddon::ActionLeaveGuild(Snowflake id) { + m_discord.LeaveGuild(id); +} + void Abaddon::ActionReloadCSS() { try { Gtk::StyleContext::remove_provider_for_screen(Gdk::Screen::get_default(), m_css_provider); diff --git a/abaddon.hpp b/abaddon.hpp index 9b4bf81..96728c6 100644 --- a/abaddon.hpp +++ b/abaddon.hpp @@ -31,6 +31,7 @@ public: void ActionConnect(); void ActionDisconnect(); void ActionSetToken(); + void ActionJoinGuildDialog(); void ActionMoveGuildUp(Snowflake id); void ActionMoveGuildDown(Snowflake id); void ActionCopyGuildID(Snowflake id); @@ -40,6 +41,7 @@ public: void ActionChatDeleteMessage(Snowflake channel_id, Snowflake id); void ActionChatEditMessage(Snowflake channel_id, Snowflake id); void ActionInsertMention(Snowflake id); + void ActionLeaveGuild(Snowflake id); void ActionReloadCSS(); @@ -48,6 +50,7 @@ public: std::string GetDiscordToken() const; bool IsDiscordActive() const; + DiscordClient &GetDiscordClient(); const DiscordClient &GetDiscordClient() const; void DiscordOnReady(); void DiscordOnChannelListRefresh(); @@ -55,6 +58,8 @@ public: void DiscordOnMessageDelete(Snowflake id, Snowflake channel_id); void DiscordOnMessageUpdate(Snowflake id, Snowflake channel_id); void DiscordOnGuildMemberListUpdate(Snowflake guild_id); + void DiscordOnGuildCreate(Snowflake guild_id); + void DiscordOnGuildDelete(Snowflake guild_id); private: DiscordClient m_discord; diff --git a/components/channels.cpp b/components/channels.cpp index 159e86b..5c12953 100644 --- a/components/channels.cpp +++ b/components/channels.cpp @@ -149,6 +149,10 @@ ChannelList::ChannelList() { m_guild_menu_copyid->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_menu_copyid)); m_guild_menu.append(*m_guild_menu_copyid); + m_guild_menu_leave = Gtk::manage(new Gtk::MenuItem("_Leave Guild", true)); + m_guild_menu_leave->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_menu_leave)); + m_guild_menu.append(*m_guild_menu_leave); + m_guild_menu.show_all(); m_list->set_activate_on_single_click(true); @@ -339,6 +343,12 @@ void ChannelList::on_menu_copyid() { m_signal_action_guild_copy_id.emit(row->ID); } +void ChannelList::on_menu_leave() { + auto row = dynamic_cast<ChannelListRow *>(m_list->get_selected_row()); + if (row != nullptr) + m_signal_action_guild_leave.emit(row->ID); +} + void ChannelList::AttachMenuHandler(Gtk::ListBoxRow *row) { row->signal_button_press_event().connect([&, row](GdkEventButton *e) -> bool { if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { @@ -371,3 +381,7 @@ ChannelList::type_signal_action_guild_move_down ChannelList::signal_action_guild ChannelList::type_signal_action_guild_copy_id ChannelList::signal_action_guild_copy_id() { return m_signal_action_guild_copy_id; } + +ChannelList::type_signal_action_guild_leave ChannelList::signal_action_guild_leave() { + return m_signal_action_guild_leave; +} diff --git a/components/channels.hpp b/components/channels.hpp index f898df7..9cd8c32 100644 --- a/components/channels.hpp +++ b/components/channels.hpp @@ -97,9 +97,11 @@ protected: Gtk::MenuItem *m_guild_menu_up; Gtk::MenuItem *m_guild_menu_down; Gtk::MenuItem *m_guild_menu_copyid; + Gtk::MenuItem *m_guild_menu_leave; void on_menu_move_up(); void on_menu_move_down(); void on_menu_copyid(); + void on_menu_leave(); Glib::Dispatcher m_update_dispatcher; //mutable std::mutex m_update_mutex; @@ -113,15 +115,18 @@ public: typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_up; typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_down; typedef sigc::signal<void, Snowflake> type_signal_action_guild_copy_id; + typedef sigc::signal<void, Snowflake> type_signal_action_guild_leave; type_signal_action_channel_item_select signal_action_channel_item_select(); type_signal_action_guild_move_up signal_action_guild_move_up(); type_signal_action_guild_move_down signal_action_guild_move_down(); type_signal_action_guild_copy_id signal_action_guild_copy_id(); + type_signal_action_guild_leave signal_action_guild_leave(); protected: type_signal_action_channel_item_select m_signal_action_channel_item_select; type_signal_action_guild_move_up m_signal_action_guild_move_up; type_signal_action_guild_move_down m_signal_action_guild_move_down; type_signal_action_guild_copy_id m_signal_action_guild_copy_id; + type_signal_action_guild_leave m_signal_action_guild_leave; }; diff --git a/dialogs/joinguild.cpp b/dialogs/joinguild.cpp new file mode 100644 index 0000000..ad9630b --- /dev/null +++ b/dialogs/joinguild.cpp @@ -0,0 +1,98 @@ +#include "joinguild.hpp" +#include "../abaddon.hpp" +#include <nlohmann/json.hpp> +#include <regex> + +JoinGuildDialog::JoinGuildDialog(Gtk::Window &parent) + : Gtk::Dialog("Join Server", parent, true) + , m_layout(Gtk::ORIENTATION_VERTICAL) + , m_ok("OK") + , m_cancel("Cancel") + , m_info("Enter code") { + set_default_size(300, 50); + + Glib::signal_idle().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_idle_slot)); + + m_entry.signal_changed().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_entry_changed)); + + m_ok.set_sensitive(false); + + m_ok.signal_clicked().connect([&]() { + m_code = m_entry.get_text(); + response(Gtk::RESPONSE_OK); + }); + + m_cancel.signal_clicked().connect([&]() { + response(Gtk::RESPONSE_CANCEL); + }); + + m_entry.set_hexpand(true); + m_layout.add(m_entry); + m_lower.set_hexpand(true); + m_lower.pack_start(m_info); + m_info.set_halign(Gtk::ALIGN_START); + m_lower.pack_start(m_ok, Gtk::PACK_SHRINK); + m_lower.pack_start(m_cancel, Gtk::PACK_SHRINK); + m_ok.set_halign(Gtk::ALIGN_END); + m_cancel.set_halign(Gtk::ALIGN_END); + m_layout.add(m_lower); + get_content_area()->add(m_layout); + + show_all_children(); +} + +void JoinGuildDialog::on_entry_changed() { + std::string s = m_entry.get_text(); + std::regex invite_regex(R"~(discord\.(gg|com)\/([a-zA-Z0-9]+)$)~", std::regex_constants::ECMAScript); + std::smatch match; + bool full_url = std::regex_search(s, match, invite_regex); + if (full_url || IsCode(s)) { + m_code = full_url ? match[2].str() : s; + m_needs_request = true; + m_ok.set_sensitive(false); + } else { + m_ok.set_sensitive(false); + } +} + +void JoinGuildDialog::CheckCode() { + // clang-format off + Abaddon::Get().GetDiscordClient().FetchInviteData( + m_code, + [this](Invite invite) { + m_ok.set_sensitive(true); + if (invite.Members != -1) + m_info.set_text(invite.Guild.Name + " (" + std::to_string(invite.Members) + " members)"); + else + m_info.set_text(invite.Guild.Name); + }, + [this](bool not_found) { + m_ok.set_sensitive(false); + if (not_found) + m_info.set_text("Invalid invite"); + else + m_info.set_text("HTTP error (try again)"); + } + ); + // clang-format on +} + +bool JoinGuildDialog::IsCode(std::string str) { + return str.length() >= 2 && std::all_of(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c); }); +} + +std::string JoinGuildDialog::GetCode() { + return m_code; +} + +static const constexpr int RateLimitMS = 1500; +bool JoinGuildDialog::on_idle_slot() { + const auto now = std::chrono::steady_clock::now(); + if (m_needs_request && ((now - m_last_req_time) > std::chrono::milliseconds(RateLimitMS))) { + m_needs_request = false; + m_last_req_time = now; + CheckCode(); + } + + return true; +} diff --git a/dialogs/joinguild.hpp b/dialogs/joinguild.hpp new file mode 100644 index 0000000..109d010 --- /dev/null +++ b/dialogs/joinguild.hpp @@ -0,0 +1,31 @@ +#pragma once +#include <gtkmm.h> +#include <string> +#include <chrono> + +class JoinGuildDialog : public Gtk::Dialog { +public: + JoinGuildDialog(Gtk::Window &parent); + std::string GetCode(); + +protected: + void on_entry_changed(); + bool IsCode(std::string str); + + Gtk::Box m_layout; + Gtk::Button m_ok; + Gtk::Button m_cancel; + Gtk::Box m_lower; + Gtk::Label m_info; + Gtk::Entry m_entry; + + void CheckCode(); + + // needs a rate limit cuz if u hit it u get ip banned from /invites for a long time :( + bool m_needs_request = false; + std::chrono::time_point<std::chrono::steady_clock> m_last_req_time; + bool on_idle_slot(); + +private: + std::string m_code; +}; diff --git a/discord/discord.cpp b/discord/discord.cpp index 3b74fd8..9d1842a 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -108,6 +108,19 @@ std::set<Snowflake> DiscordClient::GetMessagesForChannel(Snowflake id) const { return ret; } +void DiscordClient::FetchInviteData(std::string code, std::function<void(Invite)> cb, std::function<void(bool)> err) { + //printf("test: %s\n", code.c_str()); + //err(true); + m_http.MakeGET("/invites/" + code + "?with_counts=true", [this, cb, err](cpr::Response r) { + if (!CheckCode(r)) { + err(r.status_code == 404); + return; + }; + + cb(nlohmann::json::parse(r.text)); + }); +} + void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos) { nlohmann::json body; body["guild_positions"] = pos; @@ -247,6 +260,14 @@ void DiscordClient::SendLazyLoad(Snowflake id) { m_websocket.Send(j); } +void DiscordClient::JoinGuild(std::string code) { + m_http.MakePOST("/invites/" + code, "", [](auto) {}); +} + +void DiscordClient::LeaveGuild(Snowflake id) { + m_http.MakeDELETE("/users/@me/guilds/" + std::to_string(id), [](auto) {}); +} + void DiscordClient::UpdateToken(std::string token) { m_token = token; m_http.SetAuth(token); @@ -332,6 +353,12 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::GUILD_MEMBER_LIST_UPDATE: { HandleGatewayGuildMemberListUpdate(m); } break; + case GatewayEvent::GUILD_CREATE: { + HandleGatewayGuildCreate(m); + } break; + case GatewayEvent::GUILD_DELETE: { + HandleGatewayGuildDelete(m); + } break; } } break; default: @@ -343,23 +370,27 @@ void DiscordClient::HandleGatewayMessage(std::string str) { } } +void DiscordClient::ProcessNewGuild(Guild &guild) { + if (guild.IsUnavailable) { + printf("guild (%lld) unavailable\n", static_cast<uint64_t>(guild.ID)); + return; + } + + m_store.SetGuild(guild.ID, guild); + for (auto &c : guild.Channels) { + c.GuildID = guild.ID; + m_store.SetChannel(c.ID, c); + } + + for (auto &r : guild.Roles) + m_store.SetRole(r.ID, r); +} + void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) { m_ready_received = true; ReadyEventData data = msg.Data; - for (auto &g : data.Guilds) { - if (g.IsUnavailable) - printf("guild (%lld) unavailable\n", (uint64_t)g.ID); - else { - m_store.SetGuild(g.ID, g); - for (auto &c : g.Channels) { - c.GuildID = g.ID; - m_store.SetChannel(c.ID, c); - } - - for (auto &r : g.Roles) - m_store.SetRole(r.ID, r); - } - } + for (auto &g : data.Guilds) + ProcessNewGuild(g); for (const auto &dm : data.PrivateChannels) { m_store.SetChannel(dm.ID, dm); @@ -419,6 +450,34 @@ void DiscordClient::HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg m_signal_guild_member_list_update.emit(data.GuildID); } +void DiscordClient::HandleGatewayGuildCreate(const GatewayMessage &msg) { + Guild data = msg.Data; + ProcessNewGuild(data); + + m_signal_guild_create.emit(data.ID); +} + +void DiscordClient::HandleGatewayGuildDelete(const GatewayMessage &msg) { + Snowflake id = msg.Data.at("id"); + bool unavailable = msg.Data.contains("unavilable") && msg.Data.at("unavailable").get<bool>(); + + if (unavailable) + printf("guild %llu became unavailable\n", static_cast<uint64_t>(id)); + + auto *guild = m_store.GetGuild(id); + if (guild == nullptr) { + m_store.ClearGuild(id); + m_signal_guild_delete.emit(id); + return; + } + + m_store.ClearGuild(id); + for (const auto &c : guild->Channels) + m_store.ClearChannel(c.ID); + + m_signal_guild_delete.emit(id); +} + void DiscordClient::AddMessageToChannel(Snowflake msg_id, Snowflake channel_id) { m_chan_to_message_map[channel_id].insert(msg_id); } @@ -480,6 +539,8 @@ void DiscordClient::LoadEventMap() { m_event_map["MESSAGE_DELETE"] = GatewayEvent::MESSAGE_DELETE; m_event_map["MESSAGE_UPDATE"] = GatewayEvent::MESSAGE_UPDATE; m_event_map["GUILD_MEMBER_LIST_UPDATE"] = GatewayEvent::GUILD_MEMBER_LIST_UPDATE; + m_event_map["GUILD_CREATE"] = GatewayEvent::GUILD_CREATE; + m_event_map["GUILD_DELETE"] = GatewayEvent::GUILD_DELETE; } DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() { @@ -505,3 +566,11 @@ DiscordClient::type_signal_message_update DiscordClient::signal_message_update() DiscordClient::type_signal_guild_member_list_update DiscordClient::signal_guild_member_list_update() { return m_signal_guild_member_list_update; } + +DiscordClient::type_signal_guild_create DiscordClient::signal_guild_create() { + return m_signal_guild_create; +} + +DiscordClient::type_signal_guild_delete DiscordClient::signal_guild_delete() { + return m_signal_guild_delete; +} diff --git a/discord/discord.hpp b/discord/discord.hpp index 93f5527..cda3854 100644 --- a/discord/discord.hpp +++ b/discord/discord.hpp @@ -68,6 +68,7 @@ public: std::set<Snowflake> GetMessagesForChannel(Snowflake id) const; std::set<Snowflake> GetPrivateChannels() const; + void FetchInviteData(std::string code, std::function<void(Invite)> cb, std::function<void(bool)> err); void UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos); void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<Snowflake> &)> cb); void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> cb); @@ -83,6 +84,8 @@ public: void DeleteMessage(Snowflake channel_id, Snowflake id); void EditMessage(Snowflake channel_id, Snowflake id, std::string content); void SendLazyLoad(Snowflake id); + void JoinGuild(std::string code); + void LeaveGuild(Snowflake id); void UpdateToken(std::string token); @@ -91,6 +94,9 @@ private: std::vector<uint8_t> m_compressed_buf; std::vector<uint8_t> m_decompress_buf; z_stream m_zstream; + + void ProcessNewGuild(Guild &guild); + void HandleGatewayMessageRaw(std::string str); void HandleGatewayMessage(std::string str); void HandleGatewayReady(const GatewayMessage &msg); @@ -98,6 +104,8 @@ private: void HandleGatewayMessageDelete(const GatewayMessage &msg); void HandleGatewayMessageUpdate(const GatewayMessage &msg); void HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg); + void HandleGatewayGuildCreate(const GatewayMessage &msg); + void HandleGatewayGuildDelete(const GatewayMessage &msg); void HeartbeatThread(); void SendIdentify(); @@ -137,6 +145,8 @@ public: typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_delete; typedef sigc::signal<void, Snowflake, Snowflake> type_signal_message_update; typedef sigc::signal<void, Snowflake> type_signal_guild_member_list_update; + typedef sigc::signal<void, Snowflake> type_signal_guild_create; + typedef sigc::signal<void, Snowflake> type_signal_guild_delete; type_signal_gateway_ready signal_gateway_ready(); type_signal_channel_list_refresh signal_channel_list_refresh(); @@ -144,6 +154,8 @@ public: type_signal_message_delete signal_message_delete(); type_signal_message_update signal_message_update(); type_signal_guild_member_list_update signal_guild_member_list_update(); + type_signal_guild_create signal_guild_create(); + type_signal_guild_delete signal_guild_delete(); protected: type_signal_gateway_ready m_signal_gateway_ready; @@ -152,4 +164,6 @@ protected: type_signal_message_delete m_signal_message_delete; type_signal_message_update m_signal_message_update; type_signal_guild_member_list_update m_signal_guild_member_list_update; + type_signal_guild_create m_signal_guild_create; + type_signal_guild_delete m_signal_guild_delete; }; diff --git a/discord/http.cpp b/discord/http.cpp index 1e9b786..b4a0f4b 100644 --- a/discord/http.cpp +++ b/discord/http.cpp @@ -1,5 +1,6 @@ #include "http.hpp" +//#define USE_LOCAL_PROXY HTTPClient::HTTPClient(std::string api_base) : m_api_base(api_base) {} diff --git a/discord/invite.cpp b/discord/invite.cpp new file mode 100644 index 0000000..a08bdef --- /dev/null +++ b/discord/invite.cpp @@ -0,0 +1,14 @@ +#include "invite.hpp" + +void from_json(const nlohmann::json &j, Invite &m) { + JS_D("code", m.Code); + JS_O("channel", m.Channel); + JS_O("inviter", m.Inviter); + JS_O("approximate_member_count", m.Members); + + if (j.contains("guild")) { + auto x = j.at("guild"); + x.at("id").get_to(m.Guild.ID); + x.at("name").get_to(m.Guild.Name); + } +} diff --git a/discord/invite.hpp b/discord/invite.hpp new file mode 100644 index 0000000..486ecad --- /dev/null +++ b/discord/invite.hpp @@ -0,0 +1,15 @@ +#pragma once +#include "json.hpp" +#include "guild.hpp" +#include <string> + +class Invite { +public: + std::string Code; // + Guild Guild; // opt + Channel Channel; // opt + User Inviter; // opt + int Members = -1; // opt + + friend void from_json(const nlohmann::json &j, Invite &m); +}; diff --git a/discord/objects.hpp b/discord/objects.hpp index 4714c85..e2526fe 100644 --- a/discord/objects.hpp +++ b/discord/objects.hpp @@ -11,6 +11,7 @@ #include "guild.hpp" #include "usersettings.hpp" #include "message.hpp" +#include "invite.hpp" // most stuff below should just be objects that get processed and thrown away immediately @@ -29,6 +30,8 @@ enum class GatewayEvent : int { MESSAGE_DELETE, MESSAGE_UPDATE, GUILD_MEMBER_LIST_UPDATE, + GUILD_CREATE, + GUILD_DELETE, }; struct GatewayMessage { diff --git a/discord/store.cpp b/discord/store.cpp index fb0bec1..92ccaa0 100644 --- a/discord/store.cpp +++ b/discord/store.cpp @@ -114,6 +114,14 @@ const GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_ return &mit->second; } +void Store::ClearGuild(Snowflake id) { + m_guilds.erase(id); +} + +void Store::ClearChannel(Snowflake id) { + m_channels.erase(id); +} + const Store::channels_type &Store::GetChannels() const { return m_channels; } diff --git a/discord/store.hpp b/discord/store.hpp index 45b1c41..6477b50 100644 --- a/discord/store.hpp +++ b/discord/store.hpp @@ -29,6 +29,9 @@ public: const Message *GetMessage(Snowflake id) const; const GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const; + void ClearGuild(Snowflake id); + void ClearChannel(Snowflake id); + using users_type = std::unordered_map<Snowflake, User>; using channels_type = std::unordered_map<Snowflake, Channel>; using guilds_type = std::unordered_map<Snowflake, Guild>; diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp index 5e85c98..74ead8f 100644 --- a/windows/mainwindow.cpp +++ b/windows/mainwindow.cpp @@ -15,9 +15,12 @@ MainWindow::MainWindow() m_menu_discord_disconnect.set_label("Disconnect"); m_menu_discord_disconnect.set_sensitive(false); m_menu_discord_set_token.set_label("Set Token"); + m_menu_discord_join_guild.set_label("Join Guild"); + m_menu_discord_join_guild.set_sensitive(false); m_menu_discord_sub.append(m_menu_discord_connect); m_menu_discord_sub.append(m_menu_discord_disconnect); m_menu_discord_sub.append(m_menu_discord_set_token); + m_menu_discord_sub.append(m_menu_discord_join_guild); m_menu_discord.set_submenu(m_menu_discord_sub); m_menu_file.set_label("File"); @@ -40,6 +43,10 @@ MainWindow::MainWindow() m_signal_action_set_token.emit(); }); + m_menu_discord_join_guild.signal_activate().connect([&] { + m_signal_action_join_guild.emit(); + }); + m_menu_file_reload_css.signal_activate().connect([this] { m_signal_action_reload_css.emit(); }); @@ -87,8 +94,8 @@ void MainWindow::UpdateComponents() { std::string token = Abaddon::Get().GetDiscordToken(); m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active); - m_menu_discord_disconnect.set_sensitive(discord_active); + m_menu_discord_join_guild.set_sensitive(discord_active); if (!discord_active) { m_channel_list.Clear(); @@ -191,3 +198,7 @@ MainWindow::type_signal_action_set_token MainWindow::signal_action_set_token() { MainWindow::type_signal_action_reload_css MainWindow::signal_action_reload_css() { return m_signal_action_reload_css; } + +MainWindow::type_signal_action_join_guild MainWindow::signal_action_join_guild() { + return m_signal_action_join_guild; +} diff --git a/windows/mainwindow.hpp b/windows/mainwindow.hpp index 33308ce..0bff99b 100644 --- a/windows/mainwindow.hpp +++ b/windows/mainwindow.hpp @@ -30,17 +30,20 @@ public: typedef sigc::signal<void> type_signal_action_disconnect; typedef sigc::signal<void> type_signal_action_set_token; typedef sigc::signal<void> type_signal_action_reload_css; + typedef sigc::signal<void> type_signal_action_join_guild; type_signal_action_connect signal_action_connect(); type_signal_action_disconnect signal_action_disconnect(); type_signal_action_set_token signal_action_set_token(); type_signal_action_reload_css signal_action_reload_css(); + type_signal_action_join_guild signal_action_join_guild(); protected: type_signal_action_connect m_signal_action_connect; type_signal_action_disconnect m_signal_action_disconnect; type_signal_action_set_token m_signal_action_set_token; type_signal_action_reload_css m_signal_action_reload_css; + type_signal_action_join_guild m_signal_action_join_guild; protected: Gtk::Box m_main_box; @@ -58,6 +61,7 @@ protected: Gtk::MenuItem m_menu_discord_connect; Gtk::MenuItem m_menu_discord_disconnect; Gtk::MenuItem m_menu_discord_set_token; + Gtk::MenuItem m_menu_discord_join_guild; Gtk::MenuItem m_menu_file; Gtk::Menu m_menu_file_sub; |