summaryrefslogtreecommitdiff
path: root/src/discord
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2023-04-13 16:29:56 -0400
committerouwou <26526779+ouwou@users.noreply.github.com>2023-04-13 16:29:56 -0400
commitc084230767053e942b29941a8728f421e256cf1d (patch)
treeae58dc5d3978930ec5ed1fb0e65d108b56369d42 /src/discord
parent7b5dc8a86532cf00ab49a1922dbd4ce21cdaf01f (diff)
parent44ab35dfd591c4c357673cc2ce3cb3a6964a1fff (diff)
downloadabaddon-portaudio-c084230767053e942b29941a8728f421e256cf1d.tar.gz
abaddon-portaudio-c084230767053e942b29941a8728f421e256cf1d.zip
Merge branch 'master' of https://github.com/uowuo/abaddon into voice
Diffstat (limited to 'src/discord')
-rw-r--r--src/discord/discord.cpp19
-rw-r--r--src/discord/discord.hpp3
-rw-r--r--src/discord/guild.hpp10
-rw-r--r--src/discord/message.cpp13
-rw-r--r--src/discord/message.hpp3
-rw-r--r--src/discord/objects.cpp18
-rw-r--r--src/discord/objects.hpp15
-rw-r--r--src/discord/store.cpp52
-rw-r--r--src/discord/store.hpp2
9 files changed, 123 insertions, 12 deletions
diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp
index 6913ccf..64988d2 100644
--- a/src/discord/discord.cpp
+++ b/src/discord/discord.cpp
@@ -94,6 +94,18 @@ const UserData &DiscordClient::GetUserData() const {
return m_user_data;
}
+const UserGuildSettingsData &DiscordClient::GetUserGuildSettings() const {
+ return m_user_guild_settings;
+}
+
+std::optional<UserGuildSettingsEntry> DiscordClient::GetSettingsForGuild(Snowflake id) const {
+ if (const auto it = m_user_guild_settings.Entries.find(id); it != m_user_guild_settings.Entries.end()) {
+ return it->second;
+ }
+
+ return std::nullopt;
+}
+
std::vector<Snowflake> DiscordClient::GetUserSortedGuilds() const {
// sort order is unfolder'd guilds sorted by id descending, then guilds in folders in array order
// todo: make sure folder'd guilds are sorted properly
@@ -1701,6 +1713,8 @@ void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) {
m_session_id = data.SessionID;
m_user_data = data.SelfUser;
m_user_settings = data.Settings;
+ m_user_guild_settings = data.GuildSettings;
+ // TODO handle update
HandleReadyReadState(data);
HandleReadyGuildSettings(data);
@@ -2118,6 +2132,9 @@ void DiscordClient::HandleGatewayMessageAck(const GatewayMessage &msg) {
void DiscordClient::HandleGatewayUserGuildSettingsUpdate(const GatewayMessage &msg) {
UserGuildSettingsUpdateData data = msg.Data;
+
+ m_user_guild_settings.Entries[data.Settings.GuildID] = data.Settings;
+
const bool for_dms = !data.Settings.GuildID.IsValid();
const auto channels = for_dms ? GetPrivateChannels() : GetChannelsInGuild(data.Settings.GuildID);
@@ -2678,7 +2695,7 @@ void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) {
}
const auto now = Snowflake::FromNow();
- for (const auto &entry : data.GuildSettings.Entries) {
+ for (const auto &[guild_id, entry] : data.GuildSettings.Entries) {
// even if muted is true a guild/channel can be unmuted if the current time passes mute_config.end_time
if (entry.Muted) {
if (entry.MuteConfig.EndTime.has_value()) {
diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp
index 7b743ad..aadb72d 100644
--- a/src/discord/discord.hpp
+++ b/src/discord/discord.hpp
@@ -33,6 +33,8 @@ public:
std::unordered_set<Snowflake> GetGuilds() const;
const UserData &GetUserData() const;
+ const UserGuildSettingsData &GetUserGuildSettings() const;
+ std::optional<UserGuildSettingsEntry> GetSettingsForGuild(Snowflake id) const;
std::vector<Snowflake> GetUserSortedGuilds() const;
std::vector<Message> GetMessagesForChannel(Snowflake id, size_t limit = 50) const;
std::vector<Message> GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit = 50) const;
@@ -328,6 +330,7 @@ private:
UserData m_user_data;
UserSettings m_user_settings;
+ UserGuildSettingsData m_user_guild_settings;
Store m_store;
HTTPClient m_http;
diff --git a/src/discord/guild.hpp b/src/discord/guild.hpp
index 0428928..4895d30 100644
--- a/src/discord/guild.hpp
+++ b/src/discord/guild.hpp
@@ -8,6 +8,11 @@
#include <string>
#include <unordered_set>
+enum class DefaultNotificationLevel {
+ ALL_MESSAGES = 0,
+ ONLY_MENTIONS = 1,
+};
+
enum class GuildApplicationStatus {
STARTED,
PENDING,
@@ -36,9 +41,6 @@ struct GuildApplicationData {
// a bot is apparently only supposed to receive the `id` and `unavailable` as false
// but user tokens seem to get the full objects (minus users)
-
-// everythings optional cuz of muh partial guild object
-// anything not marked optional in https://discord.com/developers/docs/resources/guild#guild-object is guaranteed to be set when returned from Store::GetGuild
struct GuildData {
Snowflake ID;
std::string Name;
@@ -55,7 +57,7 @@ struct GuildData {
std::optional<bool> IsEmbedEnabled; // deprecated
std::optional<Snowflake> EmbedChannelID; // null, deprecated
std::optional<int> VerificationLevel;
- std::optional<int> DefaultMessageNotifications;
+ std::optional<DefaultNotificationLevel> DefaultMessageNotifications;
std::optional<int> ExplicitContentFilter;
std::optional<std::vector<RoleData>> Roles;
std::optional<std::vector<EmojiData>> Emojis; // only access id
diff --git a/src/discord/message.cpp b/src/discord/message.cpp
index ac12916..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);
@@ -264,9 +265,17 @@ bool Message::IsEdited() const {
return m_edited;
}
-bool Message::DoesMention(Snowflake id) const noexcept {
+bool Message::DoesMentionEveryoneOrUser(Snowflake id) const noexcept {
if (DoesMentionEveryone) return true;
return std::any_of(Mentions.begin(), Mentions.end(), [id](const UserData &user) {
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 4e332b6..df2cb38 100644
--- a/src/discord/message.hpp
+++ b/src/discord/message.hpp
@@ -183,7 +183,7 @@ struct Message {
bool IsTTS;
bool DoesMentionEveryone;
std::vector<UserData> Mentions; // full user accessible
- // std::vector<RoleData> MentionRoles;
+ std::vector<Snowflake> MentionRoles;
// std::optional<std::vector<ChannelMentionData>> MentionChannels;
std::vector<AttachmentData> Attachments;
std::vector<EmbedData> Embeds;
@@ -212,6 +212,7 @@ struct Message {
[[nodiscard]] bool IsDeleted() const;
[[nodiscard]] bool IsEdited() const;
+ [[nodiscard]] bool DoesMentionEveryoneOrUser(Snowflake id) const noexcept;
[[nodiscard]] bool DoesMention(Snowflake id) const noexcept;
private:
diff --git a/src/discord/objects.cpp b/src/discord/objects.cpp
index 37a9241..c783a3e 100644
--- a/src/discord/objects.cpp
+++ b/src/discord/objects.cpp
@@ -199,10 +199,26 @@ void to_json(nlohmann::json &j, const UserGuildSettingsEntry &m) {
j["version"] = m.Version;
}
+std::optional<UserGuildSettingsChannelOverride> UserGuildSettingsEntry::GetOverride(Snowflake channel_id) const {
+ for (const auto &override : ChannelOverrides) {
+ if (override.ChannelID == channel_id) return override;
+ }
+
+ return std::nullopt;
+}
+
void from_json(const nlohmann::json &j, UserGuildSettingsData &m) {
JS_D("version", m.Version);
JS_D("partial", m.IsPartial);
- JS_D("entries", m.Entries);
+
+ {
+ std::vector<UserGuildSettingsEntry> entries;
+ JS_D("entries", entries);
+
+ for (const auto &entry : entries) {
+ m.Entries[entry.GuildID] = entry;
+ }
+ }
}
void from_json(const nlohmann::json &j, ReadyEventData &m) {
diff --git a/src/discord/objects.hpp b/src/discord/objects.hpp
index 120ffa2..3ad4037 100644
--- a/src/discord/objects.hpp
+++ b/src/discord/objects.hpp
@@ -274,10 +274,17 @@ struct ReadStateData {
friend void from_json(const nlohmann::json &j, ReadStateData &m);
};
+enum class NotificationLevel {
+ ALL_MESSAGES = 0,
+ ONLY_MENTIONS = 1,
+ NO_MESSAGES = 2,
+ USE_UPPER = 3, // actually called "NULL"
+};
+
struct UserGuildSettingsChannelOverride {
bool Muted;
MuteConfigData MuteConfig;
- int MessageNotifications;
+ NotificationLevel MessageNotifications;
bool Collapsed;
Snowflake ChannelID;
@@ -292,19 +299,21 @@ struct UserGuildSettingsEntry {
bool Muted;
MuteConfigData MuteConfig;
bool MobilePush;
- int MessageNotifications;
+ NotificationLevel MessageNotifications;
bool HideMutedChannels;
Snowflake GuildID;
std::vector<UserGuildSettingsChannelOverride> ChannelOverrides;
friend void from_json(const nlohmann::json &j, UserGuildSettingsEntry &m);
friend void to_json(nlohmann::json &j, const UserGuildSettingsEntry &m);
+
+ std::optional<UserGuildSettingsChannelOverride> GetOverride(Snowflake channel_id) const;
};
struct UserGuildSettingsData {
int Version;
bool IsPartial;
- std::vector<UserGuildSettingsEntry> Entries;
+ std::map<Snowflake, UserGuildSettingsEntry> Entries;
friend void from_json(const nlohmann::json &j, UserGuildSettingsData &m);
};
diff --git a/src/discord/store.cpp b/src/discord/store.cpp
index 7f674c4..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<uint64_t>(id), static_cast<uint64_t>(r), m_db.ErrStr());
+ s->Reset();
+ }
+
for (const auto &a : message.Attachments) {
auto &s = m_stmt_set_attachment;
s->Bind(1, id);
@@ -779,6 +788,7 @@ std::optional<GuildData> Store::GetGuild(Snowflake id) const {
s->Get(1, r.Name);
s->Get(2, r.Icon);
s->Get(5, r.OwnerID);
+ s->Get(11, r.DefaultMessageNotifications);
s->Get(20, r.IsUnavailable);
s->Get(27, r.PremiumTier);
@@ -987,6 +997,17 @@ Message Store::GetMessageBound(std::unique_ptr<Statement> &s) const {
}
{
+ 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);
std::map<size_t, ReactionData> tmp;
@@ -1436,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,
@@ -1555,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;
@@ -2118,6 +2152,24 @@ bool Store::CreateStatements() {
return false;
}
+ m_stmt_set_role_mention = std::make_unique<Statement>(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<Statement>(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<Statement>(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);