summaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2024-05-18 14:48:12 +0500
committerilotterytea <iltsu@alright.party>2024-05-18 14:48:12 +0500
commitd1793df1eda463b10107d41785ad1d7f055ed476 (patch)
treefd3e41c3b4a05924748ae4b762e1ae55a0bc815c /src/commands
parentd7a2de17e9b7931f68b5b4079b1c36866a19d343 (diff)
upd: moved the bot part to a relative subfolder
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/command.cpp104
-rw-r--r--src/commands/command.hpp55
-rw-r--r--src/commands/request.hpp25
-rw-r--r--src/commands/request_util.cpp205
-rw-r--r--src/commands/request_util.hpp13
-rw-r--r--src/commands/response_error.hpp222
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;
- };
-
-}