11//
2- // main_handlers .cpp : Implement main API handlers directly talk with CoolQ .
2+ // handlers .cpp : Implement API handlers.
33//
44// Copyright (C) 2017 Richard Chien <[email protected] >55//
2222#include < boost/filesystem.hpp>
2323#include < boost/process.hpp>
2424
25- #include " ./handler .h"
25+ #include " ./types .h"
2626#include " structs.h"
2727#include " utils/params_class.h"
2828#include " api/server_class.h"
@@ -31,6 +31,38 @@ using namespace std;
3131
3232ApiHandlerMap api_handlers;
3333
34+ using RetCodes = ApiResult::RetCodes;
35+
36+ extern ApiHandlerMap api_handlers;
37+
38+ static bool __add_api_handler (const std::string &name, ApiHandler handler) {
39+ api_handlers[name] = handler;
40+ return true ;
41+ }
42+
43+ #define HANDLER (handler_name ) \
44+ static void __##handler_name(const Params &, ApiResult &); \
45+ static bool __dummy_##handler_name = __add_api_handler(#handler_name, __##handler_name); \
46+ static void __##handler_name(const Params ¶ms, ApiResult &result)
47+
48+ static void handle_async (const Params ¶ms, ApiResult &result, ApiHandler handler) {
49+ static const auto TAG = u8" API异步" ;
50+ if (pool) {
51+ pool->push ([params, result, handler](int ) {
52+ // copy "params" and "result" in the async task
53+ auto async_params = params;
54+ auto async_result = result;
55+ handler (async_params, async_result);
56+ Log::d (TAG, u8" 成功执行一个 API 请求异步处理任务" );
57+ });
58+ Log::d (TAG, u8" API 请求异步处理任务已进入线程池等待执行" );
59+ result.retcode = RetCodes::ASYNC;
60+ } else {
61+ Log::d (TAG, u8" 工作线程池未正确初始化,无法进行异步处理,请尝试重启插件" );
62+ result.retcode = RetCodes::BAD_THREAD_POOL;
63+ }
64+ }
65+
3466#pragma region Send Message
3567
3668HANDLER (send_private_msg) {
@@ -312,6 +344,8 @@ HANDLER(get_group_member_info) {
312344 }
313345}
314346
347+ #pragma endregion
348+
315349#pragma region Get CoolQ Information
316350
317351HANDLER (get_cookies) {
@@ -384,3 +418,88 @@ HANDLER(set_restart) {
384418}
385419
386420#pragma endregion
421+
422+ #pragma region Experimental
423+
424+ HANDLER (_get_friend_list) {
425+ const auto cookies = sdk->get_cookies ();
426+ const auto g_tk = to_string (sdk->get_csrf_token ());
427+ const auto login_qq = to_string (sdk->get_login_qq ());
428+
429+ {
430+ // try mobile QZone API
431+ const auto url = " http://m.qzone.com/friend/mfriend_list?g_tk=" + g_tk + " &res_uin=" + login_qq +
432+ " &res_type=normal&format=json" ;
433+ const auto res = get_remote_json (url, true , cookies).value_or (nullptr );
434+ try {
435+ if (res.at (" code" ).get <int >() == 0 ) {
436+ // succeeded
437+ auto resp_data = res.at (" data" );
438+ result.data = json::array ();
439+
440+ map<int64_t , int > gpid_idx_map;
441+ for (auto gp : resp_data.at (" gpnames" )) {
442+ auto res_gp = json::object ();
443+ auto gpid = gp.at (" gpid" ).get <int64_t >();
444+ res_gp[" friend_group_id" ] = gpid;
445+ res_gp[" friend_group_name" ] = gp.at (" gpname" ).get <string>();
446+ res_gp[" friends" ] = json::array ();
447+ gpid_idx_map[gpid] = result.data .size ();
448+ result.data .push_back (res_gp);
449+ }
450+
451+ for (auto frnd : resp_data.at (" list" )) {
452+ auto gpid = frnd.at (" groupid" ).get <int64_t >();
453+ auto res_frnd = json::object ();
454+ res_frnd[" user_id" ] = frnd.at (" uin" ).get <int64_t >();
455+ res_frnd[" nickname" ] = frnd.at (" nick" ).get <string>();
456+ res_frnd[" remark" ] = frnd.at (" remark" ).get <string>();
457+ result.data [gpid_idx_map[gpid]][" friends" ].push_back (res_frnd);
458+ }
459+
460+ result.retcode = RetCodes::OK;
461+ return ;
462+ }
463+ } catch (exception &) {}
464+ }
465+
466+ {
467+ // try desktop web QZone API
468+ const auto url =
469+ " https://h5.qzone.qq.com/proxy/domain/r.qzone.qq.com/cgi-bin/tfriend/friend_show_qqfriends.cgi?g_tk=" +
470+ g_tk + " &uin=" + login_qq;
471+ const auto res = get_remote_json (url, true , cookies).value_or (nullptr );
472+ try {
473+ auto resp_data = res;
474+ result.data = json::array ();
475+
476+ map<int64_t , int > gpid_idx_map;
477+ for (auto gp : resp_data.at (" gpnames" )) {
478+ auto res_gp = json::object ();
479+ auto gpid = gp.at (" gpid" ).get <int64_t >();
480+ res_gp[" friend_group_id" ] = gpid;
481+ res_gp[" friend_group_name" ] = gp.at (" gpname" ).get <string>();
482+ res_gp[" friends" ] = json::array ();
483+ gpid_idx_map[gpid] = result.data .size ();
484+ result.data .push_back (res_gp);
485+ }
486+
487+ for (auto frnd : resp_data.at (" items" )) {
488+ auto gpid = frnd.at (" groupid" ).get <int64_t >();
489+ auto res_frnd = json::object ();
490+ res_frnd[" user_id" ] = frnd.at (" uin" ).get <int64_t >();
491+ res_frnd[" nickname" ] = frnd.at (" name" ).get <string>();
492+ res_frnd[" remark" ] = frnd.at (" remark" ).get <string>();
493+ result.data [gpid_idx_map[gpid]][" friends" ].push_back (res_frnd);
494+ }
495+
496+ result.retcode = RetCodes::OK;
497+ return ;
498+ } catch (exception &) {}
499+ }
500+
501+ // failed
502+ result.data = nullptr ;
503+ }
504+
505+ #pragma endregion
0 commit comments