Refactoring

This commit is contained in:
Changhua 2025-02-06 19:33:16 +08:00
parent 2e240c3731
commit 9232bab9e0
13 changed files with 191 additions and 103 deletions

View File

@ -88,20 +88,26 @@ int invite_chatroom_member(const string &roomid, const string &wxids)
reinterpret_cast<QWORD>(wx_roomid.get()), 0));
}
bool rpc_add_chatroom_member(const string &roomid, const string &wxids, uint8_t *out, size_t *len)
bool rpc_add_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len)
{
const std::string wxids = m.wxids;
const std::string roomid = m.roomid;
return fill_response<Functions_FUNC_ADD_ROOM_MEMBERS>(
out, len, [&](Response &rsp) { rsp.msg.status = add_chatroom_member(roomid, wxids); });
}
bool rpc_del_chatroom_member(const string &roomid, const string &wxids, uint8_t *out, size_t *len)
bool rpc_delete_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len)
{
const std::string wxids = m.wxids;
const std::string roomid = m.roomid;
return fill_response<Functions_FUNC_DEL_ROOM_MEMBERS>(
out, len, [&](Response &rsp) { rsp.msg.status = del_chatroom_member(roomid, wxids); });
}
bool rpc_invite_chatroom_member(const string &roomid, const string &wxids, uint8_t *out, size_t *len)
bool rpc_invite_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len)
{
const std::string wxids = m.wxids;
const std::string roomid = m.roomid;
return fill_response<Functions_FUNC_INV_ROOM_MEMBERS>(
out, len, [&](Response &rsp) { rsp.msg.status = invite_chatroom_member(roomid, wxids); });
}

View File

@ -2,6 +2,8 @@
#include <string>
#include "wcf.pb.h"
namespace chatroom
{
@ -15,8 +17,8 @@ int del_chatroom_member(const std::string &roomid, const std::string &wxids);
int invite_chatroom_member(const std::string &roomid, const std::string &wxids);
// RPC 方法
bool rpc_add_chatroom_member(const std::string &roomid, const std::string &wxids, uint8_t *out, size_t *len);
bool rpc_del_chatroom_member(const std::string &roomid, const std::string &wxids, uint8_t *out, size_t *len);
bool rpc_invite_chatroom_member(const std::string &roomid, const std::string &wxids, uint8_t *out, size_t *len);
bool rpc_add_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len);
bool rpc_delete_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len);
bool rpc_invite_chatroom_member(const MemberMgmt &m, uint8_t *out, size_t *len);
} // namespace chatroom

View File

@ -212,8 +212,11 @@ bool rpc_get_contact_info(const string &wxid, uint8_t *out, size_t *len)
});
}
bool rpc_accept_friend(const string &v3, const string &v4, int scene, uint8_t *out, size_t *len)
bool rpc_accept_friend(const Verification &v, uint8_t *out, size_t *len)
{
const string v3 = v.v3;
const string v4 = v.v4;
int scene = v.scene;
return fill_response<Functions_FUNC_ACCEPT_FRIEND>(
out, len, [&](Response &rsp) { rsp.msg.status = accept_new_friend(v3, v4, scene); });
}

View File

@ -3,6 +3,8 @@
#include <string>
#include <vector>
#include "wcf.pb.h"
#include "pb_types.h"
namespace contact
@ -23,6 +25,6 @@ int accept_new_friend(const std::string &v3, const std::string &v4, int scene);
// RPC 方法
bool rpc_get_contacts(uint8_t *out, size_t *len);
bool rpc_get_contact_info(const std::string &wxid, uint8_t *out, size_t *len);
bool rpc_accept_friend(const std::string &v3, const std::string &v4, int scene, uint8_t *out, size_t *len);
bool rpc_accept_friend(const Verification &v, uint8_t *out, size_t *len);
} // namespace contact

View File

@ -278,8 +278,10 @@ bool rpc_get_db_tables(const std::string &db, uint8_t *out, size_t *len)
});
}
bool rpc_exec_db_query(const std::string &db, const std::string &sql, uint8_t *out, size_t *len)
bool rpc_exec_db_query(const DbQuery query, uint8_t *out, size_t *len)
{
const std::string db(query.db);
const std::string sql(query.sql);
return fill_response<Functions_FUNC_EXEC_DB_QUERY>(out, len, [&](Response &rsp) {
DbRows_t rows = exec_db_query(db, sql);
rsp.msg.rows.rows.funcs.encode = encode_rows;

View File

@ -4,6 +4,8 @@
#include <string>
#include <vector>
#include "wcf.pb.h"
#include "pb_types.h"
namespace db
@ -27,6 +29,6 @@ std::vector<uint8_t> get_audio_data(uint64_t msg_id);
// RPC 方法
bool rpc_get_db_names(uint8_t *out, size_t *len);
bool rpc_get_db_tables(const std::string &db, uint8_t *out, size_t *len);
bool rpc_exec_db_query(const std::string &db, const std::string &sql, uint8_t *out, size_t *len);
bool rpc_exec_db_query(const DbQuery query, uint8_t *out, size_t *len);
} // namespace db

View File

@ -7,6 +7,7 @@
#include "framework.h"
#include "log.hpp"
#include "pb_util.h"
#include "rpc_helper.h"
#include "userinfo_manager.h"
#include "util.h"
@ -268,7 +269,7 @@ MH_STATUS Handler::UninitializeHook()
return status;
}
bool Handler::rpc_get_msg_types()
bool Handler::rpc_get_msg_types(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_GET_MSG_TYPES>(out, len, [&](Response &rsp) {
MsgTypes_t types = GetMsgTypes();
@ -276,35 +277,4 @@ bool Handler::rpc_get_msg_types()
rsp.msg.types.types.arg = &types;
});
}
bool rpc_enable_recv_msg(void *cb, bool pyq, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_ENABLE_RECV_TXT>(out, len, [cb, pyq](Response &rsp) {
auto &handler = Handler::getInstance();
rsp.msg.status = handler.ListenMsg();
if (rsp.msg.status == 0) {
if (pyq) {
msgHandler.ListenPyq();
}
msgThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)cb, nullptr, 0, nullptr);
if (msgThread == nullptr) {
rsp.msg.status = GetLastError();
LOG_ERROR("func_enable_recv_txt failed: {}", rsp.msg.status);
}
}
});
}
bool Handler::rpc_disable_recv_msg(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_DISABLE_RECV_TXT>(out, len, [](Response &rsp) {
rsp.msg.status = UnListenMsg();
if (rsp.msg.status == 0) {
UnListenPyq();
if (msgThread != nullptr) {
TerminateThread(msgThread, 0);
msgThread = nullptr;
}
}
});
}
}

View File

@ -37,9 +37,7 @@ public:
std::condition_variable &getConditionVariable() { return cv_; };
std::mutex &getMutex() { return mutex_; };
bool rpc_get_msg_types();
bool rpc_enable_recv_msg(void *cb, bool pyq, uint8_t *out, size_t *len);
bool rpc_disable_recv_msg(uint8_t *out, size_t *len);
bool rpc_get_msg_types(uint8_t *out, size_t *len);
private:
Handler();

View File

@ -262,8 +262,10 @@ bool Sender::rpc_send_text(const TextMsg &text, uint8_t *out, size_t *len)
});
}
bool Sender::rpc_send_image(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len)
bool Sender::rpc_send_image(const PathMsg &file, uint8_t *out, size_t *len)
{
std::string path(file.path);
std::string receiver(file.receiver);
return fill_response<Functions_FUNC_SEND_IMG>(out, len, [&](Response &rsp) {
if (path.empty() || receiver.empty()) {
LOG_ERROR("Empty path or receiver.");
@ -275,8 +277,10 @@ bool Sender::rpc_send_image(const std::string &path, const std::string &receiver
});
}
bool Sender::rpc_send_file(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len)
bool Sender::rpc_send_file(const PathMsg &file, uint8_t *out, size_t *len)
{
std::string path(file.path);
std::string receiver(file.receiver);
return fill_response<Functions_FUNC_SEND_FILE>(out, len, [&](Response &rsp) {
if (path.empty() || receiver.empty()) {
LOG_ERROR("Empty path or receiver.");
@ -288,8 +292,10 @@ bool Sender::rpc_send_file(const std::string &path, const std::string &receiver,
});
}
bool Sender::rpc_send_emotion(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len)
bool Sender::rpc_send_emotion(const PathMsg &file, uint8_t *out, size_t *len)
{
std::string path(file.path);
std::string receiver(file.receiver);
return fill_response<Functions_FUNC_SEND_EMOTION>(out, len, [&](Response &rsp) {
if (path.empty() || receiver.empty()) {
LOG_ERROR("Empty path or receiver.");
@ -326,8 +332,10 @@ bool Sender::rpc_send_rich_text(const RichText &rt, uint8_t *out, size_t *len)
});
}
bool Sender::rpc_send_pat(const std::string &roomid, const std::string &wxid, uint8_t *out, size_t *len)
bool Sender::rpc_send_pat(const PatMsg &pat, uint8_t *out, size_t *len)
{
std::string wxid(pat.wxid);
std::string roomid(pat.roomid);
return fill_response<Functions_FUNC_SEND_PAT_MSG>(out, len, [&](Response &rsp) {
if (roomid.empty() || wxid.empty()) {
LOG_ERROR("Empty roomid or wxid.");
@ -338,8 +346,10 @@ bool Sender::rpc_send_pat(const std::string &roomid, const std::string &wxid, ui
});
}
bool Sender::rpc_forward(uint64_t msgid, const std::string &receiver, uint8_t *out, size_t *len)
bool Sender::rpc_forward(const ForwardMsg &fm, uint8_t *out, size_t *len)
{
uint64_t msgid = fm.id;
std::string receiver(fm.receiver);
return fill_response<Functions_FUNC_FORWARD_MSG>(out, len, [&](Response &rsp) {
if (receiver.empty()) {
LOG_ERROR("Empty receiver.");

View File

@ -4,9 +4,10 @@
#include <string>
#include <vector>
#include "spy_types.h"
#include "wcf.pb.h"
#include "spy_types.h"
namespace message
{
@ -26,13 +27,13 @@ public:
// RPC 方法
bool rpc_send_text(const TextMsg &text, uint8_t *out, size_t *len);
bool rpc_send_image(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len);
bool rpc_send_file(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len);
bool rpc_send_emotion(const std::string &path, const std::string &receiver, uint8_t *out, size_t *len);
bool rpc_send_image(const PathMsg &file, uint8_t *out, size_t *len);
bool rpc_send_file(const PathMsg &file, uint8_t *out, size_t *len);
bool rpc_send_emotion(const PathMsg &file, uint8_t *out, size_t *len);
bool rpc_send_xml(const XmlMsg &rt, uint8_t *out, size_t *len);
bool rpc_send_rich_text(const RichText &rt, uint8_t *out, size_t *len);
bool rpc_send_pat(const std::string &roomid, const std::string &wxid, uint8_t *out, size_t *len);
bool rpc_forward(uint64_t msgid, const std::string &receiver, uint8_t *out, size_t *len);
bool rpc_send_pat(const PatMsg &pat, uint8_t *out, size_t *len);
bool rpc_forward(const ForwardMsg &fm, uint8_t *out, size_t *len);
private:
Sender();
@ -76,5 +77,4 @@ private:
std::unique_ptr<WxString> new_wx_string(const std::string &str);
std::vector<WxString> parse_wxids(const std::string &wxids);
};
}

View File

@ -10,6 +10,7 @@
#include "database_executor.h"
#include "log.hpp"
#include "message_handler.h"
#include "rpc_helper.h"
#include "spy_types.h"
#include "util.h"
@ -349,4 +350,66 @@ int receive_transfer(const std::string &wxid, const std::string &transferid, con
// 别想了,这个不实现了
return -1;
}
bool rpc_is_logged_in(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_IS_LOGIN>(out, len, [](Response &rsp) { rsp.msg.status = is_logged_in(); });
}
bool rpc_get_audio(const AudioMsg &am, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_GET_AUDIO_MSG>(
out, len, [&](Response &rsp) { rsp.msg.str = (char *)get_audio(am.id, am.dir).c_str(); });
}
bool rpc_get_pcm_audio(uint64_t id, const std::filesystem::path &dir, int32_t sr, uint8_t *out, size_t *len)
{
return false;
}
bool rpc_decrypt_image(const DecPath &dec, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_DECRYPT_IMAGE>(
out, len, [&](Response &rsp) { rsp.msg.str = (char *)decrypt_image(dec.src, dec.dst).c_str(); });
}
bool rpc_get_login_url(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_REFRESH_QRCODE>(
out, len, [&](Response &rsp) { rsp.msg.str = (char *)get_login_url().c_str(); });
}
bool rpc_refresh_pyq(uint64_t id, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_REFRESH_PYQ>(out, len,
[&](Response &rsp) { rsp.msg.status = refresh_pyq(id); });
}
bool rpc_download_attachment(const AttachMsg &att, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_DOWNLOAD_ATTACH>(
out, len, [&](Response &rsp) { rsp.msg.status = download_attachment(att.id, att.thumb, att.extra); });
}
bool rpc_revoke_message(uint64_t id, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_REVOKE_MSG>(out, len,
[&](Response &rsp) { rsp.msg.status = revoke_message(id); });
}
bool rpc_get_ocr_result(const std::filesystem::path &path, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_EXEC_OCR>(out, len, [&](Response &rsp) {
OcrResult_t ret = { -1, "" };
ret = get_ocr_result(path);
rsp.msg.ocr.status = ret.status;
rsp.msg.ocr.result = (char *)ret.result.c_str();
});
}
bool rpc_receive_transfer(const Transfer &tf, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_RECV_TRANSFER>(
out, len, [&](Response &rsp) { rsp.msg.status = receive_transfer(tf.wxid, tf.tfid, tf.taid); });
}
} // namespace misc

View File

@ -30,14 +30,14 @@ int receive_transfer(const std::string &wxid, const std::string &transferid, con
// RPC
// clang-format off
bool rpc_is_logged_in(uint8_t *out, size_t *len);
bool rpc_get_audio(uint64_t id, const std::filesystem::path &dir, uint8_t *out, size_t *len);
bool rpc_get_audio(const AudioMsg &am, uint8_t *out, size_t *len);
bool rpc_get_pcm_audio(uint64_t id, const std::filesystem::path &dir, int32_t sr, uint8_t *out, size_t *len);
bool rpc_decrypt_image(const DecPath &dec, uint8_t *out, size_t *len);
bool rpc_get_login_url(uint8_t *out, size_t *len);
bool rpc_refresh_pyq(uint64_t id, uint8_t *out, size_t *len);
bool rpc_download_attachment(uint64_t id, const std::filesystem::path &thumb, const std::filesystem::path &extra, uint8_t *out, size_t *len);
bool rpc_download_attachment(const AttachMsg &att, uint8_t *out, size_t *len);
bool rpc_revoke_message(uint64_t id, uint8_t *out, size_t *len);
bool rpc_get_ocr_result(const std::filesystem::path &path, uint8_t *out, size_t *len);
bool rpc_receive_transfer(const std::string &wxid, const std::string &transferid, const std::string &transactionid, uint8_t *out, size_t *len);
bool rpc_receive_transfer(const Transfer &tf, uint8_t *out, size_t *len);
// clang-format on
} // namespace misc

View File

@ -29,6 +29,7 @@
#include "misc_manager.h"
#include "pb_types.h"
#include "pb_util.h"
#include "rpc_helper.h"
#include "spy.h"
#include "spy_types.h"
#include "userinfo_manager.h"
@ -44,52 +45,14 @@ static HANDLE cmdThread = NULL;
static HANDLE msgThread = NULL;
static nng_socket cmdSock = NNG_SOCKET_INITIALIZER; // TODO: 断开检测
static nng_socket msgSock = NNG_SOCKET_INITIALIZER; // TODO: 断开检测
auto &handler = message::Handler::getInstance();
auto &sender = message::Sender::get_instance();
using FunctionHandler = std::function<bool(const Request &, uint8_t *, size_t *)>;
inline std::string build_url(int port) { return "tcp://0.0.0.0:" + std::to_string(port); }
void receive_message_callback();
auto &handler = message::Handler::getInstance();
auto &sender = message::Sender::get_instance();
const std::unordered_map<Functions, FunctionHandler> rpc_function_map = {
// clang-format off
{ Functions_FUNC_IS_LOGIN, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_is_logged_in(out, len); } },
{ Functions_FUNC_GET_SELF_WXID, [](const Request &r, uint8_t *out, size_t *len) { return userinfo::rpc_get_self_wxid(out, len)} },
{ Functions_FUNC_GET_USER_INFO, [](const Request &r, uint8_t *out, size_t *len) { return userinfo::rpc_get_user_info(out, len); } },
{ Functions_FUNC_GET_MSG_TYPES, [](const Request &r, uint8_t *out, size_t *len) { return handler.rpc_get_msg_types(out, len); } },
{ Functions_FUNC_GET_CONTACTS, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_get_contacts(out, len); } },
{ Functions_FUNC_GET_DB_NAMES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_names(out, len); } },
{ Functions_FUNC_GET_DB_TABLES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_tables(r.msg.str, out, len); } },
{ Functions_FUNC_GET_AUDIO_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_audio(r.msg.am.id, r.msg.am.dir, out, len); } },
{ Functions_FUNC_SEND_TXT, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_text(r.msg.txt, out, len); } },
{ Functions_FUNC_SEND_IMG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_image(r.msg.file.path, r.msg.file.receiver, out, len); } },
{ Functions_FUNC_SEND_FILE, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_file(r.msg.file.path, r.msg.file.receiver, out, len); } },
{ Functions_FUNC_SEND_XML, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_xml(r.msg.xml, out, len); } },
{ Functions_FUNC_SEND_RICH_TXT, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_rich_text(r.msg.rt, out, len); } },
{ Functions_FUNC_SEND_PAT_MSG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_pat(r.msg.pm.roomid, r.msg.pm.wxid, out, len); } },
{ Functions_FUNC_FORWARD_MSG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_forward(r.msg.fm.id, r.msg.fm.receiver, out, len); } },
{ Functions_FUNC_SEND_EMOTION, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_emotion(r.msg.file.path, r.msg.file.receiver, out, len); } },
{ Functions_FUNC_ENABLE_RECV_TXT, [](const Request &r, uint8_t *out, size_t *len) { return handler.rpc_enable_recv_msg(receive_message_callback, r.msg.flag, out, len); } },
{ Functions_FUNC_DISABLE_RECV_TXT, [](const Request &r, uint8_t *out, size_t *len) { return handler.rpc_disable_recv_msg(out, len); } },
{ Functions_FUNC_EXEC_DB_QUERY, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_exec_db_query(r.msg.query.db, r.msg.query.sql, out, len); } },
{ Functions_FUNC_REFRESH_PYQ, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_refresh_pyq(r.msg.ui64, out, len); } },
{ Functions_FUNC_DOWNLOAD_ATTACH, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_download_attachment(r.msg.att, out, len); } },
{ Functions_FUNC_GET_CONTACT_INFO, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_get_contact_info(r.msg.str, out, len); } },
{ Functions_FUNC_ACCEPT_FRIEND, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_accept_friend(r.msg.v, out, len); } },
{ Functions_FUNC_RECV_TRANSFER, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_receive_transfer(r.msg.tf, out, len); } },
{ Functions_FUNC_REVOKE_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::revoke_message(r.msg.ui64, out, len); } },
{ Functions_FUNC_REFRESH_QRCODE, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_login_url(out, len); } },
{ Functions_FUNC_DECRYPT_IMAGE, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_decrypt_image(r.msg.dec, out, len); } },
{ Functions_FUNC_EXEC_OCR, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_ocr_result(r.msg.str, out, len); } },
{ Functions_FUNC_ADD_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_add_chatroom_member(r.msg.m, out, len); } },
{ Functions_FUNC_DEL_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_del_chatroom_member(r.msg.m, out, len); } },
{ Functions_FUNC_INV_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_invite_chatroom_memberr.msg.m, out, len); } },
// clang-format on
};
void receive_message_callback()
static void receive_message_callback()
{
int rv;
Response rsp = Response_init_default;
@ -155,6 +118,73 @@ void receive_message_callback()
}
}
static bool rpc_enable_recv_msg(bool pyq, uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_ENABLE_RECV_TXT>(out, len, [&](Response &rsp) {
rsp.msg.status = handler.ListenMsg();
if (rsp.msg.status == 0) {
if (pyq) {
handler.ListenPyq();
}
msgThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)receive_message_callback, nullptr, 0, nullptr);
if (msgThread == nullptr) {
rsp.msg.status = GetLastError();
LOG_ERROR("func_enable_recv_txt failed: {}", rsp.msg.status);
}
}
});
}
static bool rpc_disable_recv_msg(uint8_t *out, size_t *len)
{
return fill_response<Functions_FUNC_DISABLE_RECV_TXT>(out, len, [](Response &rsp) {
rsp.msg.status = handler.UnListenMsg();
if (rsp.msg.status == 0) {
handler.UnListenPyq();
if (msgThread != nullptr) {
TerminateThread(msgThread, 0);
msgThread = nullptr;
}
}
});
}
const std::unordered_map<Functions, FunctionHandler> rpc_function_map = {
// clang-format off
{ Functions_FUNC_IS_LOGIN, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_is_logged_in(out, len); } },
{ Functions_FUNC_GET_SELF_WXID, [](const Request &r, uint8_t *out, size_t *len) { return userinfo::rpc_get_self_wxid(out, len); } },
{ Functions_FUNC_GET_USER_INFO, [](const Request &r, uint8_t *out, size_t *len) { return userinfo::rpc_get_user_info(out, len); } },
{ Functions_FUNC_GET_MSG_TYPES, [](const Request &r, uint8_t *out, size_t *len) { return handler.rpc_get_msg_types(out, len); } },
{ Functions_FUNC_GET_CONTACTS, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_get_contacts(out, len); } },
{ Functions_FUNC_GET_DB_NAMES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_names(out, len); } },
{ Functions_FUNC_GET_DB_TABLES, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_get_db_tables(r.msg.str, out, len); } },
{ Functions_FUNC_GET_AUDIO_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_audio(r.msg.am, out, len); } },
{ Functions_FUNC_SEND_TXT, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_text(r.msg.txt, out, len); } },
{ Functions_FUNC_SEND_IMG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_image(r.msg.file, out, len); } },
{ Functions_FUNC_SEND_FILE, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_file(r.msg.file, out, len); } },
{ Functions_FUNC_SEND_XML, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_xml(r.msg.xml, out, len); } },
{ Functions_FUNC_SEND_EMOTION, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_emotion(r.msg.file, out, len); } },
{ Functions_FUNC_SEND_RICH_TXT, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_rich_text(r.msg.rt, out, len); } },
{ Functions_FUNC_SEND_PAT_MSG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_send_pat(r.msg.pm, out, len); } },
{ Functions_FUNC_FORWARD_MSG, [](const Request &r, uint8_t *out, size_t *len) { return sender.rpc_forward(r.msg.fm, out, len); } },
{ Functions_FUNC_ENABLE_RECV_TXT, [](const Request &r, uint8_t *out, size_t *len) { return rpc_enable_recv_msg(r.msg.flag, out, len); } },
{ Functions_FUNC_DISABLE_RECV_TXT, [](const Request &r, uint8_t *out, size_t *len) { return rpc_disable_recv_msg(out, len); } },
{ Functions_FUNC_EXEC_DB_QUERY, [](const Request &r, uint8_t *out, size_t *len) { return db::rpc_exec_db_query(r.msg.query, out, len); } },
{ Functions_FUNC_ACCEPT_FRIEND, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_accept_friend(r.msg.v, out, len); } },
{ Functions_FUNC_RECV_TRANSFER, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_receive_transfer(r.msg.tf, out, len); } },
{ Functions_FUNC_REFRESH_PYQ, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_refresh_pyq(r.msg.ui64, out, len); } },
{ Functions_FUNC_DOWNLOAD_ATTACH, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_download_attachment(r.msg.att, out, len); } },
{ Functions_FUNC_GET_CONTACT_INFO, [](const Request &r, uint8_t *out, size_t *len) { return contact::rpc_get_contact_info(r.msg.str, out, len); } },
{ Functions_FUNC_REVOKE_MSG, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_revoke_message(r.msg.ui64, out, len); } },
{ Functions_FUNC_REFRESH_QRCODE, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_login_url(out, len); } },
{ Functions_FUNC_DECRYPT_IMAGE, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_decrypt_image(r.msg.dec, out, len); } },
{ Functions_FUNC_EXEC_OCR, [](const Request &r, uint8_t *out, size_t *len) { return misc::rpc_get_ocr_result(r.msg.str, out, len); } },
{ Functions_FUNC_ADD_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_add_chatroom_member(r.msg.m, out, len); } },
{ Functions_FUNC_DEL_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_delete_chatroom_member(r.msg.m, out, len); } },
{ Functions_FUNC_INV_ROOM_MEMBERS, [](const Request &r, uint8_t *out, size_t *len) { return chatroom::rpc_invite_chatroom_member(r.msg.m, out, len); } },
// clang-format on
};
static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
{
bool ret = false;