Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.

Commit

Permalink
generate fragment message id
Browse files Browse the repository at this point in the history
  • Loading branch information
takayama-lily committed Dec 19, 2020
1 parent 12ef94e commit de6dd12
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 24 deletions.
2 changes: 1 addition & 1 deletion client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface ConfBot {
platform?: number, //1:安卓手机 2:aPad(默认) 3:安卓手表 4:Mac(实验性)
kickoff?: boolean, //被挤下线是否在3秒后反挤对方,默认false
ignore_self?: boolean,//群聊是否无视自己的发言,默认true
resend?: boolean, //被风控时是否尝试用分片发送,默认true (分片消息暂不支持撤回等操作)
resend?: boolean, //被风控时是否尝试用分片发送,默认true (一种古老的消息,暂不支持分片重组)
data_dir?: string, //数据存储文件夹,需要可写权限,默认主目录下的data文件夹

//触发system.offline.network事件后的重连间隔秒数,默认5(秒),不建议设置低于3(秒)
Expand Down
6 changes: 3 additions & 3 deletions docs/msgid.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
## 群消息id规则

```md
群消息id总共20字节,使用base64编码保存
群消息id总共21字节,使用base64编码保存

| 群号(int32) | 发送者QQ(int32) | 消息编号(int32) | 随机数(int32) | 时间戳(int32) |
gid uid seqid random timestamp
| 群号(int32) | 发送者QQ(int32) | 消息编号(int32) | 随机数(int32) | 时间戳(int32) | 分片数(int8) |
gid uid seqid random timestamp pktnum
```

## 私聊消息id规则
Expand Down
12 changes: 7 additions & 5 deletions lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,14 @@ function parseC2CMessageId(message_id) {
time = buf.readUInt32BE(12);
return {user_id, seq, random, time};
}
function genGroupMessageId(group_id, user_id, seq, random, time) {
const buf = Buffer.allocUnsafe(20);
function genGroupMessageId(group_id, user_id, seq, random, time, pktnum = 1) {
const buf = Buffer.allocUnsafe(21);
buf.writeUInt32BE(group_id),
buf.writeUInt32BE(user_id, 4),
buf.writeInt32BE(seq&0xffffffff, 8),
buf.writeInt32BE(random&0xffffffff, 12),
buf.writeUInt32BE(time, 16);
buf.writeUInt32BE(time, 16),
buf.writeUInt8(pktnum>1?pktnum:1, 20);
return buf.toString("base64");
}
function parseGroupMessageId(message_id) {
Expand All @@ -107,8 +108,9 @@ function parseGroupMessageId(message_id) {
user_id = buf.readUInt32BE(4),
seq = buf.readUInt32BE(8),
random = buf.readUInt32BE(12),
time = buf.readUInt32BE(16);
return {group_id, user_id, seq, random, time};
time = buf.readUInt32BE(16),
pktnum = buf.length === 21 ? buf.readUInt8(20) : 1;
return {group_id, user_id, seq, random, time, pktnum};
}
function genMessageUuid(random) {
return 16777216n << 32n | BigInt(random);
Expand Down
2 changes: 1 addition & 1 deletion lib/message/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class Builder {
}
});
}
this.stat.length += Buffer.byteLength(text);
this.stat.length += text.length;
}
}
buildAtElem(cq) {
Expand Down
66 changes: 56 additions & 10 deletions lib/message/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ async function sendMsg(target, message, escape, type) {
}
rsp = await _sendMsg({2: builder.elems});
if (this.config.resend && rsp.data && rsp.data.message_id === "") {
if (builder.stat.length <= 100) {
const emsg = "群消息发送失败,可能包含奇怪的内容所导致";
this.logger.error(`send failed: [Group: ${target}] ` + emsg);
return {result: -1, emsg};
}
this.logger.warn(`此消息将尝试使用分片发送。`);
return await _sendMsg({2: builder.elems}, true);
}
Expand Down Expand Up @@ -225,8 +230,26 @@ async function sendGroupMsgByFrag(group_id, fragments) {
++n;
this.writeUNI("MessageSvc.PbSendMsg", body);
}
this.logger.info(`send to: [Group: ${group_id} / fragments]`);
return {result: 0, data: {message_id: ""}};
const event_id = `interval.${group_id}.${random}`;
let message_id = "";
await new Promise((resolve)=>{
const timeout = setTimeout(()=>{
this.removeAllListeners(event_id);
resolve();
}, 3000);
this.once(event_id, (id)=>{
message_id = id;
clearTimeout(timeout);
resolve();
});
});
if (!message_id) {
const emsg = "群分片消息发送失败,可能包含奇怪的内容所导致";
this.logger.error(`send failed: [Group: ${group_id}] ` + emsg);
return {result: -1, emsg};
}
this.logger.info(`send to: [Group: ${group_id} / message_id: ${message_id}]`);
return {result: 0, data: {message_id}};
}

function toFragments(elems) {
Expand Down Expand Up @@ -338,17 +361,40 @@ function buildRecallPrivateMsgBody(message_id) {
});
}
function buildRecallGroupMsgBody(message_id) {
const {group_id, seq, random} = parseGroupMessageId(message_id);
var {group_id, seq, random, pktnum} = parseGroupMessageId(message_id);
if (pktnum > 1) {
//分片消息
var msg = [], pb_msg = [], n = pktnum, i = 0;
while (n-- > 0) {
msg.push(pb.encode({
1: seq,
2: random,
}));
pb_msg.push(pb.encode({
1: seq,
3: pktnum,
4: i++
}));
++seq;
}
var reserver = {
1: 1,
2: pb_msg,
}
} else {
var msg = {
1: seq,
2: random,
};
var reserver = {1: 0};
}
return pb.encode({
2: [{
1: 1,
2: 0,
3: group_id,
4: [{
1: seq,
2: random,
3: 0,
}],
5: Buffer.from([8,0]),
4: msg,
5: reserver,
}]
});
}
Expand All @@ -362,7 +408,7 @@ async function getHistoryMsg(message_id) {
if (message_id.length > 24) {
const o = await getGroupMsg.call(this, message_id);
try {
const msg = await parseGroupMsg.call(this, o[1], o[3], false);
const msg = await parseGroupMsg.call(this, o[1], o[2], o[3], false);
msg.message_type = "group";
msg.real_id = message_id;
return {result: 0, data: msg};
Expand Down
13 changes: 10 additions & 3 deletions lib/message/recv.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async function parsePrivateMsg(type, head, content, body) {
/**
* @this {import("../ref").Client}
*/
async function parseGroupMsg(head, body, ignore_self = true) {
async function parseGroupMsg(head, content, body, ignore_self = true) {

const user_id = head[1],
time = head[6],
Expand All @@ -71,8 +71,15 @@ async function parseGroupMsg(head, body, ignore_self = true) {
}

this.msgExists(group_id, 0, seq, time);
const message_id = genGroupMessageId(group_id, user_id, seq, body[1][1][3], time);
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
const message_id = genGroupMessageId(group_id, user_id, seq, body[1][1][3], time, content[1]);
if (content[1] > 1) {
//分片消息
if (content[2] === 0)
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
} else {
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
}

this.getGroupInfo(group_id);

var {chain, raw_message, extra, anon} = await parseMessage.call(this, body[1], group_id, 1);
Expand Down
2 changes: 1 addition & 1 deletion lib/online-push.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ async function onGroupMsg(blob, seq) {
return;
const o = pb.decode(blob);
try {
const msg = await parseGroupMsg.call(this, o[1][1], o[1][3]);
const msg = await parseGroupMsg.call(this, o[1][1], o[1][2], o[1][3]);
if (msg && msg.raw_message) {
const sender = msg.sender;
this.logger.info(`recv from: [Group: ${msg.group_name}(${msg.group_id}), Member: ${sender.card?sender.card:sender.nickname}(${msg.user_id})] ` + msg.raw_message);
Expand Down

0 comments on commit de6dd12

Please sign in to comment.