Last active
August 8, 2017 09:11
-
-
Save EAirPeter/6f73781945fa78ffea42e43ddbe3bab2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _CRT_SECURE_NO_WARNINGS | |
#define _SCL_SECURE_NO_WARNINGS | |
#pragma comment(lib, "crypt32.lib") | |
#pragma comment(lib, "wldap32.lib") | |
#pragma comment(lib, "ws2_32.lib") | |
#include <boost/algorithm/string.hpp> | |
#include <boost/algorithm/string/trim.hpp> | |
#include <boost/filesystem/fstream.hpp> | |
#include <boost/filesystem.hpp> | |
#include <boost/lexical_cast.hpp> | |
#include <codecvt> | |
#include <cstddef> | |
#include <iterator> | |
#include <iomanip> | |
#include <iostream> | |
#include <list> | |
#include <stdexcept> | |
#include <unordered_map> | |
#include <unordered_set> | |
#include <utility> | |
#include <vector> | |
#include <fcntl.h> | |
#include <io.h> | |
#include <curl/curl.h> | |
#include <rapidjson/document.h> | |
using boost::filesystem::directory_iterator; | |
using boost::filesystem::ifstream; | |
using boost::filesystem::path; | |
using boost::filesystem::wifstream; | |
using boost::filesystem::wofstream; | |
using std::codecvt_utf8; | |
using std::endl; | |
using std::exception; | |
using std::istreambuf_iterator; | |
using std::list; | |
using std::locale; | |
using std::pair; | |
using std::runtime_error; | |
using std::size_t; | |
using std::string; | |
using std::uint64_t; | |
using std::unordered_map; | |
using std::unordered_set; | |
using std::vector; | |
using std::wcin; | |
using std::wcout; | |
using std::wstring; | |
using std::wstring_convert; | |
using rapidjson::Document; | |
struct AdmQq { | |
uint64_t id; | |
wstring nick; | |
wstring card; | |
}; | |
struct AdmKc { | |
uint64_t id; | |
wstring name; | |
}; | |
wstring_convert<codecvt_utf8<wchar_t>> cvt; | |
size_t CurlWriteSuppress(char *, size_t size, size_t nmemb, void *) { | |
return size * nmemb; | |
} | |
size_t CurlWrite(char *ptr, size_t size, size_t nmemb, void *userdata) { | |
auto &s = *reinterpret_cast<string *>(userdata); | |
size *= nmemb; | |
s.append(ptr, size); | |
return size; | |
} | |
int main() { | |
_setmode(_fileno(stdout), _O_U16TEXT); | |
path paKcgr = boost::filesystem::current_path(); | |
try { | |
unordered_set<uint64_t> seExcept; | |
uint64_t idExcept; | |
wifstream fiExcept {paKcgr / L"except.txt"}; | |
while (fiExcept >> idExcept) | |
seExcept.insert(idExcept); | |
fiExcept.close(); | |
string jstr {}; | |
auto curl = curl_easy_init(); | |
curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://localhost:1080"); | |
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:8188/update/group-member/616147379"); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteSuppress); | |
auto res = curl_easy_perform(curl); | |
curl_easy_cleanup(curl); | |
if (res != CURLE_OK) | |
throw runtime_error("Failed to update group members"); | |
curl = curl_easy_init(); | |
curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://localhost:1080"); | |
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:8188/list/group-member/616147379"); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite); | |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &jstr); | |
res = curl_easy_perform(curl); | |
curl_easy_cleanup(curl); | |
if (res != CURLE_OK) | |
throw runtime_error("Failed to fetch group members"); | |
vector<AdmQq> vaqq; | |
uint32_t uUTotal {}; | |
uint32_t uUFetchingFailed {}; | |
Document json; | |
json.Parse(jstr.c_str()); | |
auto &m = json["result"][0]["membs"]["r"]; | |
for (size_t i = 0; i < m.Size(); ++i) { | |
++uUTotal; | |
AdmQq aqq {}; | |
string sid = m[i]["qq"].GetString(); | |
aqq.nick = cvt.from_bytes(m[i]["nick"].GetString()); | |
aqq.card = cvt.from_bytes(m[i]["card"].GetString()); | |
if (sid == "#NULL") { | |
++uUFetchingFailed; | |
wcout << L"Failed to fetch QQ information for UserNick[" << aqq.nick << L"]." << endl; | |
continue; | |
} | |
aqq.id = boost::lexical_cast<uint64_t>(sid); | |
if (seExcept.find(aqq.id) == seExcept.end()) | |
vaqq.emplace_back(aqq); | |
} | |
vector<AdmKc> vakc; | |
uint32_t uRTotal {}; | |
path paRec {paKcgr / L"rec"}; | |
for (directory_iterator di {paRec}; di != directory_iterator {}; ++di) | |
if (boost::filesystem::is_regular_file(*di)) { | |
auto pa = di->path(); | |
auto ext = pa.extension().wstring(); | |
boost::to_lower(ext); | |
if (ext == L".png" || ext == L".jpg") { | |
auto stem = pa.stem().wstring(); | |
if (stem.length() >= 4 && stem[0] == L'!') { | |
auto nHyp = stem.find(L'-'); | |
if (nHyp != stem.npos) { | |
++uRTotal; | |
AdmKc akc {}; | |
akc.id = boost::lexical_cast<uint64_t>(stem.substr(1, nHyp - 1)); | |
akc.name = stem.substr(nHyp + 1); | |
if (seExcept.find(akc.id) == seExcept.end()) | |
vakc.emplace_back(akc); | |
} | |
} | |
} | |
} | |
uint32_t uUExcepted {seExcept.size()}; | |
uint32_t uRNotInGroup {}; | |
uint32_t uRNameSharedByMultiUser {}; | |
uint32_t uRValidated {}; | |
unordered_map<uint64_t, uint32_t> mid; | |
unordered_map<wstring, list<uint64_t>> mes; | |
for (auto &aqq : vaqq) | |
mid.emplace(decltype(mid)::value_type {aqq.id, 0}); | |
for (auto &akc : vakc) { | |
auto it = mid.find(akc.id); | |
mes[akc.name].emplace_back(akc.id); | |
if (it == mid.end()) { | |
++uRNotInGroup; | |
wcout << L"UserId[" << akc.id << L"] with RecordName[" << akc.name; | |
wcout << L"] does not exist in the group." << endl; | |
} | |
else { | |
++it->second; | |
++uRValidated; | |
} | |
} | |
uint32_t uEGenerated {}; | |
wofstream foEscort {paKcgr / L"poi-escort.txt"}; | |
foEscort.imbue(locale(locale(), new codecvt_utf8<wchar_t>)); | |
for (auto &psl : mes) { | |
++uEGenerated; | |
foEscort << psl.first << L'|'; | |
if (psl.second.size() > 1) { | |
++uRNameSharedByMultiUser; | |
for (auto &id : psl.second) | |
wcout << L"UserId[" << id << "] "; | |
wcout << L"are sharing a same RecordName[" << psl.first << "]." << endl; | |
foEscort << L"(重名)"; | |
uint32_t i = 1; | |
for (auto &id : psl.second) { | |
if (i > 1) | |
foEscort << L", "; | |
foEscort << L"QQ" << i; | |
if (mid.find(id) == mid.end()) | |
foEscort << L"(已退群)"; | |
foEscort << L": " << id; | |
++i; | |
} | |
} | |
else { | |
foEscort << L"QQ"; | |
if (mid.find(psl.second.front()) == mid.end()) | |
foEscort << L"(已退群)"; | |
foEscort << L": " << psl.second.front(); | |
} | |
foEscort << endl; | |
} | |
foEscort.close(); | |
uint32_t uUHasMultiRecord {}; | |
uint32_t uUNoRecordFound {}; | |
uint32_t uUValidated {}; | |
for (auto &aqq : vaqq) { | |
uint32_t recs = mid.at(aqq.id); | |
if (!recs) { | |
++uUNoRecordFound; | |
wcout << L"No record found for UserId[" << aqq.id << L"]." << endl; | |
wcout << L" nick: " << aqq.nick << endl; | |
wcout << L" card: " << aqq.card << endl; | |
} | |
else { | |
++uUValidated; | |
if (recs > 1) { | |
++uUHasMultiRecord; | |
wcout << L"UserId[" << aqq.id << L"] has " << recs << L" records." << endl; | |
} | |
} | |
} | |
wcout << L"summary:" << endl; | |
wcout << L" [total] users : " << uUTotal << endl; | |
wcout << L" [fetching failed] users : " << uUFetchingFailed << endl; | |
wcout << L" [excepted] users : " << uUExcepted << endl; | |
wcout << L" [has multi-record] users : " << uUHasMultiRecord << endl; | |
wcout << L" [no record found] users : " << uUNoRecordFound << endl; | |
wcout << L" [validated] users : " << uUValidated << endl; | |
wcout << L" [total] records : " << uRTotal << endl; | |
wcout << L" [name shared by multi-user] records : " << uRNameSharedByMultiUser << endl; | |
wcout << L" [not in group] records : " << uRNotInGroup << endl; | |
wcout << L" [validated] records : " << uRValidated << endl; | |
wcout << L" [generated] escort items: " << uEGenerated << endl; | |
} | |
catch (exception e) { | |
wcout << L"Exception caught: " << e.what() << endl; | |
} | |
wcout << L"Press Enter to exit..." << endl; | |
wcin.get(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment