Skip to content

Instantly share code, notes, and snippets.

@EAirPeter
Last active August 8, 2017 09:11
Show Gist options
  • Save EAirPeter/6f73781945fa78ffea42e43ddbe3bab2 to your computer and use it in GitHub Desktop.
Save EAirPeter/6f73781945fa78ffea42e43ddbe3bab2 to your computer and use it in GitHub Desktop.
#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