From ea2c6c460f15a6460625d4e1fdf7b6aba29460b3 Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 23 Feb 2024 07:14:08 +0100 Subject: [PATCH 01/53] add /list languages command, minor fixes --- CMakeLists.txt | 2 +- src/message_queue.cpp | 4 ++++ src/settings.cpp | 3 ++- src/slashcommands.cpp | 35 ++++++++++++++++++++++++++++++++--- src/webhook_push.cpp | 26 ++++++++++++++++---------- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59e34f7..b26ac46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ ****************************************************************************]] cmake_minimum_required(VERSION 3.16) -project(dtranslatebot VERSION 0.1 LANGUAGES CXX) +project(dtranslatebot VERSION 0.2 LANGUAGES CXX) include(GNUInstallDirs) # dtranslatebot Source files diff --git a/src/message_queue.cpp b/src/message_queue.cpp index 7276de3..007f207 100644 --- a/src/message_queue.cpp +++ b/src/message_queue.cpp @@ -36,6 +36,10 @@ void message_queue::add(message &&message) void message_queue::process_message_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::message_create_t &event) { + // We check for conditions we want to skip translation for + if (event.msg.content.empty() || event.msg.has_thread()) + return; + if (event.msg.webhook_id) { const std::lock_guard guard(*settings); diff --git a/src/settings.cpp b/src/settings.cpp index cbce34a..a110e95 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -203,7 +203,8 @@ void process_url(const std::string &url, translator *translator) translator->url = "/"; url_v = url_v.substr(0, slash_pos); } - auto colon_pos = url_v.find_first_of(':'); + // We don't have IPv6 support here yet + auto colon_pos = url_v.find_last_of(':'); if (colon_pos != std::string_view::npos) { translator->hostname = url_v.substr(0, colon_pos); const int port = std::stoi(std::string(url_v.substr(colon_pos + 1))); diff --git a/src/slashcommands.cpp b/src/slashcommands.cpp index 2dede96..8ad0dd9 100644 --- a/src/slashcommands.cpp +++ b/src/slashcommands.cpp @@ -117,7 +117,7 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: source_valid = true; break; } - language_codes << " " << language.code; + language_codes << ' ' << language.code; } if (source_valid) { @@ -217,11 +217,38 @@ void bot::slashcommands::process_list_command(dpp::cluster *bot, bot::settings:: event.reply(dpp::message("The current guild have no translated channel!").set_flags(dpp::m_ephemeral)); } } + else if (interaction.options[0].name == "languages") { + dpp::permission user_permissions = event.command.get_resolved_permission(event.command.usr.id); + if (user_permissions.has(dpp::p_manage_webhooks)) { + const std::vector languages = settings->get_translator()->get_languages(); + std::ostringstream reply_languages; + reply_languages << "**Available Languages**\n"; + for (auto language = languages.begin(); language != languages.end();) { + reply_languages << language->name << ": " << language->code; + if (++language != languages.end()) + reply_languages << '\n'; + } + if (reply_languages.str().length() <= 2000) { + event.reply(dpp::message(reply_languages.str()).set_flags(dpp::m_ephemeral)); + } + else { + reply_languages.str({}); + reply_languages << "Available Languages:"; + for (auto language = languages.begin(); language != languages.end(); language++) { + reply_languages << ' ' << language->code; + } + event.reply(dpp::message(reply_languages.str()).set_flags(dpp::m_ephemeral)); + } + } + else { + event.reply(dpp::message("Unauthorized to list available languages!")); + } + } else { throw std::invalid_argument("Option " + interaction.options[0].name + " is not known"); } } - catch (const std::exception& exception) { + catch (const std::exception &exception) { std::cerr << "[Exception] " << exception.what() << std::endl; event.reply(dpp::message("Exception while processing command:\n"s + exception.what()).set_flags(dpp::m_ephemeral)); } @@ -258,7 +285,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti target_valid = true; if (source_valid && target_valid) break; - language_codes << " " << language.code; + language_codes << ' ' << language.code; } if (source_valid && target_valid) { @@ -404,8 +431,10 @@ void bot::slashcommands::register_commands(dpp::cluster *bot, bot::settings::set dpp::slashcommand command_list("list", "List translation settings", bot->me.id); dpp::command_option channel_list_subcommand(dpp::co_sub_command, "channel", "List current channel translation settings"); dpp::command_option guild_list_subcommand(dpp::co_sub_command, "guild", "List current guild translation settings"); + dpp::command_option languages_list_subcommand(dpp::co_sub_command, "languages", "List available languages to translate"); command_list.add_option(channel_list_subcommand); command_list.add_option(guild_list_subcommand); + command_list.add_option(languages_list_subcommand); commands.push_back(command_list); dpp::slashcommand command_translate("translate", "Translate current channel", bot->me.id); diff --git a/src/webhook_push.cpp b/src/webhook_push.cpp index 1e4a0f7..457ec3e 100644 --- a/src/webhook_push.cpp +++ b/src/webhook_push.cpp @@ -25,10 +25,12 @@ using namespace std::string_view_literals; void bot::webhook_push::run(const bot::translated_message &message, dpp::cluster *bot) { dpp::json json_body = { - {"username"s, message.author}, - {"avatar_url"s, message.avatar} + {"username"s, message.author} }; + if (!message.avatar.empty()) + json_body["avatar_url"] = message.avatar; + // We will split too long messages into multiple messages if (message.message.length() > 2000) { std::string_view message_v = message.message; @@ -73,14 +75,18 @@ void bot::webhook_push::run(const bot::translated_message &message, dpp::cluster } } +void webhook_request_completed(std::promise &promise, dpp::json &json, const dpp::http_request_completion_t &event) +{ + if (event.status != 204) + std::cerr << "[Warning] Webhook push returned unexpected code " << event.status << std::endl; + promise.set_value(event); +} + void bot::webhook_push::push_request(dpp::snowflake webhook_id, const std::string &webhook_token, const std::string &json, dpp::cluster *bot) { - std::promise _p; - std::future _f = _p.get_future(); - bot->post_rest(API_PATH "/webhooks", std::to_string(webhook_id), dpp::utility::url_encode(webhook_token), dpp::m_post, json, [&bot, &_p](dpp::json &json, const dpp::http_request_completion_t &event) { - if (event.status != 204) - std::cerr << "[Warning] Webhook push returned unexpected code " << event.status << std::endl; - _p.set_value(event); - }); - _f.wait(); + std::promise promise; + std::future future = promise.get_future(); + bot->post_rest(API_PATH "/webhooks", std::to_string(webhook_id), dpp::utility::url_encode(webhook_token), dpp::m_post, json, + std::bind(&webhook_request_completed, std::ref(promise), std::placeholders::_1, std::placeholders::_2)); + future.wait(); } From 46b80f3bdf1197e5910a843b1c71c848f93de380 Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 23 Feb 2024 11:27:17 +0100 Subject: [PATCH 02/53] message_queue: combine if condition --- src/message_queue.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/message_queue.cpp b/src/message_queue.cpp index 007f207..fffb71a 100644 --- a/src/message_queue.cpp +++ b/src/message_queue.cpp @@ -37,7 +37,7 @@ void message_queue::add(message &&message) void message_queue::process_message_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::message_create_t &event) { // We check for conditions we want to skip translation for - if (event.msg.content.empty() || event.msg.has_thread()) + if (event.msg.author.id == bot->me.id || event.msg.content.empty() || event.msg.has_thread()) return; if (event.msg.webhook_id) { @@ -48,10 +48,6 @@ void message_queue::process_message_event(dpp::cluster *bot, bot::settings::sett return; } - // Same as before, just without the involvement of webhooks - if (event.msg.author.id == bot->me.id) - return; - const std::lock_guard guard(*settings); if (const bot::settings::channel *channel = settings->get_channel(event.msg.guild_id, event.msg.channel_id)) { bot::message message; From 531c24b05017b74b17863683528bd9b9b54cac6b Mon Sep 17 00:00:00 2001 From: Syping Date: Sat, 24 Feb 2024 09:15:32 +0100 Subject: [PATCH 03/53] slashcommands: add missing ephemeral flag --- src/slashcommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slashcommands.cpp b/src/slashcommands.cpp index 8ad0dd9..49c55c2 100644 --- a/src/slashcommands.cpp +++ b/src/slashcommands.cpp @@ -241,7 +241,7 @@ void bot::slashcommands::process_list_command(dpp::cluster *bot, bot::settings:: } } else { - event.reply(dpp::message("Unauthorized to list available languages!")); + event.reply(dpp::message("Unauthorized to list available languages!").set_flags(dpp::m_ephemeral)); } } else { From 5191dcbefcbea853d6c3b13800c841e127e04990 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 26 Feb 2024 09:41:55 +0100 Subject: [PATCH 04/53] add DTRANSLATEBOT_TOKEN env value, small fixes --- cmake/FindDPP.cmake | 4 ++-- src/main.cpp | 2 +- src/settings.cpp | 17 +++++++++-------- src/settings.h | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmake/FindDPP.cmake b/cmake/FindDPP.cmake index a555a7f..55c928e 100644 --- a/cmake/FindDPP.cmake +++ b/cmake/FindDPP.cmake @@ -1,4 +1,4 @@ -find_path(DPP_INCLUDE_DIR NAMES dpp/dpp.h HINTS ${DPP_ROOT_DIR}) -find_library(DPP_LIBRARIES NAMES dpp "libdpp.a" HINTS ${DPP_ROOT_DIR}) +find_path(DPP_INCLUDE_DIR NAMES "dpp/dpp.h" HINTS "${DPP_ROOT_DIR}") +find_library(DPP_LIBRARIES NAMES "dpp" "libdpp.a" HINTS "${DPP_ROOT_DIR}") include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DPP DEFAULT_MSG DPP_LIBRARIES DPP_INCLUDE_DIR) diff --git a/src/main.cpp b/src/main.cpp index 87bd82e..d86e55d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) { std::cout << "[Launch] Requesting supported languages..." << std::endl; if (settings.get_translator()->get_languages().empty()) { std::cerr << "[Error] Failed to initialise translateable languages" << std::endl; - return 2; + return 1; } dpp::cluster bot(settings.token(), dpp::i_default_intents | dpp::i_message_content); diff --git a/src/settings.cpp b/src/settings.cpp index a110e95..d8fb47d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -455,21 +455,24 @@ bool settings::parse(const std::string &data, bool initialize) return false; } + const std::lock_guard guard(m_mutex); auto json_token = json.find("token"); - if (json_token == json.end()) { - std::cerr << "[Error] Value token not found" << std::endl; + if (json_token != json.end()) + m_token = *json_token; + else if (char *token = getenv("DTRANSLATEBOT_TOKEN")) + m_token = token; + + if (m_token.empty()) { + std::cerr << "[Error] Discord Bot Token is not configured" << std::endl; return false; } - const std::lock_guard guard(m_mutex); - m_token = *json_token; - std::filesystem::path storage_path; auto json_storage = json.find("storage"); if (json_storage != json.end()) storage_path = std::string(*json_storage); else if (char *storagepath = getenv("DTRANSLATEBOT_STORAGE")) - storage_path = storagepath; + storage_path = storagepath; if (storage_path.empty()) storage_path = std::filesystem::current_path(); @@ -484,8 +487,6 @@ bool settings::parse(const std::string &data, bool initialize) if (!process_translator_settings(*json_translator, &m_translator)) return false; - m_avatarSize = 256; - auto json_guilds = json.find("guilds"); if (json_guilds != json.end() && json_guilds->is_object()) process_guild_settings(*json_guilds, &m_guilds, &m_webhookIds); diff --git a/src/settings.h b/src/settings.h index 7f51f16..31b71c3 100644 --- a/src/settings.h +++ b/src/settings.h @@ -61,8 +61,8 @@ namespace bot { private: mutable std::recursive_mutex m_mutex; - size_t m_externallyLockedCount; - uint16_t m_avatarSize; + size_t m_externallyLockedCount = 0; + uint16_t m_avatarSize = 256; std::shared_ptr m_database; std::vector m_guilds; std::vector m_prefLangs; From 87961fe611847a6b956a51095d6594d3db7b9ca2 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 26 Feb 2024 11:33:39 +0100 Subject: [PATCH 05/53] improve code organisation, add .rc file --- .gitattributes | 16 ++++++ CMakeLists.txt | 54 +++++++++++-------- etc/dtranslatebot.example.json | 37 ------------- etc/dtranslatebot.json | 7 --- src/{database_core.cpp => core/database.cpp} | 2 +- src/{database_core.h => core/database.h} | 6 +-- src/{ => core}/main.cpp | 0 src/{ => core}/message_queue.cpp | 0 src/{ => core}/message_queue.h | 0 src/{ => core}/regex.h | 0 src/{ => core}/settings.cpp | 4 +- src/{ => core}/settings.h | 4 +- src/{ => core}/settings_types.h | 0 src/{ => core}/slashcommands.cpp | 0 src/{ => core}/slashcommands.h | 0 src/{ => core}/submit_queue.cpp | 0 src/{ => core}/submit_queue.h | 0 .../translator.cpp} | 2 +- src/{translator_core.h => core/translator.h} | 6 +-- src/{ => core}/webhook_push.cpp | 0 src/{ => core}/webhook_push.h | 0 .../file/file.cpp} | 2 +- src/{database_file.h => database/file/file.h} | 2 +- src/resources/win32/dtranslatebot.rc.in | 29 ++++++++++ .../libretranslate/libretranslate.cpp} | 2 +- .../libretranslate/libretranslate.h} | 2 +- 26 files changed, 92 insertions(+), 83 deletions(-) create mode 100644 .gitattributes delete mode 100644 etc/dtranslatebot.example.json delete mode 100644 etc/dtranslatebot.json rename src/{database_core.cpp => core/database.cpp} (99%) rename src/{database_core.h => core/database.h} (97%) rename src/{ => core}/main.cpp (100%) rename src/{ => core}/message_queue.cpp (100%) rename src/{ => core}/message_queue.h (100%) rename src/{ => core}/regex.h (100%) rename src/{ => core}/settings.cpp (99%) rename src/{ => core}/settings.h (98%) rename src/{ => core}/settings_types.h (100%) rename src/{ => core}/slashcommands.cpp (100%) rename src/{ => core}/slashcommands.h (100%) rename src/{ => core}/submit_queue.cpp (100%) rename src/{ => core}/submit_queue.h (100%) rename src/{translator_core.cpp => core/translator.cpp} (98%) rename src/{translator_core.h => core/translator.h} (94%) rename src/{ => core}/webhook_push.cpp (100%) rename src/{ => core}/webhook_push.h (100%) rename src/{database_file.cpp => database/file/file.cpp} (99%) rename src/{database_file.h => database/file/file.h} (99%) create mode 100644 src/resources/win32/dtranslatebot.rc.in rename src/{translator_libretranslate.cpp => translator/libretranslate/libretranslate.cpp} (98%) rename src/{translator_libretranslate.h => translator/libretranslate/libretranslate.h} (98%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9a45441 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +* text=auto eol=lf + +# Configuration files +*.json text eol=crlf + +# Development files +CMakeLists.txt text eol=lf +*.cmake text eol=lf +*.cpp text eol=lf +*.h text eol=lf + +# BSD and Linux development files +*.pc.in text eol=lf + +# Windows development files +*.rc.in text encoding=cp1252 eol=crlf diff --git a/CMakeLists.txt b/CMakeLists.txt index b26ac46..3e17be0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,34 +17,34 @@ ****************************************************************************]] cmake_minimum_required(VERSION 3.16) -project(dtranslatebot VERSION 0.2 LANGUAGES CXX) +project(dtranslatebot VERSION 0.2.0 LANGUAGES CXX) include(GNUInstallDirs) # dtranslatebot Source files set(DTRANSLATEBOT_HEADERS - src/database_core.h - src/database_file.h - src/message_queue.h - src/regex.h - src/settings.h - src/settings_types.h - src/slashcommands.h - src/submit_queue.h - src/translator_core.h - src/translator_libretranslate.h - src/webhook_push.h + src/core/database.h + src/core/message_queue.h + src/core/regex.h + src/core/settings.h + src/core/settings_types.h + src/core/slashcommands.h + src/core/submit_queue.h + src/core/translator.h + src/core/webhook_push.h + src/database/file/file.h + src/translator/libretranslate/libretranslate.h ) set(DTRANSLATEBOT_SOURCES - src/database_core.cpp - src/database_file.cpp - src/main.cpp - src/message_queue.cpp - src/settings.cpp - src/slashcommands.cpp - src/submit_queue.cpp - src/translator_core.cpp - src/translator_libretranslate.cpp - src/webhook_push.cpp + src/core/database.cpp + src/core/main.cpp + src/core/message_queue.cpp + src/core/settings.cpp + src/core/slashcommands.cpp + src/core/submit_queue.cpp + src/core/translator.cpp + src/core/webhook_push.cpp + src/database/file/file.cpp + src/translator/libretranslate/libretranslate.cpp ) # dtranslatebot Module Path @@ -69,8 +69,16 @@ find_package(DPP REQUIRED) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) +# dtranslatebot Win32 Shared Resources +if (WIN32) + configure_file(src/resources/win32/dtranslatebot.rc.in "${dtranslatebot_BINARY_DIR}/resources/win32/dtranslatebot.rc" @ONLY) + list(APPEND DTRANSLATEBOT_RESOURCES + "${dtranslatebot_BINARY_DIR}/resources/win32/dtranslatebot.rc" + ) +endif() + # dtranslatebot Target + Installs -add_executable(dtranslatebot ${DTRANSLATEBOT_HEADERS} ${DTRANSLATEBOT_SOURCES}) +add_executable(dtranslatebot ${DTRANSLATEBOT_HEADERS} ${DTRANSLATEBOT_SOURCES} ${DTRANSLATEBOT_RESOURCES}) target_compile_definitions(dtranslatebot PRIVATE $<$:DTRANSLATEBOT_USE_BOOST_REGEX> ) diff --git a/etc/dtranslatebot.example.json b/etc/dtranslatebot.example.json deleted file mode 100644 index 202a0ee..0000000 --- a/etc/dtranslatebot.example.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "guilds": { - "$guild1_id": { - "$channel1_id": { - "source": "en", - "target": "de", - "webhook": "https://discord.com/api/webhooks/$guild1_de_webhook_id/$guild1_de_webhook_token" - }, - "$channel2_id": { - "source": "de", - "target": "en", - "webhook": "https://discord.com/api/webhooks/$guild1_en_webhook_id/$guild1_en_webhook_token" - } - }, - "My Discord Guild": { - "id": $guild2_id, - "General English": { - "id": $channel3_id, - "source": "en", - "target": { - "de": "https://discord.com/api/webhooks/$guild2_de_webhook_id/$guild2_de_webhook_token", - "fr": "https://discord.com/api/webhooks/$guild2_fr_webhook_id/$guild2_fr_webhook_token" - } - } - } - }, - "preferred_lang": ["en", "de", "fr", ...], - "storage": "$working_directory", - "user": { - "avatar_size": 256 - }, - "token": "$bot_token", - "translator": { - "url": "http://127.0.0.1:5000/", - "apiKey": "" - } -} diff --git a/etc/dtranslatebot.json b/etc/dtranslatebot.json deleted file mode 100644 index 28381db..0000000 --- a/etc/dtranslatebot.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "token": "", - "translator": { - "url": "http://127.0.0.1:5000/", - "apiKey": "" - } -} diff --git a/src/database_core.cpp b/src/core/database.cpp similarity index 99% rename from src/database_core.cpp rename to src/core/database.cpp index b540f36..f7fb12d 100644 --- a/src/database_core.cpp +++ b/src/core/database.cpp @@ -19,7 +19,7 @@ #ifndef NDEBUG #include #endif -#include "database_core.h" +#include "database.h" using namespace bot::database; database::database() diff --git a/src/database_core.h b/src/core/database.h similarity index 97% rename from src/database_core.h rename to src/core/database.h index 6526eda..04e8cf3 100644 --- a/src/database_core.h +++ b/src/core/database.h @@ -16,8 +16,8 @@ * responsible for anything with use of the software, you are self responsible. *****************************************************************************/ -#ifndef DATABASE_CORE_H -#define DATABASE_CORE_H +#ifndef DATABASE_H +#define DATABASE_H #include "settings_types.h" @@ -52,4 +52,4 @@ namespace bot { } } -#endif // DATABASE_CORE_H +#endif // DATABASE_H diff --git a/src/main.cpp b/src/core/main.cpp similarity index 100% rename from src/main.cpp rename to src/core/main.cpp diff --git a/src/message_queue.cpp b/src/core/message_queue.cpp similarity index 100% rename from src/message_queue.cpp rename to src/core/message_queue.cpp diff --git a/src/message_queue.h b/src/core/message_queue.h similarity index 100% rename from src/message_queue.h rename to src/core/message_queue.h diff --git a/src/regex.h b/src/core/regex.h similarity index 100% rename from src/regex.h rename to src/core/regex.h diff --git a/src/settings.cpp b/src/core/settings.cpp similarity index 99% rename from src/settings.cpp rename to src/core/settings.cpp index d8fb47d..d761ea4 100644 --- a/src/settings.cpp +++ b/src/core/settings.cpp @@ -19,9 +19,9 @@ #include #include #include -#include "database_file.h" #include "settings.h" -#include "translator_libretranslate.h" +#include "../database/file/file.h" +#include "../translator/libretranslate/libretranslate.h" using namespace bot::settings; void process_database_channels(std::shared_ptr database, bot::settings::guild *guild, std::vector *webhookIds) diff --git a/src/settings.h b/src/core/settings.h similarity index 98% rename from src/settings.h rename to src/core/settings.h index 31b71c3..d02db2a 100644 --- a/src/settings.h +++ b/src/core/settings.h @@ -19,9 +19,9 @@ #ifndef SETTINGS_H #define SETTINGS_H #include -#include "database_core.h" +#include "database.h" #include "settings_types.h" -#include "translator_core.h" +#include "translator.h" namespace bot { namespace settings { diff --git a/src/settings_types.h b/src/core/settings_types.h similarity index 100% rename from src/settings_types.h rename to src/core/settings_types.h diff --git a/src/slashcommands.cpp b/src/core/slashcommands.cpp similarity index 100% rename from src/slashcommands.cpp rename to src/core/slashcommands.cpp diff --git a/src/slashcommands.h b/src/core/slashcommands.h similarity index 100% rename from src/slashcommands.h rename to src/core/slashcommands.h diff --git a/src/submit_queue.cpp b/src/core/submit_queue.cpp similarity index 100% rename from src/submit_queue.cpp rename to src/core/submit_queue.cpp diff --git a/src/submit_queue.h b/src/core/submit_queue.h similarity index 100% rename from src/submit_queue.h rename to src/core/submit_queue.h diff --git a/src/translator_core.cpp b/src/core/translator.cpp similarity index 98% rename from src/translator_core.cpp rename to src/core/translator.cpp index d32d544..4d82d16 100644 --- a/src/translator_core.cpp +++ b/src/core/translator.cpp @@ -19,7 +19,7 @@ #ifndef NDEBUG #include #endif -#include "translator_core.h" +#include "translator.h" using namespace bot::translator; translator::translator() diff --git a/src/translator_core.h b/src/core/translator.h similarity index 94% rename from src/translator_core.h rename to src/core/translator.h index 33fbf0e..d42e21b 100644 --- a/src/translator_core.h +++ b/src/core/translator.h @@ -16,8 +16,8 @@ * responsible for anything with use of the software, you are self responsible. *****************************************************************************/ -#ifndef TRANSLATOR_CORE_H -#define TRANSLATOR_CORE_H +#ifndef TRANSLATOR_H +#define TRANSLATOR_H #include #include @@ -39,4 +39,4 @@ namespace bot { } } -#endif // TRANSLATOR_CORE_H +#endif // TRANSLATOR_H diff --git a/src/webhook_push.cpp b/src/core/webhook_push.cpp similarity index 100% rename from src/webhook_push.cpp rename to src/core/webhook_push.cpp diff --git a/src/webhook_push.h b/src/core/webhook_push.h similarity index 100% rename from src/webhook_push.h rename to src/core/webhook_push.h diff --git a/src/database_file.cpp b/src/database/file/file.cpp similarity index 99% rename from src/database_file.cpp rename to src/database/file/file.cpp index db5774b..31c4cfb 100644 --- a/src/database_file.cpp +++ b/src/database/file/file.cpp @@ -27,7 +27,7 @@ #include #include #include -#include "database_file.h" +#include "file.h" using namespace bot::database; using namespace std::string_literals; diff --git a/src/database_file.h b/src/database/file/file.h similarity index 99% rename from src/database_file.h rename to src/database/file/file.h index 5947b3f..c743011 100644 --- a/src/database_file.h +++ b/src/database/file/file.h @@ -26,7 +26,7 @@ #define WIN32_LEAN_AND_MEAN #include #endif -#include "database_core.h" +#include "../../core/database.h" namespace bot { namespace database { diff --git a/src/resources/win32/dtranslatebot.rc.in b/src/resources/win32/dtranslatebot.rc.in new file mode 100644 index 0000000..a3e475d --- /dev/null +++ b/src/resources/win32/dtranslatebot.rc.in @@ -0,0 +1,29 @@ +#include +VS_VERSION_INFO VERSIONINFO +FILEVERSION @dtranslatebot_VERSION_MAJOR@, @dtranslatebot_VERSION_MINOR@, @dtranslatebot_VERSION_PATCH@, 0 +PRODUCTVERSION @dtranslatebot_VERSION_MAJOR@, @dtranslatebot_VERSION_MINOR@, @dtranslatebot_VERSION_PATCH@, 0 +FILEFLAGSMASK 0x3fL +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Syping" + VALUE "FileDescription", "Open Source Discord Translation Bot" + VALUE "FileVersion", "@dtranslatebot_VERSION@" + VALUE "InternalName", "dtranslatebot" + VALUE "LegalCopyright", "Copyright © 2023-2024 Syping" + VALUE "OriginalFilename", "dtranslatebot.exe" + VALUE "ProductName", "dtranslatebot" + VALUE "ProductVersion", "@dtranslatebot_VERSION@" + END + END +END diff --git a/src/translator_libretranslate.cpp b/src/translator/libretranslate/libretranslate.cpp similarity index 98% rename from src/translator_libretranslate.cpp rename to src/translator/libretranslate/libretranslate.cpp index 78a0026..7e5e9e7 100644 --- a/src/translator_libretranslate.cpp +++ b/src/translator/libretranslate/libretranslate.cpp @@ -18,7 +18,7 @@ #include #include -#include "translator_libretranslate.h" +#include "libretranslate.h" using namespace bot::translator; using namespace std::string_literals; diff --git a/src/translator_libretranslate.h b/src/translator/libretranslate/libretranslate.h similarity index 98% rename from src/translator_libretranslate.h rename to src/translator/libretranslate/libretranslate.h index eaa287d..0bb8afa 100644 --- a/src/translator_libretranslate.h +++ b/src/translator/libretranslate/libretranslate.h @@ -21,7 +21,7 @@ #include #include -#include "translator_core.h" +#include "../../core/translator.h" namespace bot { namespace translator { From 912ac1eced6ae7762fdae0298137e69ff1566151 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 26 Feb 2024 12:01:23 +0100 Subject: [PATCH 06/53] add systemd service file --- CMakeLists.txt | 9 +++++++++ README.md | 3 ++- src/systemd/dtranslatebot.service.in | 13 +++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/systemd/dtranslatebot.service.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e17be0..c6f84ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,15 @@ if (WIN32) ) endif() +# dtranslatebot systemd Service +if (UNIX AND NOT APPLE) + option(WITH_SYSTEMD "Build with systemd Support" OFF) + if (WITH_SYSTEMD) + configure_file(src/systemd/dtranslatebot.service.in "${dtranslatebot_BINARY_DIR}/systemd/dtranslatebot.service" @ONLY) + install(FILES "${dtranslatebot_BINARY_DIR}/systemd/dtranslatebot.service" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") + endif() +endif() + # dtranslatebot Target + Installs add_executable(dtranslatebot ${DTRANSLATEBOT_HEADERS} ${DTRANSLATEBOT_SOURCES} ${DTRANSLATEBOT_RESOURCES}) target_compile_definitions(dtranslatebot PRIVATE diff --git a/README.md b/README.md index de6ccdc..c84ce50 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,5 @@ sudo cmake --install dtranslatebot-build ``` ##### Optional CMake flags -`-DWITH_BOOST=TRUE` +`-DWITH_BOOST=TRUE` +`-DWITH_SYSTEMD=TRUE` diff --git a/src/systemd/dtranslatebot.service.in b/src/systemd/dtranslatebot.service.in new file mode 100644 index 0000000..8828423 --- /dev/null +++ b/src/systemd/dtranslatebot.service.in @@ -0,0 +1,13 @@ +[Unit] +Description=Discord Translation Bot +After=network.target + +[Service] +User=dtranslatebot +Group=dtranslatebot +WorkingDirectory="@CMAKE_INSTALL_FULL_RUNSTATEDIR@/dtranslatebot" +ExecStart="@CMAKE_INSTALL_FULL_BINDIR@/dtranslatebot" "@CMAKE_INSTALL_FULL_SYSCONFDIR@/dtranslatebot.json" +Restart=on-failure + +[Install] +WantedBy=multi-user.target From 716a03c43b9190bdc9d6e17bf250880f888d2ec6 Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 27 Feb 2024 10:02:32 +0100 Subject: [PATCH 07/53] systemd: change working directory to /var/lib/dtranslatebot --- src/systemd/dtranslatebot.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemd/dtranslatebot.service.in b/src/systemd/dtranslatebot.service.in index 8828423..b537c19 100644 --- a/src/systemd/dtranslatebot.service.in +++ b/src/systemd/dtranslatebot.service.in @@ -5,7 +5,7 @@ After=network.target [Service] User=dtranslatebot Group=dtranslatebot -WorkingDirectory="@CMAKE_INSTALL_FULL_RUNSTATEDIR@/dtranslatebot" +WorkingDirectory="@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/dtranslatebot" ExecStart="@CMAKE_INSTALL_FULL_BINDIR@/dtranslatebot" "@CMAKE_INSTALL_FULL_SYSCONFDIR@/dtranslatebot.json" Restart=on-failure From 4fe57d1a241003101f45ab5f3128ad37a66aac73 Mon Sep 17 00:00:00 2001 From: Syping Date: Thu, 29 Feb 2024 20:55:33 +0100 Subject: [PATCH 08/53] CMake: incomplete DPPAsExternalProject impl --- CMakeLists.txt | 7 ++- cmake/DPPAsExternalProject.cmake | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 cmake/DPPAsExternalProject.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c6f84ac..ad05d7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,12 @@ if (WITH_BOOST) endif() # D++ Discord API Library for Bots -find_package(DPP REQUIRED) +option(WITH_DPP_AS_EXTERNAL_PROJECT "Build with DPP as External Project" OFF) +if (WITH_DPP_AS_EXTERNAL_PROJECT) + include(DPPAsExternalProject) +else() + find_package(DPP REQUIRED) +endif() # pthread Support set(THREADS_PREFER_PTHREAD_FLAG ON) diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake new file mode 100644 index 0000000..f9f1d06 --- /dev/null +++ b/cmake/DPPAsExternalProject.cmake @@ -0,0 +1,77 @@ +#[[************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +****************************************************************************]] + +# OpenSSL needs to build with make +find_program(MAKE_EXECUTABLE NAMES make gmake) +if (NOT MAKE_EXECUTABLE) + message(SEND_ERROR "make not found") +endif() + +find_program(NPROC_EXECUTABLE nproc) +if (NPROC_EXECUTABLE) + execute_process( + COMMAND ${NPROC_EXECUTABLE} + OUTPUT_VARIABLE NPROC + ) + set(JOBS_ARGUMENT "-j${NPROC}" CACHE STRING "make jobs argument") +endif() + +include(ExternalProject) +ExternalProject_Add(ZLIB + URL https://www.zlib.net/zlib-1.3.1.tar.xz + URL_HASH SHA256=38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + CMAKE_ARGS + -DBUILD_SHARED_LIBS=OFF + "-DCMAKE_INSTALL_PREFIX=" + -DZLIB_BUILD_EXAMPLES=OFF +) +ExternalProject_Get_Property(ZLIB INSTALL_DIR) +set(ZLIB_INSTALL_DIR ${INSTALL_DIR}) + +ExternalProject_Add(OpenSSL + URL https://www.openssl.org/source/openssl-3.0.13.tar.gz + URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + CONFIGURE_COMMAND + "/config" + "--prefix=" + "--api=1.1.1" + no-deprecated + no-dtls + no-shared + no-zlib + BUILD_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} + INSTALL_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} install_sw +) +ExternalProject_Get_Property(OpenSSL INSTALL_DIR) +set(OpenSSL_INSTALL_DIR ${INSTALL_DIR}) + +ExternalProject_Add(DPP + GIT_REPOSITORY https://github.com/brainboxdotcc/DPP.git + GIT_TAG 46044c8f80134633f7b396b4d5814f83d54a96d3 + CMAKE_ARGS + -DBUILD_SHARED_LIBS=OFF + -DBUILD_VOICE_SUPPORT=OFF + "-DCMAKE_INSTALL_PREFIX=" + -DDPP_NO_VCPKG=ON + "-DOpenSSL_ROOT=${OpenSSL_INSTALL_DIR}" + "-DZLIB_ROOT=${ZLIB_INSTALL_DIR}" + DEPENDS OpenSSL + DEPENDS ZLIB +) From 820593ca2d3c63ead61805bdb67df05354b19340 Mon Sep 17 00:00:00 2001 From: Syping Date: Sat, 2 Mar 2024 17:42:20 +0100 Subject: [PATCH 09/53] DPPAsExternalProject: build should work now --- CMakeLists.txt | 3 +++ cmake/DPPAsExternalProject.cmake | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad05d7f..420013f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,9 @@ endif() # dtranslatebot Target + Installs add_executable(dtranslatebot ${DTRANSLATEBOT_HEADERS} ${DTRANSLATEBOT_SOURCES} ${DTRANSLATEBOT_RESOURCES}) +if (WITH_DPP_AS_EXTERNAL_PROJECT) + add_dependencies(dtranslatebot DPP) +endif() target_compile_definitions(dtranslatebot PRIVATE $<$:DTRANSLATEBOT_USE_BOOST_REGEX> ) diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index f9f1d06..50afe0c 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -28,7 +28,8 @@ if (NPROC_EXECUTABLE) COMMAND ${NPROC_EXECUTABLE} OUTPUT_VARIABLE NPROC ) - set(JOBS_ARGUMENT "-j${NPROC}" CACHE STRING "make jobs argument") + string(STRIP ${NPROC} NPROC) + set(JOBS_ARGUMENT "-j${NPROC}" CACHE INTERNAL "make jobs argument") endif() include(ExternalProject) @@ -42,7 +43,7 @@ ExternalProject_Add(ZLIB -DZLIB_BUILD_EXAMPLES=OFF ) ExternalProject_Get_Property(ZLIB INSTALL_DIR) -set(ZLIB_INSTALL_DIR ${INSTALL_DIR}) +set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(OpenSSL URL https://www.openssl.org/source/openssl-3.0.13.tar.gz @@ -51,7 +52,6 @@ ExternalProject_Add(OpenSSL CONFIGURE_COMMAND "/config" "--prefix=" - "--api=1.1.1" no-deprecated no-dtls no-shared @@ -60,18 +60,34 @@ ExternalProject_Add(OpenSSL INSTALL_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} install_sw ) ExternalProject_Get_Property(OpenSSL INSTALL_DIR) -set(OpenSSL_INSTALL_DIR ${INSTALL_DIR}) +set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - GIT_REPOSITORY https://github.com/brainboxdotcc/DPP.git - GIT_TAG 46044c8f80134633f7b396b4d5814f83d54a96d3 + GIT_REPOSITORY https://github.com/Syping/DPP.git + GIT_TAG dcd00001dfa145a03f80a0ad5317bc3e63252ead CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF -DBUILD_VOICE_SUPPORT=OFF "-DCMAKE_INSTALL_PREFIX=" -DDPP_NO_VCPKG=ON + -DRUN_LDCONFIG=OFF "-DOpenSSL_ROOT=${OpenSSL_INSTALL_DIR}" "-DZLIB_ROOT=${ZLIB_INSTALL_DIR}" DEPENDS OpenSSL DEPENDS ZLIB ) +ExternalProject_Get_Property(DPP INSTALL_DIR) +set(DPP_INSTALL_DIR "${INSTALL_DIR}") +set(DPP_INCLUDE_DIR "${DPP_INSTALL_DIR}/include") +set(DPP_LIBRARIES + "-L${DPP_INSTALL_DIR}/lib" + "-L${DPP_INSTALL_DIR}/lib64" + -ldpp + "-L${OpenSSL_INSTALL_DIR}/lib" + "-L${OpenSSL_INSTALL_DIR}/lib64" + -lssl + -lcrypto + "-L${ZLIB_INSTALL_DIR}/lib" + "-L${ZLIB_INSTALL_DIR}/lib64" + -lz +) From c21ed31889704add1682b1b8385485b7d2f08eab Mon Sep 17 00:00:00 2001 From: Syping Date: Sat, 2 Mar 2024 22:22:05 +0100 Subject: [PATCH 10/53] minor fixes for DPPAsExternalProject --- CMakeLists.txt | 2 +- README.md | 3 ++- cmake/DPPAsExternalProject.cmake | 28 +++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 420013f..ec2568b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ target_compile_definitions(dtranslatebot PRIVATE if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) target_compile_options(dtranslatebot PRIVATE $<$:/Zc:__cplusplus>) endif() -target_link_libraries(dtranslatebot PRIVATE Threads::Threads ${DPP_LIBRARIES} ${DTRANSLATEBOT_LIBRARIES}) +target_link_libraries(dtranslatebot PRIVATE ${DPP_LIBRARIES} ${DTRANSLATEBOT_LIBRARIES} Threads::Threads) target_include_directories(dtranslatebot PRIVATE ${DPP_INCLUDE_DIR}) set_target_properties(dtranslatebot PROPERTIES CXX_STANDARD 17 diff --git a/README.md b/README.md index c84ce50..1c79c3a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Open Source Discord Translation Bot - Translate incoming channel messages to a Webhook -- Support configuration through slashcommands and JSON +- Support configuration through slash commands and JSON - Cross-Platform #### Build Dependencies @@ -24,4 +24,5 @@ sudo cmake --install dtranslatebot-build ##### Optional CMake flags `-DWITH_BOOST=TRUE` +`-DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE` `-DWITH_SYSTEMD=TRUE` diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index 50afe0c..d1cbcbf 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -16,7 +16,17 @@ * responsible for anything with use of the software, you are self responsible. ****************************************************************************]] -# OpenSSL needs to build with make +# Needed for compiler passthrough +if (DEFINED CMAKE_C_COMPILER) + set(CC_ENV "CC=${CMAKE_C_COMPILER}") + set(DEFINE_CMAKE_C_COMPILER "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") +endif() + +if (DEFINED CMAKE_CXX_COMPILER) + set(DEFINE_CMAKE_CXX_COMPILER "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") +endif() + +# OpenSSL needs to be build with make find_program(MAKE_EXECUTABLE NAMES make gmake) if (NOT MAKE_EXECUTABLE) message(SEND_ERROR "make not found") @@ -36,9 +46,10 @@ include(ExternalProject) ExternalProject_Add(ZLIB URL https://www.zlib.net/zlib-1.3.1.tar.xz URL_HASH SHA256=38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32 - DOWNLOAD_EXTRACT_TIMESTAMP TRUE CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF + "-DCMAKE_BUILD_TYPE=$" + "${DEFINE_CMAKE_C_COMPILER}" "-DCMAKE_INSTALL_PREFIX=" -DZLIB_BUILD_EXAMPLES=OFF ) @@ -48,12 +59,15 @@ set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(OpenSSL URL https://www.openssl.org/source/openssl-3.0.13.tar.gz URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 - DOWNLOAD_EXTRACT_TIMESTAMP TRUE CONFIGURE_COMMAND + "${CC_ENV}" "/config" "--prefix=" + $<$:-d> no-deprecated no-dtls + no-dso + no-engine no-shared no-zlib BUILD_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} @@ -63,11 +77,13 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - GIT_REPOSITORY https://github.com/Syping/DPP.git - GIT_TAG dcd00001dfa145a03f80a0ad5317bc3e63252ead + URL https://github.com/Syping/DPP/archive/dcd00001dfa145a03f80a0ad5317bc3e63252ead.tar.gz + URL_HASH SHA256=42ff04b13a384591e819c100c4f40e12e31c8076769c168631eef85a8eeb0be3 CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF -DBUILD_VOICE_SUPPORT=OFF + "-DCMAKE_BUILD_TYPE=$" + "${DEFINE_CMAKE_CXX_COMPILER}" "-DCMAKE_INSTALL_PREFIX=" -DDPP_NO_VCPKG=ON -DRUN_LDCONFIG=OFF @@ -80,6 +96,7 @@ ExternalProject_Get_Property(DPP INSTALL_DIR) set(DPP_INSTALL_DIR "${INSTALL_DIR}") set(DPP_INCLUDE_DIR "${DPP_INSTALL_DIR}/include") set(DPP_LIBRARIES + -Wl,-Bstatic "-L${DPP_INSTALL_DIR}/lib" "-L${DPP_INSTALL_DIR}/lib64" -ldpp @@ -90,4 +107,5 @@ set(DPP_LIBRARIES "-L${ZLIB_INSTALL_DIR}/lib" "-L${ZLIB_INSTALL_DIR}/lib64" -lz + -Wl,-Bdynamic ) From bb099d644a176a4dd7fbf69b7e04b82e512dc37c Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 3 Mar 2024 15:17:03 +0100 Subject: [PATCH 11/53] DPPAsExternalProject: call Perl directly for OpenSSL --- CMakeLists.txt | 1 + cmake/DPPAsExternalProject.cmake | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ec2568b..264ff05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ ****************************************************************************]] cmake_minimum_required(VERSION 3.16) +cmake_policy(VERSION 3.16...3.27) project(dtranslatebot VERSION 0.2.0 LANGUAGES CXX) include(GNUInstallDirs) diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index d1cbcbf..b96dcc0 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -18,7 +18,7 @@ # Needed for compiler passthrough if (DEFINED CMAKE_C_COMPILER) - set(CC_ENV "CC=${CMAKE_C_COMPILER}") + set(CMAKE_ENV_CC_COMMAND "${CMAKE_COMMAND}" -E env "CC=${CMAKE_C_COMPILER}") set(DEFINE_CMAKE_C_COMPILER "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") endif() @@ -26,14 +26,15 @@ if (DEFINED CMAKE_CXX_COMPILER) set(DEFINE_CMAKE_CXX_COMPILER "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") endif() -# OpenSSL needs to be build with make +# OpenSSL needs to be configured with perl and build with make +find_package(Perl REQUIRED) find_program(MAKE_EXECUTABLE NAMES make gmake) -if (NOT MAKE_EXECUTABLE) +if (NOT DEFINED MAKE_EXECUTABLE) message(SEND_ERROR "make not found") endif() find_program(NPROC_EXECUTABLE nproc) -if (NPROC_EXECUTABLE) +if (DEFINED NPROC_EXECUTABLE) execute_process( COMMAND ${NPROC_EXECUTABLE} OUTPUT_VARIABLE NPROC @@ -60,18 +61,19 @@ ExternalProject_Add(OpenSSL URL https://www.openssl.org/source/openssl-3.0.13.tar.gz URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 CONFIGURE_COMMAND - "${CC_ENV}" - "/config" + ${CMAKE_ENV_CC_COMMAND} + "${PERL_EXECUTABLE}" + "/Configure" "--prefix=" $<$:-d> no-deprecated - no-dtls no-dso + no-dtls no-engine no-shared no-zlib - BUILD_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} - INSTALL_COMMAND ${MAKE_EXECUTABLE} ${JOBS_ARGUMENT} install_sw + BUILD_COMMAND "${MAKE_EXECUTABLE}" "${JOBS_ARGUMENT}" + INSTALL_COMMAND "${MAKE_EXECUTABLE}" "${JOBS_ARGUMENT}" install_sw ) ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") From 024400be46a83957cea5bc4f34e1c729ed9fe21d Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 5 Mar 2024 21:02:05 +0100 Subject: [PATCH 12/53] improved external project passthrough of variables --- cmake/ArgumentPassthrough.cmake | 54 ++++++++++++++++++++++++++++++++ cmake/DPPAsExternalProject.cmake | 22 ++++--------- 2 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 cmake/ArgumentPassthrough.cmake diff --git a/cmake/ArgumentPassthrough.cmake b/cmake/ArgumentPassthrough.cmake new file mode 100644 index 0000000..56d25d1 --- /dev/null +++ b/cmake/ArgumentPassthrough.cmake @@ -0,0 +1,54 @@ +#[[************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +****************************************************************************]] + +if (DEFINED CMAKE_BUILD_TYPE) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") +endif() +if (DEFINED CMAKE_C_COMPILER) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") + list(APPEND CMAKE_PASSTHROUGH_ENV "CC=${CMAKE_C_COMPILER}") +endif() +if (DEFINED CMAKE_C_COMPILER_TARGET) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_C_COMPILER_TARGET=${CMAKE_C_COMPILER_TARGET}") +endif() +if (DEFINED CMAKE_CXX_COMPILER) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") +endif() +if (DEFINED CMAKE_CXX_COMPILER_TARGET) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER_TARGET=${CMAKE_CXX_COMPILER_TARGET}") +endif() +if (DEFINED CMAKE_SYSROOT) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSROOT=${CMAKE_SYSROOT}") +endif() +if (DEFINED CMAKE_SYSTEM_NAME) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}") +endif() +if (DEFINED CMAKE_SYSTEM_PROCESSOR) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}") +endif() +if (DEFINED CMAKE_SYSTEM_VERSION) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") +endif() +if (DEFINED CMAKE_TOOLCHAIN_FILE) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}") +endif() +if (DEFINED CMAKE_PASSTHROUGH_ENV) + set(CMAKE_PASSTHROUGH_ENV + "${CMAKE_COMMAND}" -E env ${CMAKE_PASSTHROUGH_ENV} + ) +endif() diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index b96dcc0..4b046a4 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -16,15 +16,7 @@ * responsible for anything with use of the software, you are self responsible. ****************************************************************************]] -# Needed for compiler passthrough -if (DEFINED CMAKE_C_COMPILER) - set(CMAKE_ENV_CC_COMMAND "${CMAKE_COMMAND}" -E env "CC=${CMAKE_C_COMPILER}") - set(DEFINE_CMAKE_C_COMPILER "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") -endif() - -if (DEFINED CMAKE_CXX_COMPILER) - set(DEFINE_CMAKE_CXX_COMPILER "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") -endif() +include(ArgumentPassthrough) # OpenSSL needs to be configured with perl and build with make find_package(Perl REQUIRED) @@ -36,10 +28,10 @@ endif() find_program(NPROC_EXECUTABLE nproc) if (DEFINED NPROC_EXECUTABLE) execute_process( - COMMAND ${NPROC_EXECUTABLE} + COMMAND "${NPROC_EXECUTABLE}" OUTPUT_VARIABLE NPROC ) - string(STRIP ${NPROC} NPROC) + string(STRIP "${NPROC}" NPROC) set(JOBS_ARGUMENT "-j${NPROC}" CACHE INTERNAL "make jobs argument") endif() @@ -49,8 +41,7 @@ ExternalProject_Add(ZLIB URL_HASH SHA256=38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32 CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF - "-DCMAKE_BUILD_TYPE=$" - "${DEFINE_CMAKE_C_COMPILER}" + "${CMAKE_PASSTHROUGH_ARGS}" "-DCMAKE_INSTALL_PREFIX=" -DZLIB_BUILD_EXAMPLES=OFF ) @@ -61,7 +52,7 @@ ExternalProject_Add(OpenSSL URL https://www.openssl.org/source/openssl-3.0.13.tar.gz URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 CONFIGURE_COMMAND - ${CMAKE_ENV_CC_COMMAND} + ${CMAKE_PASSTHROUGH_ENV} "${PERL_EXECUTABLE}" "/Configure" "--prefix=" @@ -84,8 +75,7 @@ ExternalProject_Add(DPP CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF -DBUILD_VOICE_SUPPORT=OFF - "-DCMAKE_BUILD_TYPE=$" - "${DEFINE_CMAKE_CXX_COMPILER}" + "${CMAKE_PASSTHROUGH_ARGS}" "-DCMAKE_INSTALL_PREFIX=" -DDPP_NO_VCPKG=ON -DRUN_LDCONFIG=OFF From dd2de72f944e3a37fed21c90841c7b9cea691d45 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Mar 2024 15:23:11 +0100 Subject: [PATCH 13/53] ArgumentPassthrough: avoid accidental Cross-Compiling + more fixes --- cmake/ArgumentPassthrough.cmake | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cmake/ArgumentPassthrough.cmake b/cmake/ArgumentPassthrough.cmake index 56d25d1..3226ae2 100644 --- a/cmake/ArgumentPassthrough.cmake +++ b/cmake/ArgumentPassthrough.cmake @@ -22,6 +22,8 @@ endif() if (DEFINED CMAKE_C_COMPILER) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") list(APPEND CMAKE_PASSTHROUGH_ENV "CC=${CMAKE_C_COMPILER}") +elseif ($ENV{MSYSTEM} STREQUAL "CLANG64") + list(APPEND CMAKE_PASSTHROUGH_ENV "CC=clang") endif() if (DEFINED CMAKE_C_COMPILER_TARGET) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_C_COMPILER_TARGET=${CMAKE_C_COMPILER_TARGET}") @@ -32,16 +34,22 @@ endif() if (DEFINED CMAKE_CXX_COMPILER_TARGET) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER_TARGET=${CMAKE_CXX_COMPILER_TARGET}") endif() +if (DEFINED CMAKE_RC_COMPILER) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}") +endif() +if (DEFINED CMAKE_STRIP) + list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_STRIP=${CMAKE_STRIP}") +endif() if (DEFINED CMAKE_SYSROOT) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSROOT=${CMAKE_SYSROOT}") endif() -if (DEFINED CMAKE_SYSTEM_NAME) +if (DEFINED CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}") endif() -if (DEFINED CMAKE_SYSTEM_PROCESSOR) +if (DEFINED CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}") endif() -if (DEFINED CMAKE_SYSTEM_VERSION) +if (DEFINED CMAKE_SYSTEM_VERSION AND NOT CMAKE_SYTEM_VERSION STREQUAL CMAKE_HOST_SYSTEM_VERSION) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") endif() if (DEFINED CMAKE_TOOLCHAIN_FILE) From 6220277305b329a8b4ec51b3cddbe5b0e779fe7b Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Mar 2024 16:20:47 +0100 Subject: [PATCH 14/53] CMake: msys compatibility added/fixed --- CMakeLists.txt | 3 ++- cmake/DPPAsExternalProject.cmake | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 264ff05..e09803d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,12 +98,13 @@ if (WITH_DPP_AS_EXTERNAL_PROJECT) add_dependencies(dtranslatebot DPP) endif() target_compile_definitions(dtranslatebot PRIVATE + ${DPP_DEFINITIONS} $<$:DTRANSLATEBOT_USE_BOOST_REGEX> ) if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914) target_compile_options(dtranslatebot PRIVATE $<$:/Zc:__cplusplus>) endif() -target_link_libraries(dtranslatebot PRIVATE ${DPP_LIBRARIES} ${DTRANSLATEBOT_LIBRARIES} Threads::Threads) +target_link_libraries(dtranslatebot PRIVATE ${DTRANSLATEBOT_LIBRARIES} ${DPP_LIBRARIES} Threads::Threads) target_include_directories(dtranslatebot PRIVATE ${DPP_INCLUDE_DIR}) set_target_properties(dtranslatebot PROPERTIES CXX_STANDARD 17 diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index 4b046a4..3c69b59 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -77,6 +77,7 @@ ExternalProject_Add(DPP -DBUILD_VOICE_SUPPORT=OFF "${CMAKE_PASSTHROUGH_ARGS}" "-DCMAKE_INSTALL_PREFIX=" + -DDPP_BUILD_TEST=OFF -DDPP_NO_VCPKG=ON -DRUN_LDCONFIG=OFF "-DOpenSSL_ROOT=${OpenSSL_INSTALL_DIR}" @@ -91,13 +92,21 @@ set(DPP_LIBRARIES -Wl,-Bstatic "-L${DPP_INSTALL_DIR}/lib" "-L${DPP_INSTALL_DIR}/lib64" - -ldpp + dpp "-L${OpenSSL_INSTALL_DIR}/lib" "-L${OpenSSL_INSTALL_DIR}/lib64" - -lssl - -lcrypto + ssl + crypto "-L${ZLIB_INSTALL_DIR}/lib" "-L${ZLIB_INSTALL_DIR}/lib64" - -lz + $,zlibstatic,z> -Wl,-Bdynamic ) +if (WIN32) + set(DPP_DEFINITIONS DPP_STATIC) + list(APPEND DPP_LIBRARIES + ws2_32 + gdi32 + crypt32 + ) +endif() From 67b4b73400dc0712a349e8afdce0858ed8b35862 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Mar 2024 16:25:48 +0100 Subject: [PATCH 15/53] CMake: fix CMAKE_SYSTEM_VERSION spelling and add CXX passthrough --- cmake/ArgumentPassthrough.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/ArgumentPassthrough.cmake b/cmake/ArgumentPassthrough.cmake index 3226ae2..b7ba83a 100644 --- a/cmake/ArgumentPassthrough.cmake +++ b/cmake/ArgumentPassthrough.cmake @@ -30,6 +30,9 @@ if (DEFINED CMAKE_C_COMPILER_TARGET) endif() if (DEFINED CMAKE_CXX_COMPILER) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") + list(APPEND CMAKE_PASSTHROUGH_ENV "CXX=${CMAKE_CXX_COMPILER}") +elseif ($ENV{MSYSTEM} STREQUAL "CLANG64") + list(APPEND CMAKE_PASSTHROUGH_ENV "CXX=clang++") endif() if (DEFINED CMAKE_CXX_COMPILER_TARGET) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER_TARGET=${CMAKE_CXX_COMPILER_TARGET}") @@ -49,7 +52,7 @@ endif() if (DEFINED CMAKE_SYSTEM_PROCESSOR AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}") endif() -if (DEFINED CMAKE_SYSTEM_VERSION AND NOT CMAKE_SYTEM_VERSION STREQUAL CMAKE_HOST_SYSTEM_VERSION) +if (DEFINED CMAKE_SYSTEM_VERSION AND NOT CMAKE_SYSTEM_VERSION STREQUAL CMAKE_HOST_SYSTEM_VERSION) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") endif() if (DEFINED CMAKE_TOOLCHAIN_FILE) From d0139afd268456dbbabefc40cdd0c64ee77eb076 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Mar 2024 16:30:27 +0100 Subject: [PATCH 16/53] CMake: fix MSYSTEM check CMake error --- cmake/ArgumentPassthrough.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/ArgumentPassthrough.cmake b/cmake/ArgumentPassthrough.cmake index b7ba83a..a0367d2 100644 --- a/cmake/ArgumentPassthrough.cmake +++ b/cmake/ArgumentPassthrough.cmake @@ -22,7 +22,7 @@ endif() if (DEFINED CMAKE_C_COMPILER) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") list(APPEND CMAKE_PASSTHROUGH_ENV "CC=${CMAKE_C_COMPILER}") -elseif ($ENV{MSYSTEM} STREQUAL "CLANG64") +elseif ("$ENV{MSYSTEM}" STREQUAL "CLANG64") list(APPEND CMAKE_PASSTHROUGH_ENV "CC=clang") endif() if (DEFINED CMAKE_C_COMPILER_TARGET) @@ -31,7 +31,7 @@ endif() if (DEFINED CMAKE_CXX_COMPILER) list(APPEND CMAKE_PASSTHROUGH_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") list(APPEND CMAKE_PASSTHROUGH_ENV "CXX=${CMAKE_CXX_COMPILER}") -elseif ($ENV{MSYSTEM} STREQUAL "CLANG64") +elseif ("$ENV{MSYSTEM}" STREQUAL "CLANG64") list(APPEND CMAKE_PASSTHROUGH_ENV "CXX=clang++") endif() if (DEFINED CMAKE_CXX_COMPILER_TARGET) From c8239e251718fcc0e7dd7fdac9b9b616fe749381 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Mar 2024 16:42:53 +0100 Subject: [PATCH 17/53] CMake: fix zlibstatic on Linux issue --- cmake/DPPAsExternalProject.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index 3c69b59..2664cdc 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -99,7 +99,7 @@ set(DPP_LIBRARIES crypto "-L${ZLIB_INSTALL_DIR}/lib" "-L${ZLIB_INSTALL_DIR}/lib64" - $,zlibstatic,z> + $,zlibstatic,z> -Wl,-Bdynamic ) if (WIN32) From 616ce0055ba93d8d1c7514910decc0b46c34d587 Mon Sep 17 00:00:00 2001 From: Syping Date: Thu, 7 Mar 2024 23:30:33 +0100 Subject: [PATCH 18/53] delete channel from settings when no target is left - converted some pointers to references - simplified some constructors --- src/core/database.cpp | 8 --- src/core/database.h | 4 +- src/core/settings.cpp | 122 ++++++++++++++++++++----------------- src/core/settings.h | 8 ++- src/core/slashcommands.cpp | 119 ++++++++++++++++++++---------------- src/core/translator.cpp | 8 --- src/core/translator.h | 4 +- 7 files changed, 142 insertions(+), 131 deletions(-) diff --git a/src/core/database.cpp b/src/core/database.cpp index f7fb12d..2911138 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -22,14 +22,6 @@ #include "database.h" using namespace bot::database; -database::database() -{ -} - -database::~database() -{ -} - void database::add_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id, const bot::settings::target &target) { #ifndef NDEBUG diff --git a/src/core/database.h b/src/core/database.h index 04e8cf3..e22f92e 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -30,8 +30,8 @@ namespace bot { class database { public: - explicit database(); - virtual ~database(); + explicit database() = default; + virtual ~database() = default; virtual void add_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id, const bot::settings::target &target); virtual void delete_channel(dpp::snowflake guild_id, dpp::snowflake channel_id); virtual void delete_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id, const std::string &target); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index d761ea4..3acdd10 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -24,14 +24,14 @@ #include "../translator/libretranslate/libretranslate.h" using namespace bot::settings; -void process_database_channels(std::shared_ptr database, bot::settings::guild *guild, std::vector *webhookIds) +void process_database_channels(std::shared_ptr database, bot::settings::guild &guild, std::vector &webhookIds) { - const std::vector db_channels = database->get_channels(guild->id); + const std::vector db_channels = database->get_channels(guild.id); for (auto db_channel_id = db_channels.begin(); db_channel_id != db_channels.end(); db_channel_id++) { bool channel_found = false; - for (auto channel = guild->channel.begin(); channel != guild->channel.end(); channel++) { + for (auto channel = guild.channel.begin(); channel != guild.channel.end(); channel++) { if (channel->id == *db_channel_id) { - const bot::settings::channel db_channel = database->get_channel(guild->id, channel->id); + const bot::settings::channel db_channel = database->get_channel(guild.id, channel->id); if (!db_channel.source.empty()) channel->source = db_channel.source; for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) { @@ -39,14 +39,14 @@ void process_database_channels(std::shared_ptr database for (auto target = channel->targets.begin(); target != channel->targets.end(); target++) { if (target->target == db_target->target) { target->webhook = db_target->webhook; - webhookIds->push_back(db_target->webhook.id); + webhookIds.push_back(db_target->webhook.id); target_found = true; break; } } if (!target_found) { channel->targets.push_back(*db_target); - webhookIds->push_back(db_target->webhook.id); + webhookIds.push_back(db_target->webhook.id); } } channel_found = true; @@ -54,23 +54,23 @@ void process_database_channels(std::shared_ptr database } } if (!channel_found) { - const bot::settings::channel db_channel = database->get_channel(guild->id, *db_channel_id); - guild->channel.push_back(db_channel); + const bot::settings::channel db_channel = database->get_channel(guild.id, *db_channel_id); + guild.channel.push_back(db_channel); for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) - webhookIds->push_back(db_target->webhook.id); + webhookIds.push_back(db_target->webhook.id); } } } -void process_database(std::shared_ptr database, std::vector *guilds, std::vector *webhookIds) +void process_database(std::shared_ptr database, std::vector &guilds, std::vector &webhookIds) { std::cout << "[Launch] Loading database..." << std::endl; const std::vector db_guilds = database->get_guilds(); for (auto db_guild_id = db_guilds.begin(); db_guild_id != db_guilds.end(); db_guild_id++) { bool guild_found = false; - for (auto guild = guilds->begin(); guild != guilds->end(); guild++) { + for (auto guild = guilds.begin(); guild != guilds.end(); guild++) { if (guild->id == *db_guild_id) { - process_database_channels(database, &*guild, webhookIds); + process_database_channels(database, *guild, webhookIds); guild_found = true; break; } @@ -78,13 +78,13 @@ void process_database(std::shared_ptr database, std::ve if (!guild_found) { bot::settings::guild guild; guild.id = *db_guild_id; - process_database_channels(database, &guild, webhookIds); - guilds->push_back(std::move(guild)); + process_database_channels(database, guild, webhookIds); + guilds.push_back(std::move(guild)); } } } -void process_guild_settings(const dpp::json &json, std::vector *guilds, std::vector *webhookIds) +void process_guild_settings(const dpp::json &json, std::vector &guilds, std::vector &webhookIds) { for (auto json_guild = json.begin(); json_guild != json.end(); json_guild++) { if (json_guild->is_object()) { @@ -128,7 +128,7 @@ void process_guild_settings(const dpp::json &json, std::vector *guilds, s target target; target.target = *json_channel_target; target.webhook = dpp::webhook(json_channel->at("webhook")); - webhookIds->push_back(target.webhook.id); + webhookIds.push_back(target.webhook.id); channel.targets.push_back(std::move(target)); } else if (json_channel_target->is_object()) { @@ -136,7 +136,7 @@ void process_guild_settings(const dpp::json &json, std::vector *guilds, s target target; target.target = json_target.key(); target.webhook = dpp::webhook(*json_target); - webhookIds->push_back(target.webhook.id); + webhookIds.push_back(target.webhook.id); channel.targets.push_back(std::move(target)); } } @@ -146,7 +146,7 @@ void process_guild_settings(const dpp::json &json, std::vector *guilds, s guild.channel.push_back(std::move(channel)); } } - guilds->push_back(std::move(guild)); + guilds.push_back(std::move(guild)); } } } @@ -162,63 +162,63 @@ void process_preflang_settings(const dpp::json &json, std::vector * } } -void process_user_settings(const dpp::json &json, uint16_t *avatar_size) +void process_user_settings(const dpp::json &json, uint16_t &avatar_size) { auto json_avatar_size = json.find("avatar_size"); if (json_avatar_size != json.end()) { - *avatar_size = *json_avatar_size; - if (*avatar_size < 16) - *avatar_size = 16; - else if (*avatar_size > 4096) - *avatar_size = 4096; + avatar_size = *json_avatar_size; + if (avatar_size < 16) + avatar_size = 16; + else if (avatar_size > 4096) + avatar_size = 4096; } } -void process_url(const std::string &url, translator *translator) +void process_url(const std::string &url, translator &translator) { std::string_view url_v = url; if (url_v.substr(0, 7) == "http://") { - translator->tls = false; - if (!translator->port) - translator->port = 80; + translator.tls = false; + if (!translator.port) + translator.port = 80; url_v = url_v.substr(7); } else if (url_v.substr(0, 8) == "https://") { - translator->tls = true; - if (!translator->port) - translator->port = 443; + translator.tls = true; + if (!translator.port) + translator.port = 443; url_v = url_v.substr(8); } else { - translator->tls = false; - if (!translator->port) - translator->port = 80; + translator.tls = false; + if (!translator.port) + translator.port = 80; } auto slash_pos = url_v.find_first_of('/'); if (slash_pos != std::string_view::npos) { - translator->url = url_v.substr(slash_pos); + translator.url = url_v.substr(slash_pos); url_v = url_v.substr(0, slash_pos); } else { - translator->url = "/"; + translator.url = "/"; url_v = url_v.substr(0, slash_pos); } // We don't have IPv6 support here yet auto colon_pos = url_v.find_last_of(':'); if (colon_pos != std::string_view::npos) { - translator->hostname = url_v.substr(0, colon_pos); + translator.hostname = url_v.substr(0, colon_pos); const int port = std::stoi(std::string(url_v.substr(colon_pos + 1))); if (port > 0 && port < 65536) - translator->port = static_cast(port); + translator.port = static_cast(port); else throw std::invalid_argument("Port is out of range"); } else { - translator->hostname = url_v; + translator.hostname = url_v; } } -bool process_translator_settings(const dpp::json &json, translator *translator) +bool process_translator_settings(const dpp::json &json, translator &translator) { if (!json.is_object()) { std::cerr << "[Error] Value translator needs to be a object" << std::endl; @@ -227,39 +227,39 @@ bool process_translator_settings(const dpp::json &json, translator *translator) auto json_translate_hostname = json.find("hostname"); if (json_translate_hostname != json.end()) - translator->hostname = *json_translate_hostname; + translator.hostname = *json_translate_hostname; else - translator->hostname = {}; + translator.hostname = {}; auto json_translate_tls = json.find("tls"); if (json_translate_tls != json.end()) - translator->tls = *json_translate_tls; + translator.tls = *json_translate_tls; else - translator->tls = false; + translator.tls = false; auto json_translate_port = json.find("port"); if (json_translate_port != json.end()) - translator->port = *json_translate_port; + translator.port = *json_translate_port; else - translator->port = 0; + translator.port = 0; auto json_translate_url = json.find("url"); if (json_translate_url == json.end()) { std::cerr << "[Error] Value url not found in translator object" << std::endl; return false; } - if (translator->hostname.empty()) { + if (translator.hostname.empty()) { process_url(*json_translate_url, translator); } else { - translator->url = *json_translate_url; + translator.url = *json_translate_url; } auto json_translate_apiKey = json.find("apiKey"); if (json_translate_apiKey != json.end()) - translator->apiKey = *json_translate_apiKey; + translator.apiKey = *json_translate_apiKey; else - translator->apiKey.clear(); + translator.apiKey.clear(); return true; } @@ -301,6 +301,16 @@ void settings::add_translatebot_webhook(dpp::snowflake webhook_id) m_webhookIds.push_back(webhook_id); } +void settings::erase_channel(guild *guild, dpp::snowflake channel_id) +{ + for (auto channel = guild->channel.begin(); channel != guild->channel.end(); channel++) { + if (channel->id == channel_id) { + guild->channel.erase(channel); + return; + } + } +} + void settings::erase_translatebot_webhook(dpp::snowflake webhook_id) { const std::lock_guard guard(m_mutex); @@ -315,9 +325,9 @@ uint16_t settings::avatar_size() return m_avatarSize; } -channel* settings::get_channel(guild *guild, dpp::snowflake channel_id) +channel* settings::get_channel(guild &guild, dpp::snowflake channel_id) { - for (auto channel = guild->channel.begin(); channel != guild->channel.end(); channel++) { + for (auto channel = guild.channel.begin(); channel != guild.channel.end(); channel++) { if (channel->id == channel_id) return &*channel; } @@ -484,12 +494,12 @@ bool settings::parse(const std::string &data, bool initialize) std::cerr << "[Error] Value translator not found" << std::endl; return false; } - if (!process_translator_settings(*json_translator, &m_translator)) + if (!process_translator_settings(*json_translator, m_translator)) return false; auto json_guilds = json.find("guilds"); if (json_guilds != json.end() && json_guilds->is_object()) - process_guild_settings(*json_guilds, &m_guilds, &m_webhookIds); + process_guild_settings(*json_guilds, m_guilds, m_webhookIds); auto json_preflangs = json.find("preferred_lang"); if (json_preflangs != json.end() && json_preflangs->is_array()) @@ -497,9 +507,9 @@ bool settings::parse(const std::string &data, bool initialize) auto json_user = json.find("user"); if (json_user != json.end() && json_user->is_object()) - process_user_settings(*json_user, &m_avatarSize); + process_user_settings(*json_user, m_avatarSize); - process_database(m_database, &m_guilds, &m_webhookIds); + process_database(m_database, m_guilds, m_webhookIds); return true; } diff --git a/src/core/settings.h b/src/core/settings.h index d02db2a..48afdfc 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -33,11 +33,12 @@ namespace bot { void add_translatebot_webhook(dpp::snowflake webhook_id); /* erase functions */ + static void erase_channel(guild *guild, dpp::snowflake channel_id); void erase_translatebot_webhook(dpp::snowflake webhook_id); /* get functions */ uint16_t avatar_size(); - static channel* get_channel(guild *guild, dpp::snowflake channel_id); + static channel* get_channel(guild &guild, dpp::snowflake channel_id); channel* get_channel(dpp::snowflake guild_id, dpp::snowflake channel_id); guild* get_guild(dpp::snowflake guild_id); target* get_target(dpp::snowflake guild_id, dpp::snowflake channel_id, const std::string &target); @@ -59,6 +60,11 @@ namespace bot { bool parse(const std::string &data, bool initialize = true); bool parse_file(const std::string &filename, bool initialize = true); + /* prevent copies */ + settings() = default; + settings(const settings&) = delete; + settings& operator=(const settings&) = delete; + private: mutable std::recursive_mutex m_mutex; size_t m_externallyLockedCount = 0; diff --git a/src/core/slashcommands.cpp b/src/core/slashcommands.cpp index 49c55c2..0f78910 100644 --- a/src/core/slashcommands.cpp +++ b/src/core/slashcommands.cpp @@ -40,65 +40,76 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: dpp::command_interaction interaction = event.command.get_command_interaction(); if (interaction.options[0].name == "delete") { const std::lock_guard guard(*settings); - if (bot::settings::channel *channel = settings->get_channel(event.command.guild_id, event.command.channel_id)) { - const std::string target = std::get(event.get_parameter("target")); + if (bot::settings::guild *guild = settings->get_guild(event.command.guild_id)) { + if (bot::settings::channel *channel = settings->get_channel(*guild, event.command.channel_id)) { + const std::string target = std::get(event.get_parameter("target")); - std::shared_ptr database = settings->get_database(); - const bot::settings::channel db_channel = database->get_channel(event.command.guild_id, event.command.channel_id); + auto database = settings->get_database(); + const bot::settings::channel db_channel = database->get_channel(event.command.guild_id, event.command.channel_id); - if (db_channel.targets.empty()) { - event.reply(dpp::message("The current channel has no deleteable targets!").set_flags(dpp::m_ephemeral)); - } - else if (target == "**") { - std::vector targets; - for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) { - targets.push_back(db_target->target); + if (db_channel.targets.empty()) { + event.reply(dpp::message("The current channel has no deleteable targets!").set_flags(dpp::m_ephemeral)); } - for (auto target = channel->targets.begin(); target != channel->targets.end();) { - if (std::find(targets.begin(), targets.end(), target->target) != targets.end()) { - bot->delete_webhook(target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, target->webhook.id, std::placeholders::_1)); - target = channel->targets.erase(target); + else if (target == "**") { + std::vector targets; + for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) { + targets.push_back(db_target->target); } - else { - target++; + for (auto target = channel->targets.begin(); target != channel->targets.end();) { + if (std::find(targets.begin(), targets.end(), target->target) != targets.end()) { + bot->delete_webhook(target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, target->webhook.id, std::placeholders::_1)); + target = channel->targets.erase(target); + } + else { + target++; + } } + + database->delete_channel(event.command.guild_id, event.command.channel_id); + database->sync(); + + if (channel->targets.empty()) + settings->erase_channel(guild, event.command.channel_id); + + event.reply(dpp::message("Deleteable targets have being deleted!").set_flags(dpp::m_ephemeral)); } - - database->delete_channel(event.command.guild_id, event.command.channel_id); - database->sync(); - - event.reply(dpp::message("Deleteable targets have being deleted!").set_flags(dpp::m_ephemeral)); - } - else { - bool target_found = false; - for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) { - if (db_target->target == target) { - target_found = true; - break; - } - } - - if (target_found) { - for (auto _target = channel->targets.begin(); _target != channel->targets.end(); _target++) { - if (_target->target == target) { - bot->delete_webhook(_target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, _target->webhook.id, std::placeholders::_1)); - channel->targets.erase(_target); + else { + bool target_found = false; + for (auto db_target = db_channel.targets.begin(); db_target != db_channel.targets.end(); db_target++) { + if (db_target->target == target) { + target_found = true; break; } } - if (db_channel.targets.size() == 1) - database->delete_channel(event.command.guild_id, event.command.channel_id); - else - database->delete_channel_target(event.command.guild_id, event.command.channel_id, target); - database->sync(); + if (target_found) { + for (auto _target = channel->targets.begin(); _target != channel->targets.end(); _target++) { + if (_target->target == target) { + bot->delete_webhook(_target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, _target->webhook.id, std::placeholders::_1)); + channel->targets.erase(_target); + break; + } + } - event.reply(dpp::message("Target have being deleted!").set_flags(dpp::m_ephemeral)); - } - else { - event.reply(dpp::message("Target language is not being found or deleteable!").set_flags(dpp::m_ephemeral)); + if (db_channel.targets.size() == 1) + database->delete_channel(event.command.guild_id, event.command.channel_id); + else + database->delete_channel_target(event.command.guild_id, event.command.channel_id, target); + database->sync(); + + if (channel->targets.empty()) + settings->erase_channel(guild, event.command.channel_id); + + event.reply(dpp::message("Target have being deleted!").set_flags(dpp::m_ephemeral)); + } + else { + event.reply(dpp::message("Target language is not being found or deleteable!").set_flags(dpp::m_ephemeral)); + } } } + else { + event.reply(dpp::message("The current channel is not being translated!").set_flags(dpp::m_ephemeral)); + } } else { event.reply(dpp::message("The current channel is not being translated!").set_flags(dpp::m_ephemeral)); @@ -123,7 +134,7 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: if (source_valid) { channel->source = source; - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); database->set_channel_source(event.command.guild_id, event.command.channel_id, source); database->sync(); @@ -171,7 +182,7 @@ void bot::slashcommands::process_list_command(dpp::cluster *bot, bot::settings:: // We want give more information to users who can Manage Webhooks dpp::permission user_permissions = event.command.get_resolved_permission(event.command.usr.id); if (user_permissions.has(dpp::p_manage_webhooks)) { - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); const bot::settings::channel db_channel = database->get_channel(event.command.guild_id, event.command.channel_id); for (auto target = channel->targets.begin(); target != channel->targets.end(); target++) { @@ -268,13 +279,13 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti dpp::command_interaction interaction = event.command.get_command_interaction(); if (interaction.options[0].name == "channel") { v_target = event.command.get_resolved_channel( - std::get(event.get_parameter("channel"))); + std::get(event.get_parameter("channel"))); } else if (interaction.options[0].name == "webhook") { v_target = dpp::webhook(std::get(event.get_parameter("webhook"))); } - const std::vector languages = settings->get_translator()->get_languages(); + const auto languages = settings->get_translator()->get_languages(); std::ostringstream language_codes; bool source_valid = false, target_valid = false; @@ -307,7 +318,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti settings->add_channel(s_channel, event.command.guild_id); settings->add_translatebot_webhook(webhook->id); - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); database->set_channel_source(event.command.guild_id, event.command.channel_id, source); database->add_channel_target(event.command.guild_id, event.command.channel_id, s_target); database->sync(); @@ -333,7 +344,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti settings->add_target(s_target, event.command.guild_id, event.command.channel_id); settings->add_translatebot_webhook(webhook->id); - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); database->add_channel_target(event.command.guild_id, event.command.channel_id, s_target); database->sync(); @@ -374,7 +385,7 @@ void bot::slashcommands::process_translate_webhook_add_target(bot::settings::set settings->add_target(s_target, event.command.guild_id, event.command.channel_id); settings->add_translatebot_webhook(webhook.id); - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); database->add_channel_target(event.command.guild_id, event.command.channel_id, s_target); database->sync(); @@ -396,7 +407,7 @@ void bot::slashcommands::process_translate_webhook_new_channel(bot::settings::se settings->add_channel(s_channel, event.command.guild_id); settings->add_translatebot_webhook(webhook.id); - std::shared_ptr database = settings->get_database(); + auto database = settings->get_database(); database->set_channel_source(event.command.guild_id, event.command.channel_id, source); database->add_channel_target(event.command.guild_id, event.command.channel_id, s_target); database->sync(); diff --git a/src/core/translator.cpp b/src/core/translator.cpp index 4d82d16..993e198 100644 --- a/src/core/translator.cpp +++ b/src/core/translator.cpp @@ -22,14 +22,6 @@ #include "translator.h" using namespace bot::translator; -translator::translator() -{ -} - -translator::~translator() -{ -} - const std::vector translator::get_languages() { #ifndef NDEBUG diff --git a/src/core/translator.h b/src/core/translator.h index d42e21b..b4f14c0 100644 --- a/src/core/translator.h +++ b/src/core/translator.h @@ -31,8 +31,8 @@ namespace bot { class translator { public: - explicit translator(); - virtual ~translator(); + explicit translator() = default; + virtual ~translator() = default; virtual const std::vector get_languages(); virtual const std::string translate(const std::string &text, const std::string &source, const std::string &target); }; From 0dbf987ff26be181fa567dd674585353299c0a95 Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 8 Mar 2024 01:25:50 +0100 Subject: [PATCH 19/53] add ci and simplify executable description --- .github/workflows/windows.yml | 36 +++++++++++++++++++++++++ src/resources/win32/dtranslatebot.rc.in | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..53d363f --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,36 @@ +name: Windows +on: push +jobs: + Release: + runs-on: windows-latest + env: + BUILD_TYPE: Release + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: clang64 + update: true + install: >- + git + make + mingw-w64-clang-x86_64-clang + mingw-w64-clang-x86_64-cmake + mingw-w64-clang-x86_64-ninja + perl + - name: Cloning + uses: actions/checkout@v4 + - name: Configure CMake + run: cmake -B ./build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXE_LINKER_FLAGS="-static -lc++" -DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE -GNinja + - name: Build + run: cmake --build ./build --config ${{env.BUILD_TYPE}} + - name: Install + run: cmake --install ./build --config ${{env.BUILD_TYPE}} --prefix ./install --strip + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: Windows + path: | + ./install/bin/ diff --git a/src/resources/win32/dtranslatebot.rc.in b/src/resources/win32/dtranslatebot.rc.in index a3e475d..d1dc7ce 100644 --- a/src/resources/win32/dtranslatebot.rc.in +++ b/src/resources/win32/dtranslatebot.rc.in @@ -17,7 +17,7 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Syping" - VALUE "FileDescription", "Open Source Discord Translation Bot" + VALUE "FileDescription", "Discord Translation Bot" VALUE "FileVersion", "@dtranslatebot_VERSION@" VALUE "InternalName", "dtranslatebot" VALUE "LegalCopyright", "Copyright © 2023-2024 Syping" From 92d9aba8d05f74b1521df2cca752f9728d97c17a Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 8 Mar 2024 16:56:38 +0100 Subject: [PATCH 20/53] erase empty guilds from memory --- src/core/settings.cpp | 17 ++++++++++++++--- src/core/settings.h | 3 ++- src/core/slashcommands.cpp | 16 ++++++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 3acdd10..7e9528e 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -301,11 +301,22 @@ void settings::add_translatebot_webhook(dpp::snowflake webhook_id) m_webhookIds.push_back(webhook_id); } -void settings::erase_channel(guild *guild, dpp::snowflake channel_id) +void settings::erase_channel(guild &guild, dpp::snowflake channel_id) { - for (auto channel = guild->channel.begin(); channel != guild->channel.end(); channel++) { + for (auto channel = guild.channel.begin(); channel != guild.channel.end(); channel++) { if (channel->id == channel_id) { - guild->channel.erase(channel); + guild.channel.erase(channel); + return; + } + } +} + +void settings::erase_guild(dpp::snowflake guild_id) +{ + const std::lock_guard guard(m_mutex); + for (auto guild = m_guilds.begin(); guild != m_guilds.end(); guild++) { + if (guild->id == guild_id) { + m_guilds.erase(guild); return; } } diff --git a/src/core/settings.h b/src/core/settings.h index 48afdfc..fe6b219 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -33,7 +33,8 @@ namespace bot { void add_translatebot_webhook(dpp::snowflake webhook_id); /* erase functions */ - static void erase_channel(guild *guild, dpp::snowflake channel_id); + static void erase_channel(guild &guild, dpp::snowflake channel_id); + void erase_guild(dpp::snowflake guild_id); void erase_translatebot_webhook(dpp::snowflake webhook_id); /* get functions */ diff --git a/src/core/slashcommands.cpp b/src/core/slashcommands.cpp index 0f78910..37ca996 100644 --- a/src/core/slashcommands.cpp +++ b/src/core/slashcommands.cpp @@ -68,8 +68,12 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: database->delete_channel(event.command.guild_id, event.command.channel_id); database->sync(); - if (channel->targets.empty()) - settings->erase_channel(guild, event.command.channel_id); + if (channel->targets.empty()) { + settings->erase_channel(*guild, event.command.channel_id); + if (guild->channel.empty()) { + settings->erase_guild(event.command.guild_id); + } + } event.reply(dpp::message("Deleteable targets have being deleted!").set_flags(dpp::m_ephemeral)); } @@ -97,8 +101,12 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: database->delete_channel_target(event.command.guild_id, event.command.channel_id, target); database->sync(); - if (channel->targets.empty()) - settings->erase_channel(guild, event.command.channel_id); + if (channel->targets.empty()) { + settings->erase_channel(*guild, event.command.channel_id); + if (guild->channel.empty()) { + settings->erase_guild(event.command.guild_id); + } + } event.reply(dpp::message("Target have being deleted!").set_flags(dpp::m_ephemeral)); } From 0dfb2cebe9e6c1ac5e7c29c109d72dd3a3180dbe Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 11 Mar 2024 03:24:01 +0100 Subject: [PATCH 21/53] CI update and DPPAsExternalProject improvements --- .github/workflows/windows.yml | 16 +++++++++++----- cmake/DPPAsExternalProject.cmake | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 53d363f..2c5f6d4 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -23,14 +23,20 @@ jobs: - name: Cloning uses: actions/checkout@v4 - name: Configure CMake - run: cmake -B ./build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXE_LINKER_FLAGS="-static -lc++" -DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE -GNinja - - name: Build - run: cmake --build ./build --config ${{env.BUILD_TYPE}} + run: cmake -B dtranslatebot-build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXE_LINKER_FLAGS="-static -lc++" -DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE -GNinja + - name: Download and build OpenSSL + run: cmake --build dtranslatebot-build --config ${{env.BUILD_TYPE}} --target OpenSSL + - name: Download and build zlib + run: cmake --build dtranslatebot-build --config ${{env.BUILD_TYPE}} --target ZLIB + - name: Download and build DPP + run: cmake --build dtranslatebot-build --config ${{env.BUILD_TYPE}} --target DPP + - name: Build dtranslatebot + run: cmake --build dtranslatebot-build --config ${{env.BUILD_TYPE}} - name: Install - run: cmake --install ./build --config ${{env.BUILD_TYPE}} --prefix ./install --strip + run: cmake --install dtranslatebot-build --config ${{env.BUILD_TYPE}} --prefix dtranslatebot-install --strip - name: Upload uses: actions/upload-artifact@v4 with: name: Windows path: | - ./install/bin/ + dtranslatebot-install/bin/dtranslatebot.exe diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPAsExternalProject.cmake index 2664cdc..921de46 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPAsExternalProject.cmake @@ -32,7 +32,7 @@ if (DEFINED NPROC_EXECUTABLE) OUTPUT_VARIABLE NPROC ) string(STRIP "${NPROC}" NPROC) - set(JOBS_ARGUMENT "-j${NPROC}" CACHE INTERNAL "make jobs argument") + set(MAKE_JOBS_ARG "-j${NPROC}") endif() include(ExternalProject) @@ -41,13 +41,15 @@ ExternalProject_Add(ZLIB URL_HASH SHA256=38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32 CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF - "${CMAKE_PASSTHROUGH_ARGS}" + ${CMAKE_PASSTHROUGH_ARGS} "-DCMAKE_INSTALL_PREFIX=" -DZLIB_BUILD_EXAMPLES=OFF + ${ZLIB_CONFIGURE_ARGS} ) ExternalProject_Get_Property(ZLIB INSTALL_DIR) set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") +set(OPENSSL_PLATFORM_ARG $<$:mingw64>) ExternalProject_Add(OpenSSL URL https://www.openssl.org/source/openssl-3.0.13.tar.gz URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 @@ -63,8 +65,10 @@ ExternalProject_Add(OpenSSL no-engine no-shared no-zlib - BUILD_COMMAND "${MAKE_EXECUTABLE}" "${JOBS_ARGUMENT}" - INSTALL_COMMAND "${MAKE_EXECUTABLE}" "${JOBS_ARGUMENT}" install_sw + ${OPENSSL_PLATFORM_ARG} + ${OPENSSL_CONFIGURE_ARGS} + BUILD_COMMAND "${MAKE_EXECUTABLE}" ${MAKE_JOBS_ARG} build_libs + INSTALL_COMMAND "${MAKE_EXECUTABLE}" ${MAKE_JOBS_ARG} install_dev ) ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") @@ -75,15 +79,15 @@ ExternalProject_Add(DPP CMAKE_ARGS -DBUILD_SHARED_LIBS=OFF -DBUILD_VOICE_SUPPORT=OFF - "${CMAKE_PASSTHROUGH_ARGS}" + ${CMAKE_PASSTHROUGH_ARGS} "-DCMAKE_INSTALL_PREFIX=" -DDPP_BUILD_TEST=OFF -DDPP_NO_VCPKG=ON -DRUN_LDCONFIG=OFF "-DOpenSSL_ROOT=${OpenSSL_INSTALL_DIR}" "-DZLIB_ROOT=${ZLIB_INSTALL_DIR}" - DEPENDS OpenSSL - DEPENDS ZLIB + ${DPP_CONFIGURE_ARGS} + DEPENDS OpenSSL ZLIB ) ExternalProject_Get_Property(DPP INSTALL_DIR) set(DPP_INSTALL_DIR "${INSTALL_DIR}") @@ -106,7 +110,5 @@ if (WIN32) set(DPP_DEFINITIONS DPP_STATIC) list(APPEND DPP_LIBRARIES ws2_32 - gdi32 - crypt32 ) endif() From de121beaac542ca9b2f882be9f0771ad9d41af08 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 11 Mar 2024 03:45:48 +0100 Subject: [PATCH 22/53] rename DPPAsExternalProject to DPPStaticBundle - remove potential DPP AVX dependency --- .github/workflows/windows.yml | 2 +- CMakeLists.txt | 6 +++--- README.md | 2 +- cmake/{DPPAsExternalProject.cmake => DPPStaticBundle.cmake} | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) rename cmake/{DPPAsExternalProject.cmake => DPPStaticBundle.cmake} (99%) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 2c5f6d4..6d876a1 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -23,7 +23,7 @@ jobs: - name: Cloning uses: actions/checkout@v4 - name: Configure CMake - run: cmake -B dtranslatebot-build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXE_LINKER_FLAGS="-static -lc++" -DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE -GNinja + run: cmake -B dtranslatebot-build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_EXE_LINKER_FLAGS="-static -lc++" -DWITH_DPP_STATIC_BUNDLE=TRUE -GNinja - name: Download and build OpenSSL run: cmake --build dtranslatebot-build --config ${{env.BUILD_TYPE}} --target OpenSSL - name: Download and build zlib diff --git a/CMakeLists.txt b/CMakeLists.txt index e09803d..66ca3cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,9 +64,9 @@ if (WITH_BOOST) endif() # D++ Discord API Library for Bots -option(WITH_DPP_AS_EXTERNAL_PROJECT "Build with DPP as External Project" OFF) -if (WITH_DPP_AS_EXTERNAL_PROJECT) - include(DPPAsExternalProject) +option(WITH_DPP_STATIC_BUNDLE "Build with DPP Static Bundle" OFF) +if (WITH_DPP_STATIC_BUNDLE) + include(DPPStaticBundle) else() find_package(DPP REQUIRED) endif() diff --git a/README.md b/README.md index 1c79c3a..199f5f8 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,5 @@ sudo cmake --install dtranslatebot-build ##### Optional CMake flags `-DWITH_BOOST=TRUE` -`-DWITH_DPP_AS_EXTERNAL_PROJECT=TRUE` +`-DWITH_DPP_STATIC_BUNDLE=TRUE` `-DWITH_SYSTEMD=TRUE` diff --git a/cmake/DPPAsExternalProject.cmake b/cmake/DPPStaticBundle.cmake similarity index 99% rename from cmake/DPPAsExternalProject.cmake rename to cmake/DPPStaticBundle.cmake index 921de46..23304eb 100644 --- a/cmake/DPPAsExternalProject.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -77,6 +77,7 @@ ExternalProject_Add(DPP URL https://github.com/Syping/DPP/archive/dcd00001dfa145a03f80a0ad5317bc3e63252ead.tar.gz URL_HASH SHA256=42ff04b13a384591e819c100c4f40e12e31c8076769c168631eef85a8eeb0be3 CMAKE_ARGS + -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF -DBUILD_VOICE_SUPPORT=OFF ${CMAKE_PASSTHROUGH_ARGS} From 94429ca718d6490adc4ff299372c52920d69584b Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 11 Mar 2024 04:10:18 +0100 Subject: [PATCH 23/53] code style changes and remove some constructors --- src/core/database.h | 2 ++ src/core/message_queue.cpp | 2 +- src/core/slashcommands.cpp | 31 +++++++++++++++-------------- src/core/slashcommands.h | 24 +++++++++++++---------- src/core/submit_queue.cpp | 2 +- src/core/translator.h | 2 ++ src/core/webhook_push.h | 1 + src/database/file/file.cpp | 40 +++++++++++++++++++------------------- src/database/file/file.h | 6 +++--- 9 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/core/database.h b/src/core/database.h index e22f92e..2589f46 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -31,6 +31,8 @@ namespace bot { class database { public: explicit database() = default; + database(const database&) = delete; + database& operator=(const database&) = delete; virtual ~database() = default; virtual void add_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id, const bot::settings::target &target); virtual void delete_channel(dpp::snowflake guild_id, dpp::snowflake channel_id); diff --git a/src/core/message_queue.cpp b/src/core/message_queue.cpp index fffb71a..a4f1085 100644 --- a/src/core/message_queue.cpp +++ b/src/core/message_queue.cpp @@ -19,7 +19,7 @@ #include #include "message_queue.h" #include "settings.h" -using namespace bot; +using bot::message_queue; using namespace std::chrono_literals; void message_queue::add(const message &message) diff --git a/src/core/slashcommands.cpp b/src/core/slashcommands.cpp index 37ca996..b1bbc21 100644 --- a/src/core/slashcommands.cpp +++ b/src/core/slashcommands.cpp @@ -18,19 +18,20 @@ #include #include "slashcommands.h" +using bot::slashcommands; using namespace std::string_literals; -void bot::slashcommands::process_command_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) +void slashcommands::process_command_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) { if (event.command.get_command_name() == "edit") - bot::slashcommands::process_edit_command(bot, settings, event); + slashcommands::process_edit_command(bot, settings, event); else if (event.command.get_command_name() == "list") - bot::slashcommands::process_list_command(bot, settings, event); + slashcommands::process_list_command(bot, settings, event); else if (event.command.get_command_name() == "translate" || event.command.get_command_name() == "translate_pref") - bot::slashcommands::process_translate_command(bot, settings, event); + slashcommands::process_translate_command(bot, settings, event); } -void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) +void slashcommands::process_edit_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) { try { dpp::permission user_permissions = event.command.get_resolved_permission(event.command.usr.id); @@ -57,7 +58,7 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: } for (auto target = channel->targets.begin(); target != channel->targets.end();) { if (std::find(targets.begin(), targets.end(), target->target) != targets.end()) { - bot->delete_webhook(target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, target->webhook.id, std::placeholders::_1)); + bot->delete_webhook(target->webhook.id, std::bind(&slashcommands::process_deleted_webhook, settings, target->webhook.id, std::placeholders::_1)); target = channel->targets.erase(target); } else { @@ -89,7 +90,7 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: if (target_found) { for (auto _target = channel->targets.begin(); _target != channel->targets.end(); _target++) { if (_target->target == target) { - bot->delete_webhook(_target->webhook.id, std::bind(&bot::slashcommands::process_deleted_webhook, settings, _target->webhook.id, std::placeholders::_1)); + bot->delete_webhook(_target->webhook.id, std::bind(&slashcommands::process_deleted_webhook, settings, _target->webhook.id, std::placeholders::_1)); channel->targets.erase(_target); break; } @@ -166,7 +167,7 @@ void bot::slashcommands::process_edit_command(dpp::cluster *bot, bot::settings:: } } -void bot::slashcommands::process_deleted_webhook(bot::settings::settings *settings, dpp::snowflake webhook_id, const dpp::confirmation_callback_t &callback) +void slashcommands::process_deleted_webhook(bot::settings::settings *settings, dpp::snowflake webhook_id, const dpp::confirmation_callback_t &callback) { if (callback.is_error()) { std::cerr << "[Error] Failed to delete Webhook " << webhook_id << std::endl; @@ -175,7 +176,7 @@ void bot::slashcommands::process_deleted_webhook(bot::settings::settings *settin settings->erase_translatebot_webhook(webhook_id); } -void bot::slashcommands::process_list_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) +void slashcommands::process_list_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) { try { dpp::command_interaction interaction = event.command.get_command_interaction(); @@ -273,7 +274,7 @@ void bot::slashcommands::process_list_command(dpp::cluster *bot, bot::settings:: } } -void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) +void slashcommands::process_translate_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event) { try { dpp::permission user_permissions = event.command.get_resolved_permission(event.command.usr.id); @@ -317,7 +318,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti webhook.guild_id = channel->guild_id; webhook.name = "Translate Bot Webhook <" + std::to_string(event.command.channel_id) + ":" + source + ":" + target + ">"; - bot->create_webhook(webhook, std::bind(&bot::slashcommands::process_translate_webhook_new_channel, settings, event, source, target, std::placeholders::_1)); + bot->create_webhook(webhook, std::bind(&slashcommands::process_translate_webhook_new_channel, settings, event, source, target, std::placeholders::_1)); } else if (dpp::webhook *webhook = std::get_if(&v_target)) { const bot::settings::target s_target = { target, *webhook }; @@ -344,7 +345,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti webhook.guild_id = channel->guild_id; webhook.name = "Translate Bot Webhook <" + std::to_string(event.command.channel_id) + ":" + source + ":" + target + ">"; - bot->create_webhook(webhook, std::bind(&bot::slashcommands::process_translate_webhook_add_target, settings, event, target, std::placeholders::_1)); + bot->create_webhook(webhook, std::bind(&slashcommands::process_translate_webhook_add_target, settings, event, target, std::placeholders::_1)); } else if (dpp::webhook *webhook = std::get_if(&v_target)) { const bot::settings::target s_target = { target, *webhook }; @@ -379,7 +380,7 @@ void bot::slashcommands::process_translate_command(dpp::cluster *bot, bot::setti } } -void bot::slashcommands::process_translate_webhook_add_target(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &target, const dpp::confirmation_callback_t &callback) +void slashcommands::process_translate_webhook_add_target(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &target, const dpp::confirmation_callback_t &callback) { if (callback.is_error()) { event.reply(dpp::message("Failed to generate webhook!").set_flags(dpp::m_ephemeral)); @@ -400,7 +401,7 @@ void bot::slashcommands::process_translate_webhook_add_target(bot::settings::set event.reply(dpp::message("Channel will be now translated!").set_flags(dpp::m_ephemeral)); } -void bot::slashcommands::process_translate_webhook_new_channel(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &source, const std::string &target, const dpp::confirmation_callback_t &callback) +void slashcommands::process_translate_webhook_new_channel(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &source, const std::string &target, const dpp::confirmation_callback_t &callback) { if (callback.is_error()) { event.reply(dpp::message("Failed to generate webhook!").set_flags(dpp::m_ephemeral)); @@ -423,7 +424,7 @@ void bot::slashcommands::process_translate_webhook_new_channel(bot::settings::se event.reply(dpp::message("Channel will be now translated!").set_flags(dpp::m_ephemeral)); } -void bot::slashcommands::register_commands(dpp::cluster *bot, bot::settings::settings *settings) +void slashcommands::register_commands(dpp::cluster *bot, bot::settings::settings *settings) { settings->lock(); const std::vector languages = settings->get_translator()->get_languages(); diff --git a/src/core/slashcommands.h b/src/core/slashcommands.h index abcb0be..a31d37f 100644 --- a/src/core/slashcommands.h +++ b/src/core/slashcommands.h @@ -23,16 +23,20 @@ #include "settings.h" namespace bot { - namespace slashcommands { - extern void process_command_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); - extern void process_edit_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); - extern void process_deleted_webhook(bot::settings::settings *settings, dpp::snowflake webhook_id, const dpp::confirmation_callback_t &callback); - extern void process_list_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); - extern void process_translate_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); - extern void process_translate_webhook_add_target(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &target, const dpp::confirmation_callback_t &callback); - extern void process_translate_webhook_new_channel(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &source, const std::string &target, const dpp::confirmation_callback_t &callback); - extern void register_commands(dpp::cluster *bot, bot::settings::settings *settings); - } + class slashcommands { + public: + slashcommands() = delete; + static void process_command_event(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); + static void register_commands(dpp::cluster *bot, bot::settings::settings *settings); + + private: + static void process_edit_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); + static void process_deleted_webhook(bot::settings::settings *settings, dpp::snowflake webhook_id, const dpp::confirmation_callback_t &callback); + static void process_list_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); + static void process_translate_command(dpp::cluster *bot, bot::settings::settings *settings, const dpp::slashcommand_t &event); + static void process_translate_webhook_add_target(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &target, const dpp::confirmation_callback_t &callback); + static void process_translate_webhook_new_channel(bot::settings::settings *settings, const dpp::slashcommand_t &event, const std::string &source, const std::string &target, const dpp::confirmation_callback_t &callback); + }; } #endif // SLASHCOMMANDS_H diff --git a/src/core/submit_queue.cpp b/src/core/submit_queue.cpp index e752fab..12ce874 100644 --- a/src/core/submit_queue.cpp +++ b/src/core/submit_queue.cpp @@ -19,7 +19,7 @@ #include #include "submit_queue.h" #include "webhook_push.h" -using namespace bot; +using bot::submit_queue; using namespace std::chrono_literals; void submit_queue::add(const translated_message &message) diff --git a/src/core/translator.h b/src/core/translator.h index b4f14c0..c230abd 100644 --- a/src/core/translator.h +++ b/src/core/translator.h @@ -33,6 +33,8 @@ namespace bot { public: explicit translator() = default; virtual ~translator() = default; + translator(const translator&) = delete; + translator& operator=(const translator&) = delete; virtual const std::vector get_languages(); virtual const std::string translate(const std::string &text, const std::string &source, const std::string &target); }; diff --git a/src/core/webhook_push.h b/src/core/webhook_push.h index 643b20d..d4b03f9 100644 --- a/src/core/webhook_push.h +++ b/src/core/webhook_push.h @@ -26,6 +26,7 @@ namespace bot { class webhook_push { public: + webhook_push() = delete; static void run(const bot::translated_message &message, dpp::cluster *bot); private: diff --git a/src/database/file/file.cpp b/src/database/file/file.cpp index 31c4cfb..e7c6a6d 100644 --- a/src/database/file/file.cpp +++ b/src/database/file/file.cpp @@ -98,7 +98,7 @@ void file::add_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); channel.targets.push_back(target); cache_add_channel(guild_id, channel_id); guild->channel.push_back(std::move(channel)); @@ -107,7 +107,7 @@ void file::add_channel_target(dpp::snowflake guild_id, dpp::snowflake channel_id } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); channel.targets.push_back(target); cache_add_channel(guild_id, channel_id); m_dataCache.push_back({ guild_id, { std::move(channel) } }); @@ -141,7 +141,7 @@ void file::delete_channel(dpp::snowflake guild_id, dpp::snowflake channel_id) } std::vector channels; - cache_guild(guild_id, &channels); + cache_guild(guild_id, channels); for (auto channel = channels.begin(); channel != channels.end(); channel++) { if (*channel == channel_id) { channels.erase(channel); @@ -175,7 +175,7 @@ void file::delete_channel_target(dpp::snowflake guild_id, dpp::snowflake channel } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); for (auto _target = channel.targets.begin(); _target != channel.targets.end(); _target++) { if (_target->target == target) { channel.targets.erase(_target); @@ -188,7 +188,7 @@ void file::delete_channel_target(dpp::snowflake guild_id, dpp::snowflake channel } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); for (auto _target = channel.targets.begin(); _target != channel.targets.end(); _target++) { if (_target->target == target) { channel.targets.erase(_target); @@ -266,7 +266,7 @@ bot::settings::channel file::get_channel(dpp::snowflake guild_id, dpp::snowflake } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); return channel; } @@ -281,7 +281,7 @@ std::vector file::get_channels(dpp::snowflake guild_id) } std::vector channels; - cache_guild(guild_id, &channels); + cache_guild(guild_id, channels); return channels; } @@ -330,7 +330,7 @@ std::vector file::get_guilds() { const std::lock_guard guard(m_mutex); std::vector guilds; - list_guilds(&guilds); + list_guilds(guilds); return guilds; } @@ -348,7 +348,7 @@ void file::set_channel_source(dpp::snowflake guild_id, dpp::snowflake channel_id } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); channel.source = source; cache_add_channel(guild_id, channel_id); guild->channel.push_back(std::move(channel)); @@ -357,7 +357,7 @@ void file::set_channel_source(dpp::snowflake guild_id, dpp::snowflake channel_id } bot::settings::channel channel; - cache_get_channel(channel_id, &channel); + cache_get_channel(channel_id, channel); channel.source = source; cache_add_channel(guild_id, channel_id); m_dataCache.push_back({ guild_id, { std::move(channel) } }); @@ -390,16 +390,16 @@ void file::cache_add_channel(dpp::snowflake guild_id, dpp::snowflake channel_id) } std::vector channels; - cache_guild(guild_id, &channels); + cache_guild(guild_id, channels); if (std::find(channels.begin(), channels.end(), channel_id) == channels.end()) channels.push_back(channel_id); m_channelCache.push_back({ guild_id, std::move(channels) }); } -void file::cache_get_channel(dpp::snowflake channel_id, bot::settings::channel *channel) +void file::cache_get_channel(dpp::snowflake channel_id, settings::channel &channel) { - channel->id = channel_id; + channel.id = channel_id; const std::filesystem::path channel_file = m_storagePath / "channel" / (std::to_string(channel_id) + ".json"); @@ -418,7 +418,7 @@ void file::cache_get_channel(dpp::snowflake channel_id, bot::settings::channel * if (json.is_object()) { auto json_channel_source = json.find("source"); if (json_channel_source != json.end()) - channel->source = *json_channel_source; + channel.source = *json_channel_source; auto json_channel_target = json.find("target"); if (json_channel_target != json.end()) { @@ -433,7 +433,7 @@ void file::cache_get_channel(dpp::snowflake channel_id, bot::settings::channel * else if (json_target->is_string()) { target.webhook = dpp::webhook(*json_target); } - channel->targets.push_back(std::move(target)); + channel.targets.push_back(std::move(target)); } } } @@ -444,7 +444,7 @@ void file::cache_get_channel(dpp::snowflake channel_id, bot::settings::channel * } } -void file::cache_guild(dpp::snowflake guild_id, std::vector *channels) +void file::cache_guild(dpp::snowflake guild_id, std::vector &channels) { const std::filesystem::path guild_file = m_storagePath / "guild" / (std::to_string(guild_id) + ".json"); @@ -463,9 +463,9 @@ void file::cache_guild(dpp::snowflake guild_id, std::vector *cha if (json.is_array()) { for (auto channel = json.begin(); channel != json.end(); channel++) { if (channel->is_number()) - channels->push_back(*channel); + channels.push_back(*channel); else if (channel->is_string()) - channels->push_back(std::stoull(std::string(*channel))); + channels.push_back(std::stoull(std::string(*channel))); } } } @@ -474,7 +474,7 @@ void file::cache_guild(dpp::snowflake guild_id, std::vector *cha } } -void file::list_guilds(std::vector *guilds) +void file::list_guilds(std::vector &guilds) { const std::filesystem::path guild_dir = m_storagePath / "guild"; @@ -488,7 +488,7 @@ void file::list_guilds(std::vector *guilds) if (std::all_of(guild_filename.begin(), guild_filename.end(), ::isdigit)) { try { dpp::snowflake guild_id = std::stoull(guild_filename); - guilds->push_back(guild_id); + guilds.push_back(guild_id); } catch (const std::exception &exception) { std::cerr << "[Exception] " << exception.what() << std::endl; diff --git a/src/database/file/file.h b/src/database/file/file.h index c743011..f34bd4d 100644 --- a/src/database/file/file.h +++ b/src/database/file/file.h @@ -53,9 +53,9 @@ namespace bot { private: void cache_add_channel(dpp::snowflake guild_id, dpp::snowflake channel_id); - void cache_get_channel(dpp::snowflake channel_id, bot::settings::channel *channel); - void cache_guild(dpp::snowflake guild_id, std::vector *channels); - void list_guilds(std::vector *guilds); + void cache_get_channel(dpp::snowflake channel_id, bot::settings::channel &channel); + void cache_guild(dpp::snowflake guild_id, std::vector &channels); + void list_guilds(std::vector &guilds); void sync_cache(); #if defined(__unix__) int fd; From fb709b891921d8d1416c284eb0f53be5c03dd83b Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 11 Mar 2024 05:21:01 +0100 Subject: [PATCH 24/53] add stub translator for testing purposes --- CMakeLists.txt | 2 + src/core/main.cpp | 2 +- src/core/settings.cpp | 91 ++++++++++++------- src/core/settings_types.h | 5 + .../libretranslate/libretranslate.h | 1 - src/translator/stub/stub.cpp | 39 ++++++++ src/translator/stub/stub.h | 36 ++++++++ 7 files changed, 142 insertions(+), 34 deletions(-) create mode 100644 src/translator/stub/stub.cpp create mode 100644 src/translator/stub/stub.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 66ca3cc..5002e99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(DTRANSLATEBOT_HEADERS src/core/webhook_push.h src/database/file/file.h src/translator/libretranslate/libretranslate.h + src/translator/stub/stub.h ) set(DTRANSLATEBOT_SOURCES src/core/database.cpp @@ -46,6 +47,7 @@ set(DTRANSLATEBOT_SOURCES src/core/webhook_push.cpp src/database/file/file.cpp src/translator/libretranslate/libretranslate.cpp + src/translator/stub/stub.cpp ) # dtranslatebot Module Path diff --git a/src/core/main.cpp b/src/core/main.cpp index d86e55d..58b0885 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -55,7 +55,7 @@ int main(int argc, char* argv[]) { bot.on_message_create(std::bind(&bot::message_queue::process_message_event, &message_queue, &bot, &settings, std::placeholders::_1)); bot.on_slashcommand(std::bind(&bot::slashcommands::process_command_event, &bot, &settings, std::placeholders::_1)); - bot.on_ready([&bot, &settings](const dpp::ready_t &event) { + bot.on_ready([&bot, &settings]([[maybe_unused]] const dpp::ready_t &event) { if (dpp::run_once()) { bot::slashcommands::register_commands(&bot, &settings); } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 7e9528e..46a9af5 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -22,6 +22,7 @@ #include "settings.h" #include "../database/file/file.h" #include "../translator/libretranslate/libretranslate.h" +#include "../translator/stub/stub.h" using namespace bot::settings; void process_database_channels(std::shared_ptr database, bot::settings::guild &guild, std::vector &webhookIds) @@ -225,42 +226,60 @@ bool process_translator_settings(const dpp::json &json, translator &translator) return false; } - auto json_translate_hostname = json.find("hostname"); - if (json_translate_hostname != json.end()) - translator.hostname = *json_translate_hostname; - else - translator.hostname = {}; - - auto json_translate_tls = json.find("tls"); - if (json_translate_tls != json.end()) - translator.tls = *json_translate_tls; - else - translator.tls = false; - - auto json_translate_port = json.find("port"); - if (json_translate_port != json.end()) - translator.port = *json_translate_port; - else - translator.port = 0; - - auto json_translate_url = json.find("url"); - if (json_translate_url == json.end()) { - std::cerr << "[Error] Value url not found in translator object" << std::endl; - return false; + std::string translator_type = "libretranslate"; + auto json_translator_type = json.find("type"); + if (json_translator_type != json.end()) { + translator_type = *json_translator_type; + std::transform(translator_type.begin(), translator_type.end(), translator_type.begin(), ::tolower); } - if (translator.hostname.empty()) { - process_url(*json_translate_url, translator); + + if (translator_type == "libretranslate") { + translator.type = TRANSLATOR_LIBRETRANSLATE; + + auto json_lt_hostname = json.find("hostname"); + if (json_lt_hostname != json.end()) + translator.hostname = *json_lt_hostname; + else + translator.hostname = {}; + + auto json_lt_tls = json.find("tls"); + if (json_lt_tls != json.end()) + translator.tls = *json_lt_tls; + else + translator.tls = false; + + auto json_lt_port = json.find("port"); + if (json_lt_port != json.end()) + translator.port = *json_lt_port; + else + translator.port = 0; + + auto json_lt_url = json.find("url"); + if (json_lt_url == json.end()) { + std::cerr << "[Error] Value url not found in translator object" << std::endl; + return false; + } + if (translator.hostname.empty()) { + process_url(*json_lt_url, translator); + } + else { + translator.url = *json_lt_url; + } + + auto json_lt_apiKey = json.find("apiKey"); + if (json_lt_apiKey != json.end()) + translator.apiKey = *json_lt_apiKey; + else + translator.apiKey.clear(); + } + else if (translator_type == "stub") { + translator.type = TRANSLATOR_STUB; } else { - translator.url = *json_translate_url; + std::cerr << "[Error] Translator " << translator.type << " is unknown" << std::endl; + return false; } - auto json_translate_apiKey = json.find("apiKey"); - if (json_translate_apiKey != json.end()) - translator.apiKey = *json_translate_apiKey; - else - translator.apiKey.clear(); - return true; } @@ -438,7 +457,15 @@ std::shared_ptr settings::get_database() const std::unique_ptr settings::get_translator() const { const std::lock_guard guard(m_mutex); - return std::make_unique(m_translator.hostname, m_translator.port, m_translator.url, m_translator.tls, m_translator.apiKey); + + switch (m_translator.type) { + case TRANSLATOR_LIBRETRANSLATE: + return std::make_unique(m_translator.hostname, m_translator.port, m_translator.url, m_translator.tls, m_translator.apiKey); + case TRANSLATOR_STUB: + return std::make_unique(); + default: + return std::make_unique(); + } } const std::string settings::token() const diff --git a/src/core/settings_types.h b/src/core/settings_types.h index e1c5b3c..923be1c 100644 --- a/src/core/settings_types.h +++ b/src/core/settings_types.h @@ -40,7 +40,12 @@ namespace bot { dpp::snowflake id; std::vector channel; }; + enum translator_type { + TRANSLATOR_LIBRETRANSLATE, + TRANSLATOR_STUB + }; struct translator { + translator_type type; std::string hostname; uint16_t port; std::string url; diff --git a/src/translator/libretranslate/libretranslate.h b/src/translator/libretranslate/libretranslate.h index 0bb8afa..235a253 100644 --- a/src/translator/libretranslate/libretranslate.h +++ b/src/translator/libretranslate/libretranslate.h @@ -20,7 +20,6 @@ #define TRANSLATOR_LIBRETRANSLATE_H #include -#include #include "../../core/translator.h" namespace bot { diff --git a/src/translator/stub/stub.cpp b/src/translator/stub/stub.cpp new file mode 100644 index 0000000..7e7a083 --- /dev/null +++ b/src/translator/stub/stub.cpp @@ -0,0 +1,39 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#include "stub.h" +using namespace bot::translator; +using namespace std::string_literals; + +stub::stub() +{ +} + +stub::~stub() +{ +} + +const std::vector stub::get_languages() +{ + return { {"a*", "Any Language"} }; +} + +const std::string stub::translate(const std::string &text, [[maybe_unused]] const std::string &source, [[maybe_unused]] const std::string &target) +{ + return text; +} diff --git a/src/translator/stub/stub.h b/src/translator/stub/stub.h new file mode 100644 index 0000000..c6c73e4 --- /dev/null +++ b/src/translator/stub/stub.h @@ -0,0 +1,36 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#ifndef TRANSLATOR_STUB_H +#define TRANSLATOR_STUB_H + +#include "../../core/translator.h" + +namespace bot { + namespace translator { + class stub : public translator { + public: + explicit stub(); + ~stub() override; + const std::vector get_languages() override; + const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; + }; + } +} + +#endif // TRANSLATOR_STUB_H From 6f6b5eaa691ec1875e10f3dfa27bd8ebde185aee Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 12 Mar 2024 06:36:24 +0100 Subject: [PATCH 25/53] fix add_dependencies for WITH_DPP_STATIC_BUNDLE --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5002e99..df765e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ endif() # dtranslatebot Target + Installs add_executable(dtranslatebot ${DTRANSLATEBOT_HEADERS} ${DTRANSLATEBOT_SOURCES} ${DTRANSLATEBOT_RESOURCES}) -if (WITH_DPP_AS_EXTERNAL_PROJECT) +if (WITH_DPP_STATIC_BUNDLE) add_dependencies(dtranslatebot DPP) endif() target_compile_definitions(dtranslatebot PRIVATE From 6a892034154fbb73f0cebcb259b3f7348bc90c17 Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 12 Mar 2024 09:40:58 +0100 Subject: [PATCH 26/53] systemd-sysusers support and RPMSPEC added --- CMakeLists.txt | 6 ++- rpmspec/dtranslatebot.spec | 70 ++++++++++++++++++++++++++ rpmspec/dtranslatebot.sysusersd | 2 + src/systemd/dtranslatebot.sysusersd.in | 1 + 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 rpmspec/dtranslatebot.spec create mode 100644 rpmspec/dtranslatebot.sysusersd create mode 100644 src/systemd/dtranslatebot.sysusersd.in diff --git a/CMakeLists.txt b/CMakeLists.txt index df765e1..c01c808 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,8 +89,10 @@ endif() if (UNIX AND NOT APPLE) option(WITH_SYSTEMD "Build with systemd Support" OFF) if (WITH_SYSTEMD) - configure_file(src/systemd/dtranslatebot.service.in "${dtranslatebot_BINARY_DIR}/systemd/dtranslatebot.service" @ONLY) - install(FILES "${dtranslatebot_BINARY_DIR}/systemd/dtranslatebot.service" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") + configure_file(src/systemd/dtranslatebot.service.in "${dtranslatebot_BINARY_DIR}/systemd/service/dtranslatebot.service" @ONLY) + configure_file(src/systemd/dtranslatebot.sysusersd.in "${dtranslatebot_BINARY_DIR}/systemd/sysusers.d/dtranslatebot.conf" @ONLY) + install(FILES "${dtranslatebot_BINARY_DIR}/systemd/service/dtranslatebot.service" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") + install(FILES "${dtranslatebot_BINARY_DIR}/systemd/sysusers.d/dtranslatebot.conf" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/sysusers.d") endif() endif() diff --git a/rpmspec/dtranslatebot.spec b/rpmspec/dtranslatebot.spec new file mode 100644 index 0000000..415611e --- /dev/null +++ b/rpmspec/dtranslatebot.spec @@ -0,0 +1,70 @@ +%global _lto_cflags %{?_lto_cflags} -ffat-lto-objects +%global dtb_cmake_args -DCMAKE_BUILD_TYPE=Release -DWITH_DPP_STATIC_BUNDLE=TRUE -DWITH_SYSTEMD=TRUE + +Name: dtranslatebot +Version: 0.2.0 +Release: 1%{?dist} +Summary: Discord Translation Bot +License: BSD-2-Clause +URL: https://github.com/Syping/%{name} +Source0: %{name}_%{version}.tar.gz +Source1: %{name}.sysusersd + +BuildRequires: cmake >= 3.16 +%if 0%{?rhel} && 0%{?rhel} < 9 +BuildRequires: gcc-toolset-9-annobin +BuildRequires: gcc-toolset-9-gcc-c++ +%else +BuildRequires: annobin +BuildRequires: gcc-c++ +%endif +%if 0%{?rhel} +BuildRequires: epel-rpm-macros-systemd +%endif +BuildRequires: systemd-rpm-macros +%{?systemd_requires} +%{?sysusers_requires_compat} + +%description +dtranslatebot is a Discord Bot which translate incoming Discord messages to Discord webhooks. + +%prep +%setup -q + +%build +%if 0%{?rhel} && 0%{?rhel} < 9 +source /opt/rh/gcc-toolset-9/enable +%endif +%cmake %{?dtb_cmake_args} +%if 0%{?cmake_build:1} +%cmake_build +%else +%make_build +%endif + +%install +%if 0%{?cmake_install:1} +%cmake_install +%else +%make_install +%endif +mkdir -p %{buildroot}%{_localstatedir}/lib/%{name} +install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/%{name}.conf + +%pre +%sysusers_create_compat %{SOURCE1} + +%post +%systemd_post %{name}.service + +%preun +%systemd_preun %{name}.service + +%postun +%systemd_postun_with_restart %{name}.service + +%files +%{_bindir}/%{name} +%{_unitdir}/%{name}.service +%{_sysusersdir}/%{name}.conf +%dir %attr(0750,%{name},%{name}) %{_localstatedir}/lib/%{name} diff --git a/rpmspec/dtranslatebot.sysusersd b/rpmspec/dtranslatebot.sysusersd new file mode 100644 index 0000000..f181398 --- /dev/null +++ b/rpmspec/dtranslatebot.sysusersd @@ -0,0 +1,2 @@ +#Type Name ID GECOS Home directory Shell +u dtranslatebot - "Discord Translation Bot" /var/lib/translatebot - diff --git a/src/systemd/dtranslatebot.sysusersd.in b/src/systemd/dtranslatebot.sysusersd.in new file mode 100644 index 0000000..144004d --- /dev/null +++ b/src/systemd/dtranslatebot.sysusersd.in @@ -0,0 +1 @@ +u dtranslatebot - "Discord Translation Bot" "@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/dtranslatebot" - From 382f029c3bbe5fa0a11dd3f5b092d01866533984 Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 12 Mar 2024 10:15:51 +0100 Subject: [PATCH 27/53] add basic config file to RPM --- rpmsrc/dtranslatebot.json | 6 ++++++ rpmsrc/dtranslatebot.service | 13 +++++++++++++ {rpmspec => rpmsrc}/dtranslatebot.spec | 12 +++++++++--- {rpmspec => rpmsrc}/dtranslatebot.sysusersd | 0 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 rpmsrc/dtranslatebot.json create mode 100644 rpmsrc/dtranslatebot.service rename {rpmspec => rpmsrc}/dtranslatebot.spec (77%) rename {rpmspec => rpmsrc}/dtranslatebot.sysusersd (100%) diff --git a/rpmsrc/dtranslatebot.json b/rpmsrc/dtranslatebot.json new file mode 100644 index 0000000..29ba5d7 --- /dev/null +++ b/rpmsrc/dtranslatebot.json @@ -0,0 +1,6 @@ +{ + "token": "add bot token from here -> https://discord.com/developers/applications", + "translator": { + "type": "stub" + } +} diff --git a/rpmsrc/dtranslatebot.service b/rpmsrc/dtranslatebot.service new file mode 100644 index 0000000..7bd129f --- /dev/null +++ b/rpmsrc/dtranslatebot.service @@ -0,0 +1,13 @@ +[Unit] +Description=Discord Translation Bot +After=network.target + +[Service] +User=dtranslatebot +Group=dtranslatebot +WorkingDirectory=/var/lib/dtranslatebot +ExecStart=/usr/bin/dtranslatebot /etc/dtranslatebot.json +Restart=on-abnormal + +[Install] +WantedBy=multi-user.target diff --git a/rpmspec/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec similarity index 77% rename from rpmspec/dtranslatebot.spec rename to rpmsrc/dtranslatebot.spec index 415611e..d1757a7 100644 --- a/rpmspec/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -8,9 +8,12 @@ Summary: Discord Translation Bot License: BSD-2-Clause URL: https://github.com/Syping/%{name} Source0: %{name}_%{version}.tar.gz -Source1: %{name}.sysusersd +Source1: %{name}.json +Source2: %{name}.service +Source3: %{name}.sysusersd BuildRequires: cmake >= 3.16 +BuildRequires: perl %if 0%{?rhel} && 0%{?rhel} < 9 BuildRequires: gcc-toolset-9-annobin BuildRequires: gcc-toolset-9-gcc-c++ @@ -49,10 +52,12 @@ source /opt/rh/gcc-toolset-9/enable %make_install %endif mkdir -p %{buildroot}%{_localstatedir}/lib/%{name} -install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/%{name}.conf +install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/%{name}.json +install -p -D -m 0644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service +install -p -D -m 0644 %{SOURCE3} %{buildroot}%{_sysusersdir}/%{name}.conf %pre -%sysusers_create_compat %{SOURCE1} +%sysusers_create_compat %{SOURCE3} %post %systemd_post %{name}.service @@ -67,4 +72,5 @@ install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/%{name}.conf %{_bindir}/%{name} %{_unitdir}/%{name}.service %{_sysusersdir}/%{name}.conf +%config(noreplace) %attr(0640,root,%{name}) %{_sysconfdir}/%{name}.json %dir %attr(0750,%{name},%{name}) %{_localstatedir}/lib/%{name} diff --git a/rpmspec/dtranslatebot.sysusersd b/rpmsrc/dtranslatebot.sysusersd similarity index 100% rename from rpmspec/dtranslatebot.sysusersd rename to rpmsrc/dtranslatebot.sysusersd From 9380dd14ea191c2e8bb139e2ed8efbcaefa90123 Mon Sep 17 00:00:00 2001 From: Syping Date: Thu, 14 Mar 2024 03:30:45 +0100 Subject: [PATCH 28/53] fix el7 and el9 build errors in RPM SPEC file --- rpmsrc/dtranslatebot.spec | 44 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/rpmsrc/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec index d1757a7..afa628e 100644 --- a/rpmsrc/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -1,5 +1,10 @@ %global _lto_cflags %{?_lto_cflags} -ffat-lto-objects -%global dtb_cmake_args -DCMAKE_BUILD_TYPE=Release -DWITH_DPP_STATIC_BUNDLE=TRUE -DWITH_SYSTEMD=TRUE + +%if 0%{?rhel} && 0%{?rhel} < 8 +%global cmake %{?cmake3} +%global cmake_build %{?cmake3_build} +%global cmake_install %{?cmake3_install} +%endif Name: dtranslatebot Version: 0.2.0 @@ -7,21 +12,30 @@ Release: 1%{?dist} Summary: Discord Translation Bot License: BSD-2-Clause URL: https://github.com/Syping/%{name} -Source0: %{name}_%{version}.tar.gz +Source0: %{name}-%{version}.tar.gz Source1: %{name}.json Source2: %{name}.service Source3: %{name}.sysusersd -BuildRequires: cmake >= 3.16 +BuildRequires: make BuildRequires: perl -%if 0%{?rhel} && 0%{?rhel} < 9 +BuildRequires: perl-IPC-Cmd +%if 0%{?rhel} && 0%{?rhel} < 8 +BuildRequires: cmake3 >= 3.16 +BuildRequires: devtoolset-9-annobin +BuildRequires: devtoolset-9-gcc-c++ +%else +%if 0%{?rhel} && 0%{?rhel} == 8 +BuildRequires: cmake >= 3.16 BuildRequires: gcc-toolset-9-annobin BuildRequires: gcc-toolset-9-gcc-c++ %else +BuildRequires: cmake >= 3.16 BuildRequires: annobin BuildRequires: gcc-c++ %endif -%if 0%{?rhel} +%endif +%if 0%{?rhel} && 0%{?rhel} < 9 BuildRequires: epel-rpm-macros-systemd %endif BuildRequires: systemd-rpm-macros @@ -35,22 +49,22 @@ dtranslatebot is a Discord Bot which translate incoming Discord messages to Disc %setup -q %build -%if 0%{?rhel} && 0%{?rhel} < 9 +%if 0%{?rhel} && 0%{?rhel} < 8 +source /opt/rh/devtoolset-9/enable +%else +%if 0%{?rhel} && 0%{?rhel} == 8 source /opt/rh/gcc-toolset-9/enable %endif -%cmake %{?dtb_cmake_args} -%if 0%{?cmake_build:1} -%cmake_build -%else -%make_build %endif +%cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DPERL_EXECUTABLE=%{_bindir}/perl \ + -DWITH_DPP_STATIC_BUNDLE=TRUE \ + -DWITH_SYSTEMD=TRUE +%cmake_build %install -%if 0%{?cmake_install:1} %cmake_install -%else -%make_install -%endif mkdir -p %{buildroot}%{_localstatedir}/lib/%{name} install -p -D -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/%{name}.json install -p -D -m 0644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service From 7d8bbd12ce101ad805d663f66ee7b6091d4cec62 Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 15 Mar 2024 01:45:55 +0100 Subject: [PATCH 29/53] CI: add Enterprise Linux --- .github/workflows/el.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/el.yml diff --git a/.github/workflows/el.yml b/.github/workflows/el.yml new file mode 100644 index 0000000..5515982 --- /dev/null +++ b/.github/workflows/el.yml @@ -0,0 +1,37 @@ +name: Enterprise Linux +on: push +jobs: + Release: + runs-on: ubuntu-latest + strategy: + matrix: + version: [el7, el8, el9] + steps: + - name: Cloning + uses: actions/checkout@v4 + - name: Preparing + run: mkdir -m 777 ${{github.workspace}}/rpms + - name: Build RPM + uses: addnab/docker-run-action@v3 + with: + image: docker.io/syping/dtranslatebot-build:${{matrix.version}} + options: -v ${{github.workspace}}:/home/rpmbuild/dtranslatebot -v ${{github.workspace}}/rpms:/home/rpmbuild/rpmbuild/RPMS + run: | + VERSION=$(cat dtranslatebot/CMakeLists.txt | grep -oP "project\(dtranslatebot VERSION \K(\S*)(?= LANGUAGES CXX\))") + mkdir -p dtranslatebot-$VERSION + shopt -s extglob + cp -R dtranslatebot/!(rpms|rpmsrc) \ + dtranslatebot-$VERSION + tar cfz dtranslatebot-$VERSION.tar.gz dtranslatebot-$VERSION + cp dtranslatebot-$VERSION.tar.gz \ + dtranslatebot/rpmsrc/!(*.spec) \ + rpmbuild/SOURCES + cp dtranslatebot/rpmsrc/*.spec \ + rpmbuild/SPECS + rpmbuild -ba rpmbuild/SPECS/dtranslatebot.spec + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: Enterprise Linux ${{matrix.version}} + path: | + ${{github.workspace}}/rpms/x86_64/*.rpm From 66a504ac558fe2c9249eb2b906aa736c4022dbaf Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 17 Mar 2024 05:21:33 +0100 Subject: [PATCH 30/53] systemd: escape working directory --- CMakeLists.txt | 10 ++++++++++ src/systemd/dtranslatebot.service.in | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c01c808..178606b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,16 @@ endif() if (UNIX AND NOT APPLE) option(WITH_SYSTEMD "Build with systemd Support" OFF) if (WITH_SYSTEMD) + find_program(SYSTEMD_ESCAPE_EXECUTABLE NAMES systemd-escape) + if (DEFINED SYSTEMD_ESCAPE_EXECUTABLE) + execute_process( + COMMAND "${SYSTEMD_ESCAPE_EXECUTABLE}" "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/dtranslatebot" + OUTPUT_VARIABLE dtranslatebot_SERVICE_WORKDIR + ) + string(STRIP "${dtranslatebot_SERVICE_WORKDIR}" dtranslatebot_SERVICE_WORKDIR) + else() + set(dtranslatebot_SERVICE_WORKDIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/dtranslatebot") + endif() configure_file(src/systemd/dtranslatebot.service.in "${dtranslatebot_BINARY_DIR}/systemd/service/dtranslatebot.service" @ONLY) configure_file(src/systemd/dtranslatebot.sysusersd.in "${dtranslatebot_BINARY_DIR}/systemd/sysusers.d/dtranslatebot.conf" @ONLY) install(FILES "${dtranslatebot_BINARY_DIR}/systemd/service/dtranslatebot.service" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") diff --git a/src/systemd/dtranslatebot.service.in b/src/systemd/dtranslatebot.service.in index b537c19..6c2e0c9 100644 --- a/src/systemd/dtranslatebot.service.in +++ b/src/systemd/dtranslatebot.service.in @@ -5,9 +5,9 @@ After=network.target [Service] User=dtranslatebot Group=dtranslatebot -WorkingDirectory="@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/dtranslatebot" +WorkingDirectory=@dtranslatebot_SERVICE_WORKDIR@ ExecStart="@CMAKE_INSTALL_FULL_BINDIR@/dtranslatebot" "@CMAKE_INSTALL_FULL_SYSCONFDIR@/dtranslatebot.json" -Restart=on-failure +Restart=on-abnormal [Install] WantedBy=multi-user.target From 9a5f37929abca7379c6790ad487b3e91b9a2fbaf Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 17 Mar 2024 05:22:22 +0100 Subject: [PATCH 31/53] DPPStaticBundle: get perl executable with find_program --- cmake/DPPStaticBundle.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index 23304eb..50331c6 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -19,7 +19,6 @@ include(ArgumentPassthrough) # OpenSSL needs to be configured with perl and build with make -find_package(Perl REQUIRED) find_program(MAKE_EXECUTABLE NAMES make gmake) if (NOT DEFINED MAKE_EXECUTABLE) message(SEND_ERROR "make not found") @@ -35,6 +34,11 @@ if (DEFINED NPROC_EXECUTABLE) set(MAKE_JOBS_ARG "-j${NPROC}") endif() +find_program(PERL_EXECUTABLE NAMES perl) +if (NOT DEFINED PERL_EXECUTABLE) + message(SEND_ERROR "perl not found") +endif() + include(ExternalProject) ExternalProject_Add(ZLIB URL https://www.zlib.net/zlib-1.3.1.tar.xz From 6764c9c2f3164b708852f66395f70f6ab4cdeb2c Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 19 Mar 2024 13:48:42 +0100 Subject: [PATCH 32/53] rpmspec: defining PERL_EXECUTABLE is not needed anymore --- rpmsrc/dtranslatebot.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/rpmsrc/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec index afa628e..7faa5a0 100644 --- a/rpmsrc/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -58,7 +58,6 @@ source /opt/rh/gcc-toolset-9/enable %endif %cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DPERL_EXECUTABLE=%{_bindir}/perl \ -DWITH_DPP_STATIC_BUNDLE=TRUE \ -DWITH_SYSTEMD=TRUE %cmake_build From 24c14efce297194e39bdd4d277f17385f21823c9 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 20 Mar 2024 21:43:08 +0100 Subject: [PATCH 33/53] rpmspec: add suse support --- rpmsrc/dtranslatebot.spec | 51 ++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/rpmsrc/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec index 7faa5a0..163461d 100644 --- a/rpmsrc/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -4,6 +4,14 @@ %global cmake %{?cmake3} %global cmake_build %{?cmake3_build} %global cmake_install %{?cmake3_install} +%global cmake_suffix 3 +%global toolset_prefix devtoolset-9- +%endif +%if 0%{?rhel} && 0%{?rhel} == 8 +%global toolset_prefix gcc-toolset-9- +%endif +%if 0%{?suse_version} && 0%{?suse_version} < 1600 +%global toolset_version 9 %endif Name: dtranslatebot @@ -17,30 +25,21 @@ Source1: %{name}.json Source2: %{name}.service Source3: %{name}.sysusersd -BuildRequires: make -BuildRequires: perl -BuildRequires: perl-IPC-Cmd -%if 0%{?rhel} && 0%{?rhel} < 8 -BuildRequires: cmake3 >= 3.16 -BuildRequires: devtoolset-9-annobin -BuildRequires: devtoolset-9-gcc-c++ -%else -%if 0%{?rhel} && 0%{?rhel} == 8 -BuildRequires: cmake >= 3.16 -BuildRequires: gcc-toolset-9-annobin -BuildRequires: gcc-toolset-9-gcc-c++ -%else -BuildRequires: cmake >= 3.16 -BuildRequires: annobin -BuildRequires: gcc-c++ -%endif -%endif +%if 0%{?fedora} || 0%{?rhel} +BuildRequires: %{?toolset_prefix}annobin %if 0%{?rhel} && 0%{?rhel} < 9 BuildRequires: epel-rpm-macros-systemd %endif +%endif +BuildRequires: cmake%{?cmake_suffix} +BuildRequires: %{?toolset_prefix}gcc%{?toolset_version}-c++ +BuildRequires: make +BuildRequires: perl(IPC::Cmd) BuildRequires: systemd-rpm-macros -%{?systemd_requires} -%{?sysusers_requires_compat} +%systemd_requires +%if 0%{?fedora} || 0%{?rhel} +%sysusers_requires_compat +%endif %description dtranslatebot is a Discord Bot which translate incoming Discord messages to Discord webhooks. @@ -51,13 +50,16 @@ dtranslatebot is a Discord Bot which translate incoming Discord messages to Disc %build %if 0%{?rhel} && 0%{?rhel} < 8 source /opt/rh/devtoolset-9/enable -%else +%endif %if 0%{?rhel} && 0%{?rhel} == 8 source /opt/rh/gcc-toolset-9/enable %endif -%endif %cmake \ -DCMAKE_BUILD_TYPE=Release \ +%if 0%{?toolset_version} + -DCMAKE_C_COMPILER=gcc-%{toolset_version} \ + -DCMAKE_CXX_COMPILER=g++-%{toolset_version} \ +%endif -DWITH_DPP_STATIC_BUNDLE=TRUE \ -DWITH_SYSTEMD=TRUE %cmake_build @@ -70,7 +72,12 @@ install -p -D -m 0644 %{SOURCE2} %{buildroot}%{_unitdir}/%{name}.service install -p -D -m 0644 %{SOURCE3} %{buildroot}%{_sysusersdir}/%{name}.conf %pre +%if 0%{?fedora} || 0%{?rhel} %sysusers_create_compat %{SOURCE3} +%endif +%if 0%{?suse_version} +%sysusers_create_package %{name} %{SOURCE3} +%endif %post %systemd_post %{name}.service From 42755811aa6a95d6a91f61bd8fdce80269675fe3 Mon Sep 17 00:00:00 2001 From: Syping Date: Fri, 22 Mar 2024 02:37:29 +0100 Subject: [PATCH 34/53] CI: add openSUSE Leap 15.5 --- .github/workflows/{el.yml => linux-rpm.yml} | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) rename .github/workflows/{el.yml => linux-rpm.yml} (79%) diff --git a/.github/workflows/el.yml b/.github/workflows/linux-rpm.yml similarity index 79% rename from .github/workflows/el.yml rename to .github/workflows/linux-rpm.yml index 5515982..b51f55d 100644 --- a/.github/workflows/el.yml +++ b/.github/workflows/linux-rpm.yml @@ -1,11 +1,19 @@ -name: Enterprise Linux +name: Linux on: push jobs: Release: runs-on: ubuntu-latest strategy: matrix: - version: [el7, el8, el9] + include: + - name: Enterprise Linux 7 + version: el7 + - name: Enterprise Linux 8 + version: el8 + - name: Enterprise Linux 9 + version: el9 + - name: openSUSE Leap 15.5 + version: lp155 steps: - name: Cloning uses: actions/checkout@v4 @@ -32,6 +40,6 @@ jobs: - name: Upload uses: actions/upload-artifact@v4 with: - name: Enterprise Linux ${{matrix.version}} + name: ${{matrix.name}} path: | ${{github.workspace}}/rpms/x86_64/*.rpm From 0e369f5a1d20c1a5567dd375916a34b314fa00dd Mon Sep 17 00:00:00 2001 From: Syping Date: Sat, 23 Mar 2024 16:57:54 +0100 Subject: [PATCH 35/53] add experimental deepl support --- CMakeLists.txt | 2 + src/core/settings.cpp | 21 ++++++- src/core/settings_types.h | 1 + src/core/slashcommands.cpp | 4 +- src/translator/deepl/deepl.cpp | 104 +++++++++++++++++++++++++++++++++ src/translator/deepl/deepl.h | 40 +++++++++++++ 6 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 src/translator/deepl/deepl.cpp create mode 100644 src/translator/deepl/deepl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 178606b..5c169ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(DTRANSLATEBOT_HEADERS src/core/translator.h src/core/webhook_push.h src/database/file/file.h + src/translator/deepl/deepl.h src/translator/libretranslate/libretranslate.h src/translator/stub/stub.h ) @@ -46,6 +47,7 @@ set(DTRANSLATEBOT_SOURCES src/core/translator.cpp src/core/webhook_push.cpp src/database/file/file.cpp + src/translator/deepl/deepl.cpp src/translator/libretranslate/libretranslate.cpp src/translator/stub/stub.cpp ) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 46a9af5..ee0cbd9 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -21,6 +21,7 @@ #include #include "settings.h" #include "../database/file/file.h" +#include "../translator/deepl/deepl.h" #include "../translator/libretranslate/libretranslate.h" #include "../translator/stub/stub.h" using namespace bot::settings; @@ -233,7 +234,23 @@ bool process_translator_settings(const dpp::json &json, translator &translator) std::transform(translator_type.begin(), translator_type.end(), translator_type.begin(), ::tolower); } - if (translator_type == "libretranslate") { + if (translator_type == "deepl") { + translator.type = TRANSLATOR_DEEPL; + + auto json_deepl_hostname = json.find("hostname"); + if (json_deepl_hostname != json.end()) + translator.hostname = *json_deepl_hostname; + else + translator.hostname = "api-free.deepl.com"; + + auto json_deepl_apiKey = json.find("apiKey"); + if (json_deepl_apiKey == json.end()) { + std::cerr << "[Error] DeepL requires API key for authorization" << std::endl; + return false; + } + translator.apiKey = *json_deepl_apiKey; + } + else if (translator_type == "libretranslate") { translator.type = TRANSLATOR_LIBRETRANSLATE; auto json_lt_hostname = json.find("hostname"); @@ -459,6 +476,8 @@ std::unique_ptr settings::get_translator() const const std::lock_guard guard(m_mutex); switch (m_translator.type) { + case TRANSLATOR_DEEPL: + return std::make_unique(m_translator.hostname, m_translator.apiKey); case TRANSLATOR_LIBRETRANSLATE: return std::make_unique(m_translator.hostname, m_translator.port, m_translator.url, m_translator.tls, m_translator.apiKey); case TRANSLATOR_STUB: diff --git a/src/core/settings_types.h b/src/core/settings_types.h index 923be1c..3eed401 100644 --- a/src/core/settings_types.h +++ b/src/core/settings_types.h @@ -41,6 +41,7 @@ namespace bot { std::vector channel; }; enum translator_type { + TRANSLATOR_DEEPL, TRANSLATOR_LIBRETRANSLATE, TRANSLATOR_STUB }; diff --git a/src/core/slashcommands.cpp b/src/core/slashcommands.cpp index b1bbc21..a55614c 100644 --- a/src/core/slashcommands.cpp +++ b/src/core/slashcommands.cpp @@ -434,9 +434,9 @@ void slashcommands::register_commands(dpp::cluster *bot, bot::settings::settings std::vector commands; dpp::command_option source_option(dpp::co_string, "source", "Source language (ISO 639-1)", true); - source_option.set_max_length(static_cast(2)).set_min_length(static_cast(2)); + source_option.set_max_length(static_cast(5)).set_min_length(static_cast(2)); dpp::command_option target_option(dpp::co_string, "target", "Target language (ISO 639-1)", true); - target_option.set_max_length(static_cast(2)).set_min_length(static_cast(2)); + target_option.set_max_length(static_cast(5)).set_min_length(static_cast(2)); dpp::slashcommand command_edit("edit", "Edit current channel settings", bot->me.id); command_edit.set_default_permissions(dpp::p_manage_webhooks); diff --git a/src/translator/deepl/deepl.cpp b/src/translator/deepl/deepl.cpp new file mode 100644 index 0000000..43d9c76 --- /dev/null +++ b/src/translator/deepl/deepl.cpp @@ -0,0 +1,104 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#include +#include +#include "deepl.h" +using namespace bot::translator; +using namespace std::string_literals; + +deepl::deepl(const std::string &hostname, const std::string apiKey) : + m_hostname(hostname), m_apiKey(apiKey) +{ +} + +deepl::~deepl() +{ +} + +const std::vector deepl::get_languages() +{ + std::vector languages; + + try { + dpp::https_client http_request(m_hostname, 443, "/v2/languages?type=target", "GET", {}, { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} }, false); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_array()) { + for (const auto &json_language : response) { + if (json_language.is_object()) { + language language; + + auto json_lang_code = json_language.find("language"); + if (json_lang_code != json_language.end()) + language.code = *json_lang_code; + + std::transform(language.code.begin(), language.code.end(), language.code.begin(), ::tolower); + + auto json_lang_name = json_language.find("name"); + if (json_lang_name != json_language.end()) + language.name = *json_lang_name; + + if (!language.code.empty() && !language.name.empty()) + languages.push_back(std::move(language)); + } + } + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return languages; +} + +const std::string deepl::translate(const std::string &text, const std::string &source, const std::string &target) +{ + const dpp::http_headers http_headers = { + {"Authorization"s, "DeepL-Auth-Key "s + m_apiKey}, + {"Content-Type"s, "application/json"s} + }; + + dpp::json json_body = { + {"text"s, { text } }, + {"target_lang"s, target}, + }; + + try { + dpp::https_client http_request(m_hostname, 443, "/v2/translate", "POST", json_body.dump(), http_headers, false); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_object()) { + auto translations = response.find("translations"); + if (translations != response.end() && translations->is_array()) { + for (auto translation = translations->begin(); translation != translations->end(); translation++) { + auto tr_text = translation->find("text"); + if (tr_text != translation->end()) + return *tr_text; + } + } + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return text; +} diff --git a/src/translator/deepl/deepl.h b/src/translator/deepl/deepl.h new file mode 100644 index 0000000..a33031e --- /dev/null +++ b/src/translator/deepl/deepl.h @@ -0,0 +1,40 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#ifndef TRANSLATOR_DEEPL_H +#define TRANSLATOR_DEEPL_H + +#include "../../core/translator.h" + +namespace bot { + namespace translator { + class deepl : public translator { + public: + explicit deepl(const std::string &hostname, const std::string apiKey = {}); + ~deepl() override; + const std::vector get_languages() override; + const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; + + private: + std::string m_apiKey; + std::string m_hostname; + }; + } +} + +#endif // TRANSLATOR_DEEPL_H From b1329aa961efaaa33a3d2ca5bc9ef01521b35426 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 25 Mar 2024 10:52:01 +0100 Subject: [PATCH 36/53] cache available languages and make translator shared --- src/core/settings.cpp | 41 ++++++++----------- src/core/settings.h | 4 +- src/core/settings_types.h | 7 +--- src/core/translator.h | 6 +++ src/translator/deepl/deepl.cpp | 34 ++++++++++----- src/translator/deepl/deepl.h | 1 + .../libretranslate/libretranslate.cpp | 26 ++++++++---- .../libretranslate/libretranslate.h | 2 + 8 files changed, 69 insertions(+), 52 deletions(-) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index ee0cbd9..37e6f59 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -220,23 +220,24 @@ void process_url(const std::string &url, translator &translator) } } -bool process_translator_settings(const dpp::json &json, translator &translator) +bool process_translator_settings(const dpp::json &json, std::shared_ptr &translator_instance) { if (!json.is_object()) { std::cerr << "[Error] Value translator needs to be a object" << std::endl; return false; } - std::string translator_type = "libretranslate"; + bot::settings::translator translator; auto json_translator_type = json.find("type"); if (json_translator_type != json.end()) { - translator_type = *json_translator_type; - std::transform(translator_type.begin(), translator_type.end(), translator_type.begin(), ::tolower); + translator.type = *json_translator_type; + std::transform(translator.type.begin(), translator.type.end(), translator.type.begin(), ::tolower); + } + else { + translator.type = "libretranslate"; } - if (translator_type == "deepl") { - translator.type = TRANSLATOR_DEEPL; - + if (translator.type == "deepl") { auto json_deepl_hostname = json.find("hostname"); if (json_deepl_hostname != json.end()) translator.hostname = *json_deepl_hostname; @@ -249,10 +250,10 @@ bool process_translator_settings(const dpp::json &json, translator &translator) return false; } translator.apiKey = *json_deepl_apiKey; - } - else if (translator_type == "libretranslate") { - translator.type = TRANSLATOR_LIBRETRANSLATE; + translator_instance = std::make_shared(translator.hostname, translator.apiKey); + } + else if (translator.type == "libretranslate") { auto json_lt_hostname = json.find("hostname"); if (json_lt_hostname != json.end()) translator.hostname = *json_lt_hostname; @@ -288,9 +289,11 @@ bool process_translator_settings(const dpp::json &json, translator &translator) translator.apiKey = *json_lt_apiKey; else translator.apiKey.clear(); + + translator_instance = std::make_shared(translator.hostname, translator.port, translator.url, translator.tls, translator.apiKey); } - else if (translator_type == "stub") { - translator.type = TRANSLATOR_STUB; + else if (translator.type == "stub") { + translator_instance = std::make_shared(); } else { std::cerr << "[Error] Translator " << translator.type << " is unknown" << std::endl; @@ -471,20 +474,10 @@ std::shared_ptr settings::get_database() const return m_database; } -std::unique_ptr settings::get_translator() const +std::shared_ptr settings::get_translator() const { const std::lock_guard guard(m_mutex); - - switch (m_translator.type) { - case TRANSLATOR_DEEPL: - return std::make_unique(m_translator.hostname, m_translator.apiKey); - case TRANSLATOR_LIBRETRANSLATE: - return std::make_unique(m_translator.hostname, m_translator.port, m_translator.url, m_translator.tls, m_translator.apiKey); - case TRANSLATOR_STUB: - return std::make_unique(); - default: - return std::make_unique(); - } + return m_translator; } const std::string settings::token() const diff --git a/src/core/settings.h b/src/core/settings.h index fe6b219..f71f812 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -47,7 +47,7 @@ namespace bot { static const target* get_target(const channel *channel, const std::string &target); const std::vector preferred_languages() const; std::shared_ptr get_database() const; - std::unique_ptr get_translator() const; + std::shared_ptr get_translator() const; const std::string token() const; /* is functions */ @@ -73,7 +73,7 @@ namespace bot { std::shared_ptr m_database; std::vector m_guilds; std::vector m_prefLangs; - bot::settings::translator m_translator; + std::shared_ptr m_translator; std::string m_token; std::vector m_webhookIds; }; diff --git a/src/core/settings_types.h b/src/core/settings_types.h index 3eed401..96d9017 100644 --- a/src/core/settings_types.h +++ b/src/core/settings_types.h @@ -40,13 +40,8 @@ namespace bot { dpp::snowflake id; std::vector channel; }; - enum translator_type { - TRANSLATOR_DEEPL, - TRANSLATOR_LIBRETRANSLATE, - TRANSLATOR_STUB - }; struct translator { - translator_type type; + std::string type; std::string hostname; uint16_t port; std::string url; diff --git a/src/core/translator.h b/src/core/translator.h index c230abd..91502d9 100644 --- a/src/core/translator.h +++ b/src/core/translator.h @@ -19,6 +19,7 @@ #ifndef TRANSLATOR_H #define TRANSLATOR_H +#include #include #include @@ -29,6 +30,11 @@ namespace bot { std::string name; }; + struct supported_languages { + std::vector languages; + std::chrono::system_clock::time_point query_time; + }; + class translator { public: explicit translator() = default; diff --git a/src/translator/deepl/deepl.cpp b/src/translator/deepl/deepl.cpp index 43d9c76..94a7dff 100644 --- a/src/translator/deepl/deepl.cpp +++ b/src/translator/deepl/deepl.cpp @@ -20,6 +20,7 @@ #include #include "deepl.h" using namespace bot::translator; +using namespace std::chrono_literals; using namespace std::string_literals; deepl::deepl(const std::string &hostname, const std::string apiKey) : @@ -33,31 +34,41 @@ deepl::~deepl() const std::vector deepl::get_languages() { - std::vector languages; + if (!m_languages.languages.empty()) { + auto current_time = std::chrono::system_clock::now(); + auto threshold_time = m_languages.query_time + 24h; + if (current_time <= threshold_time) + return m_languages.languages; + } try { dpp::https_client http_request(m_hostname, 443, "/v2/languages?type=target", "GET", {}, { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} }, false); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_array()) { - for (const auto &json_language : response) { - if (json_language.is_object()) { + m_languages.languages.clear(); + for (auto json_language = response.begin(); json_language != response.end(); json_language++) { + if (json_language->is_object()) { language language; - auto json_lang_code = json_language.find("language"); - if (json_lang_code != json_language.end()) + auto json_lang_code = json_language->find("language"); + if (json_lang_code != json_language->end()) language.code = *json_lang_code; - std::transform(language.code.begin(), language.code.end(), language.code.begin(), ::tolower); + if (language.code.size() > 2) + std::transform(language.code.begin(), language.code.begin() + 2, language.code.begin(), ::tolower); + else + std::transform(language.code.begin(), language.code.end(), language.code.begin(), ::tolower); - auto json_lang_name = json_language.find("name"); - if (json_lang_name != json_language.end()) + auto json_lang_name = json_language->find("name"); + if (json_lang_name != json_language->end()) language.name = *json_lang_name; if (!language.code.empty() && !language.name.empty()) - languages.push_back(std::move(language)); + m_languages.languages.push_back(std::move(language)); } } + m_languages.query_time = std::chrono::system_clock::now(); } } } @@ -65,18 +76,19 @@ const std::vector deepl::get_languages() std::cerr << "[Exception] " << exception.what() << std::endl; } - return languages; + return m_languages.languages; } const std::string deepl::translate(const std::string &text, const std::string &source, const std::string &target) { const dpp::http_headers http_headers = { - {"Authorization"s, "DeepL-Auth-Key "s + m_apiKey}, + {"Authorization"s, "DeepL-Auth-Key " + m_apiKey}, {"Content-Type"s, "application/json"s} }; dpp::json json_body = { {"text"s, { text } }, + {"source_lang"s, source}, {"target_lang"s, target}, }; diff --git a/src/translator/deepl/deepl.h b/src/translator/deepl/deepl.h index a33031e..f1b6aa0 100644 --- a/src/translator/deepl/deepl.h +++ b/src/translator/deepl/deepl.h @@ -33,6 +33,7 @@ namespace bot { private: std::string m_apiKey; std::string m_hostname; + supported_languages m_languages; }; } } diff --git a/src/translator/libretranslate/libretranslate.cpp b/src/translator/libretranslate/libretranslate.cpp index 7e5e9e7..909dbb3 100644 --- a/src/translator/libretranslate/libretranslate.cpp +++ b/src/translator/libretranslate/libretranslate.cpp @@ -20,6 +20,7 @@ #include #include "libretranslate.h" using namespace bot::translator; +using namespace std::chrono_literals; using namespace std::string_literals; libretranslate::libretranslate(const std::string &hostname, uint16_t port, const std::string &url, bool tls, const std::string apiKey) : @@ -33,29 +34,36 @@ libretranslate::~libretranslate() const std::vector libretranslate::get_languages() { - std::vector languages; + if (!m_languages.languages.empty()) { + auto current_time = std::chrono::system_clock::now(); + auto threshold_time = m_languages.query_time + 24h; + if (current_time <= threshold_time) + return m_languages.languages; + } try { dpp::https_client http_request(m_hostname, m_port, m_url + "languages", "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_array()) { - for (const auto &json_language : response) { - if (json_language.is_object()) { + m_languages.languages.clear(); + for (auto json_language = response.begin(); json_language != response.end(); json_language++) { + if (json_language->is_object()) { language language; - auto json_lang_code = json_language.find("code"); - if (json_lang_code != json_language.end()) + auto json_lang_code = json_language->find("code"); + if (json_lang_code != json_language->end()) language.code = *json_lang_code; - auto json_lang_name = json_language.find("name"); - if (json_lang_name != json_language.end()) + auto json_lang_name = json_language->find("name"); + if (json_lang_name != json_language->end()) language.name = *json_lang_name; if (!language.code.empty() && !language.name.empty()) - languages.push_back(std::move(language)); + m_languages.languages.push_back(std::move(language)); } } + m_languages.query_time = std::chrono::system_clock::now(); } } } @@ -63,7 +71,7 @@ const std::vector libretranslate::get_languages() std::cerr << "[Exception] " << exception.what() << std::endl; } - return languages; + return m_languages.languages; } const std::string libretranslate::translate(const std::string &text, const std::string &source, const std::string &target) diff --git a/src/translator/libretranslate/libretranslate.h b/src/translator/libretranslate/libretranslate.h index 235a253..1af2f97 100644 --- a/src/translator/libretranslate/libretranslate.h +++ b/src/translator/libretranslate/libretranslate.h @@ -25,6 +25,7 @@ namespace bot { namespace translator { class libretranslate : public translator { + public: explicit libretranslate(const std::string &hostname, uint16_t port, const std::string &url, bool tls, const std::string apiKey = {}); ~libretranslate() override; @@ -34,6 +35,7 @@ namespace bot { private: std::string m_apiKey; std::string m_hostname; + supported_languages m_languages; uint16_t m_port; std::string m_url; bool m_tls; From 4e71f417d0dd0508dd6b2024d1f72b5df6b11282 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 25 Mar 2024 10:56:49 +0100 Subject: [PATCH 37/53] rpmspec: add debug package --- rpmsrc/dtranslatebot.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/rpmsrc/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec index 163461d..b0b5cee 100644 --- a/rpmsrc/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -46,6 +46,7 @@ dtranslatebot is a Discord Bot which translate incoming Discord messages to Disc %prep %setup -q +%{?debug_package} %build %if 0%{?rhel} && 0%{?rhel} < 8 From 420f536c9b4f73a034ea52751d59b7be3eea513d Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 25 Mar 2024 11:15:08 +0100 Subject: [PATCH 38/53] make configuration more understandable --- rpmsrc/dtranslatebot.json | 9 ++++++++- src/core/settings.cpp | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/rpmsrc/dtranslatebot.json b/rpmsrc/dtranslatebot.json index 29ba5d7..ca2aa94 100644 --- a/rpmsrc/dtranslatebot.json +++ b/rpmsrc/dtranslatebot.json @@ -1,5 +1,12 @@ { - "token": "add bot token from here -> https://discord.com/developers/applications", + /* + A DISCORD BOT TOKEN IS NECESSARY TO USE THIS APPLICATION! + + You can get a Bot Token from the Discord Developer Portal + by creating a New Application: + https://discord.com/developers/applications + */ + "token": "", "translator": { "type": "stub" } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 37e6f59..8ba95ed 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -507,7 +507,7 @@ bool settings::parse(const std::string &data, bool initialize) try { dpp::json json; try { - json = dpp::json::parse(data); + json = dpp::json::parse(data, nullptr, true, true); } catch (const std::exception &exception) { std::cerr << "[Exception] " << exception.what() << std::endl; From 6bcef831c985cc0019669ee1f6bb6280cef0e385 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 25 Mar 2024 11:20:36 +0100 Subject: [PATCH 39/53] rpmspec: revert add debug package --- rpmsrc/dtranslatebot.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/rpmsrc/dtranslatebot.spec b/rpmsrc/dtranslatebot.spec index b0b5cee..163461d 100644 --- a/rpmsrc/dtranslatebot.spec +++ b/rpmsrc/dtranslatebot.spec @@ -46,7 +46,6 @@ dtranslatebot is a Discord Bot which translate incoming Discord messages to Disc %prep %setup -q -%{?debug_package} %build %if 0%{?rhel} && 0%{?rhel} < 8 From f98478bc4da25e715a0a1216c5bd7ac81c73d8e2 Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 26 Mar 2024 20:53:10 +0100 Subject: [PATCH 40/53] little quality changes --- .github/workflows/windows.yml | 3 ++- cmake/DPPStaticBundle.cmake | 2 +- rpmsrc/dtranslatebot.json | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 6d876a1..c0607fc 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -9,7 +9,8 @@ jobs: run: shell: msys2 {0} steps: - - uses: msys2/setup-msys2@v2 + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 with: msystem: clang64 update: true diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index 50331c6..01b5c17 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -29,8 +29,8 @@ if (DEFINED NPROC_EXECUTABLE) execute_process( COMMAND "${NPROC_EXECUTABLE}" OUTPUT_VARIABLE NPROC + OUTPUT_STRIP_TRAILING_WHITESPACE ) - string(STRIP "${NPROC}" NPROC) set(MAKE_JOBS_ARG "-j${NPROC}") endif() diff --git a/rpmsrc/dtranslatebot.json b/rpmsrc/dtranslatebot.json index ca2aa94..e0a0dc0 100644 --- a/rpmsrc/dtranslatebot.json +++ b/rpmsrc/dtranslatebot.json @@ -6,6 +6,7 @@ by creating a New Application: https://discord.com/developers/applications */ + "token": "", "translator": { "type": "stub" From e94fbbf5acb1727b2322cc3ac950bc08d9820f97 Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 11 Jun 2024 04:18:07 +0200 Subject: [PATCH 41/53] DPPStaticBundle: update DPP to 10.0.30 and OpenSSL to 3.0.14 --- cmake/DPPStaticBundle.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index 01b5c17..af9f0c9 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -55,8 +55,8 @@ set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") set(OPENSSL_PLATFORM_ARG $<$:mingw64>) ExternalProject_Add(OpenSSL - URL https://www.openssl.org/source/openssl-3.0.13.tar.gz - URL_HASH SHA256=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313 + URL https://www.openssl.org/source/openssl-3.0.14.tar.gz + URL_HASH SHA256=eeca035d4dd4e84fc25846d952da6297484afa0650a6f84c682e39df3a4123ca CONFIGURE_COMMAND ${CMAKE_PASSTHROUGH_ENV} "${PERL_EXECUTABLE}" @@ -78,8 +78,8 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - URL https://github.com/Syping/DPP/archive/dcd00001dfa145a03f80a0ad5317bc3e63252ead.tar.gz - URL_HASH SHA256=42ff04b13a384591e819c100c4f40e12e31c8076769c168631eef85a8eeb0be3 + URL https://github.com/brainboxdotcc/DPP/releases/download/v10.0.30/DPP-10.0.30.tar.gz + URL_HASH SHA256=fb7019770bd5c5f0539523536250da387ee1fa9c92e59c0bcff6c9adaf3d77e8 CMAKE_ARGS -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF From 500c43d4e68a57c59fed726917e75b5e2fa48490 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 2 Oct 2024 23:36:02 +0200 Subject: [PATCH 42/53] DPPStaticBundle: update DPP to 10.0.31 and OpenSSL to 3.0.15 --- cmake/DPPStaticBundle.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index af9f0c9..bbf837c 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -55,8 +55,8 @@ set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") set(OPENSSL_PLATFORM_ARG $<$:mingw64>) ExternalProject_Add(OpenSSL - URL https://www.openssl.org/source/openssl-3.0.14.tar.gz - URL_HASH SHA256=eeca035d4dd4e84fc25846d952da6297484afa0650a6f84c682e39df3a4123ca + URL https://github.com/openssl/openssl/releases/download/openssl-3.0.15/openssl-3.0.15.tar.gz + URL_HASH SHA256=23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533 CONFIGURE_COMMAND ${CMAKE_PASSTHROUGH_ENV} "${PERL_EXECUTABLE}" @@ -78,8 +78,8 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - URL https://github.com/brainboxdotcc/DPP/releases/download/v10.0.30/DPP-10.0.30.tar.gz - URL_HASH SHA256=fb7019770bd5c5f0539523536250da387ee1fa9c92e59c0bcff6c9adaf3d77e8 + URL https://github.com/brainboxdotcc/DPP/releases/download/v10.0.31/DPP-10.0.31.tar.gz + URL_HASH SHA256=3e392868c0dc3d0f13a00cfa190a925a20bde62bea58fd87d4acf14de11062bf CMAKE_ARGS -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF From 6d89aef67cb9027e72ce7913876e9dabc3411784 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 27 Nov 2024 15:36:55 +0100 Subject: [PATCH 43/53] DPPStaticBundle: update DPP to 10.0.35 --- cmake/DPPStaticBundle.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index bbf837c..73998b2 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -78,8 +78,8 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - URL https://github.com/brainboxdotcc/DPP/releases/download/v10.0.31/DPP-10.0.31.tar.gz - URL_HASH SHA256=3e392868c0dc3d0f13a00cfa190a925a20bde62bea58fd87d4acf14de11062bf + URL https://github.com/Syping/DPP/archive/067dfb0c5728432dd24f74375173cf0fc8cbc4ca.tar.gz + URL_HASH SHA256=ea794219d32bc58eeb23536b3b18fbc119bd747773c6f7c98cf8e96e6d91693a CMAKE_ARGS -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF From a42932de12490b26719098f97deb5d4449a620dd Mon Sep 17 00:00:00 2001 From: Syping Date: Thu, 28 Nov 2024 16:41:34 +0100 Subject: [PATCH 44/53] add --wait-for-translator flag --- src/core/main.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 58b0885..43ddd75 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -24,22 +24,39 @@ #include "message_queue.h" #include "settings.h" #include "slashcommands.h" +using namespace std::chrono_literals; int main(int argc, char* argv[]) { - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " [json]" << std::endl; + bool flag_wait_for_translator = false; + std::vector args; + for (size_t i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--wait-for-translator")) + flag_wait_for_translator = true; + else + args.push_back(argv[i]); + } + if (args.size() != 1) { + std::cout << "Usage: " << argv[0] << " [--wait-for-translator] [json]" << std::endl; return 0; } std::cout << "[Launch] Processing configuration..." << std::endl; bot::settings::settings settings; - if (!settings.parse_file(argv[1])) + if (!settings.parse_file(args.at(0))) return 1; - std::cout << "[Launch] Requesting supported languages..." << std::endl; - if (settings.get_translator()->get_languages().empty()) { - std::cerr << "[Error] Failed to initialise translateable languages" << std::endl; - return 1; + for (;;) { + std::cout << "[Launch] Requesting supported languages..." << std::endl; + if (!settings.get_translator()->get_languages().empty()) { + break; + } + else if (flag_wait_for_translator) { + std::this_thread::sleep_for(5000ms); + } + else { + std::cerr << "[Error] Failed to initialise translateable languages" << std::endl; + return 1; + } } dpp::cluster bot(settings.token(), dpp::i_default_intents | dpp::i_message_content); From 691e46a507c606534b660abdd72afd013233a3ec Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 29 Dec 2024 14:26:05 +0100 Subject: [PATCH 45/53] add lingvatranslate support --- CMakeLists.txt | 2 + src/core/settings.cpp | 34 +++++++ .../lingvatranslate/lingvatranslate.cpp | 99 +++++++++++++++++++ .../lingvatranslate/lingvatranslate.h | 45 +++++++++ 4 files changed, 180 insertions(+) create mode 100644 src/translator/lingvatranslate/lingvatranslate.cpp create mode 100644 src/translator/lingvatranslate/lingvatranslate.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c169ce..8b04c9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ set(DTRANSLATEBOT_HEADERS src/database/file/file.h src/translator/deepl/deepl.h src/translator/libretranslate/libretranslate.h + src/translator/lingvatranslate/lingvatranslate.h src/translator/stub/stub.h ) set(DTRANSLATEBOT_SOURCES @@ -49,6 +50,7 @@ set(DTRANSLATEBOT_SOURCES src/database/file/file.cpp src/translator/deepl/deepl.cpp src/translator/libretranslate/libretranslate.cpp + src/translator/lingvatranslate/lingvatranslate.cpp src/translator/stub/stub.cpp ) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 8ba95ed..b2675a5 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -23,6 +23,7 @@ #include "../database/file/file.h" #include "../translator/deepl/deepl.h" #include "../translator/libretranslate/libretranslate.h" +#include "../translator/lingvatranslate/lingvatranslate.h" #include "../translator/stub/stub.h" using namespace bot::settings; @@ -292,6 +293,39 @@ bool process_translator_settings(const dpp::json &json, std::shared_ptr(translator.hostname, translator.port, translator.url, translator.tls, translator.apiKey); } + else if (translator.type == "lingvatranslate") { + auto json_lt_hostname = json.find("hostname"); + if (json_lt_hostname != json.end()) + translator.hostname = *json_lt_hostname; + else + translator.hostname = {}; + + auto json_lt_tls = json.find("tls"); + if (json_lt_tls != json.end()) + translator.tls = *json_lt_tls; + else + translator.tls = false; + + auto json_lt_port = json.find("port"); + if (json_lt_port != json.end()) + translator.port = *json_lt_port; + else + translator.port = 0; + + auto json_lt_url = json.find("url"); + if (json_lt_url == json.end()) { + std::cerr << "[Error] Value url not found in translator object" << std::endl; + return false; + } + if (translator.hostname.empty()) { + process_url(*json_lt_url, translator); + } + else { + translator.url = *json_lt_url; + } + + translator_instance = std::make_shared(translator.hostname, translator.port, translator.url, translator.tls); + } else if (translator.type == "stub") { translator_instance = std::make_shared(); } diff --git a/src/translator/lingvatranslate/lingvatranslate.cpp b/src/translator/lingvatranslate/lingvatranslate.cpp new file mode 100644 index 0000000..15c08d1 --- /dev/null +++ b/src/translator/lingvatranslate/lingvatranslate.cpp @@ -0,0 +1,99 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#include +#include +#include +#include "lingvatranslate.h" +using namespace bot::translator; +using namespace std::chrono_literals; +using namespace std::string_literals; + +lingvatranslate::lingvatranslate(const std::string &hostname, uint16_t port, const std::string &url, bool tls) : + m_hostname(hostname), m_port(port), m_url(url), m_tls(tls) +{ +} + +lingvatranslate::~lingvatranslate() +{ +} + +const std::vector lingvatranslate::get_languages() +{ + if (!m_languages.languages.empty()) { + auto current_time = std::chrono::system_clock::now(); + auto threshold_time = m_languages.query_time + 24h; + if (current_time <= threshold_time) + return m_languages.languages; + } + + try { + dpp::https_client http_request(m_hostname, m_port, m_url + "api/v1/languages/target", "GET", {}, {}, !m_tls); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_object()) { + auto languages = response.find("languages"); + if (languages != response.end()) { + m_languages.languages.clear(); + for (auto json_language = languages->begin(); json_language != languages->end(); json_language++) { + if (json_language->is_object()) { + language language; + + auto json_lang_code = json_language->find("code"); + if (json_lang_code != json_language->end()) + language.code = *json_lang_code; + + auto json_lang_name = json_language->find("name"); + if (json_lang_name != json_language->end()) + language.name = *json_lang_name; + + if (!language.code.empty() && !language.name.empty()) + m_languages.languages.push_back(std::move(language)); + } + } + m_languages.query_time = std::chrono::system_clock::now(); + } + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return m_languages.languages; +} + +const std::string lingvatranslate::translate(const std::string &text, const std::string &source, const std::string &target) +{ + try { + dpp::https_client http_request(m_hostname, m_port, m_url + "api/v1/" + source + "/" + target + "/" + dpp::utility::url_encode(text), "GET", {}, {}, !m_tls); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_object()) { + auto tr_text = response.find("translation"); + if (tr_text != response.end()) + return *tr_text; + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return text; +} diff --git a/src/translator/lingvatranslate/lingvatranslate.h b/src/translator/lingvatranslate/lingvatranslate.h new file mode 100644 index 0000000..37cf604 --- /dev/null +++ b/src/translator/lingvatranslate/lingvatranslate.h @@ -0,0 +1,45 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#ifndef TRANSLATOR_LINGVATRANSLATE_H +#define TRANSLATOR_LINGVATRANSLATE_H + +#include +#include "../../core/translator.h" + +namespace bot { + namespace translator { + class lingvatranslate : public translator { + + public: + explicit lingvatranslate(const std::string &hostname, uint16_t port, const std::string &url, bool tls); + ~lingvatranslate() override; + const std::vector get_languages() override; + const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; + + private: + std::string m_hostname; + supported_languages m_languages; + uint16_t m_port; + std::string m_url; + bool m_tls; + }; + } +} + +#endif // TRANSLATOR_LINGVATRANSLATE_H From 1dc2b2dffab188b8199f13b0a40a931de5b151d9 Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 29 Dec 2024 16:05:13 +0100 Subject: [PATCH 46/53] add mozhi support --- CMakeLists.txt | 2 + src/core/settings.cpp | 43 ++++++++++++- src/translator/mozhi/mozhi.cpp | 107 +++++++++++++++++++++++++++++++++ src/translator/mozhi/mozhi.h | 46 ++++++++++++++ 4 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 src/translator/mozhi/mozhi.cpp create mode 100644 src/translator/mozhi/mozhi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b04c9c..29bf456 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(DTRANSLATEBOT_HEADERS src/core/webhook_push.h src/database/file/file.h src/translator/deepl/deepl.h + src/translator/mozhi/mozhi.h src/translator/libretranslate/libretranslate.h src/translator/lingvatranslate/lingvatranslate.h src/translator/stub/stub.h @@ -49,6 +50,7 @@ set(DTRANSLATEBOT_SOURCES src/core/webhook_push.cpp src/database/file/file.cpp src/translator/deepl/deepl.cpp + src/translator/mozhi/mozhi.cpp src/translator/libretranslate/libretranslate.cpp src/translator/lingvatranslate/lingvatranslate.cpp src/translator/stub/stub.cpp diff --git a/src/core/settings.cpp b/src/core/settings.cpp index b2675a5..d552760 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -22,6 +22,7 @@ #include "settings.h" #include "../database/file/file.h" #include "../translator/deepl/deepl.h" +#include "../translator/mozhi/mozhi.h" #include "../translator/libretranslate/libretranslate.h" #include "../translator/lingvatranslate/lingvatranslate.h" #include "../translator/stub/stub.h" @@ -254,6 +255,46 @@ bool process_translator_settings(const dpp::json &json, std::shared_ptr(translator.hostname, translator.apiKey); } + else if (translator.type == "mozhi") { + auto json_mozhi_hostname = json.find("hostname"); + if (json_mozhi_hostname != json.end()) + translator.hostname = *json_mozhi_hostname; + else + translator.hostname = {}; + + auto json_mozhi_tls = json.find("tls"); + if (json_mozhi_tls != json.end()) + translator.tls = *json_mozhi_tls; + else + translator.tls = false; + + auto json_mozhi_port = json.find("port"); + if (json_mozhi_port != json.end()) + translator.port = *json_mozhi_port; + else + translator.port = 0; + + auto json_mozhi_url = json.find("url"); + if (json_mozhi_url == json.end()) { + std::cerr << "[Error] Value url not found in translator object" << std::endl; + return false; + } + if (translator.hostname.empty()) { + process_url(*json_mozhi_url, translator); + } + else { + translator.url = *json_mozhi_url; + } + + std::string mozhi_engine; + auto json_mozhi_engine = json.find("engine"); + if (json_mozhi_engine != json.end()) + mozhi_engine = *json_mozhi_engine; + else + mozhi_engine = "google"; + + translator_instance = std::make_shared(translator.hostname, translator.port, translator.url, translator.tls, mozhi_engine); + } else if (translator.type == "libretranslate") { auto json_lt_hostname = json.find("hostname"); if (json_lt_hostname != json.end()) @@ -288,8 +329,6 @@ bool process_translator_settings(const dpp::json &json, std::shared_ptr(translator.hostname, translator.port, translator.url, translator.tls, translator.apiKey); } diff --git a/src/translator/mozhi/mozhi.cpp b/src/translator/mozhi/mozhi.cpp new file mode 100644 index 0000000..93b18d5 --- /dev/null +++ b/src/translator/mozhi/mozhi.cpp @@ -0,0 +1,107 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#include +#include +#include +#include "mozhi.h" +using namespace bot::translator; +using namespace std::chrono_literals; +using namespace std::string_literals; + +mozhi::mozhi(const std::string &hostname, uint16_t port, const std::string &url, bool tls, const std::string &engine) : + m_hostname(hostname), m_port(port), m_url(url), m_tls(tls), m_engine(engine) +{ +} + +mozhi::~mozhi() +{ +} + +const std::vector mozhi::get_languages() +{ + if (!m_languages.languages.empty()) { + auto current_time = std::chrono::system_clock::now(); + auto threshold_time = m_languages.query_time + 24h; + if (current_time <= threshold_time) + return m_languages.languages; + } + + try { + const std::string parameters = dpp::utility::make_url_parameters({ + {"engine"s, m_engine} + }); + + dpp::https_client http_request(m_hostname, m_port, m_url + "api/target_languages" + parameters, "GET", {}, {}, !m_tls); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_array()) { + m_languages.languages.clear(); + for (auto json_language = response.begin(); json_language != response.end(); json_language++) { + if (json_language->is_object()) { + language language; + + auto json_lang_code = json_language->find("Id"); + if (json_lang_code != json_language->end()) + language.code = *json_lang_code; + + auto json_lang_name = json_language->find("Name"); + if (json_lang_name != json_language->end()) + language.name = *json_lang_name; + + if (!language.code.empty() && !language.name.empty()) + m_languages.languages.push_back(std::move(language)); + } + } + m_languages.query_time = std::chrono::system_clock::now(); + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return m_languages.languages; +} + +const std::string mozhi::translate(const std::string &text, const std::string &source, const std::string &target) +{ + try { + const std::string parameters = dpp::utility::make_url_parameters({ + {"engine"s, m_engine}, + {"from"s, source}, + {"to"s, target}, + {"text"s, text}, + }); + + dpp::https_client http_request(m_hostname, m_port, m_url + "api/translate" + parameters, "GET", {}, {}, !m_tls); + if (http_request.get_status() == 200) { + const dpp::json response = dpp::json::parse(http_request.get_content()); + if (response.is_object()) { + auto tr_text = response.find("translated-text"); + if (tr_text != response.end()) + return *tr_text; + } + } + } + catch (const std::exception &exception) { + std::cerr << "[Exception] " << exception.what() << std::endl; + } + + return text; +} diff --git a/src/translator/mozhi/mozhi.h b/src/translator/mozhi/mozhi.h new file mode 100644 index 0000000..ac3aba6 --- /dev/null +++ b/src/translator/mozhi/mozhi.h @@ -0,0 +1,46 @@ +/***************************************************************************** +* dtranslatebot Discord Translate Bot +* Copyright (C) 2024 Syping +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* This software is provided as-is, no warranties are given to you, we are not +* responsible for anything with use of the software, you are self responsible. +*****************************************************************************/ + +#ifndef TRANSLATOR_MOZHI_H +#define TRANSLATOR_MOZHI_H + +#include +#include "../../core/translator.h" + +namespace bot { + namespace translator { + class mozhi : public translator { + + public: + explicit mozhi(const std::string &hostname, uint16_t port, const std::string &url, bool tls, const std::string &engine); + ~mozhi() override; + const std::vector get_languages() override; + const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; + + private: + std::string m_engine; + std::string m_hostname; + supported_languages m_languages; + uint16_t m_port; + std::string m_url; + bool m_tls; + }; + } +} + +#endif // TRANSLATOR_MOZHI_H From 24a7b3bc992906c7754158c2b0510847fa4d4fdf Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 30 Dec 2024 16:06:51 +0100 Subject: [PATCH 47/53] reduce duplicate code --- src/core/settings.cpp | 154 ++++++++++++--------------------- src/translator/mozhi/mozhi.cpp | 2 - 2 files changed, 53 insertions(+), 103 deletions(-) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index d552760..7d68a5f 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -166,19 +166,7 @@ void process_preflang_settings(const dpp::json &json, std::vector * } } -void process_user_settings(const dpp::json &json, uint16_t &avatar_size) -{ - auto json_avatar_size = json.find("avatar_size"); - if (json_avatar_size != json.end()) { - avatar_size = *json_avatar_size; - if (avatar_size < 16) - avatar_size = 16; - else if (avatar_size > 4096) - avatar_size = 4096; - } -} - -void process_url(const std::string &url, translator &translator) +void process_server_url(const std::string &url, translator &translator) { std::string_view url_v = url; if (url_v.substr(0, 7) == "http://") { @@ -222,6 +210,55 @@ void process_url(const std::string &url, translator &translator) } } +bool process_server(const dpp::json &json, translator &translator) +{ + auto json_hostname = json.find("hostname"); + if (json_hostname != json.end()) + translator.hostname = *json_hostname; + else + translator.hostname = {}; + + auto json_tls = json.find("tls"); + if (json_tls != json.end()) + translator.tls = *json_tls; + else + translator.tls = false; + + auto json_port = json.find("port"); + if (json_port != json.end()) + translator.port = *json_port; + else + translator.port = 0; + + auto json_url = json.find("url"); + if (json_url == json.end()) { + std::cerr << "[Error] Value url not found in translator object" << std::endl; + return false; + } + if (translator.hostname.empty()) + process_server_url(*json_url, translator); + else + translator.url = *json_url; + + auto json_apiKey = json.find("apiKey"); + if (json_apiKey != json.end()) + translator.apiKey = *json_apiKey; + + return true; +} + +void process_user_settings(const dpp::json &json, uint16_t &avatar_size) +{ + auto json_avatar_size = json.find("avatar_size"); + if (json_avatar_size != json.end()) { + avatar_size = *json_avatar_size; + if (avatar_size < 16) + avatar_size = 16; + else if (avatar_size > 4096) + avatar_size = 4096; + } +} + bool process_translator_settings(const dpp::json &json, std::shared_ptr &translator_instance) { if (!json.is_object()) { @@ -256,35 +293,8 @@ bool process_translator_settings(const dpp::json &json, std::shared_ptr(translator.hostname, translator.apiKey); } else if (translator.type == "mozhi") { - auto json_mozhi_hostname = json.find("hostname"); - if (json_mozhi_hostname != json.end()) - translator.hostname = *json_mozhi_hostname; - else - translator.hostname = {}; - - auto json_mozhi_tls = json.find("tls"); - if (json_mozhi_tls != json.end()) - translator.tls = *json_mozhi_tls; - else - translator.tls = false; - - auto json_mozhi_port = json.find("port"); - if (json_mozhi_port != json.end()) - translator.port = *json_mozhi_port; - else - translator.port = 0; - - auto json_mozhi_url = json.find("url"); - if (json_mozhi_url == json.end()) { - std::cerr << "[Error] Value url not found in translator object" << std::endl; + if (!process_server(json, translator)) return false; - } - if (translator.hostname.empty()) { - process_url(*json_mozhi_url, translator); - } - else { - translator.url = *json_mozhi_url; - } std::string mozhi_engine; auto json_mozhi_engine = json.find("engine"); @@ -296,72 +306,14 @@ bool process_translator_settings(const dpp::json &json, std::shared_ptr(translator.hostname, translator.port, translator.url, translator.tls, mozhi_engine); } else if (translator.type == "libretranslate") { - auto json_lt_hostname = json.find("hostname"); - if (json_lt_hostname != json.end()) - translator.hostname = *json_lt_hostname; - else - translator.hostname = {}; - - auto json_lt_tls = json.find("tls"); - if (json_lt_tls != json.end()) - translator.tls = *json_lt_tls; - else - translator.tls = false; - - auto json_lt_port = json.find("port"); - if (json_lt_port != json.end()) - translator.port = *json_lt_port; - else - translator.port = 0; - - auto json_lt_url = json.find("url"); - if (json_lt_url == json.end()) { - std::cerr << "[Error] Value url not found in translator object" << std::endl; + if (!process_server(json, translator)) return false; - } - if (translator.hostname.empty()) { - process_url(*json_lt_url, translator); - } - else { - translator.url = *json_lt_url; - } - - auto json_lt_apiKey = json.find("apiKey"); - if (json_lt_apiKey != json.end()) - translator.apiKey = *json_lt_apiKey; translator_instance = std::make_shared(translator.hostname, translator.port, translator.url, translator.tls, translator.apiKey); } else if (translator.type == "lingvatranslate") { - auto json_lt_hostname = json.find("hostname"); - if (json_lt_hostname != json.end()) - translator.hostname = *json_lt_hostname; - else - translator.hostname = {}; - - auto json_lt_tls = json.find("tls"); - if (json_lt_tls != json.end()) - translator.tls = *json_lt_tls; - else - translator.tls = false; - - auto json_lt_port = json.find("port"); - if (json_lt_port != json.end()) - translator.port = *json_lt_port; - else - translator.port = 0; - - auto json_lt_url = json.find("url"); - if (json_lt_url == json.end()) { - std::cerr << "[Error] Value url not found in translator object" << std::endl; + if (!process_server(json, translator)) return false; - } - if (translator.hostname.empty()) { - process_url(*json_lt_url, translator); - } - else { - translator.url = *json_lt_url; - } translator_instance = std::make_shared(translator.hostname, translator.port, translator.url, translator.tls); } diff --git a/src/translator/mozhi/mozhi.cpp b/src/translator/mozhi/mozhi.cpp index 93b18d5..398cea2 100644 --- a/src/translator/mozhi/mozhi.cpp +++ b/src/translator/mozhi/mozhi.cpp @@ -46,7 +46,6 @@ const std::vector mozhi::get_languages() const std::string parameters = dpp::utility::make_url_parameters({ {"engine"s, m_engine} }); - dpp::https_client http_request(m_hostname, m_port, m_url + "api/target_languages" + parameters, "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); @@ -88,7 +87,6 @@ const std::string mozhi::translate(const std::string &text, const std::string &s {"to"s, target}, {"text"s, text}, }); - dpp::https_client http_request(m_hostname, m_port, m_url + "api/translate" + parameters, "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); From d6d22d34a80f953a16a08f5e5eb880aa68179708 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 30 Dec 2024 16:09:12 +0100 Subject: [PATCH 48/53] remove unnecessary else condition --- src/core/settings.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 7d68a5f..24181c7 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -215,8 +215,6 @@ bool process_server(const dpp::json &json, translator &translator) auto json_hostname = json.find("hostname"); if (json_hostname != json.end()) translator.hostname = *json_hostname; - else - translator.hostname = {}; auto json_tls = json.find("tls"); if (json_tls != json.end()) From b318df79e1c3703c55345a5c42363835d586bdd1 Mon Sep 17 00:00:00 2001 From: Syping Date: Mon, 30 Dec 2024 16:16:40 +0100 Subject: [PATCH 49/53] README.md: update supported translation engines --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 199f5f8..0e3049c 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,11 @@ Open Source Discord Translation Bot - Compiler with C++17 Support - [D++: A C++ Discord API Library for Bots](https://dpp.dev/) -#### Runtime Dependencies -- [LibreTranslate](https://libretranslate.com/) +#### Supported Translation Engines +- [LibreTranslate](https://libretranslate.com/) (Default) +- [Lingva Translate](https://lingva.ml/) +- [Mozhi](https://codeberg.org/aryak/mozhi) +- [DeepL](https://deepl.com/) (Experimental) #### Build dtranslatebot From 2da43810a1e545a6b1392296a8b69be64c0c5d2f Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 23 Mar 2025 19:15:28 +0100 Subject: [PATCH 50/53] DPPStaticBundle: update DPP to 10.1.2 and OpenSSL to 3.0.16 --- cmake/DPPStaticBundle.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index 73998b2..cde244f 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -55,8 +55,8 @@ set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") set(OPENSSL_PLATFORM_ARG $<$:mingw64>) ExternalProject_Add(OpenSSL - URL https://github.com/openssl/openssl/releases/download/openssl-3.0.15/openssl-3.0.15.tar.gz - URL_HASH SHA256=23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533 + URL https://github.com/openssl/openssl/releases/download/openssl-3.0.16/openssl-3.0.16.tar.gz + URL_HASH SHA256=57e03c50feab5d31b152af2b764f10379aecd8ee92f16c985983ce4a99f7ef86 CONFIGURE_COMMAND ${CMAKE_PASSTHROUGH_ENV} "${PERL_EXECUTABLE}" @@ -78,8 +78,8 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - URL https://github.com/Syping/DPP/archive/067dfb0c5728432dd24f74375173cf0fc8cbc4ca.tar.gz - URL_HASH SHA256=ea794219d32bc58eeb23536b3b18fbc119bd747773c6f7c98cf8e96e6d91693a + URL https://github.com/brainboxdotcc/DPP/releases/download/v10.1.2/DPP-10.1.2.tar.gz + URL_HASH SHA256=587ef044775e6bdd560ec17afc302c1048ebb3454455116d7241431fbb16a823 CMAKE_ARGS -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF From 13d384b14e31f3e7a7ac3254a14673a4aac4ed74 Mon Sep 17 00:00:00 2001 From: Syping Date: Sun, 23 Mar 2025 19:39:46 +0100 Subject: [PATCH 51/53] DPPStaticBundle: OpenSSL build remove no-deprecated --- cmake/DPPStaticBundle.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index cde244f..5ea1000 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -63,7 +63,6 @@ ExternalProject_Add(OpenSSL "/Configure" "--prefix=" $<$:-d> - no-deprecated no-dso no-dtls no-engine From b2da36e5760c8a0a08173b26a300c3a10541630b Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Aug 2025 18:33:46 +0200 Subject: [PATCH 52/53] fix DPP 10.1.0 or newer build errors --- src/translator/deepl/deepl.cpp | 4 ++-- src/translator/deepl/deepl.h | 2 ++ src/translator/libretranslate/libretranslate.cpp | 4 ++-- src/translator/libretranslate/libretranslate.h | 2 ++ src/translator/lingvatranslate/lingvatranslate.cpp | 4 ++-- src/translator/lingvatranslate/lingvatranslate.h | 2 ++ src/translator/mozhi/mozhi.cpp | 4 ++-- src/translator/mozhi/mozhi.h | 2 ++ 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/translator/deepl/deepl.cpp b/src/translator/deepl/deepl.cpp index 94a7dff..e81481c 100644 --- a/src/translator/deepl/deepl.cpp +++ b/src/translator/deepl/deepl.cpp @@ -42,7 +42,7 @@ const std::vector deepl::get_languages() } try { - dpp::https_client http_request(m_hostname, 443, "/v2/languages?type=target", "GET", {}, { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} }, false); + dpp::https_client http_request(&m_cluster, m_hostname, 443, "/v2/languages?type=target", "GET", {}, { {"Authorization"s, "DeepL-Auth-Key " + m_apiKey} }, false); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_array()) { @@ -93,7 +93,7 @@ const std::string deepl::translate(const std::string &text, const std::string &s }; try { - dpp::https_client http_request(m_hostname, 443, "/v2/translate", "POST", json_body.dump(), http_headers, false); + dpp::https_client http_request(&m_cluster, m_hostname, 443, "/v2/translate", "POST", json_body.dump(), http_headers, false); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_object()) { diff --git a/src/translator/deepl/deepl.h b/src/translator/deepl/deepl.h index f1b6aa0..b4e0d0d 100644 --- a/src/translator/deepl/deepl.h +++ b/src/translator/deepl/deepl.h @@ -19,6 +19,7 @@ #ifndef TRANSLATOR_DEEPL_H #define TRANSLATOR_DEEPL_H +#include #include "../../core/translator.h" namespace bot { @@ -31,6 +32,7 @@ namespace bot { const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; private: + dpp::cluster m_cluster; std::string m_apiKey; std::string m_hostname; supported_languages m_languages; diff --git a/src/translator/libretranslate/libretranslate.cpp b/src/translator/libretranslate/libretranslate.cpp index 909dbb3..3d82a89 100644 --- a/src/translator/libretranslate/libretranslate.cpp +++ b/src/translator/libretranslate/libretranslate.cpp @@ -42,7 +42,7 @@ const std::vector libretranslate::get_languages() } try { - dpp::https_client http_request(m_hostname, m_port, m_url + "languages", "GET", {}, {}, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "languages", "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_array()) { @@ -91,7 +91,7 @@ const std::string libretranslate::translate(const std::string &text, const std:: json_body["apiKey"] = m_apiKey; try { - dpp::https_client http_request(m_hostname, m_port, m_url + "translate", "POST", json_body.dump(), http_headers, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "translate", "POST", json_body.dump(), http_headers, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_object()) { diff --git a/src/translator/libretranslate/libretranslate.h b/src/translator/libretranslate/libretranslate.h index 1af2f97..75306a8 100644 --- a/src/translator/libretranslate/libretranslate.h +++ b/src/translator/libretranslate/libretranslate.h @@ -20,6 +20,7 @@ #define TRANSLATOR_LIBRETRANSLATE_H #include +#include #include "../../core/translator.h" namespace bot { @@ -33,6 +34,7 @@ namespace bot { const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; private: + dpp::cluster m_cluster; std::string m_apiKey; std::string m_hostname; supported_languages m_languages; diff --git a/src/translator/lingvatranslate/lingvatranslate.cpp b/src/translator/lingvatranslate/lingvatranslate.cpp index 15c08d1..b8352e5 100644 --- a/src/translator/lingvatranslate/lingvatranslate.cpp +++ b/src/translator/lingvatranslate/lingvatranslate.cpp @@ -43,7 +43,7 @@ const std::vector lingvatranslate::get_languages() } try { - dpp::https_client http_request(m_hostname, m_port, m_url + "api/v1/languages/target", "GET", {}, {}, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/v1/languages/target", "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_object()) { @@ -81,7 +81,7 @@ const std::vector lingvatranslate::get_languages() const std::string lingvatranslate::translate(const std::string &text, const std::string &source, const std::string &target) { try { - dpp::https_client http_request(m_hostname, m_port, m_url + "api/v1/" + source + "/" + target + "/" + dpp::utility::url_encode(text), "GET", {}, {}, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/v1/" + source + "/" + target + "/" + dpp::utility::url_encode(text), "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_object()) { diff --git a/src/translator/lingvatranslate/lingvatranslate.h b/src/translator/lingvatranslate/lingvatranslate.h index 37cf604..805dd9b 100644 --- a/src/translator/lingvatranslate/lingvatranslate.h +++ b/src/translator/lingvatranslate/lingvatranslate.h @@ -20,6 +20,7 @@ #define TRANSLATOR_LINGVATRANSLATE_H #include +#include #include "../../core/translator.h" namespace bot { @@ -33,6 +34,7 @@ namespace bot { const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; private: + dpp::cluster m_cluster; std::string m_hostname; supported_languages m_languages; uint16_t m_port; diff --git a/src/translator/mozhi/mozhi.cpp b/src/translator/mozhi/mozhi.cpp index 398cea2..e5e8ea1 100644 --- a/src/translator/mozhi/mozhi.cpp +++ b/src/translator/mozhi/mozhi.cpp @@ -46,7 +46,7 @@ const std::vector mozhi::get_languages() const std::string parameters = dpp::utility::make_url_parameters({ {"engine"s, m_engine} }); - dpp::https_client http_request(m_hostname, m_port, m_url + "api/target_languages" + parameters, "GET", {}, {}, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/target_languages" + parameters, "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_array()) { @@ -87,7 +87,7 @@ const std::string mozhi::translate(const std::string &text, const std::string &s {"to"s, target}, {"text"s, text}, }); - dpp::https_client http_request(m_hostname, m_port, m_url + "api/translate" + parameters, "GET", {}, {}, !m_tls); + dpp::https_client http_request(&m_cluster, m_hostname, m_port, m_url + "api/translate" + parameters, "GET", {}, {}, !m_tls); if (http_request.get_status() == 200) { const dpp::json response = dpp::json::parse(http_request.get_content()); if (response.is_object()) { diff --git a/src/translator/mozhi/mozhi.h b/src/translator/mozhi/mozhi.h index ac3aba6..8a8735a 100644 --- a/src/translator/mozhi/mozhi.h +++ b/src/translator/mozhi/mozhi.h @@ -20,6 +20,7 @@ #define TRANSLATOR_MOZHI_H #include +#include #include "../../core/translator.h" namespace bot { @@ -33,6 +34,7 @@ namespace bot { const std::string translate(const std::string &text, const std::string &source, const std::string &target) override; private: + dpp::cluster m_cluster; std::string m_engine; std::string m_hostname; supported_languages m_languages; From c76210a30c5f1068469c63ab2b6b972cf9db8bb7 Mon Sep 17 00:00:00 2001 From: Syping Date: Wed, 6 Aug 2025 18:34:02 +0200 Subject: [PATCH 53/53] DPPStaticBundle: update DPP to 10.1.3 and OpenSSL to 3.0.17 --- cmake/DPPStaticBundle.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/DPPStaticBundle.cmake b/cmake/DPPStaticBundle.cmake index 5ea1000..3c214ed 100644 --- a/cmake/DPPStaticBundle.cmake +++ b/cmake/DPPStaticBundle.cmake @@ -55,8 +55,8 @@ set(ZLIB_INSTALL_DIR "${INSTALL_DIR}") set(OPENSSL_PLATFORM_ARG $<$:mingw64>) ExternalProject_Add(OpenSSL - URL https://github.com/openssl/openssl/releases/download/openssl-3.0.16/openssl-3.0.16.tar.gz - URL_HASH SHA256=57e03c50feab5d31b152af2b764f10379aecd8ee92f16c985983ce4a99f7ef86 + URL https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz + URL_HASH SHA256=dfdd77e4ea1b57ff3a6dbde6b0bdc3f31db5ac99e7fdd4eaf9e1fbb6ec2db8ce CONFIGURE_COMMAND ${CMAKE_PASSTHROUGH_ENV} "${PERL_EXECUTABLE}" @@ -77,8 +77,8 @@ ExternalProject_Get_Property(OpenSSL INSTALL_DIR) set(OpenSSL_INSTALL_DIR "${INSTALL_DIR}") ExternalProject_Add(DPP - URL https://github.com/brainboxdotcc/DPP/releases/download/v10.1.2/DPP-10.1.2.tar.gz - URL_HASH SHA256=587ef044775e6bdd560ec17afc302c1048ebb3454455116d7241431fbb16a823 + URL https://github.com/brainboxdotcc/DPP/archive/refs/tags/v10.1.3.tar.gz + URL_HASH SHA256=a32d94dcd6b23430afff82918234e4e28e0616bd2ddf743c5ab2f1778c5a600b CMAKE_ARGS -DAVX_TYPE=AVX0 -DBUILD_SHARED_LIBS=OFF @@ -86,6 +86,7 @@ ExternalProject_Add(DPP ${CMAKE_PASSTHROUGH_ARGS} "-DCMAKE_INSTALL_PREFIX=" -DDPP_BUILD_TEST=OFF + -DDPP_NO_CORO=ON -DDPP_NO_VCPKG=ON -DRUN_LDCONFIG=OFF "-DOpenSSL_ROOT=${OpenSSL_INSTALL_DIR}"