Impl send rich text message
This commit is contained in:
parent
a75be1f161
commit
cf2c038256
@ -18,6 +18,7 @@ enum Functions {
|
||||
FUNC_SEND_FILE = 0x22;
|
||||
FUNC_SEND_XML = 0x23;
|
||||
FUNC_SEND_EMOTION = 0x24;
|
||||
FUNC_SEND_RICH_TXT = 0x25;
|
||||
FUNC_ENABLE_RECV_TXT = 0x30;
|
||||
FUNC_DISABLE_RECV_TXT = 0x40;
|
||||
FUNC_EXEC_DB_QUERY = 0x50;
|
||||
@ -51,6 +52,7 @@ message Request
|
||||
bool flag = 13;
|
||||
AttachMsg att = 14;
|
||||
AudioMsg am = 15;
|
||||
RichText rt = 16;
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,3 +197,14 @@ message AudioMsg
|
||||
uint64 id = 1; // 语音消息 id
|
||||
string dir = 2; // 存放目录
|
||||
}
|
||||
|
||||
message RichText
|
||||
{
|
||||
string name = 1; // 显示名字
|
||||
string account = 2; // 公众号 id
|
||||
string title = 3; // 标题
|
||||
string digest = 4; // 摘要
|
||||
string url = 5; // 链接
|
||||
string thumburl = 6; // 缩略图
|
||||
string receiver = 7; // 接收人
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ WxCalls_t wxCalls = {
|
||||
/* call1, call2, call3, call4, call5, call6*/
|
||||
{ 0x76F010, 0x792700, 0xBC0370, 0x80F110, 0x82BB40, 0x756E30},
|
||||
/* call1, call2, call3, call4, call5*/
|
||||
{0x76F010, 0x792700, 0xBC0370, 0xBB5F70, 0x756E30}
|
||||
{0x76F010, 0x792700, 0xBC0370, 0xBB5F70, 0x756E30},
|
||||
/* call1, call2, call3, call4, call5*/
|
||||
{0x76E630, 0x76AE20, 0xF59E40, 0xB73000, 0x76E350}
|
||||
};
|
||||
|
||||
int LoadCalls(const wchar_t *version, WxCalls_t *calls)
|
||||
|
@ -334,6 +334,33 @@ bool func_send_emotion(char *path, char *receiver, uint8_t *out, size_t *len)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool func_send_rich_txt(RichText rt, uint8_t *out, size_t *len)
|
||||
{
|
||||
Response rsp = Response_init_default;
|
||||
rsp.func = Functions_FUNC_SEND_RICH_TXT;
|
||||
rsp.which_msg = Response_status_tag;
|
||||
rsp.msg.status = 0;
|
||||
|
||||
RichText_t rtt;
|
||||
rtt.account = string(rt.account ? rt.account : "");
|
||||
rtt.digest = string(rt.digest ? rt.digest : "");
|
||||
rtt.name = string(rt.name ? rt.name : "");
|
||||
rtt.receiver = string(rt.receiver ? rt.receiver : "");
|
||||
rtt.thumburl = string(rt.thumburl ? rt.thumburl : "");
|
||||
rtt.title = string(rt.title ? rt.title : "");
|
||||
rtt.url = string(rt.url ? rt.url : "");
|
||||
|
||||
rsp.msg.status = SendRichTextMessage(rtt);
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(out, *len);
|
||||
if (!pb_encode(&stream, Response_fields, &rsp)) {
|
||||
LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream));
|
||||
return false;
|
||||
}
|
||||
*len = stream.bytes_written;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PushMessage()
|
||||
{
|
||||
static nng_socket msg_sock;
|
||||
@ -726,6 +753,11 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
||||
ret = func_send_txt(req.msg.txt, out, out_len);
|
||||
break;
|
||||
}
|
||||
case Functions_FUNC_SEND_RICH_TXT: {
|
||||
LOG_DEBUG("[Functions_FUNC_SEND_RICH_TXT]");
|
||||
ret = func_send_rich_txt(req.msg.rt, out, out_len);
|
||||
break;
|
||||
}
|
||||
case Functions_FUNC_SEND_IMG: {
|
||||
LOG_DEBUG("[Functions_FUNC_SEND_IMG]");
|
||||
ret = func_send_img(req.msg.file.path, req.msg.file.receiver, out, out_len);
|
||||
|
@ -171,6 +171,7 @@ void SendFileMessage(string wxid, string path)
|
||||
popad;
|
||||
}
|
||||
}
|
||||
|
||||
void SendXmlMessage(string receiver, string xml, string path, int type)
|
||||
{
|
||||
if (g_WeChatWinDllAddr == 0) {
|
||||
@ -294,3 +295,72 @@ void SendEmotionMessage(string wxid, string path)
|
||||
popad;
|
||||
}
|
||||
}
|
||||
|
||||
int SendRichTextMessage(RichText_t &rt)
|
||||
{
|
||||
int status = -1;
|
||||
char buff[0x238] = { 0 };
|
||||
|
||||
DWORD rtCall3 = g_WeChatWinDllAddr + g_WxCalls.rt.call3;
|
||||
DWORD rtCall2 = g_WeChatWinDllAddr + g_WxCalls.rt.call2;
|
||||
DWORD rtCall1 = g_WeChatWinDllAddr + g_WxCalls.rt.call1;
|
||||
DWORD rtCall5 = g_WeChatWinDllAddr + g_WxCalls.rt.call5;
|
||||
DWORD rtCall4 = g_WeChatWinDllAddr + g_WxCalls.rt.call4;
|
||||
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
lea ecx,buff;
|
||||
call rtCall1;
|
||||
popfd;
|
||||
popad;
|
||||
}
|
||||
|
||||
wstring receiver = String2Wstring(rt.receiver);
|
||||
wstring title = String2Wstring(rt.title);
|
||||
wstring url = String2Wstring(rt.url);
|
||||
wstring thumburl = String2Wstring(rt.thumburl);
|
||||
wstring account = String2Wstring(rt.account);
|
||||
wstring name = String2Wstring(rt.name);
|
||||
wstring digest = String2Wstring(rt.digest);
|
||||
|
||||
WxString wxReceiver(receiver);
|
||||
WxString wxTitle(title);
|
||||
WxString wxUrl(url);
|
||||
WxString wxThumburl(thumburl);
|
||||
WxString wxAccount(account);
|
||||
WxString wxName(name);
|
||||
WxString wxDigest(digest);
|
||||
|
||||
memcpy(&buff[0x4], &wxTitle, sizeof(wxTitle));
|
||||
memcpy(&buff[0x2C], &wxUrl, sizeof(wxUrl));
|
||||
memcpy(&buff[0x6C], &wxThumburl, sizeof(wxThumburl));
|
||||
memcpy(&buff[0x94], &wxDigest, sizeof(wxDigest));
|
||||
memcpy(&buff[0x1A0], &wxAccount, sizeof(wxAccount));
|
||||
memcpy(&buff[0x1B4], &wxName, sizeof(wxName));
|
||||
|
||||
__asm {
|
||||
pushad;
|
||||
pushfd;
|
||||
call rtCall2;
|
||||
lea ecx, buff;
|
||||
push ecx;
|
||||
sub esp, 0x14;
|
||||
mov edi, eax;
|
||||
mov ecx, esp;
|
||||
lea ebx, wxReceiver;
|
||||
push ebx;
|
||||
call rtCall3;
|
||||
mov ecx, edi;
|
||||
call rtCall4;
|
||||
mov status, eax;
|
||||
add ebx, 0x14;
|
||||
lea ecx, buff;
|
||||
push 0x0;
|
||||
call rtCall5;
|
||||
popfd;
|
||||
popad;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -4,8 +4,19 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct {
|
||||
string name;
|
||||
string account;
|
||||
string title;
|
||||
string digest;
|
||||
string url;
|
||||
string thumburl;
|
||||
string receiver;
|
||||
} RichText_t;
|
||||
|
||||
void SendTextMessage(string wxid, string msg, string atWxids);
|
||||
void SendImageMessage(string wxid, string path);
|
||||
void SendFileMessage(string wxid, string path);
|
||||
void SendXmlMessage(string receiver, string xml, string path, int type);
|
||||
void SendEmotionMessage(string wxid, string path);
|
||||
int SendRichTextMessage(RichText_t &rt);
|
||||
|
Binary file not shown.
@ -51,7 +51,7 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 39,0,6,0
|
||||
FILEVERSION 39,0,8,0
|
||||
PRODUCTVERSION 3,9,2,23
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
@ -69,7 +69,7 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "WeChatFerry"
|
||||
VALUE "FileDescription", "WeChatFerry"
|
||||
VALUE "FileVersion", "39.0.6.0"
|
||||
VALUE "FileVersion", "39.0.8.0"
|
||||
VALUE "InternalName", "spy.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||
VALUE "OriginalFilename", "spy.dll"
|
||||
|
@ -120,6 +120,14 @@ typedef struct RevokeMsg {
|
||||
DWORD call5;
|
||||
} RevokeMsg_t;
|
||||
|
||||
typedef struct CallRichText {
|
||||
DWORD call1;
|
||||
DWORD call2;
|
||||
DWORD call3;
|
||||
DWORD call4;
|
||||
DWORD call5;
|
||||
} CallRichText_t;
|
||||
|
||||
typedef struct WxCalls {
|
||||
DWORD login; // 登录状态
|
||||
UserInfoCall_t ui; // 用户信息
|
||||
@ -138,6 +146,7 @@ typedef struct WxCalls {
|
||||
Pyq_t pyq; // 接收朋友圈消息
|
||||
DlAttach_t da; // 下载资源(图片、文件、视频)
|
||||
RevokeMsg_t rm; // 撤回消息
|
||||
CallRichText_t rt; // 消息卡片
|
||||
} WxCalls_t;
|
||||
|
||||
struct WxString {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__version__ = "39.0.7.1"
|
||||
__version__ = "39.0.8.0"
|
||||
|
||||
import atexit
|
||||
import base64
|
||||
@ -415,6 +415,43 @@ class Wcf():
|
||||
rsp = self._send_request(req)
|
||||
return rsp.status
|
||||
|
||||
def send_rich_text(
|
||||
self, name: str, account: str, title: str, digest: str, url: str, thumburl: str, receiver: str) -> int:
|
||||
"""发送富文本消息
|
||||
卡片样式:
|
||||
|-------------------------------------|
|
||||
|title, 最长两行
|
||||
|(长标题, 标题短的话这行没有)
|
||||
|digest, 最多三行,会占位 |--------|
|
||||
|digest, 最多三行,会占位 |thumburl|
|
||||
|digest, 最多三行,会占位 |--------|
|
||||
|(account logo) name
|
||||
|-------------------------------------|
|
||||
Args:
|
||||
name (str): 左下显示的名字
|
||||
account (str): 填公众号 id 可以显示对应的头像(gh_ 开头的)
|
||||
title (str): 标题,最多两行
|
||||
digest (str): 摘要,三行
|
||||
url (str): 点击后跳转的链接
|
||||
thumburl (str): 缩略图的链接
|
||||
receiver (str): 接收人, wxid 或者 roomid
|
||||
|
||||
Returns:
|
||||
int: 0 为成功,其他失败
|
||||
"""
|
||||
req = wcf_pb2.Request()
|
||||
req.func = wcf_pb2.FUNC_SEND_RICH_TXT # FUNC_SEND_RICH_TXT
|
||||
req.rt.name = name
|
||||
req.rt.account = account
|
||||
req.rt.title = title
|
||||
req.rt.digest = digest
|
||||
req.rt.url = url
|
||||
req.rt.thumburl = thumburl
|
||||
req.rt.receiver = receiver
|
||||
|
||||
rsp = self._send_request(req)
|
||||
return rsp.status
|
||||
|
||||
def get_msg(self, block=True) -> WxMsg:
|
||||
"""从消息队列中获取消息
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user