wechaty-puppet-matrix 0.0.42 → 0.0.47
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/matrix/service/request.d.ts +5 -3
- package/dist/cjs/src/matrix/service/request.d.ts.map +1 -1
- package/dist/cjs/src/matrix/service/request.js +117 -87
- package/dist/esm/src/matrix/service/request.d.ts +5 -3
- package/dist/esm/src/matrix/service/request.d.ts.map +1 -1
- package/dist/esm/src/matrix/service/request.js +117 -87
- package/package.json +2 -8
- package/src/matrix/service/request.ts +118 -93
|
@@ -129,14 +129,18 @@ async function getImageInfo(imageUrl) {
|
|
|
129
129
|
}
|
|
130
130
|
const finalFilePath = path.join(tempFilePath, 'temp_image_' + Date.now() + path.extname(imageUrl));
|
|
131
131
|
await fs.writeFile(finalFilePath, response.data);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
132
|
+
try {
|
|
133
|
+
const dimensions = imageSize(finalFilePath);
|
|
134
|
+
return {
|
|
135
|
+
file_size: fileSize,
|
|
136
|
+
image_width: dimensions.width,
|
|
137
|
+
image_height: dimensions.height,
|
|
138
|
+
file_type: dimensions.type,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
await fs.unlink(finalFilePath).catch(() => undefined);
|
|
143
|
+
}
|
|
140
144
|
}
|
|
141
145
|
catch (error) {
|
|
142
146
|
console.error('获取图片信息错误:', error);
|
|
@@ -358,11 +362,13 @@ class Client extends EventEmitter {
|
|
|
358
362
|
this.hasExpired = false;
|
|
359
363
|
this.lastInitSeqInfo = { contactSeq: 0, roomSeq: 0 };
|
|
360
364
|
}
|
|
361
|
-
destroy() {
|
|
365
|
+
async destroy() {
|
|
362
366
|
log.verbose(PRE, 'destroy()');
|
|
363
367
|
this.hasEmitLogout = false;
|
|
364
|
-
|
|
365
|
-
|
|
368
|
+
if (this.socket) {
|
|
369
|
+
await new Promise(resolve => this.socket.end(false, undefined, resolve));
|
|
370
|
+
this.socket = null;
|
|
371
|
+
}
|
|
366
372
|
this.checkExpiredInterval && clearInterval(this.checkExpiredInterval);
|
|
367
373
|
this.checkExpiredInterval = undefined;
|
|
368
374
|
this.heartbeatTimer && clearTimeout(this.heartbeatTimer);
|
|
@@ -404,7 +410,11 @@ class Client extends EventEmitter {
|
|
|
404
410
|
}, 1000 * 60 * 60 * 12);
|
|
405
411
|
}
|
|
406
412
|
async initServer() {
|
|
407
|
-
await this.getTokenInfo();
|
|
413
|
+
const tokenValid = await this.getTokenInfo();
|
|
414
|
+
if (!tokenValid) {
|
|
415
|
+
log.error(PRE, 'initServer: token invalid or expired, abort');
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
408
418
|
this.checkHasExpired();
|
|
409
419
|
if (this.socket) {
|
|
410
420
|
log.error('socket had already been opened!');
|
|
@@ -517,6 +527,10 @@ class Client extends EventEmitter {
|
|
|
517
527
|
});
|
|
518
528
|
break;
|
|
519
529
|
case NotifyTypeEnum.NewMsg:
|
|
530
|
+
if (data.create_time < Math.floor(Date.now() / 1000) - 60) {
|
|
531
|
+
log.warn('消息时间超过60秒,可能是重复消息,已忽略', data);
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
520
534
|
if (data.is_chatroom_msg) {
|
|
521
535
|
atWxidList = await getAtWxidList(data.source);
|
|
522
536
|
}
|
|
@@ -635,6 +649,10 @@ class Client extends EventEmitter {
|
|
|
635
649
|
log.error('Token已到期,无法提供服务');
|
|
636
650
|
return;
|
|
637
651
|
}
|
|
652
|
+
if (!this.tokenInfo) {
|
|
653
|
+
log.error(PRE, 'postData: tokenInfo is null, skip request');
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
638
656
|
const config = {
|
|
639
657
|
data: {
|
|
640
658
|
guid: this.tokenInfo.guid,
|
|
@@ -677,21 +695,29 @@ class Client extends EventEmitter {
|
|
|
677
695
|
log.info(PRE, 'restore() res: %s', res);
|
|
678
696
|
}
|
|
679
697
|
async getStats() {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
698
|
+
try {
|
|
699
|
+
const res = await this.postData({
|
|
700
|
+
path: '/client/get_client_status',
|
|
701
|
+
data: {},
|
|
702
|
+
});
|
|
703
|
+
if (!res)
|
|
704
|
+
return { status: Status.fail };
|
|
705
|
+
const { errcode, data } = res;
|
|
706
|
+
if (!errcode) {
|
|
707
|
+
return {
|
|
708
|
+
status: data.status === 1
|
|
709
|
+
? Status.pending
|
|
710
|
+
: data.status === 2
|
|
711
|
+
? Status.normal
|
|
712
|
+
: Status.offline,
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
return { status: Status.fail };
|
|
717
|
+
}
|
|
693
718
|
}
|
|
694
|
-
|
|
719
|
+
catch (e) {
|
|
720
|
+
log.error(PRE, 'getStats(): %s', e);
|
|
695
721
|
return { status: Status.fail };
|
|
696
722
|
}
|
|
697
723
|
}
|
|
@@ -818,7 +844,11 @@ class Client extends EventEmitter {
|
|
|
818
844
|
},
|
|
819
845
|
});
|
|
820
846
|
if (res.errcode === -1 && res.errmsg === 'bridge guid not exist') {
|
|
821
|
-
|
|
847
|
+
if (bridgeId === '') {
|
|
848
|
+
log.warn(PRE, 'setBridgeId: empty bridgeId still invalid, skip retry to avoid infinite recursion');
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
log.info(PRE, 'setBridgeId(%s): %s', bridgeId, 'bridge guid not exist, retrying with empty bridgeId');
|
|
822
852
|
void this.setBridgeId('');
|
|
823
853
|
return;
|
|
824
854
|
}
|
|
@@ -1080,7 +1110,12 @@ class Client extends EventEmitter {
|
|
|
1080
1110
|
};
|
|
1081
1111
|
}
|
|
1082
1112
|
}
|
|
1083
|
-
async syncContact(init) {
|
|
1113
|
+
async syncContact(init, depth = 0) {
|
|
1114
|
+
const maxDepth = 200;
|
|
1115
|
+
if (depth >= maxDepth) {
|
|
1116
|
+
log.warn(PRE, 'syncContact: reached max recursion depth %d, stop', maxDepth);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1084
1119
|
try {
|
|
1085
1120
|
if (init) {
|
|
1086
1121
|
this.lastInitSeqInfo = { contactSeq: 0, roomSeq: 0 };
|
|
@@ -1102,7 +1137,7 @@ class Client extends EventEmitter {
|
|
|
1102
1137
|
this.emit('update-contacts', contactsInfo || []);
|
|
1103
1138
|
}
|
|
1104
1139
|
if (continueFlag) {
|
|
1105
|
-
await this.syncContact();
|
|
1140
|
+
await this.syncContact(undefined, depth + 1);
|
|
1106
1141
|
}
|
|
1107
1142
|
}
|
|
1108
1143
|
catch (e) {
|
|
@@ -1118,8 +1153,8 @@ class Client extends EventEmitter {
|
|
|
1118
1153
|
page_size: pageSize,
|
|
1119
1154
|
},
|
|
1120
1155
|
});
|
|
1121
|
-
const totalPage = res
|
|
1122
|
-
const contactList = res
|
|
1156
|
+
const totalPage = res?.total_page || 1;
|
|
1157
|
+
const contactList = (res?.contact_list || [])
|
|
1123
1158
|
.filter((item) => item.username)
|
|
1124
1159
|
.map((contact) => {
|
|
1125
1160
|
return {
|
|
@@ -1154,8 +1189,8 @@ class Client extends EventEmitter {
|
|
|
1154
1189
|
page_size: pageSize,
|
|
1155
1190
|
},
|
|
1156
1191
|
});
|
|
1157
|
-
const totalPage = res
|
|
1158
|
-
const contactList = res
|
|
1192
|
+
const totalPage = res?.total_page || 1;
|
|
1193
|
+
const contactList = (res?.contact_list || [])
|
|
1159
1194
|
.filter((item) => item.username)
|
|
1160
1195
|
.map((contact) => {
|
|
1161
1196
|
return {
|
|
@@ -1190,8 +1225,8 @@ class Client extends EventEmitter {
|
|
|
1190
1225
|
page_size: pageSize,
|
|
1191
1226
|
},
|
|
1192
1227
|
});
|
|
1193
|
-
const totalPage = res
|
|
1194
|
-
const groupList = res
|
|
1228
|
+
const totalPage = res?.total_page || 1;
|
|
1229
|
+
const groupList = (res?.room_list || [])
|
|
1195
1230
|
.filter((item) => item.username)
|
|
1196
1231
|
.map((item) => {
|
|
1197
1232
|
return {
|
|
@@ -1207,8 +1242,8 @@ class Client extends EventEmitter {
|
|
|
1207
1242
|
if (groupList.length > 0) {
|
|
1208
1243
|
this.emit('update-contacts', groupList);
|
|
1209
1244
|
}
|
|
1210
|
-
if (
|
|
1211
|
-
await this.getGroupList(
|
|
1245
|
+
if (page < totalPage) {
|
|
1246
|
+
await this.getGroupList(page + 1, pageSize);
|
|
1212
1247
|
}
|
|
1213
1248
|
}
|
|
1214
1249
|
catch (e) {
|
|
@@ -1262,8 +1297,8 @@ class Client extends EventEmitter {
|
|
|
1262
1297
|
page_size: pageSize,
|
|
1263
1298
|
},
|
|
1264
1299
|
});
|
|
1265
|
-
const totalPage = res
|
|
1266
|
-
const officeList = res
|
|
1300
|
+
const totalPage = res?.total_page || 1;
|
|
1301
|
+
const officeList = (res?.contact_list || [])
|
|
1267
1302
|
.filter((item) => item.username)
|
|
1268
1303
|
.map((contact) => {
|
|
1269
1304
|
return {
|
|
@@ -1346,6 +1381,26 @@ class Client extends EventEmitter {
|
|
|
1346
1381
|
},
|
|
1347
1382
|
});
|
|
1348
1383
|
}
|
|
1384
|
+
async retryDownload(fn) {
|
|
1385
|
+
const maxRetries = 5;
|
|
1386
|
+
const delayMs = 2000;
|
|
1387
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
1388
|
+
try {
|
|
1389
|
+
const res = await fn();
|
|
1390
|
+
if (res?.url) {
|
|
1391
|
+
return res;
|
|
1392
|
+
}
|
|
1393
|
+
log.warn(PRE, 'download attempt %d/%d failed (no url in response)', attempt, maxRetries);
|
|
1394
|
+
}
|
|
1395
|
+
catch (e) {
|
|
1396
|
+
log.warn(PRE, 'download attempt %d/%d error: %s', attempt, maxRetries, e);
|
|
1397
|
+
}
|
|
1398
|
+
if (attempt < maxRetries) {
|
|
1399
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
return null;
|
|
1403
|
+
}
|
|
1349
1404
|
async downloadImage(imageInfo) {
|
|
1350
1405
|
const params = {
|
|
1351
1406
|
file_type: 2,
|
|
@@ -1354,17 +1409,12 @@ class Client extends EventEmitter {
|
|
|
1354
1409
|
file_size: imageInfo.file_size,
|
|
1355
1410
|
file_name: `/微信图片_${format(new Date(), 'yyyyMMddHHmmss')}.png`,
|
|
1356
1411
|
};
|
|
1357
|
-
const res = await this.postData({
|
|
1358
|
-
|
|
1359
|
-
data: params,
|
|
1360
|
-
});
|
|
1361
|
-
if (res.url) {
|
|
1412
|
+
const res = await this.retryDownload(() => this.postData({ path: '/cloud/cdn_download', data: params }));
|
|
1413
|
+
if (res?.url) {
|
|
1362
1414
|
return encodeURI(res.url) || '';
|
|
1363
1415
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
return '';
|
|
1367
|
-
}
|
|
1416
|
+
log.error(PRE, 'downloadImage failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1417
|
+
return '';
|
|
1368
1418
|
}
|
|
1369
1419
|
async downloadWWMedia(imageInfo, type) {
|
|
1370
1420
|
const typeNameMap = {
|
|
@@ -1379,17 +1429,12 @@ class Client extends EventEmitter {
|
|
|
1379
1429
|
file_name: typeNameMap[type],
|
|
1380
1430
|
fast_download: false,
|
|
1381
1431
|
};
|
|
1382
|
-
const res = await this.postData({
|
|
1383
|
-
|
|
1384
|
-
data: params,
|
|
1385
|
-
});
|
|
1386
|
-
if (res.url) {
|
|
1432
|
+
const res = await this.retryDownload(() => this.postData({ path: '/cloud/cdn_download_wwfile', data: params }));
|
|
1433
|
+
if (res?.url) {
|
|
1387
1434
|
return encodeURI(res.url) || '';
|
|
1388
1435
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
return '';
|
|
1392
|
-
}
|
|
1436
|
+
log.error(PRE, 'downloadWWMedia failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1437
|
+
return '';
|
|
1393
1438
|
}
|
|
1394
1439
|
async downloadFile(imageInfo) {
|
|
1395
1440
|
const params = {
|
|
@@ -1399,17 +1444,12 @@ class Client extends EventEmitter {
|
|
|
1399
1444
|
file_size: imageInfo.file_size,
|
|
1400
1445
|
file_name: '/' + sanitizeFilename(imageInfo.file_name),
|
|
1401
1446
|
};
|
|
1402
|
-
const res = await this.postData({
|
|
1403
|
-
|
|
1404
|
-
data: params,
|
|
1405
|
-
});
|
|
1406
|
-
if (res.url) {
|
|
1447
|
+
const res = await this.retryDownload(() => this.postData({ path: '/cloud/cdn_download', data: params }));
|
|
1448
|
+
if (res?.url) {
|
|
1407
1449
|
return encodeURI(res.url) || '';
|
|
1408
1450
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
return '';
|
|
1412
|
-
}
|
|
1451
|
+
log.error(PRE, 'downloadFile failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1452
|
+
return '';
|
|
1413
1453
|
}
|
|
1414
1454
|
async downloadAudio(msgId, voiceInfo, roomId) {
|
|
1415
1455
|
const params = {
|
|
@@ -1419,17 +1459,12 @@ class Client extends EventEmitter {
|
|
|
1419
1459
|
file_name: '/voice.mp3',
|
|
1420
1460
|
to_mp3: true,
|
|
1421
1461
|
};
|
|
1422
|
-
const res = await this.postData({
|
|
1423
|
-
|
|
1424
|
-
data: params,
|
|
1425
|
-
});
|
|
1426
|
-
if (res.url) {
|
|
1462
|
+
const res = await this.retryDownload(() => this.postData({ path: '/cloud/download_voice', data: params }));
|
|
1463
|
+
if (res?.url) {
|
|
1427
1464
|
return encodeURI(res.url) || '';
|
|
1428
1465
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
return '';
|
|
1432
|
-
}
|
|
1466
|
+
log.error(PRE, 'downloadAudio failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1467
|
+
return '';
|
|
1433
1468
|
}
|
|
1434
1469
|
async downloadVideo(videoInfo) {
|
|
1435
1470
|
const params = {
|
|
@@ -1439,17 +1474,12 @@ class Client extends EventEmitter {
|
|
|
1439
1474
|
file_size: videoInfo.file_size,
|
|
1440
1475
|
file_name: `/微信视频_${format(new Date(), 'yyyyMMddHHmmss')}.mp4`,
|
|
1441
1476
|
};
|
|
1442
|
-
const res = await this.postData({
|
|
1443
|
-
|
|
1444
|
-
data: params,
|
|
1445
|
-
});
|
|
1446
|
-
if (res.url) {
|
|
1477
|
+
const res = await this.retryDownload(() => this.postData({ path: '/cloud/cdn_download', data: params }));
|
|
1478
|
+
if (res?.url) {
|
|
1447
1479
|
return encodeURI(res.url) || '';
|
|
1448
1480
|
}
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
return '';
|
|
1452
|
-
}
|
|
1481
|
+
log.error(PRE, 'downloadVideo failed after %d retries, params: %s', 5, JSON.stringify(params));
|
|
1482
|
+
return '';
|
|
1453
1483
|
}
|
|
1454
1484
|
async sendUrlImg(contactId, url, selfId) {
|
|
1455
1485
|
try {
|
|
@@ -1505,7 +1535,7 @@ class Client extends EventEmitter {
|
|
|
1505
1535
|
return {
|
|
1506
1536
|
id: res?.newMsgId || '',
|
|
1507
1537
|
timeStamp: res?.createTime || getUnixTime(new Date()),
|
|
1508
|
-
msgType: WechatMessageType.
|
|
1538
|
+
msgType: WechatMessageType.Video,
|
|
1509
1539
|
talkerId: selfId || '',
|
|
1510
1540
|
text: url,
|
|
1511
1541
|
msg: url,
|
|
@@ -1536,7 +1566,7 @@ class Client extends EventEmitter {
|
|
|
1536
1566
|
return {
|
|
1537
1567
|
id: res?.newMsgId || '',
|
|
1538
1568
|
timeStamp: res?.createTime || '',
|
|
1539
|
-
msgType: WechatMessageType.
|
|
1569
|
+
msgType: WechatMessageType.File,
|
|
1540
1570
|
talkerId: selfId || '',
|
|
1541
1571
|
text: url,
|
|
1542
1572
|
msg: url,
|
|
@@ -1859,8 +1889,8 @@ class Client extends EventEmitter {
|
|
|
1859
1889
|
const imageBaseInfo = await getImageInfo(image);
|
|
1860
1890
|
imageInfo.push({ ...res, ...imageBaseInfo });
|
|
1861
1891
|
}
|
|
1862
|
-
xmlContent = genImageSnsXml(wxid, momentInfo.content, imageInfo, momentInfo.location);
|
|
1863
1892
|
}
|
|
1893
|
+
xmlContent = genImageSnsXml(wxid, momentInfo.content, imageInfo, momentInfo.location);
|
|
1864
1894
|
}
|
|
1865
1895
|
else if (momentInfo.videoUrl) {
|
|
1866
1896
|
const mediaInfo = await this.uploadSnsVideo(momentInfo.videoUrl);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wechaty-puppet-matrix",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.47",
|
|
4
4
|
"description": "Puppet matrix for Wechaty",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"typings": "./dist/esm/src/mod.d.ts",
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
],
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@chatie/eslint-config": "^1.0.4",
|
|
44
|
-
"@chatie/git-scripts": "^0.6.2",
|
|
45
44
|
"@chatie/semver": "^0.4.7",
|
|
46
45
|
"@grpc/grpc-js": "1.9.14",
|
|
47
46
|
"@juzi/wechaty": "^1.0.104",
|
|
@@ -94,10 +93,5 @@
|
|
|
94
93
|
"bin/",
|
|
95
94
|
"dist/",
|
|
96
95
|
"src/"
|
|
97
|
-
]
|
|
98
|
-
"git": {
|
|
99
|
-
"scripts": {
|
|
100
|
-
"pre-push": "npx git-scripts-pre-push"
|
|
101
|
-
}
|
|
102
|
-
}
|
|
96
|
+
]
|
|
103
97
|
}
|