diff options
| author | ilotterytea <iltsu@alright.party> | 2024-05-18 14:48:12 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2024-05-18 14:48:12 +0500 |
| commit | d1793df1eda463b10107d41785ad1d7f055ed476 (patch) | |
| tree | fd3e41c3b4a05924748ae4b762e1ae55a0bc815c /src/commands | |
| parent | d7a2de17e9b7931f68b5b4079b1c36866a19d343 (diff) | |
upd: moved the bot part to a relative subfolder
Diffstat (limited to 'src/commands')
| -rw-r--r-- | src/commands/command.cpp | 104 | ||||
| -rw-r--r-- | src/commands/command.hpp | 55 | ||||
| -rw-r--r-- | src/commands/request.hpp | 25 | ||||
| -rw-r--r-- | src/commands/request_util.cpp | 205 | ||||
| -rw-r--r-- | src/commands/request_util.hpp | 13 | ||||
| -rw-r--r-- | src/commands/response_error.hpp | 222 |
6 files changed, 0 insertions, 624 deletions
diff --git a/src/commands/command.cpp b/src/commands/command.cpp deleted file mode 100644 index e3b45b1..0000000 --- a/src/commands/command.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "command.hpp" - -#include <algorithm> -#include <chrono> -#include <ctime> -#include <memory> -#include <optional> -#include <pqxx/pqxx> -#include <string> - -#include "../bundle.hpp" -#include "../modules/custom_command.hpp" -#include "../modules/event.hpp" -#include "../modules/help.hpp" -#include "../modules/join.hpp" -#include "../modules/massping.hpp" -#include "../modules/notify.hpp" -#include "../modules/ping.hpp" -#include "../modules/timer.hpp" -#include "../utils/chrono.hpp" -#include "request.hpp" - -namespace bot { - namespace command { - CommandLoader::CommandLoader() { - this->add_command(std::make_unique<mod::Ping>()); - this->add_command(std::make_unique<mod::Massping>()); - this->add_command(std::make_unique<mod::Event>()); - this->add_command(std::make_unique<mod::Notify>()); - this->add_command(std::make_unique<mod::Join>()); - this->add_command(std::make_unique<mod::CustomCommand>()); - this->add_command(std::make_unique<mod::Timer>()); - this->add_command(std::make_unique<mod::Help>()); - } - - void CommandLoader::add_command(std::unique_ptr<Command> command) { - this->commands.push_back(std::move(command)); - } - - std::optional<std::variant<std::vector<std::string>, std::string>> - CommandLoader::run(const InstanceBundle &bundle, - const Request &request) const { - auto command = std::find_if( - this->commands.begin(), this->commands.end(), - [&](const auto &x) { return x->get_name() == request.command_id; }); - - if (command == this->commands.end()) { - return std::nullopt; - } - - if ((*command)->get_permission_level() > - request.user_rights.get_level()) { - return std::nullopt; - } - - pqxx::work work(request.conn); - - pqxx::result action_query = work.exec( - "SELECT sent_at FROM actions WHERE user_id = " + - std::to_string(request.user.get_id()) + - " AND channel_id = " + std::to_string(request.channel.get_id()) + - " AND command = '" + request.command_id + "' ORDER BY sent_at DESC"); - - if (!action_query.empty()) { - auto last_sent_at = utils::chrono::string_to_time_point( - action_query[0][0].as<std::string>()); - - auto now = std::chrono::system_clock::now(); - auto now_time_it = std::chrono::system_clock::to_time_t(now); - auto now_tm = std::gmtime(&now_time_it); - now = std::chrono::system_clock::from_time_t(std::mktime(now_tm)); - - auto difference = std::chrono::duration_cast<std::chrono::seconds>( - now - last_sent_at); - - if (difference.count() < command->get()->get_delay_seconds()) { - return std::nullopt; - } - } - - std::string arguments; - - if (request.subcommand_id.has_value()) { - arguments += request.subcommand_id.value() + " "; - } - - if (request.message.has_value()) { - arguments += request.message.value(); - } - - work.exec( - "INSERT INTO actions(user_id, channel_id, command, arguments, " - "full_message) VALUES (" + - std::to_string(request.user.get_id()) + ", " + - std::to_string(request.channel.get_id()) + ", '" + - request.command_id + "', '" + arguments + "', '" + - request.irc_message.message + "')"); - - work.commit(); - - return (*command)->run(bundle, request); - } - } -} diff --git a/src/commands/command.hpp b/src/commands/command.hpp deleted file mode 100644 index 40ec114..0000000 --- a/src/commands/command.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include <memory> -#include <optional> -#include <string> -#include <variant> -#include <vector> - -#include "../bundle.hpp" -#include "request.hpp" - -namespace bot { - namespace command { - enum CommandArgument { - SUBCOMMAND, - MESSAGE, - INTERVAL, - NAME, - TARGET, - VALUE, - AMOUNT, - }; - - class Command { - public: - virtual std::string get_name() const = 0; - virtual std::variant<std::vector<std::string>, std::string> run( - const InstanceBundle &bundle, const Request &request) const = 0; - virtual schemas::PermissionLevel get_permission_level() const { - return schemas::PermissionLevel::USER; - } - virtual int get_delay_seconds() const { return 5; } - virtual std::vector<std::string> get_subcommand_ids() const { - return {}; - } - }; - - class CommandLoader { - public: - CommandLoader(); - ~CommandLoader() = default; - - void add_command(std::unique_ptr<Command> cmd); - std::optional<std::variant<std::vector<std::string>, std::string>> run( - const InstanceBundle &bundle, const Request &msg) const; - - const std::vector<std::unique_ptr<Command>> &get_commands() const { - return this->commands; - }; - - private: - std::vector<std::unique_ptr<Command>> commands; - }; - } -} diff --git a/src/commands/request.hpp b/src/commands/request.hpp deleted file mode 100644 index e2685f1..0000000 --- a/src/commands/request.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include <optional> -#include <pqxx/pqxx> -#include <string> - -#include "../irc/message.hpp" -#include "../schemas/channel.hpp" -#include "../schemas/user.hpp" - -namespace bot::command { - struct Request { - std::string command_id; - std::optional<std::string> subcommand_id; - std::optional<std::string> message; - const irc::Message<irc::MessageType::Privmsg> &irc_message; - - schemas::Channel channel; - schemas::ChannelPreferences channel_preferences; - schemas::User user; - schemas::UserRights user_rights; - - pqxx::connection &conn; - }; -} diff --git a/src/commands/request_util.cpp b/src/commands/request_util.cpp deleted file mode 100644 index 90750e5..0000000 --- a/src/commands/request_util.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "request_util.hpp" - -#include <algorithm> -#include <optional> -#include <pqxx/pqxx> -#include <string> - -#include "../constants.hpp" -#include "../irc/message.hpp" -#include "../schemas/channel.hpp" -#include "command.hpp" -#include "request.hpp" - -namespace bot::command { - std::optional<Request> generate_request( - const command::CommandLoader &command_loader, - const irc::Message<irc::MessageType::Privmsg> &irc_message, - pqxx::connection &conn) { - pqxx::work *work; - - work = new pqxx::work(conn); - - std::vector<std::string> parts = - utils::string::split_text(irc_message.message, ' '); - - std::string command_id = parts[0]; - - if (command_id.substr(0, DEFAULT_PREFIX.length()) != DEFAULT_PREFIX) { - delete work; - return std::nullopt; - } - - command_id = - command_id.substr(DEFAULT_PREFIX.length(), command_id.length()); - - auto cmd = std::find_if( - command_loader.get_commands().begin(), - command_loader.get_commands().end(), - [&](const auto &command) { return command->get_name() == command_id; }); - - if (cmd == command_loader.get_commands().end()) { - delete work; - return std::nullopt; - } - - parts.erase(parts.begin()); - - pqxx::result query = work->exec("SELECT * FROM channels WHERE alias_id = " + - std::to_string(irc_message.source.id)); - - // Create new channel data in the database if it didn't exist b4 - if (query.empty()) { - work->exec("INSERT INTO channels (alias_id, alias_name) VALUES (" + - std::to_string(irc_message.source.id) + ", '" + - irc_message.source.login + "')"); - - work->commit(); - - delete work; - work = new pqxx::work(conn); - - query = work->exec("SELECT * FROM channels WHERE alias_id = " + - std::to_string(irc_message.source.id)); - } - - schemas::Channel channel(query[0]); - - if (channel.get_opted_out_at().has_value()) { - delete work; - return std::nullopt; - } - - query = work->exec("SELECT * FROM channel_preferences WHERE channel_id = " + - std::to_string(channel.get_id())); - - // Create new channel preference data in the database if it didn't exist b4 - if (query.empty()) { - work->exec( - "INSERT INTO channel_preferences (channel_id, prefix, locale) VALUES " - "(" + - std::to_string(channel.get_id()) + ", '" + DEFAULT_PREFIX + "', '" + - DEFAULT_LOCALE_ID + "')"); - - work->commit(); - - delete work; - work = new pqxx::work(conn); - - query = - work->exec("SELECT * FROM channel_preferences WHERE channel_id = " + - std::to_string(channel.get_id())); - } - - schemas::ChannelPreferences channel_preferences(query[0]); - - query = work->exec("SELECT * FROM users WHERE alias_id = " + - std::to_string(irc_message.sender.id)); - - // Create new user data in the database if it didn't exist before - if (query.empty()) { - work->exec("INSERT INTO users (alias_id, alias_name) VALUES (" + - std::to_string(irc_message.sender.id) + ", '" + - irc_message.sender.login + "')"); - - work->commit(); - - delete work; - work = new pqxx::work(conn); - - query = work->exec("SELECT * FROM users WHERE alias_id = " + - std::to_string(irc_message.sender.id)); - } - - schemas::User user(query[0]); - - if (user.get_alias_name() != irc_message.sender.login) { - work->exec("UPDATE users SET alias_name = '" + irc_message.sender.login + - "' WHERE id = " + std::to_string(user.get_id())); - work->commit(); - - delete work; - work = new pqxx::work(conn); - - user.set_alias_name(irc_message.sender.login); - } - - schemas::PermissionLevel level = schemas::PermissionLevel::USER; - const auto &badges = irc_message.sender.badges; - - if (user.get_alias_id() == channel.get_alias_id()) { - level = schemas::PermissionLevel::BROADCASTER; - } else if (std::any_of(badges.begin(), badges.end(), [&](const auto &x) { - return x.first == "moderator"; - })) { - level = schemas::PermissionLevel::MODERATOR; - } else if (std::any_of(badges.begin(), badges.end(), - [&](const auto &x) { return x.first == "vip"; })) { - level = schemas::PermissionLevel::VIP; - } - - query = work->exec("SELECT * FROM user_rights WHERE user_id = " + - std::to_string(user.get_id()) + - " AND channel_id = " + std::to_string(channel.get_id())); - - if (query.empty()) { - work->exec( - "INSERT INTO user_rights (user_id, channel_id, level) VALUES (" + - std::to_string(user.get_id()) + ", " + - std::to_string(channel.get_id()) + ", " + std::to_string(level) + - ")"); - - work->commit(); - - delete work; - work = new pqxx::work(conn); - - query = work->exec("SELECT * FROM user_rights WHERE user_id = " + - std::to_string(user.get_id()) + " AND channel_id = " + - std::to_string(channel.get_id())); - } - - schemas::UserRights user_rights(query[0]); - - if (user_rights.get_level() != level) { - work->exec("UPDATE user_rights SET level = " + std::to_string(level) + - " WHERE id = " + std::to_string(query[0][0].as<int>())); - - work->commit(); - - user_rights.set_level(level); - } - - delete work; - - if (parts.empty()) { - Request req{command_id, std::nullopt, std::nullopt, - irc_message, channel, channel_preferences, - user, user_rights, conn}; - - return req; - } - - std::optional<std::string> subcommand_id = parts[0]; - auto subcommand_ids = (*cmd)->get_subcommand_ids(); - - if (std::any_of( - subcommand_ids.begin(), subcommand_ids.end(), - [&](const auto &x) { return x == subcommand_id.value(); })) { - parts.erase(parts.begin()); - } else { - subcommand_id = std::nullopt; - } - - std::optional<std::string> message = utils::string::join_vector(parts, ' '); - - if (message->empty()) { - message = std::nullopt; - } - - Request req{command_id, subcommand_id, message, - irc_message, channel, channel_preferences, - user, user_rights, conn}; - return req; - } -} diff --git a/src/commands/request_util.hpp b/src/commands/request_util.hpp deleted file mode 100644 index dea6e12..0000000 --- a/src/commands/request_util.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <optional> -#include <pqxx/pqxx> - -#include "../irc/message.hpp" -#include "command.hpp" -#include "request.hpp" - -namespace bot::command { - std::optional<Request> generate_request( - const command::CommandLoader &command_loader, - const irc::Message<irc::MessageType::Privmsg> &irc_message, - pqxx::connection &conn); -} diff --git a/src/commands/response_error.hpp b/src/commands/response_error.hpp deleted file mode 100644 index ae2c3ee..0000000 --- a/src/commands/response_error.hpp +++ /dev/null @@ -1,222 +0,0 @@ -#pragma once - -#include <exception> -#include <optional> -#include <string> -#include <type_traits> -#include <vector> - -#include "command.hpp" -#include "request.hpp" - -namespace bot { - enum ResponseError { - NOT_ENOUGH_ARGUMENTS, - INCORRECT_ARGUMENT, - - INCOMPATIBLE_NAME, - NAMESAKE_CREATION, - NOT_FOUND, - - SOMETHING_WENT_WRONG, - - EXTERNAL_API_ERROR, - INSUFFICIENT_RIGHTS, - - ILLEGAL_COMMAND - }; - - template <ResponseError T, class Enable = void> - class ResponseException; - - template <ResponseError T> - class ResponseException< - T, typename std::enable_if< - T == INCORRECT_ARGUMENT || T == INCOMPATIBLE_NAME || - T == NAMESAKE_CREATION || T == NOT_FOUND>::type> - : public std::exception { - public: - ResponseException(const command::Request &request, - const loc::Localization &localizator, - const std::string &message) - : request(request), - localizator(localizator), - message(message), - error(T) { - loc::LineId line_id; - - switch (this->error) { - case INCORRECT_ARGUMENT: - line_id = loc::LineId::ErrorIncorrectArgument; - break; - case INCOMPATIBLE_NAME: - line_id = loc::LineId::ErrorIncompatibleName; - break; - case NAMESAKE_CREATION: - line_id = loc::LineId::ErrorNamesakeCreation; - break; - case NOT_FOUND: - line_id = loc::LineId::ErrorNotFound; - break; - default: - line_id = loc::LineId::ErrorSomethingWentWrong; - break; - }; - - this->line = - this->localizator - .get_formatted_line(this->request, line_id, {this->message}) - .value(); - } - ~ResponseException() = default; - - const char *what() const noexcept override { return this->line.c_str(); } - - private: - const command::Request &request; - const loc::Localization &localizator; - std::string message, line; - ResponseError error; - }; - - template <ResponseError T> - class ResponseException<T, - typename std::enable_if<T == SOMETHING_WENT_WRONG || - T == INSUFFICIENT_RIGHTS || - T == ILLEGAL_COMMAND>::type> - : public std::exception { - public: - ResponseException(const command::Request &request, - const loc::Localization &localizator) - : request(request), localizator(localizator), error(T) { - loc::LineId line_id; - - switch (this->error) { - case INSUFFICIENT_RIGHTS: - line_id = loc::LineId::ErrorInsufficientRights; - break; - case ILLEGAL_COMMAND: - line_id = loc::LineId::ErrorIllegalCommand; - break; - default: - line_id = loc::LineId::ErrorSomethingWentWrong; - break; - } - - this->line = - this->localizator.get_formatted_line(this->request, line_id, {}) - .value(); - } - ~ResponseException() = default; - - const char *what() const noexcept override { return this->line.c_str(); } - - private: - const command::Request &request; - const loc::Localization &localizator; - std::string line; - ResponseError error; - }; - - template <ResponseError T> - class ResponseException< - T, typename std::enable_if<T == EXTERNAL_API_ERROR>::type> - : public std::exception { - public: - ResponseException( - const command::Request &request, const loc::Localization &localizator, - const int &code, - const std::optional<std::string> &message = std::nullopt) - : request(request), - localizator(localizator), - code(code), - message(message), - error(T) { - loc::LineId line_id = loc::LineId::ErrorExternalAPIError; - std::vector<std::string> args = {std::to_string(this->code)}; - - if (this->message.has_value()) { - args.push_back(" " + this->message.value()); - } - - this->line = - this->localizator.get_formatted_line(this->request, line_id, args) - .value(); - } - ~ResponseException() = default; - - const char *what() const noexcept override { return this->line.c_str(); } - - private: - const command::Request &request; - const loc::Localization &localizator; - int code; - std::optional<std::string> message; - std::string line; - ResponseError error; - }; - - template <ResponseError T> - class ResponseException< - T, typename std::enable_if<T == NOT_ENOUGH_ARGUMENTS>::type> - : public std::exception { - public: - ResponseException(const command::Request &request, - const loc::Localization &localizator, - command::CommandArgument argument) - : request(request), - localizator(localizator), - argument(argument), - error(T) { - loc::LineId line_id = loc::LineId::ErrorNotEnoughArguments; - loc::LineId arg_id; - - switch (this->argument) { - case command::SUBCOMMAND: - arg_id = loc::LineId::ArgumentSubcommand; - break; - case command::MESSAGE: - arg_id = loc::LineId::ArgumentMessage; - break; - case command::INTERVAL: - arg_id = loc::LineId::ArgumentInterval; - break; - case command::NAME: - arg_id = loc::LineId::ArgumentName; - break; - case command::TARGET: - arg_id = loc::LineId::ArgumentTarget; - break; - case command::VALUE: - arg_id = loc::LineId::ArgumentValue; - break; - case command::AMOUNT: - arg_id = loc::LineId::ArgumentAmount; - break; - default: - break; - } - - auto arg = - this->localizator - .get_localized_line( - this->request.channel_preferences.get_locale(), arg_id) - .value(); - - this->line = - this->localizator.get_formatted_line(this->request, line_id, {arg}) - .value(); - } - ~ResponseException() = default; - - const char *what() const noexcept override { return this->line.c_str(); } - - private: - const command::Request &request; - const loc::Localization &localizator; - command::CommandArgument argument; - ResponseError error; - std::string line; - }; - -} |
