member, emoji

This commit is contained in:
ouwou 2020-12-05 18:18:51 -05:00
parent 0935e43bae
commit b84a98fbb9
5 changed files with 138 additions and 70 deletions

View File

@ -185,21 +185,21 @@ const Guild *DiscordClient::GetGuild(Snowflake id) const {
return m_store.GetGuild(id);
}
const GuildMember *DiscordClient::GetMember(Snowflake user_id, Snowflake guild_id) const {
return m_store.GetGuildMemberData(guild_id, user_id);
std::optional<GuildMember> DiscordClient::GetMember(Snowflake user_id, Snowflake guild_id) const {
return m_store.GetGuildMember(guild_id, user_id);
}
std::optional<PermissionOverwrite> DiscordClient::GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const {
return m_store.GetPermissionOverwrite(channel_id, id);
}
const Emoji *DiscordClient::GetEmoji(Snowflake id) const {
std::optional<Emoji> DiscordClient::GetEmoji(Snowflake id) const {
return m_store.GetEmoji(id);
}
Snowflake DiscordClient::GetMemberHoistedRole(Snowflake guild_id, Snowflake user_id, bool with_color) const {
auto *data = m_store.GetGuildMemberData(guild_id, user_id);
if (data == nullptr) return Snowflake::Invalid;
const auto data = GetMember(guild_id, user_id);
if (!data.has_value()) return Snowflake::Invalid;
std::vector<Role> roles;
for (const auto &id : data->Roles) {
@ -220,8 +220,8 @@ Snowflake DiscordClient::GetMemberHoistedRole(Snowflake guild_id, Snowflake user
}
Snowflake DiscordClient::GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const {
const auto *data = GetMember(user_id, guild_id);
if (data == nullptr) return Snowflake::Invalid;
const auto data = GetMember(user_id, guild_id);
if (!data.has_value()) return Snowflake::Invalid;
if (data->Roles.size() == 0) return Snowflake::Invalid;
if (data->Roles.size() == 1) return data->Roles[0];
@ -263,9 +263,9 @@ bool DiscordClient::HasChannelPermission(Snowflake user_id, Snowflake channel_id
}
Permission DiscordClient::ComputePermissions(Snowflake member_id, Snowflake guild_id) const {
const auto *member = GetMember(member_id, guild_id);
const auto member = GetMember(member_id, guild_id);
const auto *guild = GetGuild(guild_id);
if (member == nullptr || guild == nullptr)
if (!member.has_value() || guild == nullptr)
return Permission::NONE;
if (guild->OwnerID == member_id)
@ -293,8 +293,8 @@ Permission DiscordClient::ComputeOverwrites(Permission base, Snowflake member_id
return Permission::ALL;
const auto *channel = GetChannel(channel_id);
const auto *member = GetMember(member_id, channel->GuildID);
if (member == nullptr || channel == nullptr)
const auto member = GetMember(member_id, channel->GuildID);
if (!member.has_value() || channel == nullptr)
return Permission::NONE;
Permission perms = base;
@ -658,7 +658,7 @@ void DiscordClient::HandleGatewayMessageDeleteBulk(const GatewayMessage &msg) {
void DiscordClient::HandleGatewayGuildMemberUpdate(const GatewayMessage &msg) {
GuildMemberUpdateMessage data = msg.Data;
auto member = GuildMember::from_update_json(msg.Data); // meh
m_store.SetGuildMemberData(data.GuildID, data.User.ID, member);
m_store.SetGuildMember(data.GuildID, data.User.ID, member);
}
void DiscordClient::HandleGatewayPresenceUpdate(const GatewayMessage &msg) {
@ -753,7 +753,7 @@ void DiscordClient::HandleGatewayGuildMemberListUpdate(const GatewayMessage &msg
auto member = static_cast<const GuildMemberListUpdateMessage::MemberItem *>(item.get());
m_store.SetUser(member->User.ID, member->User);
AddUserToGuild(member->User.ID, data.GuildID);
m_store.SetGuildMemberData(data.GuildID, member->User.ID, member->GetAsMemberData());
m_store.SetGuildMember(data.GuildID, member->User.ID, member->GetAsMemberData());
}
}
}

View File

@ -82,12 +82,12 @@ public:
void FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> cb);
std::optional<Message> GetMessage(Snowflake id) const;
const Channel *GetChannel(Snowflake id) const;
std::optional<Emoji> GetEmoji(Snowflake id) const;
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
std::optional<User> GetUser(Snowflake id) const;
std::optional<Role> GetRole(Snowflake id) const;
const Guild *GetGuild(Snowflake id) const;
const GuildMember *GetMember(Snowflake user_id, Snowflake guild_id) const;
const Emoji *GetEmoji(Snowflake id) const;
std::optional<GuildMember> GetMember(Snowflake user_id, Snowflake guild_id) const;
Snowflake GetMemberHoistedRole(Snowflake guild_id, Snowflake user_id, bool with_color = false) const;
Snowflake GetMemberHighestRole(Snowflake guild_id, Snowflake user_id) const;
std::unordered_set<Snowflake> GetUsersInGuild(Snowflake id) const;

View File

@ -6,13 +6,13 @@
#include <vector>
struct GuildMember {
User User; // opt
std::string Nickname; // null
std::vector<Snowflake> Roles; //
std::string JoinedAt; //
std::string PremiumSince; // opt, null
bool IsDeafened; //
bool IsMuted; //
std::optional<User> User; // only reliable to access id. only opt in MESSAGE_*
std::string Nickname; // null
std::vector<Snowflake> Roles;
std::string JoinedAt;
std::optional<std::string> PremiumSince; // null
bool IsDeafened;
bool IsMuted;
friend void from_json(const nlohmann::json &j, GuildMember &m);
static GuildMember from_update_json(const nlohmann::json &j);

View File

@ -103,7 +103,7 @@ void Store::SetMessage(Snowflake id, const Message &message) {
Bind(m_set_msg_stmt, 7, message.EditedTimestamp);
Bind(m_set_msg_stmt, 8, message.IsTTS);
Bind(m_set_msg_stmt, 9, message.DoesMentionEveryone);
Bind(m_set_msg_stmt, 10, "[]"s); // mentions
Bind(m_set_msg_stmt, 10, "[]"s); // mentions, a const char* literal will call the bool overload instead of std::string
{
std::string tmp;
tmp = nlohmann::json(message.Attachments).dump();
@ -141,8 +141,18 @@ void Store::SetMessage(Snowflake id, const Message &message) {
fprintf(stderr, "message insert failed: %s\n", sqlite3_errstr(m_db_err));
}
void Store::SetGuildMemberData(Snowflake guild_id, Snowflake user_id, const GuildMember &data) {
m_members[guild_id][user_id] = data;
void Store::SetGuildMember(Snowflake guild_id, Snowflake user_id, const GuildMember &data) {
Bind(m_set_member_stmt, 1, user_id);
Bind(m_set_member_stmt, 2, guild_id);
Bind(m_set_member_stmt, 3, data.Nickname);
Bind(m_set_member_stmt, 4, nlohmann::json(data.Roles).dump());
Bind(m_set_member_stmt, 5, data.JoinedAt);
Bind(m_set_member_stmt, 6, data.PremiumSince);
Bind(m_set_member_stmt, 7, data.IsDeafened);
Bind(m_set_member_stmt, 8, data.IsMuted);
if (!RunInsert(m_set_member_stmt))
fprintf(stderr, "member insert failed: %s\n", sqlite3_errstr(m_db_err));
}
void Store::SetPermissionOverwrite(Snowflake channel_id, Snowflake id, const PermissionOverwrite &perm) {
@ -177,8 +187,59 @@ void Store::SetEmoji(Snowflake id, const Emoji &emoji) {
if (!RunInsert(m_set_emote_stmt))
fprintf(stderr, "emoji insert failed: %s\n", sqlite3_errstr(m_db_err));
}
m_emojis[id] = emoji;
std::optional<Emoji> Store::GetEmoji(Snowflake id) const {
Bind(m_get_emote_stmt, 1, id);
if (!FetchOne(m_get_emote_stmt)) {
if (m_db_err != SQLITE_DONE)
fprintf(stderr, "error while fetching emoji: %s\n", sqlite3_errstr(m_db_err));
Reset(m_get_emote_stmt);
return std::nullopt;
}
Emoji ret;
ret.ID = id;
Get(m_get_emote_stmt, 1, ret.Name);
std::string tmp;
Get(m_get_emote_stmt, 2, tmp);
ret.Roles = nlohmann::json::parse(tmp).get<std::vector<Snowflake>>();
ret.Creator = std::optional<User>(User());
Get(m_get_emote_stmt, 3, ret.Creator->ID);
Get(m_get_emote_stmt, 3, ret.NeedsColons);
Get(m_get_emote_stmt, 4, ret.IsManaged);
Get(m_get_emote_stmt, 5, ret.IsAnimated);
Get(m_get_emote_stmt, 6, ret.IsAvailable);
Reset(m_get_emote_stmt);
return ret;
}
std::optional<GuildMember> Store::GetGuildMember(Snowflake guild_id, Snowflake user_id) const {
Bind(m_get_member_stmt, 1, guild_id);
Bind(m_get_member_stmt, 2, user_id);
if (!FetchOne(m_get_member_stmt)) {
if (m_db_err != SQLITE_DONE)
fprintf(stderr, "error while fetching member: %s\n", sqlite3_errstr(m_db_err));
Reset(m_get_member_stmt);
return std::nullopt;
}
GuildMember ret;
ret.User.emplace().ID = user_id;
Get(m_get_member_stmt, 2, ret.Nickname);
std::string tmp;
Get(m_get_member_stmt, 3, tmp);
ret.Roles = nlohmann::json::parse(tmp).get<std::vector<Snowflake>>();
Get(m_get_member_stmt, 4, ret.JoinedAt);
Get(m_get_member_stmt, 5, ret.PremiumSince);
Get(m_get_member_stmt, 6, ret.IsDeafened);
Get(m_get_member_stmt, 7, ret.IsMuted);
Reset(m_get_member_stmt);
return ret;
}
std::optional<Message> Store::GetMessage(Snowflake id) const {
@ -253,7 +314,7 @@ std::optional<PermissionOverwrite> Store::GetPermissionOverwrite(Snowflake chann
Reset(m_get_perm_stmt);
return std::optional<PermissionOverwrite>(std::move(ret));
return ret;
}
std::optional<Role> Store::GetRole(Snowflake id) const {
@ -279,7 +340,7 @@ std::optional<Role> Store::GetRole(Snowflake id) const {
Reset(m_get_role_stmt);
return std::optional<Role>(std::move(ret));
return ret;
}
std::optional<User> Store::GetUser(Snowflake id) const {
@ -308,7 +369,7 @@ std::optional<User> Store::GetUser(Snowflake id) const {
Reset(m_get_user_stmt);
return std::optional<User>(std::move(ret));
return ret;
}
Channel *Store::GetChannel(Snowflake id) {
@ -339,40 +400,6 @@ const Guild *Store::GetGuild(Snowflake id) const {
return &it->second;
}
GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_id) {
auto git = m_members.find(guild_id);
if (git == m_members.end())
return nullptr;
auto mit = git->second.find(user_id);
if (mit == git->second.end())
return nullptr;
return &mit->second;
}
Emoji *Store::GetEmoji(Snowflake id) {
auto it = m_emojis.find(id);
if (it != m_emojis.end())
return &it->second;
return nullptr;
}
const GuildMember *Store::GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const {
auto git = m_members.find(guild_id);
if (git == m_members.end())
return nullptr;
auto mit = git->second.find(user_id);
if (mit == git->second.end())
return nullptr;
return &mit->second;
}
const Emoji *Store::GetEmoji(Snowflake id) const {
auto it = m_emojis.find(id);
if (it != m_emojis.end())
return &it->second;
return nullptr;
}
void Store::ClearGuild(Snowflake id) {
m_guilds.erase(id);
}
@ -390,7 +417,6 @@ const Store::guilds_type &Store::GetGuilds() const {
}
void Store::ClearAll() {
m_channels.clear();
m_emojis.clear();
m_guilds.clear();
m_members.clear();
}
@ -482,6 +508,19 @@ managed BOOL,
animated BOOL,
available BOOL
)
)";
constexpr const char *create_members = R"(
CREATE TABLE IF NOT EXISTS members (
user_id INTEGER PRIMARY KEY,
guild_id INTEGER NOT NULL,
nickname TEXT,
roles TEXT NOT NULL, /* json */
joined_at TEXT NOT NULL,
premium_since TEXT,
deaf BOOL NOT NULL,
mute BOOL NOT NULL
)
)";
m_db_err = sqlite3_exec(m_db, create_users, nullptr, nullptr, nullptr);
@ -514,6 +553,12 @@ available BOOL
return false;
}
m_db_err = sqlite3_exec(m_db, create_members, nullptr, nullptr, nullptr);
if (m_db_err != SQLITE_OK) {
fprintf(stderr, "failed to create members table: %s\n", sqlite3_errstr(m_db_err));
return false;
}
return true;
}
@ -566,6 +611,16 @@ REPLACE INTO emojis VALUES (
constexpr const char *get_emoji = R"(
SELECT * FROM emojis WHERE id = ?
)";
constexpr const char *set_member = R"(
REPLACE INTO members VALUES (
?, ?, ?, ?, ?, ?, ?, ?
)
)";
constexpr const char *get_member = R"(
SELECT * FROM members WHERE user_id = ? AND guild_id = ?
)";
m_db_err = sqlite3_prepare_v2(m_db, set_user, -1, &m_set_user_stmt, nullptr);
@ -628,6 +683,18 @@ SELECT * FROM emojis WHERE id = ?
return false;
}
m_db_err = sqlite3_prepare_v2(m_db, set_member, -1, &m_set_member_stmt, nullptr);
if (m_db_err != SQLITE_OK) {
fprintf(stderr, "failed to prepare set member statement: %s\n", sqlite3_errstr(m_db_err));
return false;
}
m_db_err = sqlite3_prepare_v2(m_db, get_member, -1, &m_get_member_stmt, nullptr);
if (m_db_err != SQLITE_OK) {
fprintf(stderr, "failed to prepare get member statement: %s\n", sqlite3_errstr(m_db_err));
return false;
}
return true;
}
@ -642,6 +709,8 @@ void Store::Cleanup() {
sqlite3_finalize(m_get_role_stmt);
sqlite3_finalize(m_set_emote_stmt);
sqlite3_finalize(m_get_emote_stmt);
sqlite3_finalize(m_set_member_stmt);
sqlite3_finalize(m_get_member_stmt);
}
void Store::Bind(sqlite3_stmt *stmt, int index, int num) const {

View File

@ -22,7 +22,7 @@ public:
void SetGuild(Snowflake id, const Guild &guild);
void SetRole(Snowflake id, const Role &role);
void SetMessage(Snowflake id, const Message &message);
void SetGuildMemberData(Snowflake guild_id, Snowflake user_id, const GuildMember &data);
void SetGuildMember(Snowflake guild_id, Snowflake user_id, const GuildMember &data);
void SetPermissionOverwrite(Snowflake channel_id, Snowflake id, const PermissionOverwrite &perm);
void SetEmoji(Snowflake id, const Emoji &emoji);
@ -30,16 +30,14 @@ public:
Channel *GetChannel(Snowflake id);
Guild *GetGuild(Snowflake id);
GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id);
Emoji *GetEmoji(Snowflake id);
std::optional<Emoji> GetEmoji(Snowflake id) const;
std::optional<GuildMember> GetGuildMember(Snowflake guild_id, Snowflake user_id) const;
std::optional<Message> GetMessage(Snowflake id) const;
std::optional<PermissionOverwrite> GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const;
std::optional<Role> GetRole(Snowflake id) const;
std::optional<User> GetUser(Snowflake id) const;
const Channel *GetChannel(Snowflake id) const;
const Guild *GetGuild(Snowflake id) const;
const GuildMember *GetGuildMemberData(Snowflake guild_id, Snowflake user_id) const;
const Emoji *GetEmoji(Snowflake id) const;
void ClearGuild(Snowflake id);
void ClearChannel(Snowflake id);
@ -65,7 +63,6 @@ private:
channels_type m_channels;
guilds_type m_guilds;
members_type m_members;
emojis_type m_emojis;
bool CreateTables();
bool CreateStatements();
@ -102,6 +99,8 @@ private:
mutable sqlite3_stmt *m_get_role_stmt;
mutable sqlite3_stmt *m_set_emote_stmt;
mutable sqlite3_stmt *m_get_emote_stmt;
mutable sqlite3_stmt *m_set_member_stmt;
mutable sqlite3_stmt *m_get_member_stmt;
};
template<typename T>