diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-19 20:35:10 -0400 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-10-19 20:35:10 -0400 |
commit | cb73bba135933357878dc47f6e7a6bec3168d001 (patch) | |
tree | 0bcced1046c53b6322a6d680db4aca7edbc9371f | |
parent | 49a6e581375fdf0b5f5e82f981ca2d7cb419267f (diff) | |
download | abaddon-portaudio-cb73bba135933357878dc47f6e7a6bec3168d001.tar.gz abaddon-portaudio-cb73bba135933357878dc47f6e7a6bec3168d001.zip |
CHANNEL_CREATE, CHANNEL_UPDATE, CHANNEL_DELETE
-rw-r--r-- | abaddon.cpp | 15 | ||||
-rw-r--r-- | abaddon.hpp | 3 | ||||
-rw-r--r-- | components/channels.cpp | 161 | ||||
-rw-r--r-- | components/channels.hpp | 6 | ||||
-rw-r--r-- | discord/channel.cpp | 20 | ||||
-rw-r--r-- | discord/channel.hpp | 1 | ||||
-rw-r--r-- | discord/discord.cpp | 60 | ||||
-rw-r--r-- | discord/discord.hpp | 15 | ||||
-rw-r--r-- | discord/guild.cpp | 51 | ||||
-rw-r--r-- | discord/guild.hpp | 1 | ||||
-rw-r--r-- | discord/json.hpp | 22 | ||||
-rw-r--r-- | discord/objects.hpp | 3 | ||||
-rw-r--r-- | windows/mainwindow.cpp | 12 | ||||
-rw-r--r-- | windows/mainwindow.hpp | 3 |
14 files changed, 363 insertions, 10 deletions
diff --git a/abaddon.cpp b/abaddon.cpp index cd0982b..4da4817 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -25,6 +25,9 @@ Abaddon::Abaddon() 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)); + m_discord.signal_channel_delete().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelDelete)); + m_discord.signal_channel_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelUpdate)); + m_discord.signal_channel_create().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnChannelCreate)); } Abaddon::~Abaddon() { @@ -154,6 +157,18 @@ void Abaddon::DiscordOnGuildDelete(Snowflake guild_id) { m_main_window->UpdateChannelsRemoveGuild(guild_id); } +void Abaddon::DiscordOnChannelDelete(Snowflake channel_id) { + m_main_window->UpdateChannelsRemoveChannel(channel_id); +} + +void Abaddon::DiscordOnChannelUpdate(Snowflake channel_id) { + m_main_window->UpdateChannelsUpdateChannel(channel_id); +} + +void Abaddon::DiscordOnChannelCreate(Snowflake channel_id) { + m_main_window->UpdateChannelsCreateChannel(channel_id); +} + const SettingsManager &Abaddon::GetSettings() const { return m_settings; } diff --git a/abaddon.hpp b/abaddon.hpp index 4993cba..807448c 100644 --- a/abaddon.hpp +++ b/abaddon.hpp @@ -61,6 +61,9 @@ public: void DiscordOnGuildMemberListUpdate(Snowflake guild_id); void DiscordOnGuildCreate(Snowflake guild_id); void DiscordOnGuildDelete(Snowflake guild_id); + void DiscordOnChannelDelete(Snowflake channel_id); + void DiscordOnChannelUpdate(Snowflake channel_id); + void DiscordOnChannelCreate(Snowflake channel_id); const SettingsManager &GetSettings() const; diff --git a/components/channels.cpp b/components/channels.cpp index 30eed2c..65dd49c 100644 --- a/components/channels.cpp +++ b/components/channels.cpp @@ -156,6 +156,7 @@ ChannelList::ChannelList() { m_list->get_style_context()->add_class("channel-list"); + /* m_guild_menu_up = Gtk::manage(new Gtk::MenuItem("Move _Up", true)); m_guild_menu_up->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_guild_menu_move_up)); m_guild_menu.append(*m_guild_menu_up); @@ -163,6 +164,7 @@ ChannelList::ChannelList() { m_guild_menu_down = Gtk::manage(new Gtk::MenuItem("Move _Down", true)); m_guild_menu_down->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_guild_menu_move_down)); m_guild_menu.append(*m_guild_menu_down); + */ m_guild_menu_copyid = Gtk::manage(new Gtk::MenuItem("_Copy ID", true)); m_guild_menu_copyid->signal_activate().connect(sigc::mem_fun(*this, &ChannelList::on_guild_menu_copyid)); @@ -236,6 +238,153 @@ void ChannelList::UpdateRemoveGuild(Snowflake id) { DeleteRow(row); } +void ChannelList::UpdateRemoveChannel(Snowflake id) { + auto it = m_id_to_row.find(id); + if (it == m_id_to_row.end()) return; + auto row = dynamic_cast<ChannelListRow *>(it->second); + if (row == nullptr) return; + DeleteRow(row); +} + +// this is total shit +void ChannelList::UpdateChannelCategory(Snowflake id) { + const auto *data = Abaddon::Get().GetDiscordClient().GetChannel(id); + const auto *guild = Abaddon::Get().GetDiscordClient().GetGuild(data->GuildID); + auto git = m_guild_id_to_row.find(data->GuildID); + if (git == m_guild_id_to_row.end()) return; + auto *guild_row = git->second; + if (data == nullptr || guild == nullptr) return; + auto it = m_id_to_row.find(id); + if (it == m_id_to_row.end()) return; + auto row = dynamic_cast<ChannelListRowCategory *>(it->second); + if (row == nullptr) return; + const bool old_collapsed = row->IsUserCollapsed; + const bool visible = row->is_visible(); + std::map<int, Snowflake> child_rows; + for (auto child : row->Children) { + child_rows[child->get_index()] = child->ID; + } + guild_row->Children.erase(row); + DeleteRow(row); + + int pos = guild_row->get_index(); + const auto sorted = guild->GetSortedChannels(id); + const auto sorted_it = std::find(sorted.begin(), sorted.end(), id); + if (sorted_it == sorted.end()) return; + if (std::next(sorted_it) == sorted.end()) { + const auto x = m_id_to_row.find(*std::prev(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index() + 1; + } else { + const auto x = m_id_to_row.find(*std::next(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index(); + } + + auto *new_row = Gtk::manage(new ChannelListRowCategory(data)); + new_row->IsUserCollapsed = old_collapsed; + if (visible) + new_row->show(); + m_id_to_row[id] = new_row; + AttachChannelMenuHandler(new_row); + new_row->Parent = guild_row; + guild_row->Children.insert(new_row); + m_list->insert(*new_row, pos); + int i = 1; + for (const auto &[idx, child_id] : child_rows) { + const auto *channel = Abaddon::Get().GetDiscordClient().GetChannel(child_id); + if (channel != nullptr) { + auto *new_child = Gtk::manage(new ChannelListRowChannel(channel)); + new_row->Children.insert(new_child); + new_child->Parent = new_row; + AttachChannelMenuHandler(new_child); + m_id_to_row[child_id] = new_child; + if (visible && !new_row->IsUserCollapsed) + new_child->show(); + m_list->insert(*new_child, pos + i++); + } + } +} + +// so is this +void ChannelList::UpdateChannel(Snowflake id) { + const auto *data = Abaddon::Get().GetDiscordClient().GetChannel(id); + const auto *guild = Abaddon::Get().GetDiscordClient().GetGuild(data->GuildID); + const auto *guild_row = m_guild_id_to_row.at(data->GuildID); + if (data->Type == ChannelType::GUILD_CATEGORY) { + UpdateChannelCategory(id); + return; + } + auto row = dynamic_cast<ChannelListRowChannel *>(m_id_to_row.at(id)); + const bool old_collapsed = row->IsUserCollapsed; + const bool old_visible = row->is_visible(); + DeleteRow(row); + + int pos = guild_row->get_index() + 1; // fallback + const auto sorted = guild->GetSortedChannels(); + const auto sorted_it = std::find(sorted.begin(), sorted.end(), id); + if (sorted_it + 1 == sorted.end()) { + const auto x = m_id_to_row.find(*std::prev(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index() + 1; + } else { + const auto x = m_id_to_row.find(*std::next(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index(); + } + + auto *new_row = Gtk::manage(new ChannelListRowChannel(data)); + new_row->IsUserCollapsed = old_collapsed; + m_id_to_row[id] = new_row; + if (data->ParentID.IsValid()) { + new_row->Parent = m_id_to_row.at(data->ParentID); + } else { + new_row->Parent = m_guild_id_to_row.at(data->GuildID); + } + + new_row->Parent->Children.insert(new_row); + if (new_row->Parent->is_visible() && !new_row->Parent->IsUserCollapsed) + new_row->show(); + AttachChannelMenuHandler(new_row); + m_list->insert(*new_row, pos); +} + +void ChannelList::UpdateCreateChannel(Snowflake id) { + const auto &discord = Abaddon::Get().GetDiscordClient(); + const auto *data = discord.GetChannel(id); + const auto *guild = discord.GetGuild(data->GuildID); + auto *guild_row = m_guild_id_to_row.at(data->GuildID); + + int pos = guild_row->get_index() + 1; + const auto sorted = guild->GetSortedChannels(); + const auto sorted_it = std::find(sorted.begin(), sorted.end(), id); + if (sorted_it + 1 == sorted.end()) { + const auto x = m_id_to_row.find(*std::prev(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index() + 1; + } else { + const auto x = m_id_to_row.find(*std::next(sorted_it)); + if (x != m_id_to_row.end()) + pos = x->second->get_index(); + } + + ChannelListRow *row; + if (data->Type == ChannelType::GUILD_TEXT) { + row = Gtk::manage(new ChannelListRowChannel(data)); + } else if (data->Type == ChannelType::GUILD_CATEGORY) { + row = Gtk::manage(new ChannelListRowCategory(data)); + } else + return; + row->IsUserCollapsed = false; + if (guild_row->is_visible()) + row->show(); + AttachChannelMenuHandler(row); + row->Parent = guild_row; + guild_row->Children.insert(row); + m_id_to_row[id] = row; + m_list->insert(*row, pos); +} + void ChannelList::Clear() { //std::scoped_lock<std::mutex> guard(m_update_mutex); m_update_dispatcher.emit(); @@ -244,7 +393,6 @@ void ChannelList::Clear() { void ChannelList::CollapseRow(ChannelListRow *row) { row->Collapse(); for (auto child : row->Children) { - row->IsHidden = true; child->hide(); CollapseRow(child); } @@ -253,7 +401,6 @@ void ChannelList::CollapseRow(ChannelListRow *row) { void ChannelList::ExpandRow(ChannelListRow *row) { row->Expand(); row->show(); - row->IsHidden = false; if (!row->IsUserCollapsed) for (auto child : row->Children) ExpandRow(child); @@ -264,13 +411,14 @@ void ChannelList::DeleteRow(ChannelListRow *row) { DeleteRow(child); if (row->Parent != nullptr) row->Parent->Children.erase(row); + else + printf("row has no parent!\n"); if (dynamic_cast<ChannelListRowGuild *>(row) != nullptr) m_guild_id_to_row.erase(row->ID); else m_id_to_row.erase(row->ID); delete row; } - void ChannelList::on_row_activated(Gtk::ListBoxRow *tmprow) { auto row = dynamic_cast<ChannelListRow *>(tmprow); if (row == nullptr) return; @@ -311,7 +459,6 @@ void ChannelList::InsertGuildAt(Snowflake id, int pos) { auto *guild_row = Gtk::manage(new ChannelListRowGuild(guild_data)); guild_row->show_all(); guild_row->IsUserCollapsed = true; - guild_row->IsHidden = false; guild_row->GuildIndex = m_guild_count++; insert_and_adjust(*guild_row); m_guild_id_to_row[guild_row->ID] = guild_row; @@ -321,7 +468,7 @@ void ChannelList::InsertGuildAt(Snowflake id, int pos) { for (const auto &[pos, channel] : orphan_channels) { auto *chan_row = Gtk::manage(new ChannelListRowChannel(channel)); chan_row->IsUserCollapsed = false; - chan_row->IsHidden = true; + AttachChannelMenuHandler(chan_row); insert_and_adjust(*chan_row); guild_row->Children.insert(chan_row); chan_row->Parent = guild_row; @@ -339,7 +486,6 @@ void ChannelList::InsertGuildAt(Snowflake id, int pos) { for (const auto cat : catvec) { auto *cat_row = Gtk::manage(new ChannelListRowCategory(cat)); cat_row->IsUserCollapsed = false; - cat_row->IsHidden = true; AttachChannelMenuHandler(cat_row); insert_and_adjust(*cat_row); guild_row->Children.insert(cat_row); @@ -355,7 +501,6 @@ void ChannelList::InsertGuildAt(Snowflake id, int pos) { for (const auto &[pos, channel] : sorted_channels) { auto *chan_row = Gtk::manage(new ChannelListRowChannel(channel)); - chan_row->IsHidden = false; chan_row->IsUserCollapsed = false; AttachChannelMenuHandler(chan_row); insert_and_adjust(*chan_row); @@ -373,13 +518,11 @@ void ChannelList::AddPrivateChannels() { auto *parent_row = Gtk::manage(new ChannelListRowDMHeader); parent_row->show_all(); parent_row->IsUserCollapsed = true; - parent_row->IsHidden = false; m_list->add(*parent_row); for (const auto &dm : dms) { auto *dm_row = Gtk::manage(new ChannelListRowDMChannel(Abaddon::Get().GetDiscordClient().GetChannel(dm))); dm_row->IsUserCollapsed = false; - dm_row->IsHidden = false; m_list->add(*dm_row); parent_row->Children.insert(dm_row); } diff --git a/components/channels.hpp b/components/channels.hpp index 8989669..b5373e5 100644 --- a/components/channels.hpp +++ b/components/channels.hpp @@ -11,7 +11,6 @@ class ChannelListRow : public Gtk::ListBoxRow { public: bool IsUserCollapsed; - bool IsHidden; Snowflake ID; std::unordered_set<ChannelListRow *> Children; ChannelListRow *Parent = nullptr; @@ -89,6 +88,9 @@ public: void UpdateListing(); void UpdateNewGuild(Snowflake id); void UpdateRemoveGuild(Snowflake id); + void UpdateRemoveChannel(Snowflake id); + void UpdateChannel(Snowflake id); + void UpdateCreateChannel(Snowflake id); void Clear(); protected: @@ -99,6 +101,8 @@ protected: void ExpandRow(ChannelListRow *row); void DeleteRow(ChannelListRow *row); + void UpdateChannelCategory(Snowflake id); + void on_row_activated(Gtk::ListBoxRow *row); int m_guild_count; diff --git a/discord/channel.cpp b/discord/channel.cpp index d104337..b99971c 100644 --- a/discord/channel.cpp +++ b/discord/channel.cpp @@ -22,6 +22,26 @@ void from_json(const nlohmann::json &j, Channel &m) { JS_ON("last_pin_timestamp", m.LastPinTimestamp); } +void Channel::update_from_json(const nlohmann::json &j) { + JS_RD("type", Type); + JS_RD("guild_id", GuildID); + JS_RV("position", Position, -1); + JS_RD("permission_overwrites", PermissionOverwrites); + JS_RD("name", Name); + JS_RD("topic", Topic); + JS_RD("nsfw", IsNSFW); + JS_RD("last_message_id", LastMessageID); + JS_RD("bitrate", Bitrate); + JS_RD("user_limit", UserLimit); + JS_RD("rate_limit_per_user", RateLimitPerUser); + JS_RD("recipients", Recipients); + JS_RD("icon", Icon); + JS_RD("owner_id", OwnerID); + JS_RD("application_id", ApplicationID); + JS_RD("parent_id", ParentID); + JS_RD("last_pin_timestamp", LastPinTimestamp); +} + const PermissionOverwrite *Channel::GetOverwrite(Snowflake id) const { return Abaddon::Get().GetDiscordClient().GetPermissionOverwrite(ID, id); } diff --git a/discord/channel.hpp b/discord/channel.hpp index 7f2bcd0..845cffb 100644 --- a/discord/channel.hpp +++ b/discord/channel.hpp @@ -37,6 +37,7 @@ struct Channel { std::string LastPinTimestamp; // opt, can be null even tho docs say otherwise friend void from_json(const nlohmann::json &j, Channel &m); + void update_from_json(const nlohmann::json &j); const PermissionOverwrite *GetOverwrite(Snowflake id) const; }; diff --git a/discord/discord.cpp b/discord/discord.cpp index c296aee..9f07259 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -246,6 +246,13 @@ std::unordered_set<Snowflake> DiscordClient::GetRolesInGuild(Snowflake id) const return ret; } +std::unordered_set<Snowflake> DiscordClient::GetChannelsInGuild(Snowflake id) const { + auto it = m_guild_to_channels.find(id); + if (it != m_guild_to_channels.end()) + return it->second; + return std::unordered_set<Snowflake>(); +} + bool DiscordClient::HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const { const auto base = ComputePermissions(user_id, guild_id); return (base & perm) == perm; @@ -506,6 +513,15 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::PRESENCE_UPDATE: { HandleGatewayPresenceUpdate(m); } break; + case GatewayEvent::CHANNEL_DELETE: { + HandleGatewayChannelDelete(m); + } break; + case GatewayEvent::CHANNEL_UPDATE: { + HandleGatewayChannelUpdate(m); + } break; + case GatewayEvent::CHANNEL_CREATE: { + HandleGatewayChannelCreate(m); + } break; } } break; default: @@ -527,6 +543,7 @@ void DiscordClient::ProcessNewGuild(Guild &guild) { for (auto &c : guild.Channels) { c.GuildID = guild.ID; m_store.SetChannel(c.ID, c); + m_guild_to_channels[guild.ID].insert(c.ID); for (auto &p : c.PermissionOverwrites) { m_store.SetPermissionOverwrite(c.ID, p.ID, p); } @@ -594,6 +611,34 @@ void DiscordClient::HandleGatewayPresenceUpdate(const GatewayMessage &msg) { User::update_from_json(data.User, *cur); } +void DiscordClient::HandleGatewayChannelDelete(const GatewayMessage &msg) { + const auto id = msg.Data.at("id").get<Snowflake>(); + const auto *channel = GetChannel(id); + auto it = m_guild_to_channels.find(channel->GuildID); + if (it != m_guild_to_channels.end()) + it->second.erase(id); + m_store.ClearChannel(id); + m_signal_channel_delete.emit(id); +} + +void DiscordClient::HandleGatewayChannelUpdate(const GatewayMessage &msg) { + const auto id = msg.Data.at("id").get<Snowflake>(); + auto *cur = m_store.GetChannel(id); + if (cur != nullptr) { + cur->update_from_json(msg.Data); + m_signal_channel_update.emit(id); + } +} + +void DiscordClient::HandleGatewayChannelCreate(const GatewayMessage &msg) { + Channel data = msg.Data; + m_store.SetChannel(data.ID, data); + m_guild_to_channels[data.GuildID].insert(data.ID); + for (const auto &p : data.PermissionOverwrites) + m_store.SetPermissionOverwrite(data.ID, p.ID, p); + m_signal_channel_create.emit(data.ID); +} + void DiscordClient::HandleGatewayMessageUpdate(const GatewayMessage &msg) { Snowflake id = msg.Data.at("id"); @@ -723,6 +768,9 @@ void DiscordClient::LoadEventMap() { m_event_map["MESSAGE_DELETE_BULK"] = GatewayEvent::MESSAGE_DELETE_BULK; m_event_map["GUILD_MEMBER_UPDATE"] = GatewayEvent::GUILD_MEMBER_UPDATE; m_event_map["PRESENCE_UPDATE"] = GatewayEvent::PRESENCE_UPDATE; + m_event_map["CHANNEL_DELETE"] = GatewayEvent::CHANNEL_DELETE; + m_event_map["CHANNEL_UPDATE"] = GatewayEvent::CHANNEL_UPDATE; + m_event_map["CHANNEL_CREATE"] = GatewayEvent::CHANNEL_CREATE; } DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() { @@ -756,3 +804,15 @@ DiscordClient::type_signal_guild_create DiscordClient::signal_guild_create() { DiscordClient::type_signal_guild_delete DiscordClient::signal_guild_delete() { return m_signal_guild_delete; } + +DiscordClient::type_signal_channel_delete DiscordClient::signal_channel_delete() { + return m_signal_channel_delete; +} + +DiscordClient::type_signal_channel_update DiscordClient::signal_channel_update() { + return m_signal_channel_update; +} + +DiscordClient::type_signal_channel_create DiscordClient::signal_channel_create() { + return m_signal_channel_create; +} diff --git a/discord/discord.hpp b/discord/discord.hpp index 76a64af..240bd1e 100644 --- a/discord/discord.hpp +++ b/discord/discord.hpp @@ -87,6 +87,7 @@ public: Snowflake GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const; std::unordered_set<Snowflake> GetUsersInGuild(Snowflake id) const; std::unordered_set<Snowflake> GetRolesInGuild(Snowflake id) const; + std::unordered_set<Snowflake> GetChannelsInGuild(Snowflake id) const; bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const; bool HasChannelPermission(Snowflake user_id, Snowflake channel_id, Permission perm) const; @@ -125,6 +126,9 @@ private: void HandleGatewayMessageDeleteBulk(const GatewayMessage &msg); void HandleGatewayGuildMemberUpdate(const GatewayMessage &msg); void HandleGatewayPresenceUpdate(const GatewayMessage &msg); + void HandleGatewayChannelDelete(const GatewayMessage &msg); + void HandleGatewayChannelUpdate(const GatewayMessage &msg); + void HandleGatewayChannelCreate(const GatewayMessage &msg); void HeartbeatThread(); void SendIdentify(); @@ -138,6 +142,8 @@ private: void AddUserToGuild(Snowflake user_id, Snowflake guild_id); std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_guild_to_users; + std::unordered_map<Snowflake, std::unordered_set<Snowflake>> m_guild_to_channels; + User m_user_data; UserSettings m_user_settings; @@ -171,6 +177,9 @@ public: 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; + typedef sigc::signal<void, Snowflake> type_signal_channel_delete; + typedef sigc::signal<void, Snowflake> type_signal_channel_update; + typedef sigc::signal<void, Snowflake> type_signal_channel_create; type_signal_gateway_ready signal_gateway_ready(); type_signal_channel_list_refresh signal_channel_list_refresh(); @@ -180,6 +189,9 @@ public: 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(); + type_signal_channel_delete signal_channel_delete(); + type_signal_channel_update signal_channel_update(); + type_signal_channel_create signal_channel_create(); protected: type_signal_gateway_ready m_signal_gateway_ready; @@ -190,4 +202,7 @@ protected: 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; + type_signal_channel_delete m_signal_channel_delete; + type_signal_channel_update m_signal_channel_update; + type_signal_channel_create m_signal_channel_create; }; diff --git a/discord/guild.cpp b/discord/guild.cpp index 602cdb2..5875a11 100644 --- a/discord/guild.cpp +++ b/discord/guild.cpp @@ -1,4 +1,5 @@ #include "guild.hpp" +#include "../abaddon.hpp" void from_json(const nlohmann::json &j, Guild &m) { JS_D("id", m.ID); @@ -64,3 +65,53 @@ bool Guild::HasIcon() const { std::string Guild::GetIconURL(std::string ext, std::string size) const { return "https://cdn.discordapp.com/icons/" + std::to_string(ID) + "/" + Icon + "." + ext + "?size=" + size; } + +std::vector<Snowflake> Guild::GetSortedChannels(Snowflake ignore) const { + std::vector<Snowflake> ret; + + const auto &discord = Abaddon::Get().GetDiscordClient(); + auto channels = discord.GetChannelsInGuild(ID); + + std::unordered_map<Snowflake, std::vector<const Channel *>> category_to_channels; + std::map<int, std::vector<const Channel *>> position_to_categories; + std::map<int, std::vector<const Channel *>> orphan_channels; + for (const auto &channel_id : channels) { + const auto *data = discord.GetChannel(channel_id); + if (data == nullptr) continue; + if (!data->ParentID.IsValid() && data->Type == ChannelType::GUILD_TEXT) + orphan_channels[data->Position].push_back(data); + else if (data->ParentID.IsValid() && data->Type == ChannelType::GUILD_TEXT) + category_to_channels[data->ParentID].push_back(data); + else if (data->Type == ChannelType::GUILD_CATEGORY) + position_to_categories[data->Position].push_back(data); + } + + for (auto &[pos, channels] : orphan_channels) { + std::sort(channels.begin(), channels.end(), [&](const Channel *a, const Channel *b) -> bool { + return a->ID < b->ID; + }); + for (auto &chan : channels) + ret.push_back(chan->ID); + } + + for (auto &[pos, categories] : position_to_categories) { + std::sort(categories.begin(), categories.end(), [&](const Channel *a, const Channel *b) -> bool { + return a->ID < b->ID; + }); + for (auto &category : categories) { + ret.push_back(category->ID); + if (ignore == category->ID) continue; // stupid hack to save me some time + auto it = category_to_channels.find(category->ID); + if (it == category_to_channels.end()) continue; + auto &channels = it->second; + std::sort(channels.begin(), channels.end(), [&](const Channel *a, const Channel *b) -> bool { + return a->Position < b->Position; + }); + for (auto &channel : channels) { + ret.push_back(channel->ID); + } + } + } + + return ret; +} diff --git a/discord/guild.hpp b/discord/guild.hpp index 74ea851..e76c8c5 100644 --- a/discord/guild.hpp +++ b/discord/guild.hpp @@ -68,4 +68,5 @@ struct Guild { bool HasIcon() const; std::string GetIconURL(std::string ext = "png", std::string size = "32") const; + std::vector<Snowflake> GetSortedChannels(Snowflake ignore = Snowflake::Invalid) const; }; diff --git a/discord/json.hpp b/discord/json.hpp index 1cd4a14..3f78391 100644 --- a/discord/json.hpp +++ b/discord/json.hpp @@ -21,3 +21,25 @@ if (j.contains(k) && !j.at(k).is_null()) \ j.at(k).get_to(t); \ } while (0) + +#define JS_RD(k, t) \ + do { \ + if (j.contains(k)) { \ + if (j.at(k).is_null()) { \ + t = decltype(t)(); \ + } else { \ + j.at(k).get_to(t); \ + } \ + } \ + } while (0) + +#define JS_RV(k, t, d) \ + do { \ + if (j.contains(k)) { \ + if (j.at(k).is_null()) { \ + t = d; \ + } else { \ + j.at(k).get_to(t); \ + } \ + } \ + } while (0) diff --git a/discord/objects.hpp b/discord/objects.hpp index 1e2cb27..66d899c 100644 --- a/discord/objects.hpp +++ b/discord/objects.hpp @@ -37,6 +37,9 @@ enum class GatewayEvent : int { MESSAGE_DELETE_BULK, GUILD_MEMBER_UPDATE, PRESENCE_UPDATE, + CHANNEL_DELETE, + CHANNEL_UPDATE, + CHANNEL_CREATE, }; struct GatewayMessage { diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp index de4ae30..2d1f7c3 100644 --- a/windows/mainwindow.cpp +++ b/windows/mainwindow.cpp @@ -124,6 +124,18 @@ void MainWindow::UpdateChannelsRemoveGuild(Snowflake id) { m_channel_list.UpdateRemoveGuild(id); } +void MainWindow::UpdateChannelsRemoveChannel(Snowflake id) { + m_channel_list.UpdateRemoveChannel(id); +} + +void MainWindow::UpdateChannelsUpdateChannel(Snowflake id) { + m_channel_list.UpdateChannel(id); +} + +void MainWindow::UpdateChannelsCreateChannel(Snowflake id) { + m_channel_list.UpdateCreateChannel(id); +} + void MainWindow::UpdateChatWindowContents() { auto &discord = Abaddon::Get().GetDiscordClient(); auto allmsgs = discord.GetMessagesForChannel(m_chat.GetActiveChannel()); diff --git a/windows/mainwindow.hpp b/windows/mainwindow.hpp index 68fedd3..8a33728 100644 --- a/windows/mainwindow.hpp +++ b/windows/mainwindow.hpp @@ -13,6 +13,9 @@ public: void UpdateChannelListing(); void UpdateChannelsNewGuild(Snowflake id); void UpdateChannelsRemoveGuild(Snowflake id); + void UpdateChannelsRemoveChannel(Snowflake id); + void UpdateChannelsUpdateChannel(Snowflake id); + void UpdateChannelsCreateChannel(Snowflake id); void UpdateChatWindowContents(); void UpdateChatActiveChannel(Snowflake id); Snowflake GetChatActiveChannel() const; |