diff --git a/source/business_logic/CMakeLists.txt b/source/business_logic/CMakeLists.txt index 52966b2..cf6d53f 100644 --- a/source/business_logic/CMakeLists.txt +++ b/source/business_logic/CMakeLists.txt @@ -34,6 +34,7 @@ set(MODEL_HEADERS model/config/english_words_info_api_config/english_words_info_api_config_model.hpp model/metrics/metrics_model.hpp model/config/tg_root_user_config/tg_root_user_config_model.hpp + model/config/meme_api_config/meme_api_config_model.hpp ) set(MODEL_SOURCES @@ -45,6 +46,7 @@ set(MODEL_SOURCES model/config/english_words_info_api_config/english_words_info_api_config_model.cpp model/metrics/metrics_model.cpp model/config/tg_root_user_config/tg_root_user_config_model.cpp + model/config/meme_api_config/meme_api_config_model.cpp ) set(CONTROLLER_HEADERS @@ -62,6 +64,8 @@ set(CONTROLLER_HEADERS controller/config/english_words_info_api_config/english_words_info_api_config_controller.hpp controller/db/metrics_db/metrics_db_controller.hpp controller/config/tg_root_user_config/tg_root_user_config_controller.hpp + controller/api/meme_api/meme_api_controller.hpp + controller/config/meme_api_config/meme_api_config_controller.hpp ) set(CONTROLLER_SOURCES @@ -79,6 +83,8 @@ set(CONTROLLER_SOURCES controller/config/english_words_info_api_config/english_words_info_api_config_controller.cpp controller/db/metrics_db/metrics_db_controller.cpp controller/config/tg_root_user_config/tg_root_user_config_controller.cpp + controller/api/meme_api/meme_api_controller.cpp + controller/config/meme_api_config/meme_api_config_controller.cpp ) add_library(${LIBRARY_NAME} STATIC diff --git a/source/business_logic/controller/api/meme_api/meme_api_controller.cpp b/source/business_logic/controller/api/meme_api/meme_api_controller.cpp new file mode 100644 index 0000000..217ee33 --- /dev/null +++ b/source/business_logic/controller/api/meme_api/meme_api_controller.cpp @@ -0,0 +1,87 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#include "meme_api_controller.hpp" + +// --------------------------------------------------------------------------------------------------------------------- +nljson AMeme_API_Controller::Json_Response{}; + +// --------------------------------------------------------------------------------------------------------------------- +AMeme_API_Controller::AMeme_API_Controller(const AMeme_API_Config& meme_api_config) : + ABase_API_Controller{ "https://programming-memes-images.p.rapidapi.com/v1/memes" }, Headers{ nullptr } +{ + Headers = curl_slist_append(Headers, std::format("X-RapidAPI-Key: {}", meme_api_config.Get_API_Key()).c_str()); + Headers = curl_slist_append(Headers, std::format("X-RapidAPI-Host: {}", meme_api_config.Get_API_Host()).c_str()); +} + +// --------------------------------------------------------------------------------------------------------------------- +AMeme_API_Controller::~AMeme_API_Controller() +{ + curl_slist_free_all(Headers); +} + +// --------------------------------------------------------------------------------------------------------------------- +std::string AMeme_API_Controller::Get_Meme() +{ + if (Meme_Links_Stack.empty()) + { + Send_Request("GET"); + + for (std::size_t i{}; !Json_Response.empty() && i < 12; ++i) // 12 - default count of meme links + { + Meme_Links_Stack.push(Json_Response[i]["image"]); + } + } + + auto tmp{ Meme_Links_Stack.top() }; + Meme_Links_Stack.pop(); + + return tmp; +} + +// --------------------------------------------------------------------------------------------------------------------- +bool AMeme_API_Controller::Send_Request(std::string_view request_type) +{ + if (Curl = curl_easy_init(); Curl != nullptr) + { + curl_easy_setopt(Curl, CURLOPT_URL, Url.data()); + curl_easy_setopt(Curl, CURLOPT_CUSTOMREQUEST, request_type.data()); + curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, Headers); + curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, &ABase_API_Controller::Write_Callback); + curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &AMeme_API_Controller::Json_Response); + + curl_easy_perform(Curl); + + std::size_t resp_code{}; + curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &resp_code); + + curl_easy_cleanup(Curl); + + if (resp_code != EHTTP_STATUS::OK) + { + return false; + } + } + + return Curl != nullptr; +} \ No newline at end of file diff --git a/source/business_logic/controller/api/meme_api/meme_api_controller.hpp b/source/business_logic/controller/api/meme_api/meme_api_controller.hpp new file mode 100644 index 0000000..e21a54c --- /dev/null +++ b/source/business_logic/controller/api/meme_api/meme_api_controller.hpp @@ -0,0 +1,50 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#pragma once + +#include +#include +#include +#include + +#include + +#include + +class AMeme_API_Controller : public ABase_API_Controller +{ +public: + explicit AMeme_API_Controller(const AMeme_API_Config& meme_api_config); + ~AMeme_API_Controller() override; + + std::string Get_Meme(); + +private: + bool Send_Request(std::string_view request_type); + +private: + std::stack> Meme_Links_Stack; + static nljson Json_Response; + curl_slist* Headers; +}; \ No newline at end of file diff --git a/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.cpp b/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.cpp new file mode 100644 index 0000000..bf7ed9a --- /dev/null +++ b/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.cpp @@ -0,0 +1,42 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#include "meme_api_config_controller.hpp" + +// --------------------------------------------------------------------------------------------------------------------- +std::optional AMeme_API_Config_Controller::Load_Config() +{ + char* api_key{ std::getenv("MEME_API_KEY") }; + if (!api_key) + { + return std::nullopt; + } + + char* api_host{ std::getenv("MEME_API_HOST") }; + if (!api_host) + { + return std::nullopt; + } + + return AMeme_API_Config{ api_key, api_host }; +} \ No newline at end of file diff --git a/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.hpp b/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.hpp new file mode 100644 index 0000000..524e689 --- /dev/null +++ b/source/business_logic/controller/config/meme_api_config/meme_api_config_controller.hpp @@ -0,0 +1,37 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#pragma once + +#include + +#include + +class AMeme_API_Config_Controller +{ +public: + constexpr AMeme_API_Config_Controller() = default; + constexpr ~AMeme_API_Config_Controller() = default; + + static std::optional Load_Config(); +}; \ No newline at end of file diff --git a/source/business_logic/model/config/english_words_info_api_config/english_words_info_api_config_model.hpp b/source/business_logic/model/config/english_words_info_api_config/english_words_info_api_config_model.hpp index 8942f61..cc7a40e 100644 --- a/source/business_logic/model/config/english_words_info_api_config/english_words_info_api_config_model.hpp +++ b/source/business_logic/model/config/english_words_info_api_config/english_words_info_api_config_model.hpp @@ -29,7 +29,7 @@ class AEnglish_Words_Info_API_Config { public: explicit AEnglish_Words_Info_API_Config(std::string_view api_key, std::string_view api_host); - ~AEnglish_Words_Info_API_Config() = default; + constexpr ~AEnglish_Words_Info_API_Config() = default; [[nodiscard]] std::string_view Get_API_Key() const; [[nodiscard]] std::string_view Get_API_Host() const; diff --git a/source/business_logic/model/config/meme_api_config/meme_api_config_model.cpp b/source/business_logic/model/config/meme_api_config/meme_api_config_model.cpp new file mode 100644 index 0000000..62c02b1 --- /dev/null +++ b/source/business_logic/model/config/meme_api_config/meme_api_config_model.cpp @@ -0,0 +1,41 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#include "meme_api_config_model.hpp" + +// --------------------------------------------------------------------------------------------------------------------- +AMeme_API_Config::AMeme_API_Config(std::string_view api_key, std::string_view api_host) : + API_Key{ api_key }, API_Host{ api_host } +{ } + +// --------------------------------------------------------------------------------------------------------------------- +std::string_view AMeme_API_Config::Get_API_Key() const +{ + return API_Key; +} + +// --------------------------------------------------------------------------------------------------------------------- +std::string_view AMeme_API_Config::Get_API_Host() const +{ + return API_Host; +} diff --git a/source/business_logic/model/config/meme_api_config/meme_api_config_model.hpp b/source/business_logic/model/config/meme_api_config/meme_api_config_model.hpp new file mode 100644 index 0000000..102dcea --- /dev/null +++ b/source/business_logic/model/config/meme_api_config/meme_api_config_model.hpp @@ -0,0 +1,41 @@ +// MIT License + +// Copyright (c) 2024 The B1T Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +#pragma once + +#include +#include + +class AMeme_API_Config +{ +public: + explicit AMeme_API_Config(std::string_view api_key, std::string_view api_host); + constexpr ~AMeme_API_Config() = default; + + [[nodiscard]] std::string_view Get_API_Key() const; + [[nodiscard]] std::string_view Get_API_Host() const; + +private: + std::string_view API_Key; + std::string_view API_Host; +}; \ No newline at end of file diff --git a/source/view/handlers/message_handler/message_handler.cpp b/source/view/handlers/message_handler/message_handler.cpp index 51ed3bd..a4ec324 100644 --- a/source/view/handlers/message_handler/message_handler.cpp +++ b/source/view/handlers/message_handler/message_handler.cpp @@ -27,8 +27,8 @@ std::mutex AMessage_Handler::Mutex{ }; // --------------------------------------------------------------------------------------------------------------------- -AMessage_Handler::AMessage_Handler(TgBot::Bot& tg_bot, AUser_DB_Controller& user_db_controller, AState_DB_Controller& state_db_controller, ATask_DB_Controller& task_db_controller, AStats_DB_Controller& stats_db_controller, AEnglish_Words_Info_API_Controller& english_words_api_controller, AMetrics_DB_Controller& metrics_db_controller, ATG_Root_User_Config& tg_root_user_cfg) : - TG_Bot{ tg_bot }, User_DB_Controller{ user_db_controller }, State_DB_Controller{ state_db_controller }, Task_DB_Controller{ task_db_controller }, Stats_DB_Controller{ stats_db_controller }, English_Words_API_Controller{ english_words_api_controller }, Metrics_DB_Controller{ metrics_db_controller }, TG_Root_User_Cfg{ tg_root_user_cfg }, Words_Api_Requests_Limiter{ 2500, 24 } +AMessage_Handler::AMessage_Handler(TgBot::Bot& tg_bot, AUser_DB_Controller& user_db_controller, AState_DB_Controller& state_db_controller, ATask_DB_Controller& task_db_controller, AStats_DB_Controller& stats_db_controller, AMeme_API_Controller& meme_api_controller, AEnglish_Words_Info_API_Controller& english_words_api_controller, AMetrics_DB_Controller& metrics_db_controller, ATG_Root_User_Config& tg_root_user_cfg) : + TG_Bot{ tg_bot }, TG_Root_User_Cfg{ tg_root_user_cfg }, User_DB_Controller{ user_db_controller }, State_DB_Controller{ state_db_controller }, Task_DB_Controller{ task_db_controller }, Stats_DB_Controller{ stats_db_controller },Metrics_DB_Controller{ metrics_db_controller }, English_Words_API_Controller{ english_words_api_controller }, Meme_API_Controller{ meme_api_controller }, Words_Api_Requests_Limiter{ 2500, 24 }, Meme_Api_Requests_Limiter{ 150, 24 } { } // --------------------------------------------------------------------------------------------------------------------- @@ -167,6 +167,16 @@ void AMessage_Handler::Bind_Commands() TG_Bot.getApi().sendMessage(message->chat->id, AMessage_Reply::Get_Not_Found_Synonym_Msg()); }); + TG_Bot.getEvents().onCommand(SMessage_Commands::Get_Meme.data(), [this](TgBot::Message::Ptr message) -> void + { + if (!Meme_Api_Requests_Limiter.Can_Send_Request()) + { + TG_Bot.getApi().sendMessage(message->chat->id, AMessage_Reply::Get_Limit_Api_Requests_Msg()); + return; + } + + TG_Bot.getApi().sendMessage(message->chat->id, Meme_API_Controller.Get_Meme()); + }); TG_Bot.getEvents().onCommand(SMessage_Commands::Metrics_Range.data(), [this](TgBot::Message::Ptr message) -> void { if (!Is_Root_User(message->from->id)) diff --git a/source/view/handlers/message_handler/message_handler.hpp b/source/view/handlers/message_handler/message_handler.hpp index 511dbd9..62d3261 100644 --- a/source/view/handlers/message_handler/message_handler.hpp +++ b/source/view/handlers/message_handler/message_handler.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -50,7 +51,7 @@ class AMessage_Handler { public: - explicit AMessage_Handler(TgBot::Bot& tg_bot, AUser_DB_Controller& user_db_controller, AState_DB_Controller& state_db_controller, ATask_DB_Controller& task_db_controller, AStats_DB_Controller& stats_db_controller, AEnglish_Words_Info_API_Controller& english_words_api_controller, AMetrics_DB_Controller& metrics_db_controller, ATG_Root_User_Config& tg_root_user_cfg); + explicit AMessage_Handler(TgBot::Bot& tg_bot, AUser_DB_Controller& user_db_controller, AState_DB_Controller& state_db_controller, ATask_DB_Controller& task_db_controller, AStats_DB_Controller& stats_db_controller, AMeme_API_Controller& meme_api_controller, AEnglish_Words_Info_API_Controller& english_words_api_controller, AMetrics_DB_Controller& metrics_db_controller, ATG_Root_User_Config& tg_root_user_cfg); constexpr ~AMessage_Handler() = default; void Bind_Commands(); @@ -80,5 +81,7 @@ class AMessage_Handler AStats_DB_Controller& Stats_DB_Controller; AMetrics_DB_Controller& Metrics_DB_Controller; AEnglish_Words_Info_API_Controller& English_Words_API_Controller; + AMeme_API_Controller& Meme_API_Controller; AApi_Requests_Limiter Words_Api_Requests_Limiter; + AApi_Requests_Limiter Meme_Api_Requests_Limiter; }; \ No newline at end of file diff --git a/source/view/main.cpp b/source/view/main.cpp index c4edcd7..d9ea339 100644 --- a/source/view/main.cpp +++ b/source/view/main.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include @@ -49,7 +51,7 @@ int main() return -1; } - auto english_words_info_api_cfg{AEnglish_Words_Info_API_Config_Controller::Load_Config() }; + auto english_words_info_api_cfg{ AEnglish_Words_Info_API_Config_Controller::Load_Config() }; if (english_words_info_api_cfg == std::nullopt) { ALogger_Utility::Error("Error reading english words api config data"); @@ -62,6 +64,13 @@ int main() ALogger_Utility::Error("Error reading tg root user cfg data"); return -1; } + + auto meme_api_cfg{ AMeme_API_Config_Controller::Load_Config() }; + if (meme_api_cfg == std::nullopt) + { + ALogger_Utility::Error("Error reading meme api cfg data"); + return -1; + } #endif TgBot::Bot tg_bot{ tg_cfg->Get_TG_Token().data() }; @@ -72,8 +81,9 @@ int main() AStats_DB_Controller stats_db_controller{ *db_cfg }; AMetrics_DB_Controller metrics_db_controller{ *db_cfg }; AEnglish_Words_Info_API_Controller english_words_api_controller{ *english_words_info_api_cfg }; + AMeme_API_Controller meme_api_controller{ *meme_api_cfg }; - AMessage_Handler message_handler{ tg_bot, user_db_controller, state_db_controller, task_db_controller, stats_db_controller, english_words_api_controller, metrics_db_controller, *tg_root_user_cfg }; + AMessage_Handler message_handler{ tg_bot, user_db_controller, state_db_controller, task_db_controller, stats_db_controller, meme_api_controller, english_words_api_controller, metrics_db_controller, *tg_root_user_cfg }; message_handler.Bind_Commands(); std::thread metrics_thread([&message_handler]() -> void diff --git a/source/view/texts/message_commands/message_commands.cpp b/source/view/texts/message_commands/message_commands.cpp index 0cf650c..15bf19e 100644 --- a/source/view/texts/message_commands/message_commands.cpp +++ b/source/view/texts/message_commands/message_commands.cpp @@ -35,4 +35,5 @@ constinit std::string_view SMessage_Commands::Metrics_Range{"metrics_range" }; constinit std::string_view SMessage_Commands::Get_Metrics{ "get_metrics" }; constinit std::string_view SMessage_Commands::Get_Best_Metric{ "get_best_metric" }; constinit std::string_view SMessage_Commands::Get_Antonym{ "ant" }; -constinit std::string_view SMessage_Commands::Get_Synonym{ "syn" }; \ No newline at end of file +constinit std::string_view SMessage_Commands::Get_Synonym{ "syn" }; +constinit std::string_view SMessage_Commands::Get_Meme{ "meme" }; \ No newline at end of file diff --git a/source/view/texts/message_commands/message_commands.hpp b/source/view/texts/message_commands/message_commands.hpp index ee8172b..05cd7f0 100644 --- a/source/view/texts/message_commands/message_commands.hpp +++ b/source/view/texts/message_commands/message_commands.hpp @@ -40,4 +40,5 @@ struct SMessage_Commands constinit static std::string_view Get_Best_Metric; constinit static std::string_view Get_Antonym; constinit static std::string_view Get_Synonym; + constinit static std::string_view Get_Meme; }; \ No newline at end of file