wechaty-puppet-matrix 0.0.52 → 0.0.53
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/dist/cjs/src/engine-schema.d.ts +1 -0
- package/dist/cjs/src/engine-schema.d.ts.map +1 -1
- package/dist/cjs/src/matrix/messages/message-appmsg.d.ts +1 -0
- package/dist/cjs/src/matrix/messages/message-appmsg.d.ts.map +1 -1
- package/dist/cjs/src/matrix/messages/message-audio.js +1 -1
- package/dist/cjs/src/matrix/messages/message-chat-history.d.ts +49 -0
- package/dist/cjs/src/matrix/messages/message-chat-history.d.ts.map +1 -0
- package/dist/cjs/src/matrix/messages/message-chat-history.js +91 -0
- package/dist/cjs/src/matrix/schema-mapper/message/message-parser-audio.d.ts +3 -0
- package/dist/cjs/src/matrix/schema-mapper/message/message-parser-audio.d.ts.map +1 -0
- package/dist/cjs/src/matrix/schema-mapper/message/message-parser-audio.js +44 -0
- package/dist/cjs/src/matrix/schema-mapper/message/message-parser-refermsg.d.ts.map +1 -1
- package/dist/cjs/src/matrix/schema-mapper/message/message-parser-refermsg.js +22 -1
- package/dist/cjs/src/matrix/schema-mapper/message/mod.d.ts.map +1 -1
- package/dist/cjs/src/matrix/schema-mapper/message/mod.js +2 -0
- package/dist/cjs/src/matrix/service/request.d.ts +7 -1
- package/dist/cjs/src/matrix/service/request.d.ts.map +1 -1
- package/dist/cjs/src/matrix/service/request.js +64 -2
- package/dist/cjs/src/puppet-matrix.d.ts +5 -0
- package/dist/cjs/src/puppet-matrix.d.ts.map +1 -1
- package/dist/cjs/src/puppet-matrix.js +124 -4
- package/dist/esm/src/engine-schema.d.ts +1 -0
- package/dist/esm/src/engine-schema.d.ts.map +1 -1
- package/dist/esm/src/matrix/messages/message-appmsg.d.ts +1 -0
- package/dist/esm/src/matrix/messages/message-appmsg.d.ts.map +1 -1
- package/dist/esm/src/matrix/messages/message-audio.js +1 -1
- package/dist/esm/src/matrix/messages/message-chat-history.d.ts +49 -0
- package/dist/esm/src/matrix/messages/message-chat-history.d.ts.map +1 -0
- package/dist/esm/src/matrix/messages/message-chat-history.js +87 -0
- package/dist/esm/src/matrix/schema-mapper/message/message-parser-audio.d.ts +3 -0
- package/dist/esm/src/matrix/schema-mapper/message/message-parser-audio.d.ts.map +1 -0
- package/dist/esm/src/matrix/schema-mapper/message/message-parser-audio.js +7 -0
- package/dist/esm/src/matrix/schema-mapper/message/message-parser-refermsg.d.ts.map +1 -1
- package/dist/esm/src/matrix/schema-mapper/message/message-parser-refermsg.js +22 -1
- package/dist/esm/src/matrix/schema-mapper/message/mod.d.ts.map +1 -1
- package/dist/esm/src/matrix/schema-mapper/message/mod.js +2 -0
- package/dist/esm/src/matrix/service/request.d.ts +7 -1
- package/dist/esm/src/matrix/service/request.d.ts.map +1 -1
- package/dist/esm/src/matrix/service/request.js +64 -2
- package/dist/esm/src/puppet-matrix.d.ts +5 -0
- package/dist/esm/src/puppet-matrix.d.ts.map +1 -1
- package/dist/esm/src/puppet-matrix.js +125 -5
- package/package.json +1 -1
- package/src/engine-schema.ts +1 -0
- package/src/matrix/messages/message-appmsg.ts +1 -0
- package/src/matrix/messages/message-audio.ts +1 -1
- package/src/matrix/messages/message-chat-history.ts +135 -0
- package/src/matrix/schema-mapper/message/message-parser-audio.ts +13 -0
- package/src/matrix/schema-mapper/message/message-parser-refermsg.ts +32 -1
- package/src/matrix/schema-mapper/message/mod.ts +2 -0
- package/src/matrix/service/request.ts +80 -2
- package/src/puppet-matrix.ts +142 -5
|
@@ -679,6 +679,13 @@ class Client extends EventEmitter {
|
|
|
679
679
|
}
|
|
680
680
|
return res.data;
|
|
681
681
|
}
|
|
682
|
+
async clearProxy() {
|
|
683
|
+
const res = await this.postData({
|
|
684
|
+
path: '/client/set_proxy',
|
|
685
|
+
data: { proxy: '' },
|
|
686
|
+
});
|
|
687
|
+
log.info(PRE, 'clearProxy() res: %s', JSON.stringify(res));
|
|
688
|
+
}
|
|
682
689
|
async restore() {
|
|
683
690
|
const res = await this.postData({
|
|
684
691
|
path: '/client/restore_client',
|
|
@@ -691,7 +698,7 @@ class Client extends EventEmitter {
|
|
|
691
698
|
},
|
|
692
699
|
});
|
|
693
700
|
this.restoreTimes++;
|
|
694
|
-
log.info(PRE, 'restore() res: %s', res);
|
|
701
|
+
log.info(PRE, 'restore() res: %s', JSON.stringify(res));
|
|
695
702
|
}
|
|
696
703
|
async getStats() {
|
|
697
704
|
try {
|
|
@@ -833,9 +840,14 @@ class Client extends EventEmitter {
|
|
|
833
840
|
data: {},
|
|
834
841
|
});
|
|
835
842
|
}
|
|
836
|
-
async getSelfInfo() {
|
|
843
|
+
async getSelfInfo(proxyCleared = false) {
|
|
837
844
|
try {
|
|
838
845
|
const res = await this.postData({ path: '/user/get_profile', data: {} });
|
|
846
|
+
if (!proxyCleared && typeof res?.errmsg === 'string' && res.errmsg.includes('Could not connect to proxy')) {
|
|
847
|
+
log.warn(PRE, 'proxy unavailable, clear proxy and retry: %s', res.errmsg);
|
|
848
|
+
await this.clearProxy();
|
|
849
|
+
return await this.getSelfInfo(true);
|
|
850
|
+
}
|
|
839
851
|
if (res.errcode === -102) {
|
|
840
852
|
log.info(PRE, 'offline login:', res?.errmsg);
|
|
841
853
|
return false;
|
|
@@ -1425,6 +1437,56 @@ class Client extends EventEmitter {
|
|
|
1425
1437
|
log.error(PRE, 'downloadAudio failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1426
1438
|
return '';
|
|
1427
1439
|
}
|
|
1440
|
+
async newVoiceTransId() {
|
|
1441
|
+
return await this.postData({ path: '/msg/new_trans_voice_id', data: {} });
|
|
1442
|
+
}
|
|
1443
|
+
async checkVoiceTrans(voiceId, msgId, length) {
|
|
1444
|
+
return await this.postData({ path: '/msg/check_voice_trans', data: { voice_id: voiceId, msg_id: msgId, length } });
|
|
1445
|
+
}
|
|
1446
|
+
async uploadVoiceTrans(voiceId, msgId, length) {
|
|
1447
|
+
return await this.postData({ path: '/msg/upload_voice_trans', data: { voice_id: voiceId, msg_id: msgId, length } });
|
|
1448
|
+
}
|
|
1449
|
+
async getVoiceTrans(voiceId) {
|
|
1450
|
+
return await this.postData({ path: '/msg/get_voice_trans', data: { voice_id: voiceId } });
|
|
1451
|
+
}
|
|
1452
|
+
async voiceToText(msgId, length, timeoutMs = 20000) {
|
|
1453
|
+
try {
|
|
1454
|
+
const idRes = await this.newVoiceTransId();
|
|
1455
|
+
const voiceId = idRes?.voice_id;
|
|
1456
|
+
if (!voiceId) {
|
|
1457
|
+
log.warn(PRE, 'voiceToText: no voice_id: %s', JSON.stringify(idRes));
|
|
1458
|
+
return '';
|
|
1459
|
+
}
|
|
1460
|
+
const checkRes = await this.checkVoiceTrans(voiceId, msgId, length);
|
|
1461
|
+
if (checkRes?.baseResponse?.ret !== 0) {
|
|
1462
|
+
log.warn(PRE, 'voiceToText: check failed: %s', JSON.stringify(checkRes));
|
|
1463
|
+
return '';
|
|
1464
|
+
}
|
|
1465
|
+
const uploadRes = await this.uploadVoiceTrans(voiceId, msgId, length);
|
|
1466
|
+
if (uploadRes?.baseResponse?.ret !== 0) {
|
|
1467
|
+
log.warn(PRE, 'voiceToText: upload failed: %s', JSON.stringify(uploadRes));
|
|
1468
|
+
return '';
|
|
1469
|
+
}
|
|
1470
|
+
const interval = (checkRes?.queryCtx?.interval || 2) * 1000;
|
|
1471
|
+
const deadline = Date.now() + timeoutMs;
|
|
1472
|
+
while (Date.now() < deadline) {
|
|
1473
|
+
await new Promise(resolve => setTimeout(resolve, interval));
|
|
1474
|
+
const res = await this.getVoiceTrans(voiceId);
|
|
1475
|
+
if (res?.baseResponse?.ret !== 0) {
|
|
1476
|
+
log.warn(PRE, 'voiceToText: get result failed: %s', JSON.stringify(res));
|
|
1477
|
+
return '';
|
|
1478
|
+
}
|
|
1479
|
+
if (res?.transRes?.endFlag === 1) {
|
|
1480
|
+
return res.transRes.result || '';
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
log.warn(PRE, 'voiceToText: timeout for msg %s', msgId);
|
|
1484
|
+
}
|
|
1485
|
+
catch (e) {
|
|
1486
|
+
log.warn(PRE, 'voiceToText: error: %s', e);
|
|
1487
|
+
}
|
|
1488
|
+
return '';
|
|
1489
|
+
}
|
|
1428
1490
|
async downloadVideo(videoInfo) {
|
|
1429
1491
|
const params = {
|
|
1430
1492
|
file_type: 4,
|
|
@@ -68,6 +68,8 @@ declare class PuppetMatrix extends PUPPET.Puppet {
|
|
|
68
68
|
messageMiniProgram(messageId: string): Promise<PUPPET.payloads.MiniProgram>;
|
|
69
69
|
messageUrl(messageId: string): Promise<PUPPET.payloads.UrlLink>;
|
|
70
70
|
messageLocation(messageId: string): Promise<PUPPET.payloads.Location>;
|
|
71
|
+
messageChatHistory(messageId: string): Promise<PUPPET.payloads.ChatHistory[]>;
|
|
72
|
+
private _recordItemToChatHistory;
|
|
71
73
|
messageSendContact(toUserId: string, contactId: string): Promise<void | string>;
|
|
72
74
|
messageSendFile(conversationId: string, fileBox: FileBoxInterface): Promise<string | void>;
|
|
73
75
|
messageSendMiniProgram(toUserName: string, mpPayload: PUPPET.payloads.MiniProgram): Promise<void | string>;
|
|
@@ -93,6 +95,7 @@ declare class PuppetMatrix extends PUPPET.Puppet {
|
|
|
93
95
|
contactRawPayload(id: string): Promise<ContactPayload | undefined>;
|
|
94
96
|
messageRawPayloadParser(payload: MessagePayload): Promise<PUPPET.payloads.Message>;
|
|
95
97
|
messageRawPayload(id: string): Promise<MessagePayload>;
|
|
98
|
+
cacheMessageIfAbsent(payload: MessagePayload): Promise<void>;
|
|
96
99
|
roomRawPayloadParser(payload: ContactPayload): Promise<PUPPET.payloads.Room>;
|
|
97
100
|
roomRawPayload(id: string): Promise<ContactPayload | undefined>;
|
|
98
101
|
roomMemberRawPayload(roomId: string, contactId: string): Promise<ContactPayload>;
|
|
@@ -115,11 +118,13 @@ declare class PuppetMatrix extends PUPPET.Puppet {
|
|
|
115
118
|
private _updateRoomMember;
|
|
116
119
|
_updateRoom(roomId: string): Promise<void>;
|
|
117
120
|
private _onPushContact;
|
|
121
|
+
private _transcribeVoice;
|
|
118
122
|
private _onPushMessage;
|
|
119
123
|
private _refreshRoomInfo;
|
|
120
124
|
private _refreshContact;
|
|
121
125
|
private _startPuppetHeart;
|
|
122
126
|
private _stopPuppetHeart;
|
|
127
|
+
private _fileBoxFromUrl;
|
|
123
128
|
private _getMessageImageFileBox;
|
|
124
129
|
private _getMessageAudioFileBox;
|
|
125
130
|
private _getMessageVideoFileBox;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"puppet-matrix.d.ts","sourceRoot":"","sources":["../../../src/puppet-matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAKhD,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"puppet-matrix.d.ts","sourceRoot":"","sources":["../../../src/puppet-matrix.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { log } from '@juzi/wechaty-puppet';
|
|
2
2
|
import * as PUPPET from '@juzi/wechaty-puppet';
|
|
3
3
|
import { FileBox, FileBoxType, } from 'file-box';
|
|
4
|
+
import { WechatMessageType } from './matrix/types.js';
|
|
4
5
|
import Client from './matrix/service/request.js';
|
|
5
6
|
import { getUnixTime } from 'date-fns';
|
|
6
7
|
import { mergeWithFallback } from './matrix/utils/index.js';
|
|
7
8
|
import path from 'path';
|
|
8
9
|
import { CacheManager } from './matrix/cache-manager.js';
|
|
9
10
|
import { isIMContactId, isRoomId } from './matrix/utils/is-type.js';
|
|
10
|
-
import { parseAppmsgMessagePayload } from './matrix/messages/message-appmsg.js';
|
|
11
|
+
import { AppMessageType, parseAppmsgMessagePayload } from './matrix/messages/message-appmsg.js';
|
|
12
|
+
import { parseRecordItem, RecordItemType } from './matrix/messages/message-chat-history.js';
|
|
11
13
|
import { parseMiniProgramMessagePayload } from './matrix/messages/message-miniprogram.js';
|
|
12
14
|
import { parseEmotionMessagePayload } from './matrix/messages/message-emotion.js';
|
|
13
15
|
import { parseImageMessagePayload } from './matrix/messages/message-image.js';
|
|
@@ -649,6 +651,90 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
649
651
|
const locationPayload = await parseLocationMessagePayload(rawPayload.msg);
|
|
650
652
|
return locationPayload;
|
|
651
653
|
}
|
|
654
|
+
async messageChatHistory(messageId) {
|
|
655
|
+
const rawPayload = await this.messageRawPayload(messageId);
|
|
656
|
+
const appPayload = await parseAppmsgMessagePayload(rawPayload.msg);
|
|
657
|
+
if (appPayload.type !== AppMessageType.ChatHistory) {
|
|
658
|
+
throw new Error('Can not get chat history from non chat history payload');
|
|
659
|
+
}
|
|
660
|
+
log.verbose(PRE, `messageChatHistory recorditem: ${appPayload.recorditem}`);
|
|
661
|
+
if (!appPayload.recorditem) {
|
|
662
|
+
return [];
|
|
663
|
+
}
|
|
664
|
+
const info = await parseRecordItem(appPayload.recorditem);
|
|
665
|
+
return Promise.all(info.items.map(item => this._recordItemToChatHistory(item)));
|
|
666
|
+
}
|
|
667
|
+
async _recordItemToChatHistory(item) {
|
|
668
|
+
const base = {
|
|
669
|
+
avatar: item.sourceHeadUrl ? FileBox.fromUrl(item.sourceHeadUrl) : FileBox.fromBuffer(Buffer.alloc(0), 'avatar.png'),
|
|
670
|
+
corpName: '',
|
|
671
|
+
senderName: item.sourceName,
|
|
672
|
+
time: Math.floor((Date.parse(item.sourceTime.replace(/-/g, '/')) || 0) / 1000),
|
|
673
|
+
};
|
|
674
|
+
const unknown = { ...base, message: undefined, title: item.title, type: PUPPET.types.Message.Unknown };
|
|
675
|
+
const media = async (kind) => {
|
|
676
|
+
if (!item.cdnDataUrl) {
|
|
677
|
+
return undefined;
|
|
678
|
+
}
|
|
679
|
+
const params = { aes_key: item.cdnDataKey, file_id: item.cdnDataUrl, file_name: item.fileName || item.title, file_size: item.dataSize };
|
|
680
|
+
const url = kind === 'image' || kind === 'emoticon'
|
|
681
|
+
? await this._client?.downloadImage(params)
|
|
682
|
+
: kind === 'video' ? await this._client?.downloadVideo(params) : await this._client?.downloadFile(params);
|
|
683
|
+
return url ? FileBox.fromUrl(url, item.fileName ? { name: item.fileName } : undefined) : undefined;
|
|
684
|
+
};
|
|
685
|
+
try {
|
|
686
|
+
switch (item.type) {
|
|
687
|
+
case RecordItemType.Text:
|
|
688
|
+
return { ...base, message: item.desc, type: PUPPET.types.Message.Text };
|
|
689
|
+
case RecordItemType.Image: {
|
|
690
|
+
const box = await media('image');
|
|
691
|
+
return box ? { ...base, message: box, type: PUPPET.types.Message.Image } : unknown;
|
|
692
|
+
}
|
|
693
|
+
case RecordItemType.Video: {
|
|
694
|
+
const box = await media('video');
|
|
695
|
+
return box ? { ...base, message: box, type: PUPPET.types.Message.Video } : unknown;
|
|
696
|
+
}
|
|
697
|
+
case RecordItemType.File: {
|
|
698
|
+
const box = await media('file');
|
|
699
|
+
return box ? { ...base, message: box, type: PUPPET.types.Message.Attachment } : unknown;
|
|
700
|
+
}
|
|
701
|
+
case RecordItemType.Emoticon: {
|
|
702
|
+
const box = await media('emoticon');
|
|
703
|
+
return box ? { ...base, message: box, type: PUPPET.types.Message.Emoticon } : unknown;
|
|
704
|
+
}
|
|
705
|
+
case RecordItemType.Link:
|
|
706
|
+
if (!item.link)
|
|
707
|
+
return unknown;
|
|
708
|
+
return {
|
|
709
|
+
...base,
|
|
710
|
+
message: { description: item.link.desc, thumbnailUrl: item.link.thumbUrl, title: item.link.title, url: item.link.url },
|
|
711
|
+
type: PUPPET.types.Message.Url,
|
|
712
|
+
};
|
|
713
|
+
case RecordItemType.Location:
|
|
714
|
+
if (!item.location)
|
|
715
|
+
return unknown;
|
|
716
|
+
return {
|
|
717
|
+
...base,
|
|
718
|
+
message: { accuracy: 15, address: item.location.label, latitude: item.location.lat, longitude: item.location.lng, name: item.location.poiname },
|
|
719
|
+
type: PUPPET.types.Message.Location,
|
|
720
|
+
};
|
|
721
|
+
case RecordItemType.ChatHistory:
|
|
722
|
+
return {
|
|
723
|
+
...base,
|
|
724
|
+
message: await Promise.all((item.children || []).map(child => this._recordItemToChatHistory(child))),
|
|
725
|
+
title: item.title,
|
|
726
|
+
type: PUPPET.types.Message.ChatHistory,
|
|
727
|
+
};
|
|
728
|
+
default:
|
|
729
|
+
log.verbose(PRE, `unsupported chat history item type: ${item.type}`);
|
|
730
|
+
return unknown;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
catch (e) {
|
|
734
|
+
log.warn(PRE, `parse chat history item failed, type: ${item.type}, error: ${e}`);
|
|
735
|
+
return unknown;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
652
738
|
async messageSendContact(toUserId, contactId) {
|
|
653
739
|
log.verbose('PuppetWeChat', 'messageSend("%s", %s)', toUserId, contactId);
|
|
654
740
|
const contactPayload = await this.contactRawPayload(contactId);
|
|
@@ -898,6 +984,13 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
898
984
|
}
|
|
899
985
|
return ret;
|
|
900
986
|
}
|
|
987
|
+
async cacheMessageIfAbsent(payload) {
|
|
988
|
+
if (await this._cacheMgr.hasMessage(payload.id)) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
log.info(PRE, `cache miss for refer message ${payload.id}, rebuild from refermsg`);
|
|
992
|
+
await this._cacheMgr.setMessage(payload.id, payload);
|
|
993
|
+
}
|
|
901
994
|
async roomRawPayloadParser(payload) {
|
|
902
995
|
return engineRoomToWechaty(payload);
|
|
903
996
|
}
|
|
@@ -1189,6 +1282,26 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1189
1282
|
}
|
|
1190
1283
|
}
|
|
1191
1284
|
}
|
|
1285
|
+
async _transcribeVoice(message) {
|
|
1286
|
+
if (message.msgType !== WechatMessageType.Voice || message.talkerId === this.currentUserId) {
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
try {
|
|
1290
|
+
const audio = await parseAudioMessagePayload(message);
|
|
1291
|
+
const length = parseInt(audio.voicelength, 10);
|
|
1292
|
+
if (!length) {
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const text = await this._client?.voiceToText(message.id, length);
|
|
1296
|
+
if (text) {
|
|
1297
|
+
message.voiceText = text;
|
|
1298
|
+
await this._cacheMgr.setMessage(message.id, message);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
catch (e) {
|
|
1302
|
+
log.warn(PRE, `transcribe voice failed for ${message.id}: ${e}`);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1192
1305
|
async _onPushMessage(message) {
|
|
1193
1306
|
const messageId = message.id;
|
|
1194
1307
|
log.silly(PRE, `on push original message: ${JSON.stringify(message)}`);
|
|
@@ -1196,6 +1309,7 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1196
1309
|
return;
|
|
1197
1310
|
}
|
|
1198
1311
|
await this._cacheMgr.setMessage(message.id, message);
|
|
1312
|
+
await this._transcribeVoice(message);
|
|
1199
1313
|
const event = await parseEvent(this, message);
|
|
1200
1314
|
log.info('event-------', JSON.stringify(event));
|
|
1201
1315
|
switch (event.type) {
|
|
@@ -1330,13 +1444,19 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1330
1444
|
clearTimeout(this._heartBeatTimer);
|
|
1331
1445
|
this._heartBeatTimer = undefined;
|
|
1332
1446
|
}
|
|
1447
|
+
_fileBoxFromUrl(url, messageId, name) {
|
|
1448
|
+
if (!url) {
|
|
1449
|
+
throw new Error(`download media failed for message ${messageId}: backend returned no url (media may have expired)`);
|
|
1450
|
+
}
|
|
1451
|
+
return name ? FileBox.fromUrl(url, { name }) : FileBox.fromUrl(url);
|
|
1452
|
+
}
|
|
1333
1453
|
async _getMessageImageFileBox(messageId, messagePayload) {
|
|
1334
1454
|
const imageInfo = await parseImageMessagePayload(messagePayload);
|
|
1335
1455
|
if (!imageInfo.file_id) {
|
|
1336
1456
|
log.error(`Can not get file for message: ${messageId}`);
|
|
1337
1457
|
}
|
|
1338
1458
|
const url = imageInfo.is_ww ? await this._client?.downloadWWMedia(imageInfo, 1) : await this._client?.downloadImage(imageInfo);
|
|
1339
|
-
return
|
|
1459
|
+
return this._fileBoxFromUrl(url, messageId);
|
|
1340
1460
|
}
|
|
1341
1461
|
async _getMessageAudioFileBox(messageId, messagePayload) {
|
|
1342
1462
|
const audioInfo = await parseAudioMessagePayload(messagePayload);
|
|
@@ -1344,7 +1464,7 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1344
1464
|
log.error(`Can not get file for message: ${messageId}`);
|
|
1345
1465
|
}
|
|
1346
1466
|
const url = await this._client?.downloadAudio(messageId, audioInfo);
|
|
1347
|
-
return
|
|
1467
|
+
return this._fileBoxFromUrl(url, messageId);
|
|
1348
1468
|
}
|
|
1349
1469
|
async _getMessageVideoFileBox(messageId, messagePayload) {
|
|
1350
1470
|
const videoInfo = await parseVideoMessagePayload(messagePayload);
|
|
@@ -1353,7 +1473,7 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1353
1473
|
}
|
|
1354
1474
|
const url = videoInfo.is_ww ? await this._client?.downloadWWMedia(videoInfo, 2) : await this._client?.downloadVideo(videoInfo);
|
|
1355
1475
|
log.info(PRE, '_getMessageVideoFileBox(): %s', url);
|
|
1356
|
-
return
|
|
1476
|
+
return this._fileBoxFromUrl(url, messageId);
|
|
1357
1477
|
}
|
|
1358
1478
|
async _getMessageFileFileBox(messageId, messagePayload) {
|
|
1359
1479
|
const appPayload = await parseAppmsgMessagePayload(messagePayload.msg);
|
|
@@ -1372,7 +1492,7 @@ class PuppetMatrix extends PUPPET.Puppet {
|
|
|
1372
1492
|
if (!url) {
|
|
1373
1493
|
log.error(`Can not get file url: ${JSON.stringify(params)}`);
|
|
1374
1494
|
}
|
|
1375
|
-
return
|
|
1495
|
+
return this._fileBoxFromUrl(url, messageId, appPayload.title);
|
|
1376
1496
|
}
|
|
1377
1497
|
async syncContact(init) {
|
|
1378
1498
|
if (!this.currentUserId) {
|
package/package.json
CHANGED
package/src/engine-schema.ts
CHANGED
|
@@ -39,7 +39,7 @@ export async function parseAudioMessagePayload (rawPayload: MessagePayload): Pro
|
|
|
39
39
|
return {
|
|
40
40
|
aesKey: schema.aeskey,
|
|
41
41
|
length: schema.length,
|
|
42
|
-
voicelength: schema.
|
|
42
|
+
voicelength: schema.voicelength,
|
|
43
43
|
voiceurl: schema.voiceurl,
|
|
44
44
|
voicemd5: schema.voicemd5,
|
|
45
45
|
clientmsgid: schema.clientmsgid,
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { xmlToJson } from '../utils/xml-to-json.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 合并转发(appmsg type 19)的 recorditem 解析
|
|
5
|
+
*
|
|
6
|
+
* recorditem 是 CDATA 包着的 XML:
|
|
7
|
+
* <recordinfo><title/><desc/><datalist count="n"><dataitem datatype="1" dataid="..."><sourcename/><sourcetime/><sourceheadurl/><datadesc/>...</dataitem></datalist></recordinfo>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** 微信 dataitem.datatype */
|
|
11
|
+
export enum RecordItemType {
|
|
12
|
+
Text = 1,
|
|
13
|
+
Image = 2,
|
|
14
|
+
Voice = 3,
|
|
15
|
+
Video = 4,
|
|
16
|
+
Link = 5,
|
|
17
|
+
Location = 6,
|
|
18
|
+
File = 8,
|
|
19
|
+
MiniProgram = 19,
|
|
20
|
+
ChatHistory = 17,
|
|
21
|
+
Channel = 22,
|
|
22
|
+
Emoticon = 47,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface RecordItem {
|
|
26
|
+
type: number
|
|
27
|
+
dataId: string
|
|
28
|
+
sourceName: string
|
|
29
|
+
sourceTime: string
|
|
30
|
+
sourceHeadUrl: string
|
|
31
|
+
desc: string
|
|
32
|
+
title: string
|
|
33
|
+
cdnDataUrl: string
|
|
34
|
+
cdnDataKey: string
|
|
35
|
+
cdnThumbUrl: string
|
|
36
|
+
dataSize: number
|
|
37
|
+
dataFmt: string
|
|
38
|
+
fileName: string
|
|
39
|
+
/** 地理位置 */
|
|
40
|
+
location?: { lat: number, lng: number, label: string, poiname: string }
|
|
41
|
+
/** 链接 */
|
|
42
|
+
link?: { title: string, desc: string, url: string, thumbUrl: string }
|
|
43
|
+
/** 嵌套的合并转发 */
|
|
44
|
+
children?: RecordItem[]
|
|
45
|
+
raw: any
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface RecordInfo {
|
|
49
|
+
title: string
|
|
50
|
+
desc: string
|
|
51
|
+
items: RecordItem[]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function text (v: any): string {
|
|
55
|
+
if (v === undefined || v === null) {
|
|
56
|
+
return ''
|
|
57
|
+
}
|
|
58
|
+
if (typeof v === 'string') {
|
|
59
|
+
return v
|
|
60
|
+
}
|
|
61
|
+
// xml2js 在节点带属性时会返回 { _: 'text', $: {...} }
|
|
62
|
+
if (typeof v === 'object' && typeof v._ === 'string') {
|
|
63
|
+
return v._
|
|
64
|
+
}
|
|
65
|
+
return ''
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function asArray<T> (v: T | T[] | undefined): T[] {
|
|
69
|
+
if (v === undefined || v === null) {
|
|
70
|
+
return []
|
|
71
|
+
}
|
|
72
|
+
return Array.isArray(v) ? v : [ v ]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parseItem (item: any): RecordItem {
|
|
76
|
+
const attrs = item.$ || {}
|
|
77
|
+
const ret: RecordItem = {
|
|
78
|
+
cdnDataKey: text(item.cdndatakey),
|
|
79
|
+
// 下载接口使用 305f 开头的 file id;cdndataurl 可能是 7f0c 新格式,此时用 group.fileid
|
|
80
|
+
cdnDataUrl: [ text(item.cdndataurl), text(item.group?.fileid) ].find(u => u.startsWith('305')) || text(item.cdndataurl),
|
|
81
|
+
cdnThumbUrl: text(item.cdnthumburl),
|
|
82
|
+
dataFmt: text(item.datafmt),
|
|
83
|
+
dataId: attrs.dataid || '',
|
|
84
|
+
dataSize: parseInt(text(item.datasize), 10) || 0,
|
|
85
|
+
desc: text(item.datadesc),
|
|
86
|
+
fileName: text(item.datatitle),
|
|
87
|
+
raw: item,
|
|
88
|
+
sourceHeadUrl: text(item.sourceheadurl),
|
|
89
|
+
sourceName: text(item.sourcename),
|
|
90
|
+
sourceTime: text(item.sourcetime),
|
|
91
|
+
title: text(item.datatitle),
|
|
92
|
+
type: parseInt(attrs.datatype, 10),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const loc = item.locitem
|
|
96
|
+
if (loc) {
|
|
97
|
+
ret.location = {
|
|
98
|
+
label: text(loc.label),
|
|
99
|
+
lat: parseFloat(text(loc.lat)) || 0,
|
|
100
|
+
lng: parseFloat(text(loc.lng)) || 0,
|
|
101
|
+
poiname: text(loc.poiname),
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const web = item.weburlitem
|
|
106
|
+
if (web) {
|
|
107
|
+
ret.link = {
|
|
108
|
+
desc: text(web.desc),
|
|
109
|
+
thumbUrl: text(web.thumburl),
|
|
110
|
+
title: text(web.title),
|
|
111
|
+
url: text(web.link),
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 嵌套合并转发: recordxml 是内联 XML 对象
|
|
116
|
+
const nested = item.recordxml?.recordinfo
|
|
117
|
+
if (nested) {
|
|
118
|
+
ret.children = asArray(nested.datalist?.dataitem).map(parseItem)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return ret
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function parseRecordItem (recorditem: string): Promise<RecordInfo> {
|
|
125
|
+
const json = await xmlToJson(recorditem)
|
|
126
|
+
const info = json?.recordinfo
|
|
127
|
+
if (!info) {
|
|
128
|
+
return { desc: '', items: [], title: '' }
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
desc: text(info.desc),
|
|
132
|
+
items: asArray(info.datalist?.dataitem).map(parseItem),
|
|
133
|
+
title: text(info.title),
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as PUPPET from '@juzi/wechaty-puppet'
|
|
2
|
+
import type { MessagePayload } from '../../../engine-schema.js'
|
|
3
|
+
import type { MessageParser, MessageParserContext } from './message-parser.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 语音消息已转出文字时,把文字放到 text 上
|
|
7
|
+
*/
|
|
8
|
+
export const audioParser: MessageParser = async (engineMessage: MessagePayload, ret: PUPPET.payloads.Message, _context: MessageParserContext) => {
|
|
9
|
+
if (ret.type === PUPPET.types.Message.Audio && engineMessage.voiceText) {
|
|
10
|
+
ret.text = engineMessage.voiceText
|
|
11
|
+
}
|
|
12
|
+
return ret
|
|
13
|
+
}
|
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
import * as PUPPET from '@juzi/wechaty-puppet'
|
|
2
|
+
import { log } from '@juzi/wechaty-puppet'
|
|
2
3
|
import type { MessagePayload } from '../../../engine-schema.js'
|
|
3
4
|
import { AppMessageType, parseAppmsgMessagePayload, ReferMsgPayload } from '../../messages/message-appmsg.js'
|
|
4
5
|
import { WechatMessageType } from '../../types.js'
|
|
6
|
+
import { isIMRoomId, isRoomId } from '../../utils/is-type.js'
|
|
5
7
|
import type { MessageParser, MessageParserContext } from './message-parser.js'
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
interface ReferMessageCacheable {
|
|
10
|
+
cacheMessageIfAbsent (payload: MessagePayload): Promise<void>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 被引用消息已不在缓存时,用 refermsg 里的 type/content(原消息 XML) 合成一条 MessagePayload 写入缓存,
|
|
15
|
+
* 这样 getQuotedMessage() / toFileBox() 仍然可用
|
|
16
|
+
*/
|
|
17
|
+
async function cacheReferMessageIfAbsent (engineMessage: MessagePayload, refer: ReferMsgPayload, puppet: PUPPET.Puppet) {
|
|
18
|
+
const cacheable = puppet as unknown as Partial<ReferMessageCacheable>
|
|
19
|
+
if (!refer.svrid || typeof cacheable.cacheMessageIfAbsent !== 'function') {
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
// 群聊: fromusr 是群 id,chatusr 是原发送人,msg 格式与群消息一致 "wxid:\ncontent";单聊: fromusr 是发送人(此时 chatusr 可能也有值,不能据此判断群聊)
|
|
23
|
+
const isRoom = isRoomId(refer.fromusr) || isIMRoomId(refer.fromusr)
|
|
24
|
+
await cacheable.cacheMessageIfAbsent({
|
|
25
|
+
id: refer.svrid,
|
|
26
|
+
listenerId: engineMessage.listenerId,
|
|
27
|
+
msg: isRoom ? `${refer.chatusr || refer.fromusr}:\n${refer.content}` : refer.content,
|
|
28
|
+
msgType: parseInt(refer.type, 10),
|
|
29
|
+
talkerId: refer.fromusr,
|
|
30
|
+
text: refer.content,
|
|
31
|
+
timeStamp: parseInt(refer.createtime || '0', 10) || engineMessage.timeStamp,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const referMsgParser: MessageParser = async (engineMessage: MessagePayload, ret: PUPPET.payloads.Message, context: MessageParserContext) => {
|
|
8
36
|
if (!context.appMessagePayload || context.appMessagePayload.type !== AppMessageType.ReferMsg) {
|
|
9
37
|
return ret
|
|
10
38
|
}
|
|
@@ -14,6 +42,8 @@ export const referMsgParser: MessageParser = async (_padLocalMessage: MessagePa
|
|
|
14
42
|
let referMessageContent: string
|
|
15
43
|
|
|
16
44
|
const referMessagePayload: ReferMsgPayload = appPayload.refermsg!
|
|
45
|
+
await cacheReferMessageIfAbsent(engineMessage, referMessagePayload, context.puppet)
|
|
46
|
+
log.verbose('referMsgParser', `raw refermsg: ${JSON.stringify(referMessagePayload)}`)
|
|
17
47
|
const referMessageType = parseInt(referMessagePayload.type) as WechatMessageType
|
|
18
48
|
switch (referMessageType) {
|
|
19
49
|
case WechatMessageType.Text:
|
|
@@ -47,6 +77,7 @@ export const referMsgParser: MessageParser = async (_padLocalMessage: MessagePa
|
|
|
47
77
|
}
|
|
48
78
|
|
|
49
79
|
ret.type = PUPPET.types.Message.Text
|
|
80
|
+
ret.quoteId = referMessagePayload.svrid
|
|
50
81
|
ret.text = `「${referMessagePayload.displayname}:${referMessageContent}」\n- - - - - - - - - - - - - - -\n${appPayload.title}`
|
|
51
82
|
|
|
52
83
|
return ret
|
|
@@ -4,6 +4,7 @@ import { roomParser } from './message-parser-room.js'
|
|
|
4
4
|
import { singleChatParser } from './message-parser-single-chat.js'
|
|
5
5
|
import { appMsgParser } from './message-parser-appmsg.js'
|
|
6
6
|
import { referMsgParser } from './message-parser-refermsg.js'
|
|
7
|
+
import { audioParser } from './message-parser-audio.js'
|
|
7
8
|
import { sysmsgParser } from './message-parser-sysmsg.js'
|
|
8
9
|
|
|
9
10
|
// The order of message parser is important
|
|
@@ -12,6 +13,7 @@ addMessageParser(roomParser)
|
|
|
12
13
|
addMessageParser(singleChatParser)
|
|
13
14
|
addMessageParser(appMsgParser)
|
|
14
15
|
addMessageParser(referMsgParser)
|
|
16
|
+
addMessageParser(audioParser)
|
|
15
17
|
addMessageParser(sysmsgParser)
|
|
16
18
|
|
|
17
19
|
export { executeMessageParsers }
|