From b83bf2a622ecfb667cc89909ebae9180ed5ac117 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 16 Mar 2023 20:27:59 -0400 Subject: handle role mentions --- src/discord/discord.cpp | 2 +- src/discord/message.cpp | 11 +++++++- src/discord/message.hpp | 3 ++- src/discord/store.cpp | 51 +++++++++++++++++++++++++++++++++++++ src/discord/store.hpp | 2 ++ src/notifications/notifications.cpp | 4 +-- 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 8e435aa..9b31e05 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1646,7 +1646,7 @@ void DiscordClient::HandleGatewayMessageCreate(const GatewayMessage &msg) { m_last_message_id[data.ChannelID] = data.ID; if (data.Author.ID != GetUserData().ID) m_unread[data.ChannelID]; - if (data.DoesMentionEveryoneOrUser(GetUserData().ID)) { + if (data.DoesMention(GetUserData().ID)) { m_unread[data.ChannelID]++; } m_signal_message_create.emit(data); diff --git a/src/discord/message.cpp b/src/discord/message.cpp index 5e15fa9..f5d8ad8 100644 --- a/src/discord/message.cpp +++ b/src/discord/message.cpp @@ -197,7 +197,7 @@ void from_json(const nlohmann::json &j, Message &m) { JS_D("tts", m.IsTTS); JS_D("mention_everyone", m.DoesMentionEveryone); JS_D("mentions", m.Mentions); - // JS_D("mention_roles", m.MentionRoles); + JS_D("mention_roles", m.MentionRoles); // JS_O("mention_channels", m.MentionChannels); JS_D("attachments", m.Attachments); JS_D("embeds", m.Embeds); @@ -235,6 +235,7 @@ void Message::from_json_edited(const nlohmann::json &j) { JS_O("tts", IsTTS); JS_O("mention_everyone", DoesMentionEveryone); JS_O("mentions", Mentions); + JS_O("mention_roles", MentionRoles); JS_O("embeds", Embeds); JS_O("nonce", Nonce); JS_O("pinned", IsPinned); @@ -270,3 +271,11 @@ bool Message::DoesMentionEveryoneOrUser(Snowflake id) const noexcept { return user.ID == id; }); } + +bool Message::DoesMention(Snowflake id) const noexcept { + if (DoesMentionEveryoneOrUser(id)) return true; + if (!GuildID.has_value()) return false; // nothing left to check + const auto member = Abaddon::Get().GetDiscordClient().GetMember(id, *GuildID); + if (!member.has_value()) return false; + return std::find_first_of(MentionRoles.begin(), MentionRoles.end(), member->Roles.begin(), member->Roles.end()) != MentionRoles.end(); +} diff --git a/src/discord/message.hpp b/src/discord/message.hpp index 22a1c5c..df2cb38 100644 --- a/src/discord/message.hpp +++ b/src/discord/message.hpp @@ -183,7 +183,7 @@ struct Message { bool IsTTS; bool DoesMentionEveryone; std::vector Mentions; // full user accessible - // std::vector MentionRoles; + std::vector MentionRoles; // std::optional> MentionChannels; std::vector Attachments; std::vector Embeds; @@ -213,6 +213,7 @@ struct Message { [[nodiscard]] bool IsEdited() const; [[nodiscard]] bool DoesMentionEveryoneOrUser(Snowflake id) const noexcept; + [[nodiscard]] bool DoesMention(Snowflake id) const noexcept; private: bool m_deleted = false; diff --git a/src/discord/store.cpp b/src/discord/store.cpp index 8393322..41b2069 100644 --- a/src/discord/store.cpp +++ b/src/discord/store.cpp @@ -346,6 +346,15 @@ void Store::SetMessage(Snowflake id, const Message &message) { s->Reset(); } + for (const auto &r : message.MentionRoles) { + auto &s = m_stmt_set_role_mention; + s->Bind(1, id); + s->Bind(2, r); + if (!s->Insert()) + fprintf(stderr, "message role mention insert failed for %" PRIu64 "/%" PRIu64 ": %s\n", static_cast(id), static_cast(r), m_db.ErrStr()); + s->Reset(); + } + for (const auto &a : message.Attachments) { auto &s = m_stmt_set_attachment; s->Bind(1, id); @@ -987,6 +996,17 @@ Message Store::GetMessageBound(std::unique_ptr &s) const { s->Reset(); } + { + auto &s = m_stmt_get_role_mentions; + s->Bind(1, r.ID); + while (s->FetchOne()) { + Snowflake id; + s->Get(0, id); + r.MentionRoles.push_back(id); + } + s->Reset(); + } + { auto &s = m_stmt_get_reactions; s->Bind(1, r.ID); @@ -1437,6 +1457,14 @@ bool Store::CreateTables() { ) )"; + const char *create_mention_roles = R"( + CREATE TABLE IF NOT EXISTS mention_roles ( + message INTEGER NOT NULL, + role INTEGER NOT NULL, + PRIMARY KEY(message, role) + ) + )"; + const char *create_attachments = R"( CREATE TABLE IF NOT EXISTS attachments ( message INTEGER NOT NULL, @@ -1556,6 +1584,11 @@ bool Store::CreateTables() { return false; } + if (m_db.Execute(create_mention_roles) != SQLITE_OK) { + fprintf(stderr, "failed to create role mentions table: %s\n", m_db.ErrStr()); + return false; + } + if (m_db.Execute(create_attachments) != SQLITE_OK) { fprintf(stderr, "failed to create attachments table: %s\n", m_db.ErrStr()); return false; @@ -2119,6 +2152,24 @@ bool Store::CreateStatements() { return false; } + m_stmt_set_role_mention = std::make_unique(m_db, R"( + REPLACE INTO mention_roles VALUES ( + ?, ? + ) + )"); + if (!m_stmt_set_role_mention->OK()) { + fprintf(stderr, "failed to prepare set role mention statement: %s\n", m_db.ErrStr()); + return false; + } + + m_stmt_get_role_mentions = std::make_unique(m_db, R"( + SELECT role FROM mention_roles WHERE message = ? + )"); + if (!m_stmt_get_role_mentions->OK()) { + fprintf(stderr, "failed to prepare get role mentions statement: %s\n", m_db.ErrStr()); + return false; + } + m_stmt_set_attachment = std::make_unique(m_db, R"( REPLACE INTO attachments VALUES ( ?, ?, ?, ?, ?, ?, ?, ? diff --git a/src/discord/store.hpp b/src/discord/store.hpp index 8e57e43..875a5af 100644 --- a/src/discord/store.hpp +++ b/src/discord/store.hpp @@ -299,6 +299,8 @@ private: STMT(get_emoji_roles); STMT(set_mention); STMT(get_mentions); + STMT(set_role_mention); + STMT(get_role_mentions); STMT(set_attachment); STMT(get_attachments); STMT(set_recipient); diff --git a/src/notifications/notifications.cpp b/src/notifications/notifications.cpp index a962765..fc7a2d6 100644 --- a/src/notifications/notifications.cpp +++ b/src/notifications/notifications.cpp @@ -22,7 +22,7 @@ bool CheckGuildMessage(const Message &message) { case DefaultNotificationLevel::ALL_MESSAGES: return true; case DefaultNotificationLevel::ONLY_MENTIONS: - return message.DoesMentionEveryoneOrUser(discord.GetUserData().ID); + return message.DoesMention(discord.GetUserData().ID); default: return false; } @@ -78,7 +78,7 @@ bool CheckGuildMessage(const Message &message) { case NotificationLevel::ALL_MESSAGES: return true; case NotificationLevel::ONLY_MENTIONS: - return message.DoesMentionEveryoneOrUser(discord.GetUserData().ID); + return message.DoesMention(discord.GetUserData().ID); case NotificationLevel::NO_MESSAGES: return false; default: -- cgit v1.2.3