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_FILE = 0x22;
|
||||||
FUNC_SEND_XML = 0x23;
|
FUNC_SEND_XML = 0x23;
|
||||||
FUNC_SEND_EMOTION = 0x24;
|
FUNC_SEND_EMOTION = 0x24;
|
||||||
|
FUNC_SEND_RICH_TXT = 0x25;
|
||||||
FUNC_ENABLE_RECV_TXT = 0x30;
|
FUNC_ENABLE_RECV_TXT = 0x30;
|
||||||
FUNC_DISABLE_RECV_TXT = 0x40;
|
FUNC_DISABLE_RECV_TXT = 0x40;
|
||||||
FUNC_EXEC_DB_QUERY = 0x50;
|
FUNC_EXEC_DB_QUERY = 0x50;
|
||||||
@ -51,6 +52,7 @@ message Request
|
|||||||
bool flag = 13;
|
bool flag = 13;
|
||||||
AttachMsg att = 14;
|
AttachMsg att = 14;
|
||||||
AudioMsg am = 15;
|
AudioMsg am = 15;
|
||||||
|
RichText rt = 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,3 +197,14 @@ message AudioMsg
|
|||||||
uint64 id = 1; // 语音消息 id
|
uint64 id = 1; // 语音消息 id
|
||||||
string dir = 2; // 存放目录
|
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*/
|
/* call1, call2, call3, call4, call5, call6*/
|
||||||
{ 0x76F010, 0x792700, 0xBC0370, 0x80F110, 0x82BB40, 0x756E30},
|
{ 0x76F010, 0x792700, 0xBC0370, 0x80F110, 0x82BB40, 0x756E30},
|
||||||
/* call1, call2, call3, call4, call5*/
|
/* 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)
|
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;
|
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 void PushMessage()
|
||||||
{
|
{
|
||||||
static nng_socket msg_sock;
|
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);
|
ret = func_send_txt(req.msg.txt, out, out_len);
|
||||||
break;
|
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: {
|
case Functions_FUNC_SEND_IMG: {
|
||||||
LOG_DEBUG("[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);
|
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;
|
popad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendXmlMessage(string receiver, string xml, string path, int type)
|
void SendXmlMessage(string receiver, string xml, string path, int type)
|
||||||
{
|
{
|
||||||
if (g_WeChatWinDllAddr == 0) {
|
if (g_WeChatWinDllAddr == 0) {
|
||||||
@ -294,3 +295,72 @@ void SendEmotionMessage(string wxid, string path)
|
|||||||
popad;
|
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;
|
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 SendTextMessage(string wxid, string msg, string atWxids);
|
||||||
void SendImageMessage(string wxid, string path);
|
void SendImageMessage(string wxid, string path);
|
||||||
void SendFileMessage(string wxid, string path);
|
void SendFileMessage(string wxid, string path);
|
||||||
void SendXmlMessage(string receiver, string xml, string path, int type);
|
void SendXmlMessage(string receiver, string xml, string path, int type);
|
||||||
void SendEmotionMessage(string wxid, string path);
|
void SendEmotionMessage(string wxid, string path);
|
||||||
|
int SendRichTextMessage(RichText_t &rt);
|
||||||
|
Binary file not shown.
@ -51,7 +51,7 @@ END
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 39,0,6,0
|
FILEVERSION 39,0,8,0
|
||||||
PRODUCTVERSION 3,9,2,23
|
PRODUCTVERSION 3,9,2,23
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@ -69,7 +69,7 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "WeChatFerry"
|
VALUE "CompanyName", "WeChatFerry"
|
||||||
VALUE "FileDescription", "WeChatFerry"
|
VALUE "FileDescription", "WeChatFerry"
|
||||||
VALUE "FileVersion", "39.0.6.0"
|
VALUE "FileVersion", "39.0.8.0"
|
||||||
VALUE "InternalName", "spy.dll"
|
VALUE "InternalName", "spy.dll"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2023"
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
VALUE "OriginalFilename", "spy.dll"
|
VALUE "OriginalFilename", "spy.dll"
|
||||||
|
@ -120,6 +120,14 @@ typedef struct RevokeMsg {
|
|||||||
DWORD call5;
|
DWORD call5;
|
||||||
} RevokeMsg_t;
|
} RevokeMsg_t;
|
||||||
|
|
||||||
|
typedef struct CallRichText {
|
||||||
|
DWORD call1;
|
||||||
|
DWORD call2;
|
||||||
|
DWORD call3;
|
||||||
|
DWORD call4;
|
||||||
|
DWORD call5;
|
||||||
|
} CallRichText_t;
|
||||||
|
|
||||||
typedef struct WxCalls {
|
typedef struct WxCalls {
|
||||||
DWORD login; // 登录状态
|
DWORD login; // 登录状态
|
||||||
UserInfoCall_t ui; // 用户信息
|
UserInfoCall_t ui; // 用户信息
|
||||||
@ -138,6 +146,7 @@ typedef struct WxCalls {
|
|||||||
Pyq_t pyq; // 接收朋友圈消息
|
Pyq_t pyq; // 接收朋友圈消息
|
||||||
DlAttach_t da; // 下载资源(图片、文件、视频)
|
DlAttach_t da; // 下载资源(图片、文件、视频)
|
||||||
RevokeMsg_t rm; // 撤回消息
|
RevokeMsg_t rm; // 撤回消息
|
||||||
|
CallRichText_t rt; // 消息卡片
|
||||||
} WxCalls_t;
|
} WxCalls_t;
|
||||||
|
|
||||||
struct WxString {
|
struct WxString {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__version__ = "39.0.7.1"
|
__version__ = "39.0.8.0"
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
import base64
|
import base64
|
||||||
@ -415,6 +415,43 @@ class Wcf():
|
|||||||
rsp = self._send_request(req)
|
rsp = self._send_request(req)
|
||||||
return rsp.status
|
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:
|
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