#pragma once #include "../util.hpp" #include "objects.hpp" #include #include #include #include #include #ifdef GetMessage // fuck you windows.h #undef GetMessage #endif class Store { public: Store(bool mem_store = false); ~Store(); bool IsValid() const; void SetUser(Snowflake id, const UserData &user); void SetChannel(Snowflake id, const ChannelData &chan); void SetGuild(Snowflake id, const GuildData &guild); void SetRole(Snowflake id, const RoleData &role); void SetMessage(Snowflake id, const Message &message); 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 EmojiData &emoji); void SetBan(Snowflake guild_id, Snowflake user_id, const BanData &ban); // slap const on everything even tho its not *really* const std::optional GetChannel(Snowflake id) const; std::optional GetEmoji(Snowflake id) const; std::optional GetGuild(Snowflake id) const; std::optional GetGuildMember(Snowflake guild_id, Snowflake user_id) const; std::optional GetMessage(Snowflake id) const; std::optional GetPermissionOverwrite(Snowflake channel_id, Snowflake id) const; std::optional GetRole(Snowflake id) const; std::optional GetUser(Snowflake id) const; std::optional GetBan(Snowflake guild_id, Snowflake user_id) const; std::vector GetBans(Snowflake guild_id) const; std::vector GetLastMessages(Snowflake id, size_t num) const; std::vector GetChannelMessageIDs(Snowflake id) const; std::vector GetPinnedMessages(Snowflake channel_id) const; void ClearGuild(Snowflake id); void ClearChannel(Snowflake id); void ClearBan(Snowflake guild_id, Snowflake user_id); using users_type = std::unordered_map; using channels_type = std::unordered_map; using guilds_type = std::unordered_map; using roles_type = std::unordered_map; using messages_type = std::unordered_map; using members_type = std::unordered_map>; // [guild][user] using permission_overwrites_type = std::unordered_map>; // [channel][user/role] using emojis_type = std::unordered_map; const std::unordered_set &GetChannels() const; const std::unordered_set &GetGuilds() const; void ClearAll(); void BeginTransaction(); void EndTransaction(); private: Message GetMessageBound(sqlite3_stmt *stmt) const; void SetMessageInteractionPair(Snowflake message_id, const MessageInteractionData &interaction); std::unordered_set m_channels; std::unordered_set m_guilds; bool CreateTables(); bool CreateStatements(); void Cleanup(); template void Bind(sqlite3_stmt *stmt, int index, const std::optional &opt) const; template typename std::enable_if::value, void>::type Bind(sqlite3_stmt *stmt, int index, T val) const; void Bind(sqlite3_stmt *stmt, int index, int num) const; void Bind(sqlite3_stmt *stmt, int index, uint64_t num) const; void Bind(sqlite3_stmt *stmt, int index, const std::string &str) const; void Bind(sqlite3_stmt *stmt, int index, bool val) const; void Bind(sqlite3_stmt *stmt, int index, std::nullptr_t) const; bool RunInsert(sqlite3_stmt *stmt); bool FetchOne(sqlite3_stmt *stmt) const; template void Get(sqlite3_stmt *stmt, int index, std::optional &out) const; template typename std::enable_if::value, void>::type Get(sqlite3_stmt *stmt, int index, T &out) const; void Get(sqlite3_stmt *stmt, int index, int &out) const; void Get(sqlite3_stmt *stmt, int index, uint64_t &out) const; void Get(sqlite3_stmt *stmt, int index, std::string &out) const; void Get(sqlite3_stmt *stmt, int index, bool &out) const; void Get(sqlite3_stmt *stmt, int index, Snowflake &out) const; bool IsNull(sqlite3_stmt *stmt, int index) const; void Reset(sqlite3_stmt *stmt) const; std::filesystem::path m_db_path; mutable sqlite3 *m_db; mutable int m_db_err; mutable sqlite3_stmt *m_set_user_stmt; mutable sqlite3_stmt *m_get_user_stmt; mutable sqlite3_stmt *m_set_perm_stmt; mutable sqlite3_stmt *m_get_perm_stmt; mutable sqlite3_stmt *m_set_msg_stmt; mutable sqlite3_stmt *m_get_msg_stmt; mutable sqlite3_stmt *m_set_role_stmt; 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; mutable sqlite3_stmt *m_set_guild_stmt; mutable sqlite3_stmt *m_get_guild_stmt; mutable sqlite3_stmt *m_set_chan_stmt; mutable sqlite3_stmt *m_get_chan_stmt; mutable sqlite3_stmt *m_set_ban_stmt; mutable sqlite3_stmt *m_get_ban_stmt; mutable sqlite3_stmt *m_clear_ban_stmt; mutable sqlite3_stmt *m_get_bans_stmt; mutable sqlite3_stmt *m_set_msg_interaction_stmt; mutable sqlite3_stmt *m_get_last_msgs_stmt; mutable sqlite3_stmt *m_get_msg_ids_stmt; mutable sqlite3_stmt *m_get_pins_stmt; }; template inline void Store::Bind(sqlite3_stmt *stmt, int index, const std::optional &opt) const { if (opt.has_value()) Bind(stmt, index, *opt); else sqlite3_bind_null(stmt, index); } template inline typename std::enable_if::value, void>::type Store::Bind(sqlite3_stmt *stmt, int index, T val) const { Bind(stmt, index, static_cast::type>(val)); } template inline void Store::Get(sqlite3_stmt *stmt, int index, std::optional &out) const { if (sqlite3_column_type(stmt, index) == SQLITE_NULL) out = std::nullopt; else { T v; Get(stmt, index, v); out = std::optional(v); } } template inline typename std::enable_if::value, void>::type Store::Get(sqlite3_stmt *stmt, int index, T &out) const { out = static_cast(sqlite3_column_int(stmt, index)); }