我正在尝试将 webhook 发送到以下网址:
我的代码:
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 返回数据。
我正在努力让它向我的不和谐频道发送消息。它不起作用,我不确定为什么。
上面 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);
}
这是我的实现,它可能对有的人有用 有关的问题(还有一个使用 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
}