#pragma once #include #ifdef USE_DATABASE #include #include #include #include #include #include #include #include class Database { public: using time_point = std::chrono::system_clock::time_point; struct Uuid: Column { static constexpr auto name = "uuid_"; }; struct Owner: Column { static constexpr auto name = "owner_"; }; struct IrcChanName: Column { static constexpr auto name = "ircChanName_"; }; struct Channel: Column { static constexpr auto name = "channel_"; }; struct IrcServerName: Column { static constexpr auto name = "ircServerName_"; }; struct Server: Column { static constexpr auto name = "server_"; }; struct Date: Column { static constexpr auto name = "date_"; }; struct Body: Column { static constexpr auto name = "body_"; }; struct Nick: Column { static constexpr auto name = "nick_"; }; struct Pass: Column { static constexpr auto name = "pass_"; }; struct Ports: Column { static constexpr auto name = "ports_"; Ports(): Column("6667") {} }; struct TlsPorts: Column { static constexpr auto name = "tlsPorts_"; TlsPorts(): Column("6697;6670") {} }; struct Username: Column { static constexpr auto name = "username_"; }; struct Realname: Column { static constexpr auto name = "realname_"; }; struct AfterConnectionCommand: Column { static constexpr auto name = "afterConnectionCommand_"; }; struct TrustedFingerprint: Column { static constexpr auto name = "trustedFingerprint_"; }; struct EncodingOut: Column { static constexpr auto name = "encodingOut_"; }; struct EncodingIn: Column { static constexpr auto name = "encodingIn_"; }; struct MaxHistoryLength: Column { static constexpr auto name = "maxHistoryLength_"; MaxHistoryLength(): Column(20) {} }; struct RecordHistory: Column { static constexpr auto name = "recordHistory_"; RecordHistory(): Column(true) {}}; struct RecordHistoryOptional: Column { static constexpr auto name = "recordHistory_"; }; struct VerifyCert: Column { static constexpr auto name = "verifyCert_"; VerifyCert(): Column(true) {} }; struct Persistent: Column { static constexpr auto name = "persistent_"; Persistent(): Column(false) {} }; struct LocalJid: Column { static constexpr auto name = "local"; }; struct RemoteJid: Column { static constexpr auto name = "remote"; }; using MucLogLineTable = Table; using MucLogLine = MucLogLineTable::RowType; using GlobalOptionsTable = Table; using GlobalOptions = GlobalOptionsTable::RowType; using IrcServerOptionsTable = Table; using IrcServerOptions = IrcServerOptionsTable::RowType; using IrcChannelOptionsTable = Table; using IrcChannelOptions = IrcChannelOptionsTable::RowType; using RosterTable = Table; using RosterItem = RosterTable::RowType; Database() = default; ~Database() = default; Database(const Database&) = delete; Database(Database&&) = delete; Database& operator=(const Database&) = delete; Database& operator=(Database&&) = delete; static GlobalOptions get_global_options(const std::string& owner); static IrcServerOptions get_irc_server_options(const std::string& owner, const std::string& server); static IrcChannelOptions get_irc_channel_options(const std::string& owner, const std::string& server, const std::string& channel); static IrcChannelOptions get_irc_channel_options_with_server_default(const std::string& owner, const std::string& server, const std::string& channel); static IrcChannelOptions get_irc_channel_options_with_server_and_global_default(const std::string& owner, const std::string& server, const std::string& channel); static std::vector get_muc_logs(const std::string& owner, const std::string& chan_name, const std::string& server, int limit=-1, const std::string& start="", const std::string& end=""); static std::string store_muc_message(const std::string& owner, const std::string& chan_name, const std::string& server_name, time_point date, const std::string& body, const std::string& nick); static void add_roster_item(const std::string& local, const std::string& remote); static bool has_roster_item(const std::string& local, const std::string& remote); static void delete_roster_item(const std::string& local, const std::string& remote); static std::vector get_contact_list(const std::string& local); static std::vector get_full_roster(); static void close(); static void open(const std::string& filename); template static int64_t count(const TableType& table) { CountQuery query{table.get_name()}; return query.execute(Database::db); } static MucLogLineTable muc_log_lines; static GlobalOptionsTable global_options; static IrcServerOptionsTable irc_server_options; static IrcChannelOptionsTable irc_channel_options; static RosterTable roster; static sqlite3* db; /** * Some caches, to avoid doing very frequent query requests for a few options. */ using CacheKey = std::tuple; static EncodingIn::real_type get_encoding_in(const std::string& owner, const std::string& server, const std::string& channel) { CacheKey channel_key{owner, server, channel}; auto it = Database::encoding_in_cache.find(channel_key); if (it == Database::encoding_in_cache.end()) { auto options = Database::get_irc_channel_options_with_server_default(owner, server, channel); EncodingIn::real_type result = options.col(); if (result.empty()) result = "ISO-8859-1"; it = Database::encoding_in_cache.insert(std::make_pair(channel_key, result)).first; } return it->second; } static void invalidate_encoding_in_cache(const std::string& owner, const std::string& server, const std::string& channel) { CacheKey channel_key{owner, server, channel}; Database::encoding_in_cache.erase(channel_key); } static void invalidate_encoding_in_cache() { Database::encoding_in_cache.clear(); } private: static std::string gen_uuid(); static std::map encoding_in_cache; }; #endif /* USE_DATABASE */