yz-yuki-plugin 2.0.7-17 → 2.0.7-19
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/CHANGELOG.md
CHANGED
|
@@ -380,65 +380,119 @@ class BiliTask {
|
|
|
380
380
|
async sendDynamicMessage(messageMap, biliConfigData) {
|
|
381
381
|
let liveAtAll = !!biliConfigData.liveAtAll === true ? true : false; // 直播动态是否@全体成员,默认false
|
|
382
382
|
let liveAtAllCD = biliConfigData.liveAtAllCD || 1800; // 直播动态@全体成员 冷却时间CD,默认 30 分钟
|
|
383
|
+
let forwardSendDynamic = biliConfigData.forwardSendDynamic === 0 || biliConfigData.forwardSendDynamic === false ? false : true; // 转发动态是否合并发送,默认 true
|
|
383
384
|
// 直播动态@全体成员的群组/好友列表,默认空数组,为空则不进行@全体成员操作
|
|
384
385
|
let liveAtAllGroupList = new Set(Array.isArray(biliConfigData?.liveAtAllGroupList) ? Array.from(biliConfigData.liveAtAllGroupList).map(item => String(item)) : []);
|
|
385
386
|
const LogMark = new Set(); // 日志mark
|
|
386
387
|
for (const [chatType, botMap] of messageMap) {
|
|
387
388
|
for (const [bot_id, chatMap] of botMap) {
|
|
388
389
|
for (const [chatId, messageCombinationList] of chatMap) {
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
390
|
+
// 区分群聊和私聊
|
|
391
|
+
let markKey = chatType === 'group' ? this.groupKey : this.privateKey;
|
|
392
|
+
if (!LogMark.has('1')) {
|
|
393
|
+
global?.logger?.mark('优纪插件: B站动态执行推送');
|
|
394
|
+
LogMark.add('1');
|
|
395
|
+
}
|
|
396
|
+
let liveAtAllMark = await Redis.get(`${markKey}${chatId}:liveAtAllMark`); // 直播动态@全体成员标记,默认 0
|
|
397
|
+
const hasLiveDynamic = messageCombinationList.some(m => m.dynamicType === 'DYNAMIC_TYPE_LIVE_RCMD');
|
|
398
|
+
// 如果开启了直播动态@全体成员
|
|
399
|
+
if (liveAtAll && !liveAtAllMark && hasLiveDynamic && liveAtAllGroupList.has(String(chatId))) {
|
|
400
|
+
try {
|
|
401
|
+
await this.sendMsgApi(chatId, bot_id, chatType, [Segment.at('all')]);
|
|
402
|
+
await Redis.set(`${markKey}${chatId}:liveAtAllMark`, 1, { EX: liveAtAllCD }); // 设置直播动态@全体成员标记为 1
|
|
401
403
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
404
|
+
catch (error) {
|
|
405
|
+
logger.error(`直播动态发送@全体成员失败,请检查 <机器人> 是否有 [管理员权限] 或 [聊天平台是否支持] :${error}`);
|
|
406
|
+
let liveAtAllErrMsg = !!biliConfigData.liveAtAllErrMsg === false ? false : true; // 直播动态@全体成员失败是否发送错误提示消息,默认 false
|
|
407
|
+
if (liveAtAllErrMsg) {
|
|
408
|
+
await this.sendMsgApi(chatId, bot_id, chatType, ['直播动态发送@全体成员失败,请检查权限或平台是否支持']);
|
|
409
|
+
}
|
|
405
410
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
411
|
+
}
|
|
412
|
+
// 统计图片数量和文字长度
|
|
413
|
+
let imageCount = 0;
|
|
414
|
+
let textLength = 0;
|
|
415
|
+
for (const messageCombination of messageCombinationList) {
|
|
416
|
+
const { messages } = messageCombination;
|
|
417
|
+
for (const msg of messages) {
|
|
418
|
+
if (typeof msg === 'object' && msg.type === 'image') {
|
|
419
|
+
imageCount++;
|
|
420
|
+
}
|
|
421
|
+
else if (typeof msg === 'string') {
|
|
422
|
+
textLength += msg.length;
|
|
423
|
+
}
|
|
409
424
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
425
|
+
}
|
|
426
|
+
// 满足条件才使用合并转发
|
|
427
|
+
const useForward = imageCount > 2 || textLength > 300;
|
|
428
|
+
if (forwardSendDynamic && useForward) {
|
|
429
|
+
const forwardNodes = [];
|
|
430
|
+
// 合并所有消息
|
|
431
|
+
const forwardSendMardKeyList = [];
|
|
432
|
+
forwardNodes.push({
|
|
433
|
+
name: '优纪酱通知',
|
|
434
|
+
uin: String(80000000),
|
|
435
|
+
message: ['有新的B站动态了~'],
|
|
436
|
+
time: Date.now()
|
|
437
|
+
});
|
|
438
|
+
for (const messageCombination of messageCombinationList) {
|
|
439
|
+
const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
|
|
440
|
+
const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
|
|
441
|
+
// 原子性设置标记,防止并发重复
|
|
442
|
+
const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
|
|
443
|
+
if (!setResult) {
|
|
444
|
+
continue; // 已有标记,跳过
|
|
416
445
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
446
|
+
forwardSendMardKeyList.push(sendMarkKey); // 收集合并转发的标记键
|
|
447
|
+
// 每条动态一个 node
|
|
448
|
+
forwardNodes.push({
|
|
449
|
+
name: '匿名消息',
|
|
450
|
+
uin: String(80000000),
|
|
451
|
+
message: messages,
|
|
452
|
+
time: Date.now()
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
// 尝试合并转发动态
|
|
456
|
+
if ((await this.sendMsgApi(chatId, bot_id, chatType, '优纪酱B站动态通知~')) &&
|
|
457
|
+
(await this.sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes))) {
|
|
458
|
+
await this.randomDelay(1000, 2000);
|
|
459
|
+
continue; // 合并转发成功,跳过后续单条发送逻辑
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
for (const sendMarkKey of forwardSendMardKeyList) {
|
|
463
|
+
await Redis.del(sendMarkKey); // 发送消息失败,删除合并转发成功标记
|
|
423
464
|
}
|
|
424
465
|
}
|
|
466
|
+
}
|
|
467
|
+
// 合并转发失败,回退为原有方式
|
|
468
|
+
for (const messageCombination of messageCombinationList) {
|
|
469
|
+
const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
|
|
470
|
+
const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
|
|
471
|
+
// 原子性设置标记,防止并发重复
|
|
472
|
+
const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
|
|
473
|
+
if (!setResult) {
|
|
474
|
+
continue; // 已有标记,跳过
|
|
475
|
+
}
|
|
476
|
+
let sendSuccess = true;
|
|
425
477
|
if (sendMode === 'SINGLE') {
|
|
426
|
-
let allSent = true;
|
|
427
478
|
for (let i = 0; i < messages.length; i++) {
|
|
428
|
-
if (!(await this.
|
|
429
|
-
|
|
430
|
-
break;
|
|
479
|
+
if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages[i]))) {
|
|
480
|
+
sendSuccess = false;
|
|
481
|
+
break;
|
|
431
482
|
}
|
|
432
483
|
}
|
|
433
|
-
if (
|
|
434
|
-
await Redis.
|
|
435
|
-
|
|
484
|
+
if (!sendSuccess) {
|
|
485
|
+
await Redis.del(sendMarkKey); // 失败删除标记
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
await this.randomDelay(1000, 2000);
|
|
436
489
|
}
|
|
437
490
|
}
|
|
438
491
|
else if (sendMode === 'MERGE') {
|
|
439
|
-
if (await this.
|
|
440
|
-
await Redis.
|
|
492
|
+
if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages))) {
|
|
493
|
+
await Redis.del(sendMarkKey); // 失败删除标记
|
|
441
494
|
}
|
|
495
|
+
await this.randomDelay(1000, 2000);
|
|
442
496
|
}
|
|
443
497
|
}
|
|
444
498
|
}
|
|
@@ -453,7 +507,7 @@ class BiliTask {
|
|
|
453
507
|
* @param chatType 聊天类型
|
|
454
508
|
* @param message 消息内容
|
|
455
509
|
*/
|
|
456
|
-
async
|
|
510
|
+
async sendMsgApi(chatId, bot_id, chatType, message) {
|
|
457
511
|
try {
|
|
458
512
|
if (chatType === 'group') {
|
|
459
513
|
await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(message); // 发送群聊
|
|
@@ -468,6 +522,30 @@ class BiliTask {
|
|
|
468
522
|
return false; // 发送失败
|
|
469
523
|
}
|
|
470
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* 发送合并转发消息
|
|
527
|
+
* @param chatId 聊天 ID
|
|
528
|
+
* @param bot_id 机器人 ID
|
|
529
|
+
* @param chatType 聊天类型
|
|
530
|
+
* @param message 消息内容
|
|
531
|
+
* @returns 是否发送成功
|
|
532
|
+
*/
|
|
533
|
+
async sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes) {
|
|
534
|
+
const forwardMsg = await Bot.makeForwardMsg(forwardNodes);
|
|
535
|
+
try {
|
|
536
|
+
if (chatType === 'group') {
|
|
537
|
+
await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(forwardMsg); // 发送群聊合并转发
|
|
538
|
+
}
|
|
539
|
+
else if (chatType === 'private') {
|
|
540
|
+
await (Bot[bot_id] ?? Bot)?.pickFriend(String(chatId)).sendMsg(forwardMsg); // 发送好友私聊合并转发
|
|
541
|
+
}
|
|
542
|
+
return true; // 发送成功
|
|
543
|
+
}
|
|
544
|
+
catch (error) {
|
|
545
|
+
global?.logger?.error(`${chatType === 'group' ? '群聊' : '私聊'} ${chatId} 合并转发消息发送失败:${JSON.stringify(error)}`);
|
|
546
|
+
return false; // 发送失败
|
|
547
|
+
}
|
|
548
|
+
}
|
|
471
549
|
/**
|
|
472
550
|
* 随机延时
|
|
473
551
|
* @param min 最小延时时间
|
|
@@ -344,48 +344,101 @@ class WeiboTask {
|
|
|
344
344
|
* @param biliConfigData 微博配置数据
|
|
345
345
|
*/
|
|
346
346
|
async sendDynamicMessage(messageMap, weiboConfigData) {
|
|
347
|
+
let forwardSendDynamic = weiboConfigData.forwardSendDynamic === 0 || weiboConfigData.forwardSendDynamic === false ? false : true; // 转发动态是否合并发送,默认 true
|
|
347
348
|
const LogMark = new Set(); // 日志mark
|
|
348
349
|
for (const [chatType, botMap] of messageMap) {
|
|
349
350
|
for (const [bot_id, chatMap] of botMap) {
|
|
350
351
|
for (const [chatId, messageCombinationList] of chatMap) {
|
|
351
|
-
//
|
|
352
|
+
// 区分群聊和私聊
|
|
353
|
+
let markKey = chatType === 'group' ? this.groupKey : this.privateKey;
|
|
354
|
+
if (!LogMark.has('1')) {
|
|
355
|
+
global?.logger?.mark('优纪插件: B站动态执行推送');
|
|
356
|
+
LogMark.add('1');
|
|
357
|
+
}
|
|
358
|
+
// 统计图片数量和文字长度
|
|
359
|
+
let imageCount = 0;
|
|
360
|
+
let textLength = 0;
|
|
352
361
|
for (const messageCombination of messageCombinationList) {
|
|
353
|
-
const {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
362
|
+
const { messages } = messageCombination;
|
|
363
|
+
for (const msg of messages) {
|
|
364
|
+
if (typeof msg === 'object' && msg.type === 'image') {
|
|
365
|
+
imageCount++;
|
|
366
|
+
}
|
|
367
|
+
else if (typeof msg === 'string') {
|
|
368
|
+
textLength += msg.length;
|
|
369
|
+
}
|
|
359
370
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
371
|
+
}
|
|
372
|
+
// 满足条件才使用合并转发
|
|
373
|
+
const useForward = imageCount > 2 || textLength > 300;
|
|
374
|
+
if (forwardSendDynamic && useForward) {
|
|
375
|
+
const forwardNodes = [];
|
|
376
|
+
// 合并所有消息
|
|
377
|
+
const forwardSendMardKeyList = [];
|
|
378
|
+
forwardNodes.push({
|
|
379
|
+
name: '优纪酱通知',
|
|
380
|
+
uin: String(80000000),
|
|
381
|
+
message: ['有新的微博动态了~'],
|
|
382
|
+
time: Date.now()
|
|
383
|
+
});
|
|
384
|
+
for (const messageCombination of messageCombinationList) {
|
|
385
|
+
const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
|
|
386
|
+
const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
|
|
387
|
+
// 原子性设置标记,防止并发重复
|
|
388
|
+
const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
|
|
389
|
+
if (!setResult) {
|
|
390
|
+
continue; // 已有标记,跳过
|
|
391
|
+
}
|
|
392
|
+
forwardSendMardKeyList.push(sendMarkKey); // 收集合并转发的标记键
|
|
393
|
+
// 每条动态一个 node
|
|
394
|
+
forwardNodes.push({
|
|
395
|
+
name: '匿名消息',
|
|
396
|
+
uin: String(80000000),
|
|
397
|
+
message: messages,
|
|
398
|
+
time: Date.now()
|
|
399
|
+
});
|
|
363
400
|
}
|
|
364
|
-
|
|
365
|
-
if (
|
|
366
|
-
|
|
401
|
+
// 尝试合并转发动态
|
|
402
|
+
if ((await this.sendMsgApi(chatId, bot_id, chatType, '优纪酱微博动态通知~')) &&
|
|
403
|
+
(await this.sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes))) {
|
|
404
|
+
await this.randomDelay(1000, 2000);
|
|
405
|
+
continue; // 合并转发成功,跳过后续单条发送逻辑
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
for (const sendMarkKey of forwardSendMardKeyList) {
|
|
409
|
+
await Redis.del(sendMarkKey); // 发送消息失败,删除合并转发成功标记
|
|
410
|
+
}
|
|
367
411
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
412
|
+
}
|
|
413
|
+
// 合并转发失败,回退为原有方式
|
|
414
|
+
for (const messageCombination of messageCombinationList) {
|
|
415
|
+
const { sendMode, dynamicUUid_str, dynamicType, messages } = messageCombination;
|
|
416
|
+
const sendMarkKey = `${markKey}${chatId}:${dynamicUUid_str}`;
|
|
417
|
+
// 原子性设置标记,防止并发重复
|
|
418
|
+
const setResult = await Redis.set(sendMarkKey, '1', { NX: true, EX: 3600 * 72 });
|
|
419
|
+
if (!setResult) {
|
|
420
|
+
continue; // 已有标记,跳过
|
|
371
421
|
}
|
|
422
|
+
let sendSuccess = true;
|
|
372
423
|
if (sendMode === 'SINGLE') {
|
|
373
|
-
let allSent = true;
|
|
374
424
|
for (let i = 0; i < messages.length; i++) {
|
|
375
|
-
if (!(await this.
|
|
376
|
-
|
|
377
|
-
break;
|
|
425
|
+
if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages[i]))) {
|
|
426
|
+
sendSuccess = false;
|
|
427
|
+
break;
|
|
378
428
|
}
|
|
379
429
|
}
|
|
380
|
-
if (
|
|
381
|
-
await Redis.
|
|
382
|
-
|
|
430
|
+
if (!sendSuccess) {
|
|
431
|
+
await Redis.del(sendMarkKey); // 失败删除标记
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
await this.randomDelay(1000, 2000);
|
|
383
435
|
}
|
|
384
436
|
}
|
|
385
437
|
else if (sendMode === 'MERGE') {
|
|
386
|
-
if (await this.
|
|
387
|
-
await Redis.
|
|
438
|
+
if (!(await this.sendMsgApi(chatId, bot_id, chatType, messages))) {
|
|
439
|
+
await Redis.del(sendMarkKey); // 失败删除标记
|
|
388
440
|
}
|
|
441
|
+
await this.randomDelay(1000, 2000);
|
|
389
442
|
}
|
|
390
443
|
}
|
|
391
444
|
}
|
|
@@ -400,7 +453,7 @@ class WeiboTask {
|
|
|
400
453
|
* @param chatType 聊天类型
|
|
401
454
|
* @param message 消息内容
|
|
402
455
|
*/
|
|
403
|
-
async
|
|
456
|
+
async sendMsgApi(chatId, bot_id, chatType, message) {
|
|
404
457
|
try {
|
|
405
458
|
if (chatType === 'group') {
|
|
406
459
|
await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(message); // 发送群聊
|
|
@@ -415,6 +468,30 @@ class WeiboTask {
|
|
|
415
468
|
return false; // 发送失败
|
|
416
469
|
}
|
|
417
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* 发送合并转发消息
|
|
473
|
+
* @param chatId 聊天 ID
|
|
474
|
+
* @param bot_id 机器人 ID
|
|
475
|
+
* @param chatType 聊天类型
|
|
476
|
+
* @param message 消息内容
|
|
477
|
+
* @returns 是否发送成功
|
|
478
|
+
*/
|
|
479
|
+
async sendForwardMsgApi(chatId, bot_id, chatType, forwardNodes) {
|
|
480
|
+
const forwardMsg = await Bot.makeForwardMsg(forwardNodes);
|
|
481
|
+
try {
|
|
482
|
+
if (chatType === 'group') {
|
|
483
|
+
await (Bot[bot_id] ?? Bot)?.pickGroup(String(chatId)).sendMsg(forwardMsg); // 发送群聊合并转发
|
|
484
|
+
}
|
|
485
|
+
else if (chatType === 'private') {
|
|
486
|
+
await (Bot[bot_id] ?? Bot)?.pickFriend(String(chatId)).sendMsg(forwardMsg); // 发送好友私聊合并转发
|
|
487
|
+
}
|
|
488
|
+
return true; // 发送成功
|
|
489
|
+
}
|
|
490
|
+
catch (error) {
|
|
491
|
+
global?.logger?.error(`${chatType === 'group' ? '群聊' : '私聊'} ${chatId} 合并转发消息发送失败:${JSON.stringify(error)}`);
|
|
492
|
+
return false; // 发送失败
|
|
493
|
+
}
|
|
494
|
+
}
|
|
418
495
|
/**
|
|
419
496
|
* 随机延时
|
|
420
497
|
* @param min 最小延时时间
|