From dfd642bb82d2998cc563f0f401f2d522632692c1 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 20 Jan 2022 01:34:36 -0500 Subject: show unread indicators for threads --- src/discord/discord.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/discord/discord.cpp') diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 5b3cdb5..ff269df 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -2343,10 +2343,14 @@ void DiscordClient::StoreMessageData(Message &msg) { // here the absence of an entry in m_unread indicates a read channel and the value is only the mention count since the message doesnt matter // no entry.id cannot be a guild even though sometimes it looks like it void DiscordClient::HandleReadyReadState(const ReadyEventData &data) { - for (const auto &guild : data.Guilds) + for (const auto &guild : data.Guilds) { for (const auto &channel : *guild.Channels) if (channel.LastMessageID.has_value()) m_last_message_id[channel.ID] = *channel.LastMessageID; + for (const auto &thread : *guild.Threads) + if (thread.LastMessageID.has_value()) + m_last_message_id[thread.ID] = *thread.LastMessageID; + } for (const auto &channel : data.PrivateChannels) if (channel.LastMessageID.has_value()) m_last_message_id[channel.ID] = *channel.LastMessageID; -- cgit v1.2.3 From 2328c8bafee708fc33dcd004562a270183ebcf30 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 20 Jan 2022 01:40:27 -0500 Subject: handle initial muted state for threads --- src/discord/channel.cpp | 2 ++ src/discord/channel.hpp | 10 ++++++++++ src/discord/discord.cpp | 6 +++++- src/discord/objects.hpp | 8 -------- 4 files changed, 17 insertions(+), 9 deletions(-) (limited to 'src/discord/discord.cpp') diff --git a/src/discord/channel.cpp b/src/discord/channel.cpp index 2f5c3c1..dcd3b8f 100644 --- a/src/discord/channel.cpp +++ b/src/discord/channel.cpp @@ -13,6 +13,8 @@ void from_json(const nlohmann::json &j, ThreadMemberObject &m) { JS_O("user_id", m.UserID); JS_D("join_timestamp", m.JoinTimestamp); JS_D("flags", m.Flags); + JS_O("muted", m.IsMuted); + JS_ON("mute_config", m.MuteConfig); } void from_json(const nlohmann::json &j, ChannelData &m) { diff --git a/src/discord/channel.hpp b/src/discord/channel.hpp index 195a09a..4485b0b 100644 --- a/src/discord/channel.hpp +++ b/src/discord/channel.hpp @@ -49,9 +49,19 @@ struct ThreadMetadataData { friend void from_json(const nlohmann::json &j, ThreadMetadataData &m); }; +struct MuteConfigData { + std::optional EndTime; // nullopt is encoded as null + int SelectedTimeWindow; + + friend void from_json(const nlohmann::json &j, MuteConfigData &m); + friend void to_json(nlohmann::json &j, const MuteConfigData &m); +}; + struct ThreadMemberObject { std::optional ThreadID; std::optional UserID; + std::optional IsMuted; + std::optional MuteConfig; std::string JoinTimestamp; int Flags; diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index ff269df..e123818 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -2389,10 +2389,14 @@ void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) { // i dont like this implementation for muted categories but its rather simple and doesnt use a horriiible amount of ram std::unordered_map> category_children; - for (const auto &guild : data.Guilds) + for (const auto &guild : data.Guilds) { for (const auto &channel : *guild.Channels) if (channel.ParentID.has_value() && !channel.IsThread()) category_children[*channel.ParentID].push_back(channel.ID); + for (const auto &thread : *guild.Threads) + if (thread.ThreadMember.has_value() && thread.ThreadMember->IsMuted.has_value() && *thread.ThreadMember->IsMuted) + m_muted_channels.insert(thread.ID); + } const auto now = Snowflake::FromNow(); for (const auto &entry : data.GuildSettings.Entries) { diff --git a/src/discord/objects.hpp b/src/discord/objects.hpp index c72361b..8568222 100644 --- a/src/discord/objects.hpp +++ b/src/discord/objects.hpp @@ -244,14 +244,6 @@ struct ReadStateData { friend void from_json(const nlohmann::json &j, ReadStateData &m); }; -struct MuteConfigData { - std::optional EndTime; // nullopt is encoded as null - int SelectedTimeWindow; - - friend void from_json(const nlohmann::json &j, MuteConfigData &m); - friend void to_json(nlohmann::json &j, const MuteConfigData &m); -}; - struct UserGuildSettingsChannelOverride { bool Muted; MuteConfigData MuteConfig; -- cgit v1.2.3 From d7f3ee9f983458bdaf504c5813adc93bed1404e4 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 20 Jan 2022 01:52:48 -0500 Subject: handle mute/unmute updates for threads --- src/discord/discord.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/discord/discord.cpp') diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index e123818..ab821a8 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1921,9 +1921,24 @@ void DiscordClient::HandleGatewayThreadMembersUpdate(const GatewayMessage &msg) void DiscordClient::HandleGatewayThreadMemberUpdate(const GatewayMessage &msg) { ThreadMemberUpdateData data = msg.Data; + if (!data.Member.ThreadID.has_value()) return; + m_joined_threads.insert(*data.Member.ThreadID); if (*data.Member.UserID == GetUserData().ID) m_signal_added_to_thread.emit(*data.Member.ThreadID); + + if (data.Member.IsMuted.has_value()) { + const bool was_muted = IsChannelMuted(*data.Member.ThreadID); + const bool now_muted = *data.Member.IsMuted; + + if (was_muted && !now_muted) { + m_muted_channels.erase(*data.Member.ThreadID); + m_signal_channel_unmuted.emit(*data.Member.ThreadID); + } else if (!was_muted && now_muted) { + m_muted_channels.insert(*data.Member.ThreadID); + m_signal_channel_muted.emit(*data.Member.ThreadID); + } + } } void DiscordClient::HandleGatewayThreadUpdate(const GatewayMessage &msg) { -- cgit v1.2.3 From b6b215ee6f08e4e7d6d987ffd676cebeb8638a62 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 20 Jan 2022 02:45:28 -0500 Subject: add mark as unread/toggle mute for threads --- src/components/channels.cpp | 27 ++++++++++++++++++++++++--- src/components/channels.hpp | 2 ++ src/discord/discord.cpp | 18 ++++++++++++++++++ src/discord/discord.hpp | 2 ++ 4 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src/discord/discord.cpp') diff --git a/src/components/channels.cpp b/src/components/channels.cpp index 5385b23..c0d1a8b 100644 --- a/src/components/channels.cpp +++ b/src/components/channels.cpp @@ -22,7 +22,8 @@ ChannelList::ChannelList() , m_menu_thread_copy_id("_Copy ID", true) , m_menu_thread_leave("_Leave", true) , m_menu_thread_archive("_Archive", true) - , m_menu_thread_unarchive("_Unarchive", true) { + , m_menu_thread_unarchive("_Unarchive", true) + , m_menu_thread_mark_as_read("Mark as _Read", true) { get_style_context()->add_class("channel-list"); // todo: move to method @@ -187,10 +188,23 @@ ChannelList::ChannelList() m_menu_thread_unarchive.signal_activate().connect([this] { Abaddon::Get().GetDiscordClient().UnArchiveThread(static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]), [](...) {}); }); - m_menu_thread.append(m_menu_thread_copy_id); + m_menu_thread_mark_as_read.signal_activate().connect([this] { + Abaddon::Get().GetDiscordClient().MarkChannelAsRead(static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]), NOOP_CALLBACK); + }); + m_menu_thread_toggle_mute.signal_activate().connect([this] { + const auto id = static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); + auto &discord = Abaddon::Get().GetDiscordClient(); + if (discord.IsChannelMuted(id)) + discord.UnmuteThread(id, NOOP_CALLBACK); + else + discord.MuteThread(id, NOOP_CALLBACK); + }); + m_menu_thread.append(m_menu_thread_mark_as_read); + m_menu_thread.append(m_menu_thread_toggle_mute); m_menu_thread.append(m_menu_thread_leave); m_menu_thread.append(m_menu_thread_archive); m_menu_thread.append(m_menu_thread_unarchive); + m_menu_thread.append(m_menu_thread_copy_id); m_menu_thread.show_all(); m_menu_guild.signal_popped_up().connect(sigc::mem_fun(*this, &ChannelList::OnGuildSubmenuPopup)); @@ -914,7 +928,14 @@ void ChannelList::OnThreadSubmenuPopup(const Gdk::Rectangle *flipped_rect, const auto &discord = Abaddon::Get().GetDiscordClient(); auto iter = m_model->get_iter(m_path_for_menu); if (!iter) return; - auto channel = discord.GetChannel(static_cast((*iter)[m_columns.m_id])); + const auto id = static_cast((*iter)[m_columns.m_id]); + + if (discord.IsChannelMuted(id)) + m_menu_thread_toggle_mute.set_label("Unmute"); + else + m_menu_thread_toggle_mute.set_label("Mute"); + + auto channel = discord.GetChannel(id); if (!channel.has_value() || !channel->ThreadMetadata.has_value()) return; if (!discord.HasGuildPermission(discord.GetUserData().ID, *channel->GuildID, Permission::MANAGE_THREADS)) return; diff --git a/src/components/channels.hpp b/src/components/channels.hpp index 4ec0587..a2553fd 100644 --- a/src/components/channels.hpp +++ b/src/components/channels.hpp @@ -131,6 +131,8 @@ protected: Gtk::MenuItem m_menu_thread_leave; Gtk::MenuItem m_menu_thread_archive; Gtk::MenuItem m_menu_thread_unarchive; + Gtk::MenuItem m_menu_thread_mark_as_read; + Gtk::MenuItem m_menu_thread_toggle_mute; void OnGuildSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y); void OnCategorySubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y); diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index ab821a8..8d1cf12 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -983,6 +983,24 @@ void DiscordClient::UnmuteGuild(Snowflake id, sigc::slot callback) { + m_http.MakePATCH("/channels/" + std::to_string(id) + "/thread-members/@me/settings", R"({"muted":true})", [this, callback](const http::response_type &response) { + if (CheckCode(response)) + callback(DiscordError::NONE); + else + callback(GetCodeFromResponse(response)); + }); +} + +void DiscordClient::UnmuteThread(Snowflake id, sigc::slot callback) { + m_http.MakePATCH("/channels/" + std::to_string(id) + "/thread-members/@me/settings", R"({"muted":false})", [this, callback](const http::response_type &response) { + if (CheckCode(response)) + callback(DiscordError::NONE); + else + callback(GetCodeFromResponse(response)); + }); +} + void DiscordClient::FetchPinned(Snowflake id, sigc::slot, DiscordError code)> callback) { // return from db if we know the pins have already been requested if (m_channels_pinned_requested.find(id) != m_channels_pinned_requested.end()) { diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index 1a6aa14..4a7593d 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -146,6 +146,8 @@ public: void MarkAllAsRead(sigc::slot callback); void MuteGuild(Snowflake id, sigc::slot callback); void UnmuteGuild(Snowflake id, sigc::slot callback); + void MuteThread(Snowflake id, sigc::slot callback); + void UnmuteThread(Snowflake id, sigc::slot callback); bool CanModifyRole(Snowflake guild_id, Snowflake role_id) const; bool CanModifyRole(Snowflake guild_id, Snowflake role_id, Snowflake user_id) const; -- cgit v1.2.3 From 7d49f934bc1bb87a5b811374433f574733963188 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:43:47 -0500 Subject: muted dms dont contribute to unread count --- src/discord/discord.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/discord/discord.cpp') diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 8d1cf12..78f2c35 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1224,7 +1224,7 @@ int DiscordClient::GetUnreadDMsCount() const { const auto channels = GetPrivateChannels(); int count = 0; for (const auto channel_id : channels) - if (GetUnreadStateForChannel(channel_id) > -1) count++; + if (!IsChannelMuted(channel_id) && GetUnreadStateForChannel(channel_id) > -1) count++; return count; } -- cgit v1.2.3 From 17f1289c84af11b6e02f5f5de4714c8aad18e47e Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 3 Mar 2022 03:01:09 -0500 Subject: fill out gateway op enum using internal names --- src/discord/discord.cpp | 2 +- src/discord/objects.cpp | 4 ++-- src/discord/objects.hpp | 25 ++++++++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src/discord/discord.cpp') diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 78f2c35..6ea0ea6 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1328,7 +1328,7 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayOp::InvalidSession: { HandleGatewayInvalidSession(m); } break; - case GatewayOp::Event: { + case GatewayOp::Dispatch: { auto iter = m_event_map.find(m.Type); if (iter == m_event_map.end()) { printf("Unknown event %s\n", m.Type.c_str()); diff --git a/src/discord/objects.cpp b/src/discord/objects.cpp index 8d85f9a..0ee96dc 100644 --- a/src/discord/objects.cpp +++ b/src/discord/objects.cpp @@ -77,7 +77,7 @@ void from_json(const nlohmann::json &j, GuildMemberListUpdateMessage &m) { } void to_json(nlohmann::json &j, const LazyLoadRequestMessage &m) { - j["op"] = GatewayOp::LazyLoadRequest; + j["op"] = GatewayOp::GuildSubscriptions; j["d"] = nlohmann::json::object(); j["d"]["guild_id"] = m.GuildID; if (m.Channels.has_value()) { @@ -98,7 +98,7 @@ void to_json(nlohmann::json &j, const LazyLoadRequestMessage &m) { } void to_json(nlohmann::json &j, const UpdateStatusMessage &m) { - j["op"] = GatewayOp::UpdateStatus; + j["op"] = GatewayOp::PresenceUpdate; j["d"] = nlohmann::json::object(); j["d"]["since"] = m.Since; j["d"]["activities"] = m.Activities; diff --git a/src/discord/objects.hpp b/src/discord/objects.hpp index 8568222..fae592a 100644 --- a/src/discord/objects.hpp +++ b/src/discord/objects.hpp @@ -24,16 +24,35 @@ // most stuff below should just be objects that get processed and thrown away immediately enum class GatewayOp : int { - Event = 0, + Dispatch = 0, Heartbeat = 1, Identify = 2, - UpdateStatus = 3, + PresenceUpdate = 3, + VoiceStateUpdate = 4, + VoiceServerPing = 5, Resume = 6, Reconnect = 7, + RequestGuildMembers = 8, InvalidSession = 9, Hello = 10, HeartbeatAck = 11, - LazyLoadRequest = 14, + // 12 unused + CallConnect = 13, + GuildSubscriptions = 14, + LobbyConnect = 15, + LobbyDisconnect = 16, + LobbyVoiceStatesUpdate = 17, + StreamCreate = 18, + StreamDelete = 19, + StreamWatch = 20, + StreamPing = 21, + StreamSetPaused = 22, + // 23 unused + RequestGuildApplicationCommands = 24, + EmbeddedActivityLaunch = 25, + EmbeddedActivityClose = 26, + EmbeddedActivityUpdate = 27, + RequestForumUnreads = 28, }; enum class GatewayEvent : int { -- cgit v1.2.3 From 7f1d3df4a5d640ae3a885886139236e8f9c5555c Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 3 Mar 2022 23:45:30 -0500 Subject: start sending request guild members for unknown members --- src/abaddon.cpp | 19 ++++++++++++++++++- src/abaddon.hpp | 2 ++ src/discord/discord.cpp | 16 ++++++++++++++++ src/discord/discord.hpp | 14 ++++++++++++++ src/discord/objects.cpp | 13 +++++++++++++ src/discord/objects.hpp | 22 ++++++++++++++++++++++ 6 files changed, 85 insertions(+), 1 deletion(-) (limited to 'src/discord/discord.cpp') diff --git a/src/abaddon.cpp b/src/abaddon.cpp index 51f8052..b287e17 100644 --- a/src/abaddon.cpp +++ b/src/abaddon.cpp @@ -325,6 +325,22 @@ void Abaddon::ShowGuildVerificationGateDialog(Snowflake guild_id) { } } +void Abaddon::CheckMessagesForMembers(const ChannelData &chan, const std::vector &msgs) { + if (!chan.GuildID.has_value()) return; + + // TODO sql query + std::set fetch; + std::set ids; + for (const auto& msg : msgs) + ids.insert(msg.Author.ID); + for (const auto id : ids) { + const auto member = m_discord.GetMember(id, *chan.GuildID); + if (!member.has_value()) + fetch.insert(id); + } + m_discord.RequestMembers(*chan.GuildID, fetch.begin(), fetch.end()); +} + void Abaddon::SetupUserMenu() { m_user_menu = Gtk::manage(new Gtk::Menu); m_user_menu_insert_mention = Gtk::manage(new Gtk::MenuItem("Insert Mention")); @@ -536,7 +552,8 @@ void Abaddon::ActionChannelOpened(Snowflake id) { if (m_channels_requested.find(id) == m_channels_requested.end()) { // dont fire requests we know will fail if (can_access) { - m_discord.FetchMessagesInChannel(id, [this, id](const std::vector &msgs) { + m_discord.FetchMessagesInChannel(id, [channel, this, id](const std::vector &msgs) { + CheckMessagesForMembers(*channel, msgs); m_main_window->UpdateChatWindowContents(); m_channels_requested.insert(id); }); diff --git a/src/abaddon.hpp b/src/abaddon.hpp index d9d0bb0..311dcc5 100644 --- a/src/abaddon.hpp +++ b/src/abaddon.hpp @@ -93,6 +93,8 @@ public: protected: void ShowGuildVerificationGateDialog(Snowflake guild_id); + void CheckMessagesForMembers(const ChannelData &chan, const std::vector &msgs); + void SetupUserMenu(); void SaveState(); void LoadState(); diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 6ea0ea6..c11210d 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1464,6 +1464,9 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::USER_GUILD_SETTINGS_UPDATE: { HandleGatewayUserGuildSettingsUpdate(m); } break; + case GatewayEvent::GUILD_MEMBERS_CHUNK: { + HandleGatewayGuildMembersChunk(m); + } break; } } break; default: @@ -2049,6 +2052,14 @@ void DiscordClient::HandleGatewayUserGuildSettingsUpdate(const GatewayMessage &m } } +void DiscordClient::HandleGatewayGuildMembersChunk(const GatewayMessage &msg) { + GuildMembersChunkData data = msg.Data; + m_store.BeginTransaction(); + for (const auto &member : data.Members) + m_store.SetGuildMember(data.GuildID, member.User->ID, member); + m_store.EndTransaction(); +} + void DiscordClient::HandleGatewayReadySupplemental(const GatewayMessage &msg) { ReadySupplementalData data = msg.Data; for (const auto &p : data.MergedPresences.Friends) { @@ -2511,6 +2522,7 @@ void DiscordClient::LoadEventMap() { m_event_map["THREAD_MEMBER_LIST_UPDATE"] = GatewayEvent::THREAD_MEMBER_LIST_UPDATE; m_event_map["MESSAGE_ACK"] = GatewayEvent::MESSAGE_ACK; m_event_map["USER_GUILD_SETTINGS_UPDATE"] = GatewayEvent::USER_GUILD_SETTINGS_UPDATE; + m_event_map["GUILD_MEMBERS_CHUNK"] = GatewayEvent::GUILD_MEMBERS_CHUNK; } DiscordClient::type_signal_gateway_ready DiscordClient::signal_gateway_ready() { @@ -2677,6 +2689,10 @@ DiscordClient::type_signal_message_ack DiscordClient::signal_message_ack() { return m_signal_message_ack; } +DiscordClient::type_signal_guild_members_chunk DiscordClient::signal_guild_members_chunk() { + return m_signal_guild_members_chunk; +} + DiscordClient::type_signal_added_to_thread DiscordClient::signal_added_to_thread() { return m_signal_added_to_thread; } diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index 4a7593d..63f8bd5 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -152,6 +152,16 @@ public: bool CanModifyRole(Snowflake guild_id, Snowflake role_id) const; bool CanModifyRole(Snowflake guild_id, Snowflake role_id, Snowflake user_id) const; + // send op 8 to get member data for unknown members + template + void RequestMembers(Snowflake guild_id, Iter begin, Iter end) { + RequestGuildMembersMessage obj; + obj.GuildID = guild_id; + obj.Presences = false; + obj.UserIDs = { begin, end }; + m_websocket.Send(obj); + } + // real client doesn't seem to use the single role endpoints so neither do we template auto SetMemberRoles(Snowflake guild_id, Snowflake user_id, Iter begin, Iter end, sigc::slot callback) { @@ -262,6 +272,7 @@ private: void HandleGatewayThreadMemberListUpdate(const GatewayMessage &msg); void HandleGatewayMessageAck(const GatewayMessage &msg); void HandleGatewayUserGuildSettingsUpdate(const GatewayMessage &msg); + void HandleGatewayGuildMembersChunk(const GatewayMessage &msg); void HandleGatewayReadySupplemental(const GatewayMessage &msg); void HandleGatewayReconnect(const GatewayMessage &msg); void HandleGatewayInvalidSession(const GatewayMessage &msg); @@ -372,6 +383,7 @@ public: typedef sigc::signal type_signal_thread_update; typedef sigc::signal type_signal_thread_member_list_update; typedef sigc::signal type_signal_message_ack; + typedef sigc::signal type_signal_guild_members_chunk; // not discord dispatch events typedef sigc::signal type_signal_added_to_thread; @@ -427,6 +439,7 @@ public: type_signal_thread_update signal_thread_update(); type_signal_thread_member_list_update signal_thread_member_list_update(); type_signal_message_ack signal_message_ack(); + type_signal_guild_members_chunk signal_guild_members_chunk(); type_signal_added_to_thread signal_added_to_thread(); type_signal_removed_from_thread signal_removed_from_thread(); @@ -479,6 +492,7 @@ protected: type_signal_thread_update m_signal_thread_update; type_signal_thread_member_list_update m_signal_thread_member_list_update; type_signal_message_ack m_signal_message_ack; + type_signal_guild_members_chunk m_signal_guild_members_chunk; type_signal_removed_from_thread m_signal_removed_from_thread; type_signal_added_to_thread m_signal_added_to_thread; diff --git a/src/discord/objects.cpp b/src/discord/objects.cpp index 0ee96dc..3c9f770 100644 --- a/src/discord/objects.cpp +++ b/src/discord/objects.cpp @@ -119,6 +119,14 @@ void to_json(nlohmann::json &j, const UpdateStatusMessage &m) { } } +void to_json(nlohmann::json &j, const RequestGuildMembersMessage &m) { + j["op"] = GatewayOp::RequestGuildMembers; + j["d"] = nlohmann::json::object(); + j["d"]["guild_id"] = m.GuildID; + j["d"]["presences"] = m.Presences; + j["d"]["user_ids"] = m.UserIDs; +} + void from_json(const nlohmann::json &j, ReadStateEntry &m) { JS_ON("mention_count", m.MentionCount); JS_ON("last_message_id", m.LastMessageID); @@ -626,3 +634,8 @@ void to_json(nlohmann::json &j, const AckBulkData &m) { void from_json(const nlohmann::json &j, UserGuildSettingsUpdateData &m) { m.Settings = j; } + +void from_json(const nlohmann::json &j, GuildMembersChunkData &m) { + JS_D("members", m.Members); + JS_D("guild_id", m.GuildID); +} diff --git a/src/discord/objects.hpp b/src/discord/objects.hpp index fae592a..27542cc 100644 --- a/src/discord/objects.hpp +++ b/src/discord/objects.hpp @@ -99,6 +99,7 @@ enum class GatewayEvent : int { THREAD_MEMBER_LIST_UPDATE, MESSAGE_ACK, USER_GUILD_SETTINGS_UPDATE, + GUILD_MEMBERS_CHUNK, }; enum class GatewayCloseCode : uint16_t { @@ -245,6 +246,14 @@ struct UpdateStatusMessage { friend void to_json(nlohmann::json &j, const UpdateStatusMessage &m); }; +struct RequestGuildMembersMessage { + Snowflake GuildID; + bool Presences; + std::vector UserIDs; + + friend void to_json(nlohmann::json &j, const RequestGuildMembersMessage &m); +}; + struct ReadStateEntry { int MentionCount; Snowflake LastMessageID; @@ -841,3 +850,16 @@ struct UserGuildSettingsUpdateData { friend void from_json(const nlohmann::json &j, UserGuildSettingsUpdateData &m); }; + +struct GuildMembersChunkData { + /* + not needed so not deserialized + int ChunkCount; + int ChunkIndex; + std::vector NotFound; + */ + Snowflake GuildID; + std::vector Members; + + friend void from_json(const nlohmann::json &j, GuildMembersChunkData &m); +}; -- cgit v1.2.3