oicq-icalingua-plus-plus 1.26.13 → 1.26.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/http-api/README.md +1 -0
- package/index.d.ts +14 -1
- package/lib/client.js +3 -0
- package/lib/core/friendlist.js +1 -0
- package/lib/core/troop.js +24 -1
- package/lib/message/parser.js +3 -1
- package/lib/onlinepush.js +284 -144
- package/package.json +3 -3
package/http-api/README.md
CHANGED
|
@@ -158,6 +158,7 @@ notice事件有部分格式默认与cqhttp中的格式不同。
|
|
|
158
158
|
|群组文件|表现为CQ码 |notice.group_upload |
|
|
159
159
|
|群戳一戳|notice.group.poke | |
|
|
160
160
|
|群设置变|notice.group.setting | |
|
|
161
|
+
|表情回应|notice.group.reaction | |
|
|
161
162
|
|元事件|meta_event.lifecycle.enable|meta_event.lifecycle.enable|
|
|
162
163
|
|元事件|meta_event.lifecycle.disable|meta_event.lifecycle.disable|
|
|
163
164
|
|元事件|meta_event.lifecycle.connect|meta_event.lifecycle.connect|
|
package/index.d.ts
CHANGED
|
@@ -210,7 +210,7 @@ export interface MemberInfo extends MemberBaseInfo {
|
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
212
|
* 使用cqhttp风格的消息元素类型
|
|
213
|
-
* @see https://github.com/
|
|
213
|
+
* @see https://github.com/botuniverse/onebot/blob/main/specs/interface/message/segments.md 在此基础上进行了扩展
|
|
214
214
|
*/
|
|
215
215
|
export type MessageElem = TextElem | AtElem | FaceElem | BfaceElem | MfaceElem |
|
|
216
216
|
ImgPttElem | LocationElem | MusicElem | ShareElem | JsonElem | XmlElem |
|
|
@@ -623,6 +623,15 @@ export interface GroupEssenceEventData extends CommonGroupNoticeEventData {
|
|
|
623
623
|
operator_id: number, //操作者
|
|
624
624
|
operator_name: string, //操作者昵称
|
|
625
625
|
}
|
|
626
|
+
/** 群表情回应 */
|
|
627
|
+
export interface GroupReactionEvent extends CommonGroupNoticeEventData {
|
|
628
|
+
sub_type: "reaction"; //群表情回应
|
|
629
|
+
user_id: number; //设置回应者
|
|
630
|
+
id: string; //回应的表情id
|
|
631
|
+
type: number; //回应的表情类型
|
|
632
|
+
seq: number; //消息seq
|
|
633
|
+
set: boolean; //设置/取消回应
|
|
634
|
+
}
|
|
626
635
|
export interface MemberIncreaseEventData extends CommonGroupNoticeEventData {
|
|
627
636
|
sub_type: "increase", //群增加或群员增加
|
|
628
637
|
group_id: number,
|
|
@@ -936,6 +945,8 @@ export interface EventMap {
|
|
|
936
945
|
"notice.group.sign": (this: Client, data: GroupSignEventData) => void;
|
|
937
946
|
/**群精华事件 */
|
|
938
947
|
"notice.group.essence": (this: Client, data: GroupEssenceEventData) => void;
|
|
948
|
+
/**群表情回应事件 */
|
|
949
|
+
"notice.group.reaction": (this: Client, data: GroupReactionEventData) => void;
|
|
939
950
|
/**群设置变更事件 */
|
|
940
951
|
"notice.group.setting": (this: Client, data: GroupSettingEventData) => void;
|
|
941
952
|
/**监听以上所有好友notice事件 */
|
|
@@ -1127,6 +1138,8 @@ export class Client extends EventEmitter {
|
|
|
1127
1138
|
sendGroupSign(group_id: number): Promise<Ret>;
|
|
1128
1139
|
/** 设置群备注名 */
|
|
1129
1140
|
setGroupRemark(group_id: number, remark: string): Promise<Ret>;
|
|
1141
|
+
/** 设置群消息表情回应 */
|
|
1142
|
+
setEmojiReaction(group_id: number, msg_seq: number, id: string, type?: number, set?: boolean): Promise<Ret>;
|
|
1130
1143
|
|
|
1131
1144
|
/** 处理好友请求 */
|
|
1132
1145
|
setFriendAddRequest(flag: string, approve?: boolean, remark?: string, block?: boolean): Promise<Ret>;
|
package/lib/client.js
CHANGED
|
@@ -550,6 +550,9 @@ class Client extends EventEmitter {
|
|
|
550
550
|
setGroupRemark(group_id, remark = "") {
|
|
551
551
|
return this._useProtocol(troop.setGroupRemark, arguments);
|
|
552
552
|
}
|
|
553
|
+
setEmojiReaction(group_id, msg_seq, id, type = 1, set = true) {
|
|
554
|
+
return this._useProtocol(troop.setEmojiReaction, arguments);
|
|
555
|
+
}
|
|
553
556
|
|
|
554
557
|
///////////////////////////////////////////////////
|
|
555
558
|
|
package/lib/core/friendlist.js
CHANGED
|
@@ -456,6 +456,7 @@ async function getSI(user_id, no_cache = false) {
|
|
|
456
456
|
* @returns {Promise<number>}
|
|
457
457
|
*/
|
|
458
458
|
async function uid2uin(uid) {
|
|
459
|
+
if (Number.isInteger(Number(uid))) return Number(uid); // 纯数字的uid是误调用的uin,直接返回
|
|
459
460
|
if (this.uid2uin_map.has(uid))
|
|
460
461
|
return this.uid2uin_map.get(uid);
|
|
461
462
|
const body = pb.encode({
|
package/lib/core/troop.js
CHANGED
|
@@ -660,10 +660,33 @@ async function setFriendRemark(user_id, remark) {
|
|
|
660
660
|
const rsp = jce.decode(blob);
|
|
661
661
|
return { result: rsp[0] };
|
|
662
662
|
}
|
|
663
|
+
/**
|
|
664
|
+
* 设置表情回应,参考(https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType)
|
|
665
|
+
* @this {import("./ref").Client}
|
|
666
|
+
* @param {number} group_id
|
|
667
|
+
* @param {number} msg_seq
|
|
668
|
+
* @param {string} id
|
|
669
|
+
* @param {number} type
|
|
670
|
+
* @param {boolean} set
|
|
671
|
+
* @returns {import("./ref").ProtocolResponse}
|
|
672
|
+
*/
|
|
673
|
+
async function setEmojiReaction(group_id, msg_seq, id, type = 1, set = true) {
|
|
674
|
+
[group_id] = uinAutoCheck(group_id);
|
|
675
|
+
const body = pb.encode({
|
|
676
|
+
2: group_id,
|
|
677
|
+
3: msg_seq,
|
|
678
|
+
4: String(id),
|
|
679
|
+
5: type,
|
|
680
|
+
});
|
|
681
|
+
const cmd = set ? "OidbSvcTrpcTcp.0x9082_1" : "OidbSvcTrpcTcp.0x9082_2";
|
|
682
|
+
const blob = await this.sendOidb(cmd, body);
|
|
683
|
+
const rsp = pb.decode(blob);
|
|
684
|
+
return { result: rsp[3] };
|
|
685
|
+
}
|
|
663
686
|
|
|
664
687
|
module.exports = {
|
|
665
688
|
setAdmin, setTitle, setCard, setting, setAnonymous, muteAnonymous, getGroupNotice,
|
|
666
689
|
kickMember, muteMember, pokeMember, quitGroup, addGroup, inviteFriend,
|
|
667
690
|
setProfile, setSignature, addFriend, delFriend, setPortrait, setGroupPortrait,
|
|
668
|
-
groupSign, getSignature, setGroupRemark, setFriendRemark
|
|
691
|
+
groupSign, getSignature, setGroupRemark, setFriendRemark, setEmojiReaction,
|
|
669
692
|
};
|
package/lib/message/parser.js
CHANGED
|
@@ -1087,16 +1087,18 @@ async function parseForwardMsg(resid, fileName) {
|
|
|
1087
1087
|
/**
|
|
1088
1088
|
* @type {import("../ref").Msg[]}
|
|
1089
1089
|
*/
|
|
1090
|
-
let msgs = pb.decode(blob)[2];
|
|
1090
|
+
let msgs = pb.decode(blob)[2], flag = false;
|
|
1091
1091
|
if (!Array.isArray(msgs))
|
|
1092
1092
|
msgs = [msgs];
|
|
1093
1093
|
for (let msg1 of msgs) {
|
|
1094
1094
|
const m_fileName = msg1[1].toString();
|
|
1095
1095
|
if (m_fileName === fileName) {
|
|
1096
1096
|
msgs = msg1;
|
|
1097
|
+
flag = true;
|
|
1097
1098
|
break;
|
|
1098
1099
|
}
|
|
1099
1100
|
}
|
|
1101
|
+
if (!flag) throw new Error("wrong fileName");
|
|
1100
1102
|
if (Array.isArray(msgs))
|
|
1101
1103
|
msgs = msgs[0];
|
|
1102
1104
|
msgs = msgs[2][1];
|
package/lib/onlinepush.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
const pb = require("./algo/pb");
|
|
7
7
|
const jce = require("./algo/jce");
|
|
8
8
|
const sysmsg = require("./core/sysmsg");
|
|
9
|
-
const { parseC2CMsg
|
|
9
|
+
const { parseC2CMsg, parseGroupMsg, parseDiscussMsg } = require("./message/parser");
|
|
10
10
|
const { genC2CMessageId, genGroupMessageId, log, uin2code, BUF0, timestamp } = require("./common");
|
|
11
11
|
const { updateFL, uid2uin } = require("./core/friendlist");
|
|
12
12
|
|
|
@@ -62,14 +62,8 @@ const sub0x27 = {
|
|
|
62
62
|
5: async function (data, time) {
|
|
63
63
|
let user_id = data[14][1];
|
|
64
64
|
let nickname = "";
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
if (this.config.useNT) {
|
|
68
|
-
//nt uid
|
|
69
|
-
user_id = await uid2uin.call(this, String(user_id));
|
|
70
|
-
} else {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
65
|
+
if (this.config.useNT) {
|
|
66
|
+
user_id = await uid2uin.call(this, user_id);
|
|
73
67
|
}
|
|
74
68
|
try {
|
|
75
69
|
nickname = this.fl.get(user_id).nickname;
|
|
@@ -80,50 +74,58 @@ const sub0x27 = {
|
|
|
80
74
|
user_id, nickname, time
|
|
81
75
|
});
|
|
82
76
|
},
|
|
83
|
-
20: function (data, time) {
|
|
77
|
+
20: async function (data, time) {
|
|
84
78
|
// 20002昵称 20009性别 20031生日 23109农历生日 20019说明 20032地区 24002故乡 27372在线状态
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
o = o[0];
|
|
79
|
+
let user_id = data[8][1];
|
|
80
|
+
if (this.config.useNT) {
|
|
81
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
89
82
|
}
|
|
90
|
-
let
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
value = String(o[2]);
|
|
94
|
-
} else if (o[1] === 20009) {
|
|
95
|
-
key = "sex";
|
|
96
|
-
value = ["unknown", "male", "female"][o[2].toBuffer()[0]];
|
|
97
|
-
} else if (o[1] === 20031) {
|
|
98
|
-
key = "age";
|
|
99
|
-
value = new Date().getFullYear() - o[2].toBuffer().readUInt16BE();
|
|
100
|
-
} else if (o[1] === 20019) {
|
|
101
|
-
key = "description";
|
|
102
|
-
value = String(o[2]);
|
|
103
|
-
} else if (o[1] === 27372 && user_id === this.uin) {
|
|
104
|
-
const status = o[2].toBuffer()[o[2].toBuffer().length - 1];
|
|
105
|
-
const old_status = this.online_status, new_status = status_map[status] || 11;
|
|
106
|
-
this.online_status = new_status;
|
|
107
|
-
if (old_status !== new_status)
|
|
108
|
-
this.em("sync.status", { old_status, new_status });
|
|
109
|
-
return
|
|
110
|
-
} else {
|
|
111
|
-
return;
|
|
83
|
+
let list = data[8][2];
|
|
84
|
+
if (!Array.isArray(list)) {
|
|
85
|
+
list = [list];
|
|
112
86
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
87
|
+
for (let o of list) {
|
|
88
|
+
let key, value;
|
|
89
|
+
if (o[1] === 20002) {
|
|
90
|
+
key = "nickname";
|
|
91
|
+
value = String(o[2]);
|
|
92
|
+
} else if (o[1] === 20009) {
|
|
93
|
+
key = "sex";
|
|
94
|
+
value = ["unknown", "male", "female"][o[2].toBuffer()[0]];
|
|
95
|
+
} else if (o[1] === 20031) {
|
|
96
|
+
key = "age";
|
|
97
|
+
value = new Date().getFullYear() - o[2].toBuffer().readUInt16BE();
|
|
98
|
+
} else if (o[1] === 20019) {
|
|
99
|
+
key = "description";
|
|
100
|
+
value = String(o[2]);
|
|
101
|
+
} else if (o[1] === 27372 && user_id === this.uin) {
|
|
102
|
+
const status = o[2].toBuffer()[o[2].toBuffer().length - 1];
|
|
103
|
+
const old_status = this.online_status, new_status = status_map[status] || 11;
|
|
104
|
+
this.online_status = new_status;
|
|
105
|
+
if (old_status !== new_status)
|
|
106
|
+
this.em("sync.status", { old_status, new_status });
|
|
107
|
+
continue;
|
|
108
|
+
} else {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
this.fl.get(user_id)[key] = value;
|
|
113
|
+
} catch (e) { }
|
|
114
|
+
if (user_id === this.uin) {
|
|
115
|
+
this[key] = value;
|
|
116
|
+
this.em("sync.profile", { [key]: value });
|
|
117
|
+
} else {
|
|
118
|
+
const e = { user_id, time };
|
|
119
|
+
e[key] = value;
|
|
120
|
+
this.em("notice.friend.profile", e);
|
|
121
|
+
}
|
|
123
122
|
}
|
|
124
123
|
},
|
|
125
|
-
60: function (data, time) {
|
|
126
|
-
|
|
124
|
+
60: async function (data, time) {
|
|
125
|
+
let user_id = data[10][1];
|
|
126
|
+
if (this.config.useNT) {
|
|
127
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
128
|
+
}
|
|
127
129
|
const sign = String(data[10][2]);
|
|
128
130
|
try {
|
|
129
131
|
this.fl.get(user_id).signature = sign;
|
|
@@ -137,9 +139,13 @@ const sub0x27 = {
|
|
|
137
139
|
});
|
|
138
140
|
}
|
|
139
141
|
},
|
|
140
|
-
40: function (data, time) {
|
|
142
|
+
40: async function (data, time) {
|
|
141
143
|
try {
|
|
142
|
-
const o = data[9][1]
|
|
144
|
+
const o = data[9][1];
|
|
145
|
+
let user_id = o[2];
|
|
146
|
+
if (this.config.useNT) {
|
|
147
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
148
|
+
}
|
|
143
149
|
const remark = String(o[3]);
|
|
144
150
|
// 0好友备注 1群备注
|
|
145
151
|
if (o[1] === 1) {
|
|
@@ -151,15 +157,16 @@ const sub0x27 = {
|
|
|
151
157
|
}
|
|
152
158
|
} catch (e) { }
|
|
153
159
|
},
|
|
154
|
-
21: function (data, time) {
|
|
155
|
-
if (data[11][1] ===
|
|
156
|
-
|
|
157
|
-
} else if (data[11][1] === 1) {
|
|
160
|
+
21: async function (data, time) {
|
|
161
|
+
if (data[11] && data[11][1] === 1) {
|
|
162
|
+
const user_id = data[11][4]; //这里NT上线也是uin,不需要转换
|
|
158
163
|
this.em("notice.group.setting", {
|
|
159
164
|
group_id: data[11][3], time,
|
|
160
|
-
user_id:
|
|
165
|
+
user_id: user_id,
|
|
161
166
|
avatar: true,
|
|
162
167
|
});
|
|
168
|
+
} else {
|
|
169
|
+
this.em("sync.profile", { avatar: true });
|
|
163
170
|
}
|
|
164
171
|
}
|
|
165
172
|
};
|
|
@@ -193,14 +200,8 @@ const push528 = {
|
|
|
193
200
|
0xB3: async function (buf, time) {
|
|
194
201
|
const data = pb.decode(buf)[2];
|
|
195
202
|
let user_id = data[1], nickname = String(data[5]);
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
if (this.config.useNT) {
|
|
199
|
-
//nt uid
|
|
200
|
-
user_id = await uid2uin.call(this, String(user_id));
|
|
201
|
-
} else {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
203
|
+
if (this.config.useNT) {
|
|
204
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
204
205
|
}
|
|
205
206
|
this.fl.set(user_id, {
|
|
206
207
|
user_id, nickname,
|
|
@@ -248,13 +249,8 @@ const push528 = {
|
|
|
248
249
|
0x115: async function (buf, time) {
|
|
249
250
|
const data = pb.decode(buf);
|
|
250
251
|
let user_id = data[1];
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
//nt uid
|
|
254
|
-
user_id = await uid2uin.call(this, String(user_id));
|
|
255
|
-
} else {
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
252
|
+
if (this.config.useNT) {
|
|
253
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
258
254
|
}
|
|
259
255
|
const end = data[3][4] === 2;
|
|
260
256
|
this.em("internal.input", { user_id, end });
|
|
@@ -282,19 +278,19 @@ function parsePoke(data) {
|
|
|
282
278
|
for (let o of data[7]) {
|
|
283
279
|
const name = String(o[1]), val = String(o[2]);
|
|
284
280
|
switch (name) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
281
|
+
case "action_str":
|
|
282
|
+
case "alt_str1":
|
|
283
|
+
action = action || val;
|
|
284
|
+
break;
|
|
285
|
+
case "uin_str1":
|
|
286
|
+
operator_id = parseInt(val);
|
|
287
|
+
break;
|
|
288
|
+
case "uin_str2":
|
|
289
|
+
user_id = parseInt(val);
|
|
290
|
+
break;
|
|
291
|
+
case "suffix_str":
|
|
292
|
+
suffix = val;
|
|
293
|
+
break;
|
|
298
294
|
}
|
|
299
295
|
}
|
|
300
296
|
if (!operator_id)
|
|
@@ -310,15 +306,15 @@ function parseSign(data) {
|
|
|
310
306
|
for (let o of data[7]) {
|
|
311
307
|
const name = String(o[1]), val = String(o[2]);
|
|
312
308
|
switch (name) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
309
|
+
case "user_sign":
|
|
310
|
+
sign_text = sign_text || val;
|
|
311
|
+
break;
|
|
312
|
+
case "mqq_uin":
|
|
313
|
+
user_id = parseInt(val);
|
|
314
|
+
break;
|
|
315
|
+
case "mqq_nick":
|
|
316
|
+
nickname = val;
|
|
317
|
+
break;
|
|
322
318
|
}
|
|
323
319
|
}
|
|
324
320
|
return { user_id, nickname, sign_text };
|
|
@@ -330,11 +326,12 @@ function parseSign(data) {
|
|
|
330
326
|
* @param {string} field
|
|
331
327
|
* @param {boolean} enable
|
|
332
328
|
* @param {number} time
|
|
329
|
+
* @param {number} user_id
|
|
333
330
|
*/
|
|
334
|
-
function onGroupSetting(group_id, field, enable, time) {
|
|
331
|
+
function onGroupSetting(group_id, field, enable, time, user_id) {
|
|
335
332
|
if (!field) return;
|
|
336
333
|
const e = {
|
|
337
|
-
group_id, time
|
|
334
|
+
group_id, time, user_id
|
|
338
335
|
};
|
|
339
336
|
e[field] = !!enable;
|
|
340
337
|
this.em("notice.group.setting", e);
|
|
@@ -344,10 +341,18 @@ function onGroupSetting(group_id, field, enable, time) {
|
|
|
344
341
|
* @type {({[k: number]: (this: import("./ref").Client, group_id: number, buf: Buffer, time: number) => void})}
|
|
345
342
|
*/
|
|
346
343
|
const push732 = {
|
|
347
|
-
0x0C: function (group_id, buf, time) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
344
|
+
0x0C: async function (group_id, buf, time) {
|
|
345
|
+
let operator_id, user_id, duration;
|
|
346
|
+
if (this.config.useNT) {
|
|
347
|
+
const o = pb.decode(buf);
|
|
348
|
+
operator_id = await uid2uin.call(this, String(o[4]));
|
|
349
|
+
user_id = o[5][3][1] ? await uid2uin.call(this, String(o[5][3][1])) : 0;
|
|
350
|
+
duration = o[5][3][2];
|
|
351
|
+
} else {
|
|
352
|
+
operator_id = buf.readUInt32BE(6);
|
|
353
|
+
user_id = buf.readUInt32BE(16);
|
|
354
|
+
duration = buf.readUInt32BE(20);
|
|
355
|
+
}
|
|
351
356
|
try {
|
|
352
357
|
if (user_id === 0) {
|
|
353
358
|
duration = duration ? 0xffffffff : 0;
|
|
@@ -369,10 +374,8 @@ const push732 = {
|
|
|
369
374
|
let user_id = msg[6];
|
|
370
375
|
if (this.config.useNT) {
|
|
371
376
|
//nt uid
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
user_id = await uid2uin.call(this, user_id);
|
|
375
|
-
operator_id = await uid2uin.call(this, operator_id);
|
|
377
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
378
|
+
operator_id = await uid2uin.call(this, String(operator_id));
|
|
376
379
|
}
|
|
377
380
|
const message_id = genGroupMessageId(group_id, user_id, msg[1], msg[3], msg[2], Array.isArray(data[3]) ? data[3].length : 1);
|
|
378
381
|
this.em("notice.group.recall", {
|
|
@@ -437,20 +440,66 @@ const push732 = {
|
|
|
437
440
|
var enable = buf[8] === 0x0 || buf[8] === 0x20;
|
|
438
441
|
onGroupSetting.call(this, group_id, field, enable, time);
|
|
439
442
|
},
|
|
440
|
-
0x10: function (group_id, buf, time) {
|
|
441
|
-
if (buf[6] === 0x22) {
|
|
442
|
-
let field;
|
|
443
|
-
if (buf[buf.length - 2] === 0x08)
|
|
444
|
-
field = "enable_show_honor";
|
|
445
|
-
if (buf[buf.length - 2] === 0x10)
|
|
446
|
-
field = "enable_show_level";
|
|
447
|
-
let enable = buf[buf.length - 1] === 0;
|
|
448
|
-
return onGroupSetting.call(this, group_id, field, enable, time);
|
|
449
|
-
}
|
|
443
|
+
0x10: async function (group_id, buf, time) {
|
|
450
444
|
if (buf[6] === 0x26) {
|
|
451
445
|
// 改群分类 <Buffer 44 25 6e 9f 10 00 26 08 18 10 96 8a e3 fa 05 18 ff ff ff ff 0f 20 9f dd 95 a1 04 68 17 a8 01 f5 ef e8 b1 01 f2 01 06 18 8c 04 40 9a 4e>
|
|
452
446
|
}
|
|
453
447
|
const sub = pb.decode(buf.slice(7));
|
|
448
|
+
const sub_type = sub[13];
|
|
449
|
+
switch (sub_type) {
|
|
450
|
+
case 23: { // 群荣誉相关设置
|
|
451
|
+
const data = sub[30];
|
|
452
|
+
const field_map = {
|
|
453
|
+
1: "enable_show_honor",
|
|
454
|
+
2: "enable_show_level",
|
|
455
|
+
};
|
|
456
|
+
for (let field of Object.keys(field_map)) {
|
|
457
|
+
if (data[field] != null) {
|
|
458
|
+
const enable = data[field] === 0;
|
|
459
|
+
let user_id = sub[21];
|
|
460
|
+
if (this.config.useNT) {
|
|
461
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
462
|
+
}
|
|
463
|
+
onGroupSetting.call(this, group_id, field_map[field], enable, time, user_id);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
case 12: { // 群名称修改
|
|
469
|
+
let user_id = sub[21];
|
|
470
|
+
if (this.config.useNT) {
|
|
471
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
472
|
+
}
|
|
473
|
+
const group_name = String(sub[5][2]);
|
|
474
|
+
try {
|
|
475
|
+
this.gl.get(group_id).group_name = group_name;
|
|
476
|
+
} catch (e) { }
|
|
477
|
+
return this.em("notice.group.setting", {
|
|
478
|
+
group_id, time,
|
|
479
|
+
user_id: user_id,
|
|
480
|
+
group_name: group_name,
|
|
481
|
+
});
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
case 35: { // 消息回应
|
|
485
|
+
const data = sub[44];
|
|
486
|
+
let user_id = data[1][1][3][4];
|
|
487
|
+
if (this.config.useNT) {
|
|
488
|
+
user_id = await uid2uin.call(this, String(user_id));
|
|
489
|
+
}
|
|
490
|
+
const set = data[1][1][3][5] === 1;
|
|
491
|
+
return this.em("notice.group.reaction", {
|
|
492
|
+
group_id, time,
|
|
493
|
+
user_id: user_id,
|
|
494
|
+
id: String(data[1][1][3][1]),
|
|
495
|
+
type: data[1][1][3][2],
|
|
496
|
+
seq: data[1][1][2][1],
|
|
497
|
+
set,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
default:
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
454
503
|
if (sub[5] && sub[5][2]) {
|
|
455
504
|
let str = String(sub[5][2]);
|
|
456
505
|
if (str.includes("获得群主授予的")) {
|
|
@@ -495,15 +544,7 @@ const push732 = {
|
|
|
495
544
|
}
|
|
496
545
|
|
|
497
546
|
let field, enable;
|
|
498
|
-
if (sub[13]
|
|
499
|
-
try {
|
|
500
|
-
this.gl.get(group_id).group_name = str;
|
|
501
|
-
} catch (e) { }
|
|
502
|
-
return this.em("notice.group.setting", {
|
|
503
|
-
group_id, time,
|
|
504
|
-
user_id: sub[21],
|
|
505
|
-
group_name: str,
|
|
506
|
-
});
|
|
547
|
+
if (sub[13]) {
|
|
507
548
|
} else if (str.includes("坦白说")) {
|
|
508
549
|
field = "enable_confess";
|
|
509
550
|
enable = str.includes("开启");
|
|
@@ -542,6 +583,7 @@ function onlinePushListener(blob, seq) {
|
|
|
542
583
|
this.uin, v[1], v[3], v[8], 0, 0, 0, 0, 0, 0, 0
|
|
543
584
|
]));
|
|
544
585
|
if (!this.sync_finished) continue;
|
|
586
|
+
if (this.config.useNT) continue; // NT上线忽略老推送
|
|
545
587
|
const time = v[5];
|
|
546
588
|
if (v[2] === 528) {
|
|
547
589
|
const decoded = jce.decodeNested(v[6]);
|
|
@@ -566,6 +608,7 @@ function onlinePushTransListener(blob, seq) {
|
|
|
566
608
|
const push = pb.decode(blob);
|
|
567
609
|
handleOnlinePush.call(this, push[11], seq);
|
|
568
610
|
if (!this.sync_finished) return;
|
|
611
|
+
if (this.config.useNT) return; // NT上线忽略老推送
|
|
569
612
|
const time = push[8];
|
|
570
613
|
const buf = push[10].toBuffer();
|
|
571
614
|
const group_id = buf.readUInt32BE();
|
|
@@ -671,7 +714,7 @@ async function groupMsgListener(blob, seq) {
|
|
|
671
714
|
//重组分片消息
|
|
672
715
|
if (content[2] === 0)
|
|
673
716
|
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
|
|
674
|
-
msg = rebuildFragments(msg);
|
|
717
|
+
msg = rebuildFragments(msg, group_id, this.uin, user_id);
|
|
675
718
|
if (!msg)
|
|
676
719
|
return;
|
|
677
720
|
} else {
|
|
@@ -728,14 +771,17 @@ const FRAG = new Map;
|
|
|
728
771
|
* 1.是最后一个分片,返回组装好的消息
|
|
729
772
|
* 2.不是最后一个分片,返回空
|
|
730
773
|
* @param {import("./ref").Msg} msg
|
|
774
|
+
* @param {number} chat_id
|
|
775
|
+
* @param {number} self_id
|
|
776
|
+
* @param {number} user_id
|
|
731
777
|
* @returns {import("./ref").Msg}
|
|
732
778
|
*/
|
|
733
|
-
function rebuildFragments(msg) {
|
|
779
|
+
function rebuildFragments(msg, chat_id, self_id, user_id) {
|
|
734
780
|
const head = msg[1], content = msg[2], body = msg[3];
|
|
735
|
-
const cnt = content[1], index = content[2], div = content[3];
|
|
736
|
-
const id =
|
|
781
|
+
const cnt = content[1] || 0, index = content[2] || 0, div = content[3] || 0;
|
|
782
|
+
const id = self_id + "-" + user_id + "-" + chat_id + "-" + div; //self_id-user_id-chat_id-div
|
|
737
783
|
if (!FRAG.has(id)) {
|
|
738
|
-
FRAG.set(id, {3: new Array(cnt)});
|
|
784
|
+
FRAG.set(id, { 3: new Array(cnt) });
|
|
739
785
|
setTimeout(() => {
|
|
740
786
|
FRAG.delete(id);
|
|
741
787
|
}, 5000);
|
|
@@ -771,6 +817,20 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
771
817
|
const o = pb.decode(blob);
|
|
772
818
|
const type = o[1][2] ? o[1][2][1] : 114514;
|
|
773
819
|
//this.logger.debug("NT message type", type);
|
|
820
|
+
if (o[4]) {
|
|
821
|
+
let trans_info = BUF0;
|
|
822
|
+
try {
|
|
823
|
+
const trans_info = pb.decode(sso.reserved)[23] || BUF0;
|
|
824
|
+
} catch (e) {
|
|
825
|
+
this.logger.debug(e);
|
|
826
|
+
}
|
|
827
|
+
this.writeUni("trpc.msg.olpush.OlPushService.SsoPushAck", pb.encode({
|
|
828
|
+
1: o[4],
|
|
829
|
+
}), undefined, {
|
|
830
|
+
trans_info: trans_info,
|
|
831
|
+
nt_core: true,
|
|
832
|
+
});
|
|
833
|
+
}
|
|
774
834
|
switch (type) {
|
|
775
835
|
case 82: //群聊消息
|
|
776
836
|
if (!this.sync_finished) return;
|
|
@@ -782,8 +842,19 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
782
842
|
const user_id = head[1], time = head[6], seq = head[5];
|
|
783
843
|
const group_id = head[9][1], random = body[1][1][3];
|
|
784
844
|
const message_id = genGroupMessageId(group_id, user_id, seq, random, time, content[1]);
|
|
785
|
-
|
|
786
|
-
|
|
845
|
+
|
|
846
|
+
if (content[1] > 1) {
|
|
847
|
+
//重组分片消息
|
|
848
|
+
if (content[2] === 0)
|
|
849
|
+
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
|
|
850
|
+
msg = rebuildFragments(msg, group_id, this.uin, user_id);
|
|
851
|
+
if (!msg)
|
|
852
|
+
return;
|
|
853
|
+
} else {
|
|
854
|
+
//非分片消息
|
|
855
|
+
this.emit(`interval.${group_id}.${body[1][1][3]}`, message_id);
|
|
856
|
+
}
|
|
857
|
+
|
|
787
858
|
++this.stat.recv_msg_cnt;
|
|
788
859
|
//解析消息
|
|
789
860
|
const data = await parseGroupMsg.call(this, msg, true);
|
|
@@ -859,6 +930,17 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
859
930
|
if (!this.sync_finished) return;
|
|
860
931
|
try {
|
|
861
932
|
const msg = c2cNTMsgConverter.call(this, o[1]);
|
|
933
|
+
const user_id = msg[1][1];
|
|
934
|
+
|
|
935
|
+
if (msg[2][1] > 1) {
|
|
936
|
+
//重组分片消息
|
|
937
|
+
msg = rebuildFragments(msg, -user_id, this.uin, user_id);
|
|
938
|
+
if (!msg)
|
|
939
|
+
return;
|
|
940
|
+
} else {
|
|
941
|
+
//非分片消息
|
|
942
|
+
}
|
|
943
|
+
|
|
862
944
|
const data = await parseC2CMsg.call(this, msg, true);
|
|
863
945
|
if (data.user_id === this.uin) {
|
|
864
946
|
data.user_id = msg[1][2];
|
|
@@ -898,8 +980,6 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
898
980
|
const group_uin = o[1][1][1];
|
|
899
981
|
const group_id = uin2code(group_uin);
|
|
900
982
|
const type = o[1][2][3], buf = o[1][3][2].toBuffer(), time = o[1][2][6];
|
|
901
|
-
const no_parse = [0x0C, 0x10]; //这些也会推送jce的老包,就不管其只有uid的nt推送了
|
|
902
|
-
if (no_parse.includes(type)) break;
|
|
903
983
|
if (!this.sync_finished) throw new Error("sync not finished");
|
|
904
984
|
if (typeof push732[type] === "function")
|
|
905
985
|
push732[type].call(this, group_id, buf, time);
|
|
@@ -907,6 +987,75 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
907
987
|
this.logger.debug(e);
|
|
908
988
|
}
|
|
909
989
|
break;
|
|
990
|
+
case 44: //群管理权限变动
|
|
991
|
+
try {
|
|
992
|
+
const group_id = uin2code(o[1][1][1]);
|
|
993
|
+
const msg = o[1][3][2], time = o[1][2][6];
|
|
994
|
+
const type = msg[3];
|
|
995
|
+
if (type === 0 || type === 1) {
|
|
996
|
+
const data = msg[4][type === 0 ? 1 : 2];
|
|
997
|
+
const user_id = await uid2uin.call(this, String(data[1]));
|
|
998
|
+
const set = data[2] === 1;
|
|
999
|
+
try {
|
|
1000
|
+
(await this.getGroupMemberInfo(group_id, user_id)).data.role = (set ? "admin" : "member");
|
|
1001
|
+
} catch (e) { }
|
|
1002
|
+
this.em("notice.group.admin", {
|
|
1003
|
+
group_id, user_id, set, time
|
|
1004
|
+
});
|
|
1005
|
+
} else if (type === 0xFF) {
|
|
1006
|
+
const operator_id = await uid2uin.call(this, String(msg[4][3][1])),
|
|
1007
|
+
user_id = await uid2uin.call(this, String(msg[4][3][2]));
|
|
1008
|
+
try {
|
|
1009
|
+
this.gl.get(group_id).owner_id = user_id;
|
|
1010
|
+
(await this.getGroupMemberInfo(group_id, operator_id)).data.role = "member";
|
|
1011
|
+
(await this.getGroupMemberInfo(group_id, user_id)).data.role = "owner";
|
|
1012
|
+
} catch (e) { }
|
|
1013
|
+
this.em("notice.group.transfer", {
|
|
1014
|
+
group_id, operator_id, user_id, time
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
} catch (e) {
|
|
1018
|
+
this.logger.debug(e);
|
|
1019
|
+
}
|
|
1020
|
+
break;
|
|
1021
|
+
case 34: //群成员离开
|
|
1022
|
+
try {
|
|
1023
|
+
const group_id = uin2code(o[1][1][1]);
|
|
1024
|
+
const msg = o[1][3][2], time = o[1][2][6];
|
|
1025
|
+
const user_id = await uid2uin.call(this, String(msg[3]));
|
|
1026
|
+
const exit_type = msg[4];
|
|
1027
|
+
let operator_id, dismiss = false, member, group;
|
|
1028
|
+
if (exit_type === 0x82 || exit_type === 0x2) {
|
|
1029
|
+
operator_id = user_id;
|
|
1030
|
+
try {
|
|
1031
|
+
this.gml.get(group_id).delete(user_id);
|
|
1032
|
+
} catch { }
|
|
1033
|
+
} else {
|
|
1034
|
+
operator_id = msg[5] && msg[5][1] ? await uid2uin.call(this, String(msg[5][1][1])) : user_id;
|
|
1035
|
+
if (exit_type === 0x01 || exit_type === 0x81)
|
|
1036
|
+
dismiss = true;
|
|
1037
|
+
if (user_id === this.uin) {
|
|
1038
|
+
group = this.gl.get(group_id);
|
|
1039
|
+
this.gl.delete(group_id);
|
|
1040
|
+
this.gml.delete(group_id);
|
|
1041
|
+
this.logger.info(`更新了群列表,删除了群:${group_id}`);
|
|
1042
|
+
} else {
|
|
1043
|
+
try {
|
|
1044
|
+
this.gml.get(group_id).delete(user_id);
|
|
1045
|
+
} catch { }
|
|
1046
|
+
this.logger.info(`${user_id}离开了群${group_id}`);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
this.gl.get(group_id).member_count--;
|
|
1051
|
+
} catch { }
|
|
1052
|
+
this.em("notice.group.decrease", {
|
|
1053
|
+
group_id, user_id, operator_id, dismiss, member, group, time
|
|
1054
|
+
});
|
|
1055
|
+
} catch (e) {
|
|
1056
|
+
this.logger.debug(e);
|
|
1057
|
+
}
|
|
1058
|
+
break;
|
|
910
1059
|
case 114514: // 1919810
|
|
911
1060
|
// 部分消息没有content
|
|
912
1061
|
break;
|
|
@@ -914,20 +1063,6 @@ async function NTMsgListener(blob, seq, sso) {
|
|
|
914
1063
|
this.logger.warn("Unknown NT message type", type);
|
|
915
1064
|
break;
|
|
916
1065
|
}
|
|
917
|
-
if (o[4]) {
|
|
918
|
-
let trans_info = BUF0;
|
|
919
|
-
try {
|
|
920
|
-
const trans_info = pb.decode(sso.reserved)[23] || BUF0;
|
|
921
|
-
} catch (e) {
|
|
922
|
-
this.logger.debug(e);
|
|
923
|
-
}
|
|
924
|
-
this.writeUni("trpc.msg.olpush.OlPushService.SsoPushAck", pb.encode({
|
|
925
|
-
1: o[4],
|
|
926
|
-
}), undefined, {
|
|
927
|
-
trans_info: trans_info,
|
|
928
|
-
nt_core: true,
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
1066
|
}
|
|
932
1067
|
|
|
933
1068
|
/**
|
|
@@ -949,6 +1084,8 @@ function groupNTMsgConverter(msg) {
|
|
|
949
1084
|
header[11] = headerNT[4];
|
|
950
1085
|
|
|
951
1086
|
content[1] = contentNT[7];
|
|
1087
|
+
content[2] = contentNT[8];
|
|
1088
|
+
content[3] = contentNT[9];
|
|
952
1089
|
|
|
953
1090
|
return {
|
|
954
1091
|
1: header,
|
|
@@ -981,6 +1118,9 @@ function c2cNTMsgConverter(msg) {
|
|
|
981
1118
|
return {
|
|
982
1119
|
1: header,
|
|
983
1120
|
2: {
|
|
1121
|
+
1: contentNT[7],
|
|
1122
|
+
2: contentNT[8],
|
|
1123
|
+
3: contentNT[9],
|
|
984
1124
|
4: contentNT[10], //auto_reply
|
|
985
1125
|
},
|
|
986
1126
|
3: body,
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oicq-icalingua-plus-plus",
|
|
3
3
|
"app_name": "oicq-icalingua-plus-plus",
|
|
4
|
-
"version": "1.26.
|
|
5
|
-
"app_version": "1.26.
|
|
6
|
-
"upday": "2026/
|
|
4
|
+
"version": "1.26.16",
|
|
5
|
+
"app_version": "1.26.16",
|
|
6
|
+
"upday": "2026/08/09",
|
|
7
7
|
"protocol_version": "v11",
|
|
8
8
|
"description": "oicq(https://github.com/takayama-lily/oicq) v1 for Icalingua++",
|
|
9
9
|
"main": "index.js",
|