From 169e01b53d105cee6a9d32a466e1ec23fe150a5b Mon Sep 17 00:00:00 2001 From: soler_j Date: Sun, 4 May 2025 02:19:10 +0200 Subject: Mise à jour de la configuration et amélioration de la gestion des actions : - Changement du répertoire source CMake dans settings.json. - Ajout de la gestion des données et des intentions par défaut lors du démarrage du bot. - Modification des signatures des fonctions delete_action et handle_actions pour retourner des résultats plus détaillés. - Amélioration de la logique de réponse dans handle_actions pour gérer les erreurs et les succès. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 2 +- app/cmd/main.go | 30 +++- app/internal/create_bot.go | 4 +- bot/include/actions/delete.hpp | 2 +- bot/include/handle_actions.hpp | 2 +- bot/src/actions/delete.cpp | 25 ++-- bot/src/handle_actions.cpp | 24 +++- bot/src/main.cpp | 310 ++++++++++++++++++++++++----------------- 8 files changed, 252 insertions(+), 147 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 798eedd..42e44f8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "cmake.sourceDirectory": "/Users/jeremy/Documents/bot-creator-api/bot", + "cmake.sourceDirectory": "/home/exa/perso/bot-creator-api/bot", "files.associations": { "map": "cpp", "__bit_reference": "cpp", diff --git a/app/cmd/main.go b/app/cmd/main.go index 2232c8e..c42a013 100644 --- a/app/cmd/main.go +++ b/app/cmd/main.go @@ -69,8 +69,36 @@ func main() { return } // let's check if the bot is already running + // let's parse the body. + var body map[string]interface{} - bot, err = internal.Start(bot) + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + log.Printf("[SERVER] Error decoding JSON: %v", err) + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + if body["intents"] == nil { + // intents are the default ones we can set the default ones + body["intents"] = "3243773" + } + if body["data"] == nil { + // data are the default ones we can set the default ones + fmt.Printf("[SERVER] No data found, setting default ones") + body["data"] = map[string]interface{}{} + } + + // let's convert the data to a string + data, err := json.Marshal(body["data"]) + if err != nil { + log.Printf("[SERVER] Error marshaling JSON: %v", err) + http.Error(w, "Error marshaling JSON", http.StatusInternalServerError) + return + } + + fmt.Printf("[SERVER] Starting bot with data: %s", string(data)) + + bot, err = internal.Start(bot, string(data), fmt.Sprint(body["intents"])) if err != nil { log.Printf("[SERVER] Error starting bot: %v", err) http.Error(w, "Error starting bot", http.StatusInternalServerError) diff --git a/app/internal/create_bot.go b/app/internal/create_bot.go index ce70cdd..ed4d59e 100644 --- a/app/internal/create_bot.go +++ b/app/internal/create_bot.go @@ -17,10 +17,10 @@ type Bot struct { client *http.Client } -func Start(b *Bot) (*Bot, error) { +func Start(b *Bot, data string, intents string) (*Bot, error) { // Create a new ZeroMQ socket specifically for this bot // Configuration du bot - cmd := exec.Command("./discord-bot", b.BotToken, b.ProcessID) // Passer le port unique + cmd := exec.Command("./discord-bot", b.BotToken, b.ProcessID, data, intents) cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, // Permet de tuer le processus enfant si nécessaire } diff --git a/bot/include/actions/delete.hpp b/bot/include/actions/delete.hpp index 8e4766e..bd582ec 100644 --- a/bot/include/actions/delete.hpp +++ b/bot/include/actions/delete.hpp @@ -1,3 +1,3 @@ #include -dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann::json &action, const std::unordered_map &key_values, dpp::user &user_ptr, dpp::cluster *cluster); +dpp::task> delete_action(const dpp::slashcommand_t &event, const nlohmann::json &action, const std::unordered_map &key_values, dpp::user &user_ptr, dpp::cluster *cluster); diff --git a/bot/include/handle_actions.hpp b/bot/include/handle_actions.hpp index 107e93d..c1dff78 100644 --- a/bot/include/handle_actions.hpp +++ b/bot/include/handle_actions.hpp @@ -1,3 +1,3 @@ #include -dpp::task handle_actions(const dpp::slashcommand_t& event, const nlohmann::json& actions, const std::unordered_map& key_values); +dpp::task> handle_actions(const dpp::slashcommand_t& event, const nlohmann::json& actions, const std::unordered_map& key_values); diff --git a/bot/src/actions/delete.cpp b/bot/src/actions/delete.cpp index da74bbf..d8748d2 100644 --- a/bot/src/actions/delete.cpp +++ b/bot/src/actions/delete.cpp @@ -1,4 +1,5 @@ #include "../../include/utils.hpp" +#include const std::unordered_map> error_messages_map = { @@ -16,7 +17,7 @@ const std::unordered_map> err }} }; -dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann::json &action, +dpp::task> delete_action(const dpp::slashcommand_t &event, const nlohmann::json &action, const std::unordered_map &key_values, dpp::user &user_ptr, dpp::cluster *cluster) { @@ -51,14 +52,14 @@ dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann:: if (!member_ptr || !bot_member_ptr) { event.edit_response(error_messages.at("error_perm_channel")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error_perm_channel")}}; } const bool has_permissions = channel_ptr->get_user_permissions(*member_ptr).has(dpp::p_manage_messages) && channel_ptr->get_user_permissions(*bot_member_ptr).has(dpp::p_manage_messages); if (!has_permissions) { event.edit_response(error_messages.at("error_perm_channel")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error_perm_channel")}}; } int amount = 0; @@ -73,13 +74,13 @@ dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann:: if (amount < 1 || amount > 100) { event.edit_response(error_messages.at("error_amount")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error_amount")}}; } } catch (const std::exception &e) { event.edit_response(error_messages.at("error")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error")}}; } } } @@ -92,14 +93,14 @@ dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann:: if (callback.is_error()) { event.edit_response(error_messages.at("error")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error")}}; } const auto &messages = callback.get(); if (messages.empty()) { event.edit_response(error_messages.at("error_no_messages")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error_no_messages")}}; } std::vector msg_ids; @@ -122,10 +123,16 @@ dpp::task delete_action(const dpp::slashcommand_t &event, const nlohmann:: if (delete_result.is_error()) { event.edit_response(error_messages.at("error")); - co_return false; + co_return std::unordered_map{{"error", error_messages.at("error")}}; } + amount = msg_ids.size(); } } - co_return true; + std::string key = action.contains("key") ? action["key"] : "delete"; + + co_return std::unordered_map{ + {"success", "Messages deleted successfully."}, + {key + ".amount", std::to_string(amount)}, + }; } diff --git a/bot/src/handle_actions.cpp b/bot/src/handle_actions.cpp index 0b3f2ff..ef6e1c0 100644 --- a/bot/src/handle_actions.cpp +++ b/bot/src/handle_actions.cpp @@ -1,6 +1,7 @@ #include "../include/actions/delete.hpp" -dpp::task handle_actions(const dpp::slashcommand_t &event, const nlohmann::json &actions, const std::unordered_map &key_values) +dpp::task> handle_actions(const dpp::slashcommand_t &event, const nlohmann::json &actions, const std::unordered_map &key_values) { + std::unordered_map workflow_key_values = {{}}; dpp::cluster *cluster = event.owner; dpp::user user_ptr = event.command.get_issuing_user(); dpp::async thinking = event.co_thinking(false); @@ -15,12 +16,23 @@ dpp::task handle_actions(const dpp::slashcommand_t &event, const nlohmann: std::string action_type = action["type"]; if (action_type == "delete_messages" && event.command.is_guild_interaction()) { - auto return_value = co_await delete_action(event, action, key_values, user_ptr, cluster); + std::unordered_map return_value = co_await delete_action(event, action, key_values, user_ptr, cluster); co_await thinking; // if it's a false, we need to return false ! - if (!return_value) + if (return_value.contains("error")) { - co_return false; + co_return return_value; + } + else + { + // return everything expect the success message + for (const auto &[key, value] : return_value) + { + if (key != "success") + { + workflow_key_values[key] = value; + } + } } @@ -30,10 +42,10 @@ dpp::task handle_actions(const dpp::slashcommand_t &event, const nlohmann: { co_await thinking; - co_return true; + co_return workflow_key_values; } } } co_await thinking; - co_return true; + co_return workflow_key_values; } diff --git a/bot/src/main.cpp b/bot/src/main.cpp index 1edac34..73bae00 100644 --- a/bot/src/main.cpp +++ b/bot/src/main.cpp @@ -1,140 +1,198 @@ -#include "../include/utils.hpp" -#include "../include/http_webhook_server.hpp" #include "../include/handle_actions.hpp" +#include "../include/http_webhook_server.hpp" +#include "../include/utils.hpp" #include - - -dpp::activity_type activity_type_from_string(const std::string& type) { - if (type == "playing") { - return dpp::activity_type::at_game; - } else if (type == "streaming") { - return dpp::activity_type::at_streaming; - } else if (type == "listening") { - return dpp::activity_type::at_listening; - } else if (type == "watching") { - return dpp::activity_type::at_watching; - } else if (type == "custom") { - return dpp::activity_type::at_custom; - } else if (type == "competing") { - return dpp::activity_type::at_competing; - } else { - return dpp::activity_type::at_game; // Default to "playing" if the type is unknown - } +#include + +dpp::activity_type activity_type_from_string(const std::string &type) { + if (type == "playing") { + return dpp::activity_type::at_game; + } else if (type == "streaming") { + return dpp::activity_type::at_streaming; + } else if (type == "listening") { + return dpp::activity_type::at_listening; + } else if (type == "watching") { + return dpp::activity_type::at_watching; + } else if (type == "custom") { + return dpp::activity_type::at_custom; + } else if (type == "competing") { + return dpp::activity_type::at_competing; + } else { + return dpp::activity_type::at_game; // Default to "playing" if the type is + // unknown + } } -int main(int argc, char* argv[]) { - if (argc > 2) { - setenv("BOT_TOKEN", argv[1], 1); - setenv("PORT", argv[2], 1); +int main(int argc, char *argv[]) { + int intents = dpp::i_default_intents; + std::unique_ptr json_data = + std::make_unique(); + if (argc > 2) { + setenv("BOT_TOKEN", argv[1], 1); + setenv("PORT", argv[2], 1); + if (argc > 3) { + json_data = + std::make_unique(nlohmann::json::parse(argv[3])); + } + if (argc > 4) { + intents = std::stoi(argv[4]); + } + } + + const std::string BOT_TOKEN = getenv("BOT_TOKEN"); + const std::string PORT = getenv("PORT"); + dpp::cluster bot(BOT_TOKEN, intents); + + bot.on_log(dpp::utility::cout_logger()); + + bot.on_slashcommand([&json_data, &bot]( + const dpp::slashcommand_t &event) -> dpp::task { + std::unordered_map key_values = + app::generate_key_values(event); + std::string command_name = event.command.get_command_name(); + std::string response = "Interaction found, but no response found."; + + if (!command_name.empty() && json_data->contains(command_name)) { + auto &command_data = (*json_data)[command_name]; + if (command_data.contains("actions")) { + auto &action = command_data["actions"]; + // Actions are a list of Objects + if (action.is_array()) { + std::cout << "Executing → Actions: " << action.dump() << std::endl; + std::unordered_map + already_returned_message = + co_await handle_actions(event, action, key_values); + if (already_returned_message.contains("error")) { + std::cout << "Error: " << already_returned_message["error"] + << std::endl; + } else { + std::cout << "Actions executed successfully." << std::endl; + // let's push the values to the key_values + for (const auto &[key, value] : already_returned_message) { + if (key != "success") { + key_values[key] = value; + } + } + } + } + // let's retrieve final response. + response = command_data["response"]; + auto update_response = app::update_string(response, key_values); + std::cout << "Executing → Response: " << update_response << std::endl; + co_return event.edit_response(update_response); + } + if (command_data.contains("response")) { + response = command_data["response"]; + } + // } - const std::string BOT_TOKEN = getenv("BOT_TOKEN"); - const std::string PORT = getenv("PORT"); - - dpp::cluster bot(BOT_TOKEN); - std::unique_ptr json_data = std::make_unique(); - - bot.on_log(dpp::utility::cout_logger()); - - bot.on_slashcommand([&json_data, &bot](const dpp::slashcommand_t& event) -> dpp::task { - std::unordered_map key_values = app::generate_key_values(event); - std::string command_name = event.command.get_command_name(); - std::string response = "Interaction found, but no response found."; - - if (!command_name.empty() && json_data->contains(command_name)) { - auto& command_data = (*json_data)[command_name]; - if (command_data.contains("actions")) { - auto& action = command_data["actions"]; - // Actions are a list of Objects - if (action.is_array()) { - std::cout << "Executing → Actions: " << action.dump() << std::endl; - auto already_returned_message = co_await handle_actions(event, action, key_values); - if(!already_returned_message) { - std::cout << "Command: " << command_name << " → Action: " << action.dump() << std::endl; - co_return; - }else { - // This mean we need to edit the response, not reply - if(command_data.contains("response")) { - response = command_data["response"]; - std::cout << "Command: " << command_name << " → Response: " << response << std::endl; - } - event.edit_response(app::update_string(response, key_values)); - co_return; + auto update_response = app::update_string(response, key_values); + std::cout << "Executing → Response: " << update_response << std::endl; + co_return event.reply(update_response); + }); + + bot.on_ready([&bot, &json_data, &PORT](const dpp::ready_t &event) { + if (dpp::run_once()) { + std::thread http_thread([&json_data, &PORT, &bot]() { + try { + HttpWebhookServer server(std::stoi(PORT), [&json_data, &bot]( + const HttpWebhookServer:: + HttpRequest &req) { + HttpWebhookServer::HttpResponse res; + + if (req.method == "POST") { + res.status_code = 200; + res.headers["Content-Type"] = "application/json"; + + try { + nlohmann::json body_json = app::json_from_string(req.body); + res.body = R"({"received": "POST request received"})"; + + if (body_json.contains("command")) { + if (body_json["command"] == "update") { + json_data = + std::make_unique(body_json["data"]); + } else if (body_json["command"] == "update_status") { + std::string status = body_json.contains("status") + ? body_json["status"] + : "online"; + std::string activity = body_json.contains("activity") + ? body_json["activity"] + : ""; + std::string activity_status = + body_json.contains("activity_status") + ? body_json["activity_status"] + : ""; + std::string activity_url = + body_json.contains("activity_url") + ? body_json["activity_url"] + : ""; + std::string activity_type = + body_json.contains("activity_type") + ? body_json["activity_type"] + : "playing"; + dpp::presence p; + if (status == "online") { + p = dpp::presence( + dpp::presence_status::ps_online, + dpp::activity( + activity_type_from_string(activity_type), + activity, activity_status, activity_url)); + } else if (status == "offline") { + p = dpp::presence( + dpp::presence_status::ps_offline, + dpp::activity( + activity_type_from_string(activity_type), + activity, activity_status, activity_url)); + } else if (status == "dnd") { + p = dpp::presence( + dpp::presence_status::ps_dnd, + dpp::activity( + activity_type_from_string(activity_type), + activity, activity_status, activity_url)); + } else if (status == "idle") { + p = dpp::presence( + dpp::presence_status::ps_idle, + dpp::activity( + activity_type_from_string(activity_type), + activity, activity_status, activity_url)); + } else if (status == "invisible") { + p = dpp::presence( + dpp::presence_status::ps_invisible, + dpp::activity( + activity_type_from_string(activity_type), + activity, activity_status, activity_url)); } + bot.set_presence(p); + } + res.body = + R"({"status": "success", "message": "Command executed successfully"})"; } + } catch (const std::exception &e) { + res.status_code = 400; + res.body = std::string("{\"error\": \"") + e.what() + "\"}"; + } + } else { + res.status_code = 400; + res.headers["Content-Type"] = "text/plain"; + res.body = "Invalid request method."; } - if (command_data.contains("response")) { - response = command_data["response"]; - std::cout << "Command: " << command_name << " → Response: " << response << std::endl; - } - } - - event.reply(app::update_string(response, key_values)); - }); - - bot.on_ready([&bot, &json_data, &PORT](const dpp::ready_t& event) { - if (dpp::run_once()) { - std::thread http_thread([&json_data, &PORT,&bot]() { - try { - HttpWebhookServer server(std::stoi(PORT), [&json_data, &bot](const HttpWebhookServer::HttpRequest& req) { - HttpWebhookServer::HttpResponse res; - - if (req.method == "POST") { - res.status_code = 200; - res.headers["Content-Type"] = "application/json"; - try { - nlohmann::json body_json = app::json_from_string(req.body); - res.body = R"({"received": "POST request received"})"; + return res; + }); - if (body_json.contains("command")) { - if(body_json["command"] == "update"){ - json_data = std::make_unique(body_json["data"]); - }else if(body_json["command"] == "update_status"){ - std::string status = body_json.contains("status") ? body_json["status"] : "online"; - std::string activity = body_json.contains("activity") ? body_json["activity"] : ""; - std::string activity_status = body_json.contains("activity_status") ? body_json["activity_status"] : ""; - std::string activity_url = body_json.contains("activity_url") ? body_json["activity_url"] : ""; - std::string activity_type = body_json.contains("activity_type") ? body_json["activity_type"] : "playing"; - dpp::presence p; - if (status == "online") { - p = dpp::presence(dpp::presence_status::ps_online, dpp::activity(activity_type_from_string(activity_type), activity, activity_status, activity_url)); - } else if (status == "offline") { - p = dpp::presence(dpp::presence_status::ps_offline, dpp::activity(activity_type_from_string(activity_type), activity, activity_status, activity_url)); - } else if (status == "dnd") { - p = dpp::presence(dpp::presence_status::ps_dnd, dpp::activity(activity_type_from_string(activity_type), activity, activity_status, activity_url)); - } else if (status == "idle") { - p = dpp::presence(dpp::presence_status::ps_idle, dpp::activity(activity_type_from_string(activity_type), activity, activity_status, activity_url)); - } else if (status == "invisible") { - p = dpp::presence(dpp::presence_status::ps_invisible, dpp::activity(activity_type_from_string(activity_type), activity, activity_status, activity_url)); - } - bot.set_presence(p); - } - res.body = R"({"status": "success", "message": "Command executed successfully"})"; - } - } catch (const std::exception& e) { - res.status_code = 400; - res.body = std::string("{\"error\": \"") + e.what() + "\"}"; - } - } else { - res.status_code = 400; - res.headers["Content-Type"] = "text/plain"; - res.body = "Invalid request method."; - } - - return res; - }); - - std::cout << "[BOT] Webhook server running on port " << PORT << "..." << std::endl; - server.start(); - } catch (const std::exception& e) { - std::cerr << "[BOT] Server error: " << e.what() << std::endl; - } - }); - - http_thread.detach(); + std::cout << "[BOT] Webhook server running on port " << PORT << "..." + << std::endl; + server.start(); + } catch (const std::exception &e) { + std::cerr << "[BOT] Server error: " << e.what() << std::endl; } - }); + }); + + http_thread.detach(); + } + }); - bot.start(dpp::st_wait); + bot.start(dpp::st_wait); } -- cgit v1.2.3