diff --git a/Dice/DiceMsgSend.cpp b/Dice/DiceMsgSend.cpp index 40a0cadf..c4a80130 100644 --- a/Dice/DiceMsgSend.cpp +++ b/Dice/DiceMsgSend.cpp @@ -1,151 +1,151 @@ -/* - * _______ ________ ________ ________ __ - * | __ \ |__ __| | _____| | _____| | | - * | | | | | | | | | |_____ | | - * | | | | | | | | | _____| |__| - * | |__| | __| |__ | |_____ | |_____ __ - * |_______/ |________| |________| |________| |__| - * - * Dice! QQ Dice Robot for TRPG - * Copyright (C) 2018-2019 w4123溯洄 - * - * This program is free software: you can redistribute it and/or modify it under the terms - * of the GNU Affero General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License along with this - * program. If not, see . - */ -#include -#include -#include -#include -#include "OneBotAPI.h" -#include "DiceMsgSend.h" -#include "MsgFormat.h" -#include "GlobalVar.h" -#include "DiceConsole.h" -using namespace std; - -chatInfo::chatInfo(long long u, long long g, long long c) :uid(u), gid(g), chid(c) { - if (gid) { - if (chid)type = msgtype::Channel; - else type = msgtype::Group; - } - else { - if (chid)type = msgtype::ChannelPrivate; - else type = msgtype::Private; - } -} -chatInfo::chatInfo(const AttrObject& obj):uid(obj.get_ll("uid")), chid(obj.get_ll("chid")) { - type = (gid = obj.get_ll("gid")) - ? chid ? msgtype::ChannelPrivate : msgtype::Private - : chid ? msgtype::Channel : msgtype::Group; -} -bool chatInfo::operator<(const chatInfo& other)const { - return type == other.type - ? uid == other.uid - ? gid == other.gid - ? chid < other.chid - : gid < other.gid - : uid < other.uid - : type < other.type; -} -bool chatInfo::operator==(const chatInfo& other)const { - return uid == other.uid - && gid == other.gid - && chid == other.chid; -} -fifo_json to_json(const chatInfo& chat) { - fifo_json j = fifo_json::object(); - if (chat.chid)j["chid"] = chat.chid; - if (chat.gid)j["gid"] = chat.gid; - if (chat.uid)j["uid"] = chat.uid; - return j; -} -chatInfo chatInfo::from_json(const fifo_json& chat) { - if (chat.is_null())return {}; - long long uid{ 0 }, gid{ 0 }, chid{ 0 }; - if (chat.count("uid"))chat["uid"].get_to(uid); - if (chat.count("gid"))chat["gid"].get_to(gid); - if (chat.count("chid"))chat["chid"].get_to(chid); - return chatInfo{ uid,gid,chid }; -} - -// 消息发送存储结构体 -struct msg_t -{ - string msg; - chatInfo target{}; - msg_t() = default; - - msg_t(string msg, chatInfo ct) : msg(move(msg)),target(ct) - { - } -}; - -// 消息发送队列 -std::queue msgQueue; - -// 消息发送队列锁 -mutex msgQueueMutex; - -void AddMsgToQueue(const string& msg, long long target_id) -{ - lock_guard lock_queue(msgQueueMutex); - msgQueue.emplace(msg_t(msg, { target_id })); -} - -void AddMsgToQueue(const std::string& msg, chatInfo ct) -{ - lock_guard lock_queue(msgQueueMutex); - msgQueue.emplace(msg_t(msg, ct)); -} - - -void SendMsg() -{ - msgSendThreadRunning = true; - while (Enabled) - { - msg_t msg; - { - lock_guard lock_queue(msgQueueMutex); - if (!msgQueue.empty()) - { - msg = msgQueue.front(); - msgQueue.pop(); - } - } - if (!msg.msg.empty()) - { - if (int pos = msg.msg.find_first_not_of(" \t\r\n"); pos && pos != string::npos) { - msg.msg = msg.msg.substr(pos); - } - if (int pos = msg.msg.find('\f'); pos != string::npos) - { - AddMsgToQueue(msg.msg.substr(pos + 1), msg.target); - msg.msg = msg.msg.substr(0, pos); - } - if (msg.target.type == msgtype::Private) - { - api::sendPrivateMsg(msg.target.uid, msg.msg); - } - else if (msg.target.type == msgtype::Group) - { - api::sendGroupMsg(msg.target.gid, msg.msg); - } - else if (msg.target.type == msgtype::Channel) - { - api::sendChannelMsg(msg.target.gid, msg.target.chid, msg.msg); - } - } - if (msgQueue.size() > 2)this_thread::sleep_for(chrono::milliseconds(console["SendIntervalBusy"])); - else this_thread::sleep_for(chrono::milliseconds(console["SendIntervalIdle"])); - } - msgSendThreadRunning = false; -} +/* + * _______ ________ ________ ________ __ + * | __ \ |__ __| | _____| | _____| | | + * | | | | | | | | | |_____ | | + * | | | | | | | | | _____| |__| + * | |__| | __| |__ | |_____ | |_____ __ + * |_______/ |________| |________| |________| |__| + * + * Dice! QQ Dice Robot for TRPG + * Copyright (C) 2018-2019 w4123婧磩 + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +#include +#include +#include +#include +#include "OneBotAPI.h" +#include "DiceMsgSend.h" +#include "MsgFormat.h" +#include "GlobalVar.h" +#include "DiceConsole.h" +using namespace std; + +chatInfo::chatInfo(long long u, long long g, long long c) :uid(u), gid(g), chid(c) { + if (gid) { + if (chid)type = msgtype::Channel; + else type = msgtype::Group; + } + else { + if (chid)type = msgtype::ChannelPrivate; + else type = msgtype::Private; + } +} +chatInfo::chatInfo(const AttrObject& obj):uid(obj.get_ll("uid")), chid(obj.get_ll("chid")) { + type = (gid = obj.get_ll("gid")) + ? chid ? msgtype::ChannelPrivate : msgtype::Private + : chid ? msgtype::Channel : msgtype::Group; +} +bool chatInfo::operator<(const chatInfo& other)const { + return type == other.type + ? uid == other.uid + ? gid == other.gid + ? chid < other.chid + : gid < other.gid + : uid < other.uid + : type < other.type; +} +bool chatInfo::operator==(const chatInfo& other)const { + return uid == other.uid + && gid == other.gid + && chid == other.chid; +} +fifo_json to_json(const chatInfo& chat) { + fifo_json j = fifo_json::object(); + if (chat.chid)j["chid"] = chat.chid; + if (chat.gid)j["gid"] = chat.gid; + if (chat.uid)j["uid"] = chat.uid; + return j; +} +chatInfo chatInfo::from_json(const fifo_json& chat) { + if (chat.is_null())return {}; + long long uid{ 0 }, gid{ 0 }, chid{ 0 }; + if (chat.count("uid"))chat["uid"].get_to(uid); + if (chat.count("gid"))chat["gid"].get_to(gid); + if (chat.count("chid"))chat["chid"].get_to(chid); + return chatInfo{ uid,gid,chid }; +} + +// 娑堟伅鍙戦佸瓨鍌ㄧ粨鏋勪綋 +struct msg_t +{ + string msg; + chatInfo target{}; + msg_t() = default; + + msg_t(string msg, chatInfo ct) : msg(move(msg)),target(ct) + { + } +}; + +// 娑堟伅鍙戦侀槦鍒 +std::queue msgQueue; + +// 娑堟伅鍙戦侀槦鍒楅攣 +mutex msgQueueMutex; + +void AddMsgToQueue(const string& msg, long long target_id) +{ + lock_guard lock_queue(msgQueueMutex); + msgQueue.emplace(msg_t(msg, { target_id })); +} + +void AddMsgToQueue(const std::string& msg, chatInfo ct) +{ + lock_guard lock_queue(msgQueueMutex); + msgQueue.emplace(msg_t(msg, ct)); +} + + +void SendMsg() +{ + msgSendThreadRunning = true; + while (Enabled) + { + msg_t msg; + { + lock_guard lock_queue(msgQueueMutex); + if (!msgQueue.empty()) + { + msg = msgQueue.front(); + msgQueue.pop(); + } + } + if (!msg.msg.empty()) + { + if (int pos = msg.msg.find_first_not_of(" \t\r\n"); pos && pos != string::npos) { + msg.msg = msg.msg.substr(pos); + } + if (int pos = msg.msg.find('\f'); pos != string::npos) + { + AddMsgToQueue(msg.msg.substr(pos + 1), msg.target); + msg.msg = msg.msg.substr(0, pos); + } + if (msg.target.type == msgtype::Private) + { + api::sendPrivateMsg(msg.target.uid, msg.msg); + } + else if (msg.target.type == msgtype::Group) + { + api::sendGroupMsg(msg.target.gid, msg.msg); + } + else if (msg.target.type == msgtype::Channel) + { + api::sendChannelMsg(msg.target.gid, msg.target.chid, msg.msg); + } + } + if (msgQueue.size() > 2)this_thread::sleep_for(chrono::milliseconds(console["SendIntervalBusy"])); + else this_thread::sleep_for(chrono::milliseconds(console["SendIntervalIdle"])); + } + msgSendThreadRunning = false; +} diff --git a/Dice/DiceNetwork.cpp b/Dice/DiceNetwork.cpp index ed470fdf..05eaa89d 100644 --- a/Dice/DiceNetwork.cpp +++ b/Dice/DiceNetwork.cpp @@ -1,419 +1,419 @@ -/* - * _______ ________ ________ ________ __ - * | __ \ |__ __| | _____| | _____| | | - * | | | | | | | | | |_____ | | - * | | | | | | | | | _____| |__| - * | |__| | __| |__ | |_____ | |_____ __ - * |_______/ |________| |________| |________| |__| - * - * Dice! QQ Dice Robot for TRPG - * Copyright (C) 2018-2019 w4123溯洄 - * - * This program is free software: you can redistribute it and/or modify it under the terms - * of the GNU Affero General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License along with this - * program. If not, see . - */ -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#pragma comment(lib, "WinInet.lib") -#else -#include -#endif - -#include -#include -#include "GlobalVar.h" -#include "MsgFormat.h" -#include "DiceNetwork.h" -#include "StrExtern.hpp" - -namespace Network -{ -#ifndef _WIN32 - thread_local CURLcode lastError; - - size_t curlWriteToString(void *contents, size_t size, size_t nmemb, std::string *s) - { - size_t newLength = size*nmemb; - s->append((char*)contents, newLength); - return newLength; - } -#endif - - std::string getLastErrorMsg() - { -#ifdef _WIN32 - DWORD dwError = GetLastError(); - if (dwError == ERROR_INTERNET_EXTENDED_ERROR) - { - DWORD size = 512; - wchar_t* szFormatBuffer = new wchar_t[size]; - if (InternetGetLastResponseInfoW(&dwError, szFormatBuffer, &size)) - { - std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); - while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); - delete[] szFormatBuffer; - return ret; - } - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - size++; - delete[] szFormatBuffer; - szFormatBuffer = new wchar_t[size]; - if (InternetGetLastResponseInfoW(&dwError, szFormatBuffer, &size)) - { - std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); - while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); - delete[] szFormatBuffer; - return ret; - } - delete[] szFormatBuffer; - return getMsg("strUnableToGetErrorMsg"); - } - delete[] szFormatBuffer; - return getMsg("strUnableToGetErrorMsg"); - } - wchar_t szFormatBuffer[512]; - DWORD dwBaseLength = FormatMessageW( - FORMAT_MESSAGE_FROM_HMODULE, // dwFlags - GetModuleHandleW(L"wininet.dll"), // lpSource - dwError, // dwMessageId - MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), // dwLanguageId - szFormatBuffer, // lpBuffer - 512, // nSize - nullptr); - - if (dwBaseLength == 0) - { - dwBaseLength = FormatMessageW( - FORMAT_MESSAGE_FROM_HMODULE, // dwFlags - GetModuleHandleW(L"wininet.dll"), // lpSource - dwError, // dwMessageId - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // dwLanguageId - szFormatBuffer, // lpBuffer - 512, // nSize - nullptr); - } - - if (dwBaseLength) - { - std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); - while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); - return ret; - } - return getMsg("strUnableToGetErrorMsg"); -#else - return curl_easy_strerror(lastError); -#endif - } - - bool POST(const string& url, const string& postContent, const string& postHeader, std::string& des) - { - std::string strHeader = postHeader.empty() ? "Content-Type: application/x-www-form-urlencoded" : postHeader; -#ifdef _WIN32 - std::string UserAgent{ DiceRequestHeader }; - static std::regex re{ R"(User-Agent: ([^\r\n]*))" }; - std::smatch match; - if (std::regex_search(strHeader, match, re)) { - UserAgent = match[1].str(); - } - URL_COMPONENTSA urlComponents{}; - urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); - urlComponents.dwHostNameLength = 1024; - urlComponents.dwPasswordLength = 0; - urlComponents.dwSchemeLength = 1024; - urlComponents.dwUrlPathLength = 1024; - urlComponents.dwUserNameLength = 0; - urlComponents.dwExtraInfoLength = 1024; - urlComponents.lpszHostName = nullptr; - urlComponents.lpszPassword = nullptr; - urlComponents.lpszScheme = nullptr; - urlComponents.lpszUrlPath = nullptr; - urlComponents.lpszUserName = nullptr; - urlComponents.lpszExtraInfo = nullptr; - if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) - { - des = getLastErrorMsg(); - return false; - } - - if (urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) - { - des = "Unknown URL Scheme"; - return false; - } - - const char* acceptTypes[] = {"*/*", nullptr}; - - const HINTERNET hInternet = InternetOpenA(UserAgent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); - const HINTERNET hConnect = InternetConnectA(hInternet, std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength).c_str(), urlComponents.nPort, nullptr, nullptr, - INTERNET_SERVICE_HTTP, 0, 0); - const HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", (std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength) + std::string(urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength)).c_str(), "HTTP/1.1", nullptr, acceptTypes, - (urlComponents.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0), 0); - const BOOL res = HttpSendRequestA(hRequest, strHeader.c_str(), strHeader.length(), (void*)postContent.c_str(), postContent.length()); - - - if (res) - { - DWORD dwRetCode = 0; - DWORD dwBufferLength = sizeof(dwRetCode); - if (!HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwRetCode, &dwBufferLength, - nullptr)) - { - des = getLastErrorMsg(); - goto InternetClose; - } - if (dwRetCode != 200) - { - des = getMsg("strRequestRetCodeErr", AttrVars{ {"error", std::to_string(dwRetCode)} }); - goto InternetClose; - } - DWORD preRcvCnt; - if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) - { - des = getLastErrorMsg(); - goto InternetClose; - } - if (preRcvCnt == 0) - { - des = getMsg("strRequestNoResponse"); - return false; - } - std::string finalRcvData; - while (preRcvCnt) - { - char* rcvData = new char[preRcvCnt]; - DWORD rcvCnt; - - if (!InternetReadFile(hRequest, rcvData, preRcvCnt, &rcvCnt)) - { - des = getLastErrorMsg(); - delete[] rcvData; - goto InternetClose; - } - - if (rcvCnt != preRcvCnt){ - des = getMsg("strUnknownErr"); - delete[] rcvData; - goto InternetClose; - } - - finalRcvData += std::string(rcvData, rcvCnt); - - if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) { - des = getLastErrorMsg(); - delete[] rcvData; - goto InternetClose; - } - - delete[] rcvData; - } - - des = finalRcvData; - - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return true; - } - des = getLastErrorMsg(); -InternetClose: - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return false; - -#else - - CURL* curl; - curl = curl_easy_init(); - if (curl) - { - struct curl_slist* header = NULL; - header = curl_slist_append(header, strHeader.c_str()); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_USERAGENT, DiceRequestHeader); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postContent.c_str()); - curl_easy_setopt(curl, CURLOPT_POST, 1L); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteToString); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &des); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - - lastError = curl_easy_perform(curl); - if (lastError != CURLE_OK) - { - des = getLastErrorMsg(); - } - curl_slist_free_all(header); - curl_easy_cleanup(curl); - return lastError == CURLE_OK; - } - return false; -#endif - - } - - bool GET(const string& url, std::string& des) { -#ifdef _WIN32 - URL_COMPONENTSA urlComponents{}; - urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); - urlComponents.dwHostNameLength = 1024; - urlComponents.dwPasswordLength = 0; - urlComponents.dwSchemeLength = 1024; - urlComponents.dwUrlPathLength = 1024; - urlComponents.dwUserNameLength = 0; - urlComponents.dwExtraInfoLength = 1024; - urlComponents.lpszHostName = nullptr; - urlComponents.lpszPassword = nullptr; - urlComponents.lpszScheme = nullptr; - urlComponents.lpszUrlPath = nullptr; - urlComponents.lpszUserName = nullptr; - urlComponents.lpszExtraInfo = nullptr; - if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) - { - des = getLastErrorMsg(); - return false; - } - - if (urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) - { - des = "Unknown URL Scheme"; - return false; - } - - const char* acceptTypes[] = {"*/*", nullptr}; - - const HINTERNET hInternet = InternetOpenA(DiceRequestHeader, INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); - const HINTERNET hConnect = InternetConnectA(hInternet, std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength).c_str(), urlComponents.nPort, nullptr, nullptr, - INTERNET_SERVICE_HTTP, 0, 0); - const HINTERNET hRequest = HttpOpenRequestA(hConnect, "GET", - (std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength) + std::string(urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength)).c_str(), - "HTTP/1.1", nullptr, acceptTypes, (urlComponents.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0) | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0); - const BOOL res = HttpSendRequestA(hRequest, nullptr, 0, nullptr, 0); - - - if (res) - { - DWORD dwRetCode = 0; - DWORD dwBufferLength = sizeof(dwRetCode); - if (!HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwRetCode, &dwBufferLength, - nullptr)) - { - des = getLastErrorMsg(); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return false; - } - if (dwRetCode != 200) - { - des = getMsg("strRequestRetCodeErr", AttrVars{ {"error", std::to_string(dwRetCode)} }); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return false; - } - DWORD preRcvCnt; - if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) - { - des = getLastErrorMsg(); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return false; - } - if (preRcvCnt == 0) - { - des = getMsg("strRequestNoResponse"); - return false; - } - std::string finalRcvData; - while (preRcvCnt) - { - char* rcvData = new char[preRcvCnt]; - DWORD rcvCnt; - - if (!InternetReadFile(hRequest, rcvData, preRcvCnt, &rcvCnt)) - { - des = getLastErrorMsg(); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - delete[] rcvData; - return false; - } - - if (rcvCnt != preRcvCnt) - { - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - des = getMsg("strUnknownErr"); - delete[] rcvData; - return false; - } - - finalRcvData += std::string(rcvData, rcvCnt); - - if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) - { - des = getLastErrorMsg(); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - delete[] rcvData; - return false; - } - - delete[] rcvData; - } - - des = finalRcvData; - - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return true; - } - des = getLastErrorMsg(); - InternetCloseHandle(hRequest); - InternetCloseHandle(hConnect); - InternetCloseHandle(hInternet); - return false; -#else - CURL* curl; - curl = curl_easy_init(); - if (curl) - { - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_USERAGENT, DiceRequestHeader); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteToString); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &des); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - - lastError = curl_easy_perform(curl); - if (lastError != CURLE_OK) - { - des = getLastErrorMsg(); - } - - curl_easy_cleanup(curl); - return lastError == CURLE_OK; - } - return false; -#endif - } - -} +/* + * _______ ________ ________ ________ __ + * | __ \ |__ __| | _____| | _____| | | + * | | | | | | | | | |_____ | | + * | | | | | | | | | _____| |__| + * | |__| | __| |__ | |_____ | |_____ __ + * |_______/ |________| |________| |________| |__| + * + * Dice! QQ Dice Robot for TRPG + * Copyright (C) 2018-2019 w4123婧磩 + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#pragma comment(lib, "WinInet.lib") +#else +#include +#endif + +#include +#include +#include "GlobalVar.h" +#include "MsgFormat.h" +#include "DiceNetwork.h" +#include "StrExtern.hpp" + +namespace Network +{ +#ifndef _WIN32 + thread_local CURLcode lastError; + + size_t curlWriteToString(void *contents, size_t size, size_t nmemb, std::string *s) + { + size_t newLength = size*nmemb; + s->append((char*)contents, newLength); + return newLength; + } +#endif + + std::string getLastErrorMsg() + { +#ifdef _WIN32 + DWORD dwError = GetLastError(); + if (dwError == ERROR_INTERNET_EXTENDED_ERROR) + { + DWORD size = 512; + wchar_t* szFormatBuffer = new wchar_t[size]; + if (InternetGetLastResponseInfoW(&dwError, szFormatBuffer, &size)) + { + std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); + while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); + delete[] szFormatBuffer; + return ret; + } + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + size++; + delete[] szFormatBuffer; + szFormatBuffer = new wchar_t[size]; + if (InternetGetLastResponseInfoW(&dwError, szFormatBuffer, &size)) + { + std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); + while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); + delete[] szFormatBuffer; + return ret; + } + delete[] szFormatBuffer; + return getMsg("strUnableToGetErrorMsg"); + } + delete[] szFormatBuffer; + return getMsg("strUnableToGetErrorMsg"); + } + wchar_t szFormatBuffer[512]; + DWORD dwBaseLength = FormatMessageW( + FORMAT_MESSAGE_FROM_HMODULE, // dwFlags + GetModuleHandleW(L"wininet.dll"), // lpSource + dwError, // dwMessageId + MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), // dwLanguageId + szFormatBuffer, // lpBuffer + 512, // nSize + nullptr); + + if (dwBaseLength == 0) + { + dwBaseLength = FormatMessageW( + FORMAT_MESSAGE_FROM_HMODULE, // dwFlags + GetModuleHandleW(L"wininet.dll"), // lpSource + dwError, // dwMessageId + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // dwLanguageId + szFormatBuffer, // lpBuffer + 512, // nSize + nullptr); + } + + if (dwBaseLength) + { + std::string ret(convert_w2a(reinterpret_cast(szFormatBuffer))); + while (ret[ret.length() - 1] == '\n' || ret[ret.length() - 1] == '\r')ret.erase(ret.length() - 1); + return ret; + } + return getMsg("strUnableToGetErrorMsg"); +#else + return curl_easy_strerror(lastError); +#endif + } + + bool POST(const string& url, const string& postContent, const string& postHeader, std::string& des) + { + std::string strHeader = postHeader.empty() ? "Content-Type: application/x-www-form-urlencoded" : postHeader; +#ifdef _WIN32 + std::string UserAgent{ DiceRequestHeader }; + static std::regex re{ R"(User-Agent: ([^\r\n]*))" }; + std::smatch match; + if (std::regex_search(strHeader, match, re)) { + UserAgent = match[1].str(); + } + URL_COMPONENTSA urlComponents{}; + urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); + urlComponents.dwHostNameLength = 1024; + urlComponents.dwPasswordLength = 0; + urlComponents.dwSchemeLength = 1024; + urlComponents.dwUrlPathLength = 1024; + urlComponents.dwUserNameLength = 0; + urlComponents.dwExtraInfoLength = 1024; + urlComponents.lpszHostName = nullptr; + urlComponents.lpszPassword = nullptr; + urlComponents.lpszScheme = nullptr; + urlComponents.lpszUrlPath = nullptr; + urlComponents.lpszUserName = nullptr; + urlComponents.lpszExtraInfo = nullptr; + if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) + { + des = getLastErrorMsg(); + return false; + } + + if (urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) + { + des = "Unknown URL Scheme"; + return false; + } + + const char* acceptTypes[] = {"*/*", nullptr}; + + const HINTERNET hInternet = InternetOpenA(UserAgent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); + const HINTERNET hConnect = InternetConnectA(hInternet, std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength).c_str(), urlComponents.nPort, nullptr, nullptr, + INTERNET_SERVICE_HTTP, 0, 0); + const HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", (std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength) + std::string(urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength)).c_str(), "HTTP/1.1", nullptr, acceptTypes, + (urlComponents.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0), 0); + const BOOL res = HttpSendRequestA(hRequest, strHeader.c_str(), strHeader.length(), (void*)postContent.c_str(), postContent.length()); + + + if (res) + { + DWORD dwRetCode = 0; + DWORD dwBufferLength = sizeof(dwRetCode); + if (!HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwRetCode, &dwBufferLength, + nullptr)) + { + des = getLastErrorMsg(); + goto InternetClose; + } + if (dwRetCode != 200) + { + des = getMsg("strRequestRetCodeErr", AttrVars{ {"error", std::to_string(dwRetCode)} }); + goto InternetClose; + } + DWORD preRcvCnt; + if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) + { + des = getLastErrorMsg(); + goto InternetClose; + } + if (preRcvCnt == 0) + { + des = getMsg("strRequestNoResponse"); + return false; + } + std::string finalRcvData; + while (preRcvCnt) + { + char* rcvData = new char[preRcvCnt]; + DWORD rcvCnt; + + if (!InternetReadFile(hRequest, rcvData, preRcvCnt, &rcvCnt)) + { + des = getLastErrorMsg(); + delete[] rcvData; + goto InternetClose; + } + + if (rcvCnt != preRcvCnt){ + des = getMsg("strUnknownErr"); + delete[] rcvData; + goto InternetClose; + } + + finalRcvData += std::string(rcvData, rcvCnt); + + if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) { + des = getLastErrorMsg(); + delete[] rcvData; + goto InternetClose; + } + + delete[] rcvData; + } + + des = finalRcvData; + + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return true; + } + des = getLastErrorMsg(); +InternetClose: + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return false; + +#else + + CURL* curl; + curl = curl_easy_init(); + if (curl) + { + struct curl_slist* header = NULL; + header = curl_slist_append(header, strHeader.c_str()); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_USERAGENT, DiceRequestHeader); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postContent.c_str()); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteToString); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &des); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + + lastError = curl_easy_perform(curl); + if (lastError != CURLE_OK) + { + des = getLastErrorMsg(); + } + curl_slist_free_all(header); + curl_easy_cleanup(curl); + return lastError == CURLE_OK; + } + return false; +#endif + + } + + bool GET(const string& url, std::string& des) { +#ifdef _WIN32 + URL_COMPONENTSA urlComponents{}; + urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); + urlComponents.dwHostNameLength = 1024; + urlComponents.dwPasswordLength = 0; + urlComponents.dwSchemeLength = 1024; + urlComponents.dwUrlPathLength = 1024; + urlComponents.dwUserNameLength = 0; + urlComponents.dwExtraInfoLength = 1024; + urlComponents.lpszHostName = nullptr; + urlComponents.lpszPassword = nullptr; + urlComponents.lpszScheme = nullptr; + urlComponents.lpszUrlPath = nullptr; + urlComponents.lpszUserName = nullptr; + urlComponents.lpszExtraInfo = nullptr; + if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) + { + des = getLastErrorMsg(); + return false; + } + + if (urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) + { + des = "Unknown URL Scheme"; + return false; + } + + const char* acceptTypes[] = {"*/*", nullptr}; + + const HINTERNET hInternet = InternetOpenA(DiceRequestHeader, INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0); + const HINTERNET hConnect = InternetConnectA(hInternet, std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength).c_str(), urlComponents.nPort, nullptr, nullptr, + INTERNET_SERVICE_HTTP, 0, 0); + const HINTERNET hRequest = HttpOpenRequestA(hConnect, "GET", + (std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength) + std::string(urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength)).c_str(), + "HTTP/1.1", nullptr, acceptTypes, (urlComponents.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0) | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, 0); + const BOOL res = HttpSendRequestA(hRequest, nullptr, 0, nullptr, 0); + + + if (res) + { + DWORD dwRetCode = 0; + DWORD dwBufferLength = sizeof(dwRetCode); + if (!HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwRetCode, &dwBufferLength, + nullptr)) + { + des = getLastErrorMsg(); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return false; + } + if (dwRetCode != 200) + { + des = getMsg("strRequestRetCodeErr", AttrVars{ {"error", std::to_string(dwRetCode)} }); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return false; + } + DWORD preRcvCnt; + if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) + { + des = getLastErrorMsg(); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return false; + } + if (preRcvCnt == 0) + { + des = getMsg("strRequestNoResponse"); + return false; + } + std::string finalRcvData; + while (preRcvCnt) + { + char* rcvData = new char[preRcvCnt]; + DWORD rcvCnt; + + if (!InternetReadFile(hRequest, rcvData, preRcvCnt, &rcvCnt)) + { + des = getLastErrorMsg(); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + delete[] rcvData; + return false; + } + + if (rcvCnt != preRcvCnt) + { + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + des = getMsg("strUnknownErr"); + delete[] rcvData; + return false; + } + + finalRcvData += std::string(rcvData, rcvCnt); + + if (!InternetQueryDataAvailable(hRequest, &preRcvCnt, 0, 0)) + { + des = getLastErrorMsg(); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + delete[] rcvData; + return false; + } + + delete[] rcvData; + } + + des = finalRcvData; + + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return true; + } + des = getLastErrorMsg(); + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return false; +#else + CURL* curl; + curl = curl_easy_init(); + if (curl) + { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_USERAGENT, DiceRequestHeader); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteToString); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &des); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + + lastError = curl_easy_perform(curl); + if (lastError != CURLE_OK) + { + des = getLastErrorMsg(); + } + + curl_easy_cleanup(curl); + return lastError == CURLE_OK; + } + return false; +#endif + } + +} diff --git a/Dice/GlobalVar.cpp b/Dice/GlobalVar.cpp index 8efe35d3..d9ea14dc 100644 --- a/Dice/GlobalVar.cpp +++ b/Dice/GlobalVar.cpp @@ -356,23 +356,18 @@ const dict_ci PlainMsg {"strPropList", "{nick}鐨剓char}灞炴у垪琛ㄤ负锛歿show}"}, {"strStErr", "鏍煎紡閿欒:璇峰弬鑰/help st鑾峰彇.st鍛戒护鐨勪娇鐢ㄦ柟娉"}, {"strRulesFormatErr", "鏍煎紡閿欒:姝g‘鏍煎紡涓.rules[瑙勫垯鍚嶇О:]瑙勫垯鏉$洰 濡.rules COC7:鍔涢噺"}, - {"strLeaveDiscuss", "{self}鐜颁笉鏀寔璁ㄨ缁勬湇鍔★紝鍗冲皢閫鍑"}, - {"strLeaveNoPower", "{self}鏈幏寰楃兢绠$悊锛屽嵆灏嗛缇"}, - {"strLeaveUnused", "{self}宸茬粡鍦ㄨ繖閲岃鏀剧疆{day}澶╁暒锛岄┈涓婂氨浼氱寮杩欓噷浜"}, {"strGlobalOff", "{self}浼戝亣涓紝鏆傚仠鏈嶅姟脳"}, {"strPreserve", "{self}绉佹湁绉佺敤锛屽嬁鎵板嬁鎬猏n濡傞渶鐢宠璁稿彲璇峰彂閫!authorize +[缇ゅ彿] 鐢宠鐢ㄩ:[ **璇峰啓鍏ョ悊鐢** ] 鎴戝凡浜嗚ВDice!鍩烘湰鐢ㄦ硶锛屼粩缁嗛槄璇诲苟淇濊瘉閬靛畧{strSelfName}鐨勭敤鎴峰崗璁紝濡傞渶鍋滅敤鎸囦护浣跨敤[ **璇峰啓鍏ユ寚浠** ]锛岀敤鍚庝娇鐢╗ **璇峰啓鍏ユ寚浠** ]閫佸嚭缇"}, {"strJrrp", "{nick}浠婂ぉ鐨勪汉鍝佸兼槸: {res}"}, {"strJrrpErr", "JRRP鑾峰彇澶辫触! 閿欒淇℃伅: \n{res}"}, { "strFriendDenyNotUser", "寰堥仐鎲撅紝浣犳病鏈夊{self}浣跨敤鎸囦护鐨勮褰" }, { "strFriendDenyNoTrust", "寰堥仐鎲撅紝浣犱笉鏄瘂self}淇′换鐨勭敤鎴凤紝濡傞渶浣跨敤鍙仈绯粄print:master}" }, - {"strAddFriendWhiteQQ", "{strAddFriend}"}, //鐧藉悕鍗曠敤鎴锋坊鍔犲ソ鍙嬫椂鍥炲姝ゅ彞 { "strAddFriend", R"(娆㈣繋閫夋嫨{strSelfName}鐨勫厤璐规幏楠版湇鍔★紒 /help鍗忚 纭鏈嶅姟鍗忚 /help鎸囦护 鏌ョ湅鎸囦护鍒楄〃 /help璁惧畾 纭楠板璁惧畾 -/help閾炬帴 鏌ョ湅婧愮爜鏂囨。 浣跨敤鏈嶅姟榛樿宸茬粡鍚屾剰鏈嶅姟鍗忚)" }, //鍚屾剰娣诲姞濂藉弸鏃堕澶栧彂閫佺殑璇彞 { @@ -381,7 +376,6 @@ const dict_ci PlainMsg /help鍗忚 纭鏈嶅姟鍗忚 /help鎸囦护 鏌ョ湅鎸囦护鍒楄〃 /help璁惧畾 纭楠板璁惧畾 -/help閾炬帴 鏌ョ湅婧愮爜鏂囨。 閭璇峰叆缇ら粯璁よ涓哄悓鎰忔湇鍔″崗璁紝鐭ユ檽绂佽█鎴栫Щ鍑虹殑鍚庢灉)" }, { "strNewMaster","璇曢棶锛屼綘灏辨槸{strSelfName}鐨凪aster鈭歕n璇疯鐪熼槄璇诲綋鍓嶇増鏈琈aster鎵嬪唽浠ュ強鐢ㄦ埛鎵嬪唽銆傝娉ㄦ剰鐗堟湰鍙峰搴: https://v2docs.kokona.tech\f{strSelfName}" }, @@ -394,9 +388,7 @@ const dict_ci PlainMsg {"strHlpMsg", R"(璇蜂娇鐢 /help鍗忚 纭鏈嶅姟鍗忚 /help鎸囦护 鏌ョ湅鎸囦护鍒楄〃 -/help缇ょ 鏌ョ湅缇ょ鎸囦护 /help璁惧畾 纭楠板璁惧畾 -/help閾炬帴 鏌ョ湅婧愮爜鏂囨。 瀹樻柟璁哄潧: kokona鐐箃ech Dice!浼楃璁″垝: afdian@suhuiw4123)" } @@ -530,7 +522,7 @@ const dict_ci<> HelpDoc = { 8.鏈崗璁唴瀹归殢鏃舵湁鍙兘鏀瑰姩銆傝娉ㄦ剰甯姪淇℃伅銆佺鍚嶃佺┖闂淬佸畼鏂圭兢绛夊鐨勯濞樺姩鎬併 9.楠板鎻愪緵鎺烽鏈嶅姟鏄畬鍏ㄥ厤璐圭殑锛屾杩庤嚜鎰挎姇椋熴 10.鏈湇鍔℃渶缁堣В閲婃潈褰掓湇鍔℃彁渚涙柟鎵鏈夈)"}, -{"閾炬帴","Dice!璁哄潧: https://kokona.tech\nDice!鎵嬪唽: https://v2docs.kokona.tech\n鏀寔Shiki: https://afdian.net/@dice_shiki"}, +{"閾炬帴","Dice!璁哄潧: https://kokona.tech\nDice!鎵嬪唽: https://v2docs.kokona.tech\n鏀寔Shiki: https://afdian@dice_shiki"}, {"璁惧畾",R"(Master锛歿print:master} 缇ゅ唴浣跨敤锛歿case:self.Private?else=鐧藉悕鍗曞埗锛岄渶棰勭敵璇&0={case:self.CheckGroupLicense?2=瀹℃牳鍒讹紝闇鐢宠鍚庝娇鐢&1=瀹℃牳鍒讹紝鍏ユ柊缇ら渶鐢宠&else=榛戝悕鍗曞埗锛岃嚜鐢变娇鐢▆} 鍒峰睆鐩戞祴锛歿case:self.ListenSpam?0=鍏抽棴&else=寮鍚瘆 @@ -544,21 +536,17 @@ const dict_ci<> HelpDoc = { {at:self}.bot on 璇/help瀵瑰簲鎸囦护 鑾峰彇璇︾粏淇℃伅锛屽/help r 浜掑姩鎸囦护: -.nn 璁剧疆绉板懠 +/nn 璁剧疆绉板懠 .bot 鐗堟湰淇℃伅 -.group 缇ょ .send 鍚戝悗鍙板彂閫佹秷鎭 -.mod 妯″潡鎿嶄綔)" -"\f" -R"([绗簩椤礭璺戝洟鎸囦护 +璺戝洟鎸囦护 .game 娓告垙棰嗗煙 -.r 鎺烽 +/r 鎺烽 .rules 瑙勫垯閫熸煡 -.log 鏃ュ織璁板綍 .set 璁剧疆榛樿楠 .coc COC浜虹墿浣滄垚 .dnd DND浜虹墿浣滄垚 -.st 灞炴ц褰 +.st 瑙掕壊灞炴ц褰 .pc 瑙掕壊鍗¤褰 .rc 妫瀹 .setcoc 璁剧疆rc鎴胯 @@ -566,9 +554,8 @@ R"([绗簩椤礭璺戝洟鎸囦护 .en 鎴愰暱/澧炲己妫瀹 .ri 鍏堟敾 .init 鍏堟敾鍒楄〃 -.ww 楠版睜)" -"\f" -R"([绗笁椤礭鍏朵粬鎸囦护 +.ww 楠版睜 +鍏朵粬鎸囦护 .draw 鎶界墝 .deck 鐗屽爢瀹炰緥 .name 闅忔満濮撳悕 @@ -825,25 +812,6 @@ Type=[鍥炲鎬ц川](Reply/Order) .welcome show //鏌ョ湅娆㈣繋璇 鏃犺鎸囦护鏄惁鍋滅敤锛屽彧瑕佹湁娆㈣繋璇嶆椂鏈変汉鍏ョ兢锛岄兘浼氬搷搴)" }, - {"group", "&缇ょ"}, - { - "缇ょ", - R"(缇ょ鎸囦护.group(缇ょ鐞嗗憳闄愬畾) -.group state //鏌ョ湅鍦ㄧ兢鍐呭楠板鐨勮缃 -.group pause/restart //缇ゅ叏浣撶瑷/鍏ㄤ綋瑙i櫎绂佽█ -.group card [at/鐢ㄦ埛QQ] [鍚嶇墖] //璁剧疆缇ゅ憳鍚嶇墖 -.group title [at/鐢ㄦ埛QQ] [澶磋] //璁剧疆缇ゅ憳澶磋 -.group diver //鏌ョ湅娼滄按鎴愬憳 -.group +/-[缇ょ璇嶆潯] //涓虹兢鍔犲噺璁剧疆锛岄渶瑕佸搴旀潈闄 -渚:.group +绂佺敤鍥炲 //鍏抽棴鏈兢鑷畾涔夊洖澶 -缇ょ璇嶆潯:鍋滅敤鎸囦护/绂佺敤鍥炲/绂佺敤jrrp/绂佺敤draw/绂佺敤me/绂佺敤help/绂佺敤ob/鎷︽埅娑堟伅/璁稿彲浣跨敤/鍏嶆竻/鍏嶉粦)" - }, - { "groups_list", "&鍙栫兢鍒楄〃" }, - { "鍙栫兢鍒楄〃", R"(鍙栫兢鍒楄〃.groups list(绠$悊闄愬畾) -.groups list idle //鎸夐棽缃ぉ鏁伴檷搴忓垪鍑虹兢 -.groups list size //鎸夌兢瑙勬ā闄嶅簭鍒楀嚭缇 -.groups list [缇ょ璇嶆潯] //鍒楀嚭甯︽湁璇嶆潯鐨勭兢 -缇ょ璇嶆潯:鍋滅敤鎸囦护/绂佺敤鍥炲/绂佺敤jrrp/绂佺敤draw/绂佺敤me/绂佺敤help/绂佺敤ob/鎷︽埅娑堟伅/璁稿彲浣跨敤/鍏嶆竻/鍏嶉粦)" }, { "鏁忔劅璇嶆娴","&censor" }, {"censor",R"(鏁忔劅璇嶆娴.admin censor .admin censor +([瑙﹀彂绛夌骇])=[鏁忔劅璇0](|[鏁忔劅璇1]...) //娣诲姞鏁忔劅璇 diff --git a/Dice/GlobalVar.h b/Dice/GlobalVar.h index abac8f8c..96b535d7 100644 --- a/Dice/GlobalVar.h +++ b/Dice/GlobalVar.h @@ -44,7 +44,7 @@ constexpr unsigned short Dice_Build = 655u; inline const std::string Dice_Ver_Without_Build = "2.7.0beta6[Alter]"; constexpr auto DiceRequestHeader = "Dice/2.7.0"; inline const std::string Dice_Ver = Dice_Ver_Without_Build + "(" + std::to_string(Dice_Build) + ")"; -inline const std::string Dice_Short_Ver = "Dice! by 婧磩 & Shiki Ver " + Dice_Ver; +inline const std::string Dice_Short_Ver = "Dice!Alter by 婧磩 & Shiki Ver " + Dice_Ver; constexpr bool isDev = true; #ifdef __clang__ diff --git a/Dice/RandomGenerator.cpp b/Dice/RandomGenerator.cpp index e341efc5..b64dcfa2 100644 --- a/Dice/RandomGenerator.cpp +++ b/Dice/RandomGenerator.cpp @@ -1,97 +1,97 @@ -/* - * _______ ________ ________ ________ __ - * | __ \ |__ __| | _____| | _____| | | - * | | | | | | | | | |_____ | | - * | | | | | | | | | _____| |__| - * | |__| | __| |__ | |_____ | |_____ __ - * |_______/ |________| |________| |________| |__| - * - * Dice! QQ Dice Robot for TRPG - * Copyright (C) 2018-2019 w4123溯洄 - * - * This program is free software: you can redistribute it and/or modify it under the terms - * of the GNU Affero General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License along with this - * program. If not, see . - */ -#include "RandomGenerator.h" -#include -#include - -#if defined(__i386__) || defined(__x86_64__) -#ifdef _MSC_VER -#include -#else -#include -#endif -#endif -constexpr const char digit_chars[]{ "0123456789" }; -constexpr const char hex_chars[]{ "0123456789abcdef" }; -constexpr const char alpha_chars[]{ "abcdefghijklmnopqrstuvwxyz" }; -constexpr const char alnum_chars[]{ "abcdefghijklmnopqrstuvwxyz0123456789" }; -constexpr const char base64_chars[]{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; -constexpr const char base64url_chars[]{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" }; - -namespace RandomGenerator -{ - unsigned long long GetCycleCount() - { -#if defined(__i386__) || defined(__x86_64__) - return __rdtsc(); -#else - return static_cast (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); -#endif - } - -#if defined(__i386__) || defined(__x86_64__) - int Randint(int lowest, int highest) - { - std::mt19937 gen(static_cast(GetCycleCount())); - std::uniform_int_distribution dis(lowest, highest); - return dis(gen); - } -#else - std::mt19937 gen(static_cast(GetCycleCount())); - int Randint(int lowest, int highest) - { - std::uniform_int_distribution dis(lowest, highest); - return dis(gen); - } -#endif - std::string genKey(size_t len, Code mode) { - std::string res; - std::string charset; - switch (mode) { - case RandomGenerator::Code::Hex: - charset = hex_chars; - break; - case RandomGenerator::Code::Alpha: - charset = alpha_chars; - break; - case RandomGenerator::Code::Alnum: - charset = alnum_chars; - break; - case RandomGenerator::Code::Base64: - charset = base64_chars; - break; - case RandomGenerator::Code::UrlBase64: - charset = base64url_chars; - break; - case RandomGenerator::Code::Decimal: - default: - charset = digit_chars; - break; - } - size_t size{ charset.length() - 1 }; - for (size_t i = 0; i < len; ++i) { - res += charset[Randint(0, size)]; - } - return res; - } -} +/* + * _______ ________ ________ ________ __ + * | __ \ |__ __| | _____| | _____| | | + * | | | | | | | | | |_____ | | + * | | | | | | | | | _____| |__| + * | |__| | __| |__ | |_____ | |_____ __ + * |_______/ |________| |________| |________| |__| + * + * Dice! QQ Dice Robot for TRPG + * Copyright (C) 2018-2019 w4123婧磩 + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this + * program. If not, see . + */ +#include "RandomGenerator.h" +#include +#include + +#if defined(__i386__) || defined(__x86_64__) +#ifdef _MSC_VER +#include +#else +#include +#endif +#endif +constexpr const char digit_chars[]{ "0123456789" }; +constexpr const char hex_chars[]{ "0123456789abcdef" }; +constexpr const char alpha_chars[]{ "abcdefghijklmnopqrstuvwxyz" }; +constexpr const char alnum_chars[]{ "abcdefghijklmnopqrstuvwxyz0123456789" }; +constexpr const char base64_chars[]{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; +constexpr const char base64url_chars[]{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" }; + +namespace RandomGenerator +{ + unsigned long long GetCycleCount() + { +#if defined(__i386__) || defined(__x86_64__) + return __rdtsc(); +#else + return static_cast (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); +#endif + } + +#if defined(__i386__) || defined(__x86_64__) + int Randint(int lowest, int highest) + { + std::mt19937 gen(static_cast(GetCycleCount())); + std::uniform_int_distribution dis(lowest, highest); + return dis(gen); + } +#else + std::mt19937 gen(static_cast(GetCycleCount())); + int Randint(int lowest, int highest) + { + std::uniform_int_distribution dis(lowest, highest); + return dis(gen); + } +#endif + std::string genKey(size_t len, Code mode) { + std::string res; + std::string charset; + switch (mode) { + case RandomGenerator::Code::Hex: + charset = hex_chars; + break; + case RandomGenerator::Code::Alpha: + charset = alpha_chars; + break; + case RandomGenerator::Code::Alnum: + charset = alnum_chars; + break; + case RandomGenerator::Code::Base64: + charset = base64_chars; + break; + case RandomGenerator::Code::UrlBase64: + charset = base64url_chars; + break; + case RandomGenerator::Code::Decimal: + default: + charset = digit_chars; + break; + } + size_t size{ charset.length() - 1 }; + for (size_t i = 0; i < len; ++i) { + res += charset[Randint(0, size)]; + } + return res; + } +} diff --git a/OneBot/OneBotAPI.cpp b/OneBot/OneBotAPI.cpp index f1921ef2..5d0029b9 100644 --- a/OneBot/OneBotAPI.cpp +++ b/OneBot/OneBotAPI.cpp @@ -487,7 +487,6 @@ void OneBot_Event(fifo_json& j) { } //缇よ亰 else if (j["message_type"] == "group") { - api::printLog("group msg:" + msg); ptr Msg(std::make_shared( AttrObject({ { "Event", "Message" }, { "fromMsg", msg },