使用 Wininet 发送 Discord Webhook

问题描述 投票:0回答:2

我正在尝试将 webhook 发送到以下网址:

https://discord.com/api/webhooks/781132765195747359/XDXDH08HsJ0GzkYFKvlDFO6QE3MtzKOqIaKpBruLmqLDJPvlLQEuQQNjr_R8x4y9zCjx

我的代码:

HINTERNET hIntSession = InternetOpenA((""), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);

if (!hIntSession)
{
    return request_data;
}

HINTERNET hHttpSession = InternetConnectA(hIntSession, ("discord.com"), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);

if (!hHttpSession)
{
    return request_data;
}

HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, ("POST"), url.c_str()
    , 0, 0, 0, INTERNET_FLAG_RELOAD, 0);

if (!hHttpSession)
{
    return request_data;
}

char* szHeaders = ("Content-Type: application/json\r\nUser-Agent: License");
char* szRequest = ("{ \"content\": \"test\" }");

if (!HttpSendRequest(hHttpRequest, NULL, 0, szRequest, strlen(szRequest)))
{
    return request_data;
}

CHAR szBuffer[1024] = { 0 };
DWORD dwRead = 0;

while (InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer) - 1, &dwRead) && dwRead)
{
    request_data.append(szBuffer, dwRead);
}

InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);

我还不能发布那个请求,url 返回数据。

我正在努力让它向我的不和谐频道发送消息。它不起作用,我不确定为什么。

c discord wininet
2个回答
1
投票

上面 Remy 的评论提到缺少标头。这与其他一些小错误一起得到了修复。你可以对照你所拥有的进行检查。

LPCTSTR szUserAgent = _T("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43");
LPCTSTR szHost = _T("discordapp.com");
LPCTSTR szUrlPath = _T("/api/webhooks/740632765195747359/m8FGH08HsJ0GzkYFKvlDFO6QE3MtzKOqIaKpZH4LmqLDJPvlLQEuQQNjr_R8x4y9zCjx");
LPCTSTR szAcceptTypes[] = { _T("application/json"), NULL };

LPCTSTR szContentTypeHeader = _T("Content-Type: application/json");
LPCSTR szPostData = "{ \"username\":\"ANDY from StackOverflow\", \"content\": \"Test string again\" }";
const DWORD dwPostDataLength = strlen(szPostData);

HINTERNET hIntSession = InternetOpen(szUserAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hIntSession) {
    HINTERNET hHttpSession = InternetConnect(hIntSession, szHost,
        INTERNET_DEFAULT_HTTPS_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
    if (hHttpSession) {
        HINTERNET hHttpRequest = HttpOpenRequest(hHttpSession, _T("POST"), szUrlPath,
            NULL, NULL, szAcceptTypes,
            (INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE |
                INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE), 0);
        if (hHttpRequest) {
            if (HttpSendRequest(hHttpRequest,
                szContentTypeHeader, -1, (LPVOID)szPostData,
                dwPostDataLength)) {

                DWORD dwStatusCode = 0;
                {
                    TCHAR szStatusCode[32] = { 0 };
                    DWORD dwStatusCodeSize = sizeof(szStatusCode) / sizeof(TCHAR);
                    if (HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE,
                        szStatusCode, &dwStatusCodeSize, NULL)) {
                        dwStatusCode = _ttoi(szStatusCode);
                    }
                }

                //
                // dwStatusCode: [200,299] means success, any other value
                // means something went wrong
                //

                unsigned char* lpResponse = NULL;
                DWORD dwTotalSize = 0;
                {
                    unsigned char* lpBuffer = (unsigned char*)malloc(2048);
                    DWORD dwRead = 0;
                    while (InternetReadFile(hHttpRequest, lpBuffer, sizeof(lpBuffer), &dwRead) && dwRead) {
                        unsigned char* lpTmp = (unsigned char*)realloc(lpResponse, dwTotalSize + dwRead);
                        if (lpTmp) {
                            lpResponse = lpTmp;
                            memcpy(&lpResponse[dwTotalSize], lpBuffer, dwRead);
                            dwTotalSize += dwRead;
                        }
                        dwRead = 0;
                    }
                    free(lpBuffer);
                }

                //
                // lpResponse now has your data with length of dwTotalSize.
                // Do with it what you want.
                // Keep in mind that a successful request will return
                // no data.
                //

                if (lpResponse) { free(lpResponse); }
            }
            InternetCloseHandle(hHttpRequest);
        }
        InternetCloseHandle(hHttpSession);
    }
    InternetCloseHandle(hIntSession);
}

0
投票

这是我的实现,它可能对有的人有用 有关的问题(还有一个使用 dpp 的 linux 或其他操作系统的实现)

#if defined(WIN32)
void WebHook::closeConnection(HINTERNET hSession /* = nullptr*/, HINTERNET hConnect /* = nullptr*/, HINTERNET hRequest /* = nullptr*/) {
    InternetCloseHandle(hSession);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hRequest);
}
#endif

std::string WebHook::getPayload(std::string title, std::string message, int color) {
    time_t now;
    time(&now);
    struct tm tm;

#ifdef _MSC_VER
    gmtime_s(&tm, &now);
#else
    gmtime_r(&now, &tm);
#endif

    char time_buf[sizeof "00:00"];
    strftime(time_buf, sizeof time_buf, "%R", &tm);

    std::stringstream footer_text;
    footer_text
        << g_configManager().getString(IP) << ":"
        << g_configManager().getNumber(GAME_PORT) << " | "
        << time_buf << " UTC";

    Json::Value footer(Json::objectValue);
    footer["text"] = Json::Value(footer_text.str());

    Json::Value embed(Json::objectValue);
    embed["title"] = Json::Value(title);
    embed["description"] = Json::Value(message);
    embed["footer"] = footer;
    if (color >= 0) {
        embed["color"] = color;
    }

    Json::Value embeds(Json::arrayValue);
    embeds.append(embed);

    Json::Value payload(Json::objectValue);
    payload["embeds"] = embeds;

    Json::StreamWriterBuilder builder;
    builder["commentSyle"] = "None";
    builder["indentation"] = "";

    std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
    std::stringstream out;
    writer->write(payload, &out);
    return out.str();
}

void WebHook::sendMessage(std::string title, std::string message, int color) {
    std::string webhookUrl = g_configManager().getString(DISCORD_WEBHOOK_URL);
    std::string payload = getPayload(title, message, color);
    // Break empty informations
    if (title.empty() || message.empty() || webhookUrl.empty() || payload.empty()) {
        return;
    }

#if defined(WIN32)
    HINTERNET hSession = InternetOpenA((LPCSTR)STATUS_SERVER_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hSession) {
        SPDLOG_ERROR("Failed to create WinHTTP session");
        return;
    }

    HINTERNET hConnect = InternetConnectA(hSession, "discordapp.com", INTERNET_DEFAULT_HTTPS_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) {
        closeConnection(hSession);
        SPDLOG_ERROR("[WebHook] Failed to connect to Discord");
        return;
    }

    HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", webhookUrl.c_str(), 0, 0, 0, INTERNET_FLAG_SECURE, 0);
    if (!hRequest) {
        closeConnection(hSession, hConnect);
        SPDLOG_ERROR("[WebHook] Failed to create HTTP request");
        return;
    }

    std::string contentTypeHeader = "Content-Type: application/json";
    if (!HttpAddRequestHeadersA(hRequest, contentTypeHeader.c_str(), contentTypeHeader.length(), HTTP_ADDREQ_FLAG_REPLACE)) {
        closeConnection(hSession, hConnect, hRequest);
        SPDLOG_ERROR("[WebHook] Failed to set request headers");
        return;
    }

    // Try to send message
    DWORD dataSize = static_cast<DWORD>(payload.length());
    if (!HttpSendRequestA(hRequest, 0, 0, (LPVOID)payload.c_str(), dataSize)) {
        closeConnection(hSession, hConnect, hRequest);
        SPDLOG_ERROR("[WebHook] Failed to send HTTP request");
        return;
    }

    DWORD statusCode = 0;
    DWORD statusCodeSize = sizeof(statusCode);
    HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statusCode, &statusCodeSize, 0);

    if (statusCode < 200 || statusCode >= 300) {
        closeConnection(hSession, hConnect, hRequest);
        SPDLOG_ERROR("[WebHook] Received unsuccessful HTTP status code {}", statusCode);
        return;
    }

    closeConnection(hSession, hConnect, hRequest);
#elif
    dpp::cluster bot("");

    bot.on_log(dpp::utility::cout_logger());

    // Construct a webhook object using the URL you got from Discord
    dpp::webhook wh("https://discord.com/" + webhookUrl);

    // Send a message with this webhook
    bot.execute_webhook_sync(wh, dpp::message(payload));
#endif
}

© www.soinside.com 2019 - 2024. All rights reserved.