Chat global

Chat
Loading the chat ...
Notificações via Di...
 
Notifications
Clear all

Notificações via Discord

4 Posts
4 Usuários
5 Reactions
46 Visualizações
(@corleonneh)
Posts: 2
Apoiador Ativo
Topic starter
 

Salvee

Esse é um sistema que desenvolvi há bastante tempo. Acabei deixando de lado, mas revisitando achei interessante — e acredito que possa ser útil para alguém.

O sistema envia notificações em um canal do Discord por meio de Webhooks.
Atualmente está configurado para alertas de Boss, Drops e Kills, mas é fácil adaptar, adicionar novas funções e melhorar o que já existe.

 

Arquivos principais: 

Spoiler
AlertaDiscord.cpp
#include "alertadiscord.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <nlohmann/json.hpp>
#include <string>
#include <curl/curl.h>
#include <sstream>

DiscordAlertManager::DiscordAlertManager(size_t numThreads, std::chrono::milliseconds delay)
    : stop(false), sendDelay(delay) {
    for (size_t i = 0; i < numThreads; ++i) {
        threads.emplace_back(&DiscordAlertManager::worker, this);
    }
}

DiscordAlertManager::~DiscordAlertManager() {
    {
        std::unique_lock<std::mutex> lock(queueMutex);
        stop = true;
    }
    cv.notify_all();
    for (std::thread& thread : threads) {
        if (thread.joinable()) {
            thread.join();
        }
    }
}

void DiscordAlertManager::sendDiscordAlert(const std::string& webhook_url, const std::string& message) {
    if (!validateWebhookUrl(webhook_url)) {
        std::cerr << "[Discord] URL de webhook invalida: " << webhook_url << std::endl;
        return;
    }

    {
        std::lock_guard<std::mutex> lock(queueMutex);
        taskQueue.emplace(webhook_url, message);
    }
    cv.notify_one();
}

void DiscordAlertManager::worker() {
    while (true) {
        std::tuple<std::string, std::string> task;

        {
            std::unique_lock<std::mutex> lock(queueMutex);
            cv.wait(lock, [this] { return stop || !taskQueue.empty(); });

            if (stop && taskQueue.empty()) {
                return;
            }

            task = std::move(taskQueue.front());
            taskQueue.pop();
        }

        alertadiscord_impl(std::get<0>(task), std::get<1>(task));

        std::this_thread::sleep_for(sendDelay);
    }
}

// Callback para capturar a resposta do Discord
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response) {
    size_t totalSize = size * nmemb;
    response->append((char*)contents, totalSize);
    return totalSize;
}

bool DiscordAlertManager::validateWebhookUrl(const std::string& url) {
    // Valida se a URL é um webhook do Discord
    return url.find("https://discord.com/api/webhooks/") == 0 ||
           url.find("https://discordapp.com/api/webhooks/") == 0;
}

void DiscordAlertManager::alertadiscord_impl(const std::string& webhook_url, const std::string& message) {
    using json = nlohmann::json;

    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cerr << "[Discord] Falha ao inicializar cURL" << std::endl;
        return;
    }

    // Cria o JSON usando a biblioteca nlohmann (escape automático)
    json payload = {
        {"content", nullptr},
        {"embeds", json::array({
            {
                {"description", message},
                {"color", 4062976}
            }
        })},
        {"attachments", json::array()}
    };

    std::string json_data = payload.dump();
    std::string response;

    // Configura headers
    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, "Content-Type: application/json");

    // Configura opções do cURL
    curl_easy_setopt(curl, CURLOPT_URL, webhook_url.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data.c_str());
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // Timeout de 10 segundos
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L); // Timeout de conexão de 5 segundos

    // Executa a requisição
    CURLcode res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        std::cerr << "[Discord] Erro ao enviar: " << curl_easy_strerror(res) << std::endl;
    } else {
        long http_code = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);

        if (http_code >= 200 && http_code < 300) {
            std::cout << "[Discord] Mensagem enviada com sucesso (HTTP " << http_code << ")" << std::endl;
        } else {
            std::cerr << "[Discord] Erro HTTP " << http_code << ": " << response << std::endl;
        }
    }

    // Limpeza
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
}
Spoiler
AlertaDiscord.h
#ifndef ALERTADISCORD_H
#define ALERTADISCORD_H

#include <string>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <tuple>
#include <vector>
#include <chrono>

class DiscordAlertManager {
public:
    static DiscordAlertManager& getInstance(size_t numThreads = 5, std::chrono::milliseconds delay = std::chrono::milliseconds(5000)) {
        static DiscordAlertManager instance(numThreads, delay);
        return instance;
    }

    DiscordAlertManager(const DiscordAlertManager&) = delete;
    DiscordAlertManager& operator=(const DiscordAlertManager&) = delete;

    void sendDiscordAlert(const std::string& webhook_url, const std::string& message);

    ~DiscordAlertManager(); 

private:
    DiscordAlertManager(size_t numThreads, std::chrono::milliseconds delay); 
    void worker(); 
    void alertadiscord_impl(const std::string& webhook_url, const std::string& message);
    bool validateWebhookUrl(const std::string& url); 

    std::queue<std::tuple<std::string, std::string>> taskQueue;

    std::mutex queueMutex;
    std::condition_variable cv;
    bool stop;
    std::vector<std::thread> threads;

    std::chrono::milliseconds sendDelay; 
};

#endif // ALERTADISCORD_H

 

No server.ini, adicione as WebHooks:

Spoiler
Server.ini
[DiscordAlerta]
WebhookDrops= https://discord.com/api/webhooks/123456789/SuaWebhookKeyAqui 
WebhookPVP= https://discord.com/api/webhooks/987654321/OutraWebhookKeyAqui 
WebhookBOSS= https://discord.com/api/webhooks/555555555/MaisUmaWebhookKey 

No fileread.cpp, faça a chamada para carregar e salvar as WebHooks:

Spoiler
fileread.cpp
std::string WebhookURLDrops;
std::string WebhookURLPVP;
std::string WebhookURLBOSS;

{
    char szBuf[512] = { 0 };  
    LeIniStr("DiscordAlerta", "WebhookDrops", "Server\\Config\\Server.ini", szBuf);
    WebhookURLDrops = szBuf;
}
{
    char szBuf[512] = { 0 };
    LeIniStr("DiscordAlerta", "WebhookPVP", "Server\\Config\\Server.ini", szBuf);
    WebhookURLPVP = szBuf;
}
{
    char szBuf[512] = { 0 };
    LeIniStr("DiscordAlerta", "WebhookBOSS", "Server\\Config\\Server.ini", szBuf);
    WebhookURLBOSS = szBuf;
}

Exemplos de uso

Exemplo no OnServer para notificar sobre Boss:

Spoiler
Onsever.cpp
#include "..//alertadiscord.h"

extern  std::string WebhookURLDrops;
extern  std::string WebhookURLPVP;
extern  std::string WebhookURLBOSS;

// Boss Alert
char mensagemBOSS[70] = { 0 };
wsprintf(mensagemBOSS, " Alerta Boss> %s nasce em 5 minutos no mapa %s!", 
         lpBossMonster->MasterMonster->szName, 
         MapasEventos[lpStgArea->lpField->FieldCode][1]);
DiscordAlertManager::getInstance().sendDiscordAlert(WebhookURLBOSS, mensagemBOSS);

Exemplo para notificar sobre Drop:

Spoiler
Alerta.cpp
#include "..//alertadiscord.h"

extern  std::string WebhookURLDrops;
extern  std::string WebhookURLPVP;
extern  std::string WebhookURLBOSS;

wsprintf(mensagem, " [ %s ] Dropou [ %s ]. ", PlayerName, sLog.ItemName);
DiscordAlertManager::getInstance().sendDiscordAlert(WebhookURLDrops, mensagem);

 
Postado : 04/12/2025 4:38 am
PoTrAs18, Prad, ViGo and 2 people reacted
Raka
 Raka
(@rakabr)
Posts: 46
Admin
 

show! 😉


Apenas criando um legado 😊

 
Postado : 04/12/2025 11:49 am
(@datway)
Posts: 49
Conselheiro
 

Top demais!


 
Postado : 04/12/2025 1:04 pm
ALUCARD
(@alucard)
Posts: 115
Guia Valioso
 

eu uso um que avisa , "coisas importantes" direto no telegram.


#DEFINE -> | |
The Witcher

 
Postado : 04/12/2025 1:19 pm
Compartilhar:

Anúncio