koishi-plugin-maibot 1.7.31 → 1.7.32
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/lib/database.d.ts +2 -0
- package/lib/database.d.ts.map +1 -1
- package/lib/database.js +3 -1
- package/lib/database.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +374 -93
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -674,13 +674,26 @@ async function waitForUserReply(session, ctx, timeout) {
|
|
|
674
674
|
}
|
|
675
675
|
/**
|
|
676
676
|
* 交互式获取二维码文本(qr_text)
|
|
677
|
-
*
|
|
678
|
-
*
|
|
677
|
+
* 支持10分钟内使用上次输入的SGID缓存
|
|
678
|
+
* 如果缓存存在且有效,直接使用;否则提示用户输入
|
|
679
679
|
*/
|
|
680
|
-
async function getQrText(session, ctx, api, binding, config, timeout = 60000, promptMessage
|
|
680
|
+
async function getQrText(session, ctx, api, binding, config, timeout = 60000, promptMessage, useCache = true // 是否使用缓存(默认启用)
|
|
681
|
+
) {
|
|
681
682
|
const logger = ctx.logger('maibot');
|
|
682
|
-
//
|
|
683
|
-
|
|
683
|
+
// 如果启用缓存且binding存在,检查是否有10分钟内的SGID缓存
|
|
684
|
+
if (useCache && binding && binding.lastQrCode && binding.lastQrCodeTime) {
|
|
685
|
+
const cacheAge = Date.now() - new Date(binding.lastQrCodeTime).getTime();
|
|
686
|
+
const cacheValidDuration = 10 * 60 * 1000; // 10分钟
|
|
687
|
+
if (cacheAge < cacheValidDuration && binding.lastQrCode.startsWith('SGWCMAID')) {
|
|
688
|
+
logger.info(`使用缓存的SGID(${Math.floor(cacheAge / 1000)}秒前输入)`);
|
|
689
|
+
// 直接返回缓存的SGID,不验证(让调用方验证,如果失败再提示输入)
|
|
690
|
+
return { qrText: binding.lastQrCode, fromCache: true };
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
logger.debug(`缓存已过期(${Math.floor(cacheAge / 1000)}秒前输入,超过10分钟)`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
// 没有有效缓存,提示用户输入
|
|
684
697
|
const actualTimeout = timeout;
|
|
685
698
|
const message = promptMessage || `请在${actualTimeout / 1000}秒内发送SGID(长按玩家二维码识别后发送)或公众号提供的网页地址`;
|
|
686
699
|
try {
|
|
@@ -749,12 +762,14 @@ async function getQrText(session, ctx, api, binding, config, timeout = 60000, pr
|
|
|
749
762
|
await session.send('❌ 无效或过期的二维码,请重新发送');
|
|
750
763
|
return { qrText: '', error: '无效或过期的二维码' };
|
|
751
764
|
}
|
|
752
|
-
// 如果binding存在,更新数据库中的qrCode
|
|
765
|
+
// 如果binding存在,更新数据库中的qrCode和缓存
|
|
753
766
|
if (binding) {
|
|
754
767
|
await ctx.database.set('maibot_bindings', { userId: binding.userId }, {
|
|
755
768
|
qrCode: qrText,
|
|
769
|
+
lastQrCode: qrText, // 更新缓存
|
|
770
|
+
lastQrCodeTime: new Date(), // 更新时间戳
|
|
756
771
|
});
|
|
757
|
-
logger.info(`已更新用户 ${binding.userId} 的qrCode
|
|
772
|
+
logger.info(`已更新用户 ${binding.userId} 的qrCode和缓存`);
|
|
758
773
|
}
|
|
759
774
|
return { qrText: qrText };
|
|
760
775
|
}
|
|
@@ -907,6 +922,8 @@ async function promptForRebind(session, ctx, api, binding, config, timeout = 600
|
|
|
907
922
|
bindTime: new Date(),
|
|
908
923
|
userName,
|
|
909
924
|
rating,
|
|
925
|
+
lastQrCode: qrCode, // 保存为缓存
|
|
926
|
+
lastQrCodeTime: new Date(), // 保存时间戳
|
|
910
927
|
});
|
|
911
928
|
// 发送成功反馈
|
|
912
929
|
await session.send(`✅ 重新绑定成功!${userName ? `\n用户名: ${userName}` : ''}${rating ? `\nRating: ${rating}` : ''}\n\n⚠️ 为了确保账户安全,请手动撤回群内包含SGID的消息`);
|
|
@@ -1670,6 +1687,8 @@ function apply(ctx, config) {
|
|
|
1670
1687
|
bindTime: new Date(),
|
|
1671
1688
|
userName,
|
|
1672
1689
|
rating,
|
|
1690
|
+
lastQrCode: qrCode, // 保存为缓存
|
|
1691
|
+
lastQrCodeTime: new Date(), // 保存时间戳
|
|
1673
1692
|
});
|
|
1674
1693
|
return `✅ 绑定成功!\n` +
|
|
1675
1694
|
(userName ? `用户名: ${userName}\n` : '') +
|
|
@@ -2400,34 +2419,73 @@ function apply(ctx, config) {
|
|
|
2400
2419
|
await session.send('请求成功提交,请等待服务器响应。(通常需要2-3分钟)');
|
|
2401
2420
|
// 使用新API获取功能票(需要qr_text)
|
|
2402
2421
|
let ticketResult;
|
|
2422
|
+
let usedCache = qrTextResult.fromCache === true;
|
|
2403
2423
|
try {
|
|
2404
2424
|
ticketResult = await api.getTicket(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, multiple, qrTextResult.qrText);
|
|
2405
2425
|
}
|
|
2406
2426
|
catch (error) {
|
|
2407
|
-
//
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
//
|
|
2411
|
-
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
2427
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2428
|
+
if (usedCache) {
|
|
2429
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2430
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2412
2431
|
if (retryQrText.error) {
|
|
2413
|
-
return `❌
|
|
2432
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
2414
2433
|
}
|
|
2434
|
+
// 在调用API前加入队列
|
|
2435
|
+
await waitForQueue(session);
|
|
2415
2436
|
ticketResult = await api.getTicket(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, multiple, retryQrText.qrText);
|
|
2416
2437
|
}
|
|
2417
2438
|
else {
|
|
2418
|
-
|
|
2439
|
+
// 如果API返回失败,可能需要重新绑定
|
|
2440
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
2441
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
2442
|
+
// 重新绑定成功,重试获取功能票
|
|
2443
|
+
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
2444
|
+
if (retryQrText.error) {
|
|
2445
|
+
return `❌ 重新绑定后获取二维码失败:${retryQrText.error}`;
|
|
2446
|
+
}
|
|
2447
|
+
// 在调用API前加入队列
|
|
2448
|
+
await waitForQueue(session);
|
|
2449
|
+
ticketResult = await api.getTicket(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, multiple, retryQrText.qrText);
|
|
2450
|
+
}
|
|
2451
|
+
else {
|
|
2452
|
+
throw error;
|
|
2453
|
+
}
|
|
2419
2454
|
}
|
|
2420
2455
|
}
|
|
2421
2456
|
if (!ticketResult.TicketStatus || !ticketResult.LoginStatus || !ticketResult.LogoutStatus) {
|
|
2422
|
-
//
|
|
2423
|
-
if (!ticketResult.QrStatus || ticketResult.LoginStatus === false) {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2457
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2458
|
+
if (usedCache && (!ticketResult.QrStatus || ticketResult.LoginStatus === false)) {
|
|
2459
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2460
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2461
|
+
if (retryQrText.error) {
|
|
2462
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
2463
|
+
}
|
|
2464
|
+
// 在调用API前加入队列
|
|
2465
|
+
await waitForQueue(session);
|
|
2466
|
+
ticketResult = await api.getTicket(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, multiple, retryQrText.qrText);
|
|
2467
|
+
if (!ticketResult.TicketStatus || !ticketResult.LoginStatus || !ticketResult.LogoutStatus) {
|
|
2468
|
+
if (!ticketResult.QrStatus || ticketResult.LoginStatus === false) {
|
|
2469
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
2470
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
2471
|
+
return `✅ 重新绑定成功!请重新执行发票操作。`;
|
|
2472
|
+
}
|
|
2473
|
+
return `❌ 发放功能票失败:服务器返回未成功\n重新绑定失败:${rebindResult.error || '未知错误'}`;
|
|
2474
|
+
}
|
|
2475
|
+
return '❌ 发票失败:服务器返回未成功,请确认是否已在短时间内多次执行发票指令或稍后再试或点击获取二维码刷新账号后再试。';
|
|
2427
2476
|
}
|
|
2428
|
-
return `❌ 发放功能票失败:服务器返回未成功\n重新绑定失败:${rebindResult.error || '未知错误'}`;
|
|
2429
2477
|
}
|
|
2430
|
-
|
|
2478
|
+
else {
|
|
2479
|
+
// 如果返回失败,可能需要重新绑定
|
|
2480
|
+
if (!ticketResult.QrStatus || ticketResult.LoginStatus === false) {
|
|
2481
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
2482
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
2483
|
+
return `✅ 重新绑定成功!请重新执行发票操作。`;
|
|
2484
|
+
}
|
|
2485
|
+
return `❌ 发放功能票失败:服务器返回未成功\n重新绑定失败:${rebindResult.error || '未知错误'}`;
|
|
2486
|
+
}
|
|
2487
|
+
return '❌ 发票失败:服务器返回未成功,请确认是否已在短时间内多次执行发票指令或稍后再试或点击获取二维码刷新账号后再试。';
|
|
2488
|
+
}
|
|
2431
2489
|
}
|
|
2432
2490
|
return `✅ 已发放 ${multiple} 倍票\n请稍等几分钟在游戏内确认`;
|
|
2433
2491
|
}
|
|
@@ -2629,41 +2687,76 @@ function apply(ctx, config) {
|
|
|
2629
2687
|
await waitForQueue(session);
|
|
2630
2688
|
// 上传B50(使用新API,需要qr_text)
|
|
2631
2689
|
let result;
|
|
2690
|
+
let usedCache = qrTextResult.fromCache === true;
|
|
2632
2691
|
try {
|
|
2633
2692
|
result = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, qrTextResult.qrText, binding.fishToken);
|
|
2634
2693
|
}
|
|
2635
2694
|
catch (error) {
|
|
2636
|
-
//
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
//
|
|
2640
|
-
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
2695
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2696
|
+
if (usedCache) {
|
|
2697
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2698
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2641
2699
|
if (retryQrText.error) {
|
|
2642
|
-
return `❌
|
|
2700
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
2643
2701
|
}
|
|
2644
2702
|
// 在调用API前加入队列
|
|
2645
2703
|
await waitForQueue(session);
|
|
2646
2704
|
result = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, binding.fishToken);
|
|
2647
2705
|
}
|
|
2648
2706
|
else {
|
|
2649
|
-
|
|
2707
|
+
// 如果API返回失败,可能需要重新绑定
|
|
2708
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
2709
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
2710
|
+
// 重新绑定成功,重试上传
|
|
2711
|
+
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
2712
|
+
if (retryQrText.error) {
|
|
2713
|
+
return `❌ 重新绑定后获取二维码失败:${retryQrText.error}`;
|
|
2714
|
+
}
|
|
2715
|
+
// 在调用API前加入队列
|
|
2716
|
+
await waitForQueue(session);
|
|
2717
|
+
result = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, binding.fishToken);
|
|
2718
|
+
}
|
|
2719
|
+
else {
|
|
2720
|
+
throw error;
|
|
2721
|
+
}
|
|
2650
2722
|
}
|
|
2651
2723
|
}
|
|
2652
2724
|
if (!result.UploadStatus) {
|
|
2653
|
-
|
|
2654
|
-
|
|
2725
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2726
|
+
if (usedCache && (result.msg?.includes('二维码') || result.msg?.includes('qr_text') || result.msg?.includes('无效'))) {
|
|
2727
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2728
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2729
|
+
if (retryQrText.error) {
|
|
2730
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
2731
|
+
return `❌ 上传失败:${result.msg || '未知错误'}\n获取新二维码失败:${retryQrText.error}${taskIdInfo}`;
|
|
2732
|
+
}
|
|
2733
|
+
// 在调用API前加入队列
|
|
2734
|
+
await waitForQueue(session);
|
|
2735
|
+
result = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, binding.fishToken);
|
|
2736
|
+
if (!result.UploadStatus) {
|
|
2737
|
+
if (result.msg === '该账号下存在未完成的任务') {
|
|
2738
|
+
return '⚠️ 当前账号已有未完成的水鱼B50任务,请耐心等待任务完成,预计1-10分钟,无需重复上传。';
|
|
2739
|
+
}
|
|
2740
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
2741
|
+
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
2742
|
+
}
|
|
2655
2743
|
}
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2744
|
+
else {
|
|
2745
|
+
if (result.msg === '该账号下存在未完成的任务') {
|
|
2746
|
+
return '⚠️ 当前账号已有未完成的水鱼B50任务,请耐心等待任务完成,预计1-10分钟,无需重复上传。';
|
|
2747
|
+
}
|
|
2748
|
+
// 如果返回失败,可能需要重新绑定
|
|
2749
|
+
if (result.msg?.includes('二维码') || result.msg?.includes('qr_text') || result.msg?.includes('无效')) {
|
|
2750
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
2751
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
2752
|
+
return `✅ 重新绑定成功!请重新执行上传操作。`;
|
|
2753
|
+
}
|
|
2754
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
2755
|
+
return `❌ 上传失败:${result.msg || '未知错误'}\n重新绑定失败:${rebindResult.error || '未知错误'}${taskIdInfo}`;
|
|
2661
2756
|
}
|
|
2662
2757
|
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
2663
|
-
return `❌ 上传失败:${result.msg || '未知错误'}
|
|
2758
|
+
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
2664
2759
|
}
|
|
2665
|
-
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
2666
|
-
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
2667
2760
|
}
|
|
2668
2761
|
scheduleB50Notification(session, result.task_id);
|
|
2669
2762
|
return `✅ B50上传任务已提交!\n任务ID: ${result.task_id}\n\n请耐心等待任务完成,预计1-10分钟`;
|
|
@@ -2775,7 +2868,20 @@ function apply(ctx, config) {
|
|
|
2775
2868
|
const fishAbort = await (async () => {
|
|
2776
2869
|
try {
|
|
2777
2870
|
await waitForQueue(session);
|
|
2778
|
-
|
|
2871
|
+
let fishResult = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, qrTextResult.qrText, fishToken);
|
|
2872
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2873
|
+
if (qrTextResult.fromCache && !fishResult.UploadStatus && (fishResult.msg?.includes('二维码') || fishResult.msg?.includes('qr_text') || fishResult.msg?.includes('无效'))) {
|
|
2874
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2875
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2876
|
+
if (retryQrText.error) {
|
|
2877
|
+
const taskIdInfo = fishResult.task_id ? `\n任务ID: ${fishResult.task_id}` : '';
|
|
2878
|
+
results.push(`🐟 水鱼: ❌ 上传失败:${fishResult.msg || '未知错误'}\n获取新二维码失败:${retryQrText.error}${taskIdInfo}`);
|
|
2879
|
+
return null;
|
|
2880
|
+
}
|
|
2881
|
+
// 在调用API前加入队列
|
|
2882
|
+
await waitForQueue(session);
|
|
2883
|
+
fishResult = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, fishToken);
|
|
2884
|
+
}
|
|
2779
2885
|
if (!fishResult.UploadStatus) {
|
|
2780
2886
|
if (fishResult.msg === '该账号下存在未完成的任务') {
|
|
2781
2887
|
results.push('🐟 水鱼: ⚠️ 当前账号已有未完成的B50任务,请稍后再试,无需重复上传。');
|
|
@@ -2798,20 +2904,64 @@ function apply(ctx, config) {
|
|
|
2798
2904
|
return null;
|
|
2799
2905
|
}
|
|
2800
2906
|
catch (error) {
|
|
2801
|
-
|
|
2802
|
-
if (
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2907
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2908
|
+
if (qrTextResult.fromCache) {
|
|
2909
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2910
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2911
|
+
if (retryQrText.error) {
|
|
2912
|
+
results.push(`🐟 水鱼: ❌ 获取二维码失败:${retryQrText.error}`);
|
|
2913
|
+
return null;
|
|
2914
|
+
}
|
|
2915
|
+
// 在调用API前加入队列
|
|
2916
|
+
await waitForQueue(session);
|
|
2917
|
+
try {
|
|
2918
|
+
const fishResult = await api.uploadB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, fishToken);
|
|
2919
|
+
if (!fishResult.UploadStatus) {
|
|
2920
|
+
if (fishResult.msg === '该账号下存在未完成的任务') {
|
|
2921
|
+
results.push('🐟 水鱼: ⚠️ 当前账号已有未完成的B50任务,请稍后再试,无需重复上传。');
|
|
2922
|
+
return null;
|
|
2923
|
+
}
|
|
2924
|
+
const taskIdInfo = fishResult.task_id ? `\n任务ID: ${fishResult.task_id}` : '';
|
|
2925
|
+
results.push(`🐟 水鱼: ❌ 上传失败:${fishResult.msg || '未知错误'}${taskIdInfo}`);
|
|
2926
|
+
return null;
|
|
2927
|
+
}
|
|
2928
|
+
scheduleB50Notification(session, fishResult.task_id);
|
|
2929
|
+
results.push(`🐟 水鱼: ✅ B50任务已提交!\n任务ID: ${fishResult.task_id}\n请耐心等待任务完成,预计1-10分钟`);
|
|
2930
|
+
return null;
|
|
2931
|
+
}
|
|
2932
|
+
catch (retryError) {
|
|
2933
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, retryError, rebindTimeout);
|
|
2934
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
2935
|
+
return '✅ 重新绑定成功!请重新执行 /maiua 上传操作。';
|
|
2936
|
+
}
|
|
2937
|
+
if (retryError?.code === 'ECONNABORTED' || String(retryError?.message || '').includes('timeout')) {
|
|
2938
|
+
results.push('🐟 水鱼: ❌ 上传超时,请稍后再试一次。');
|
|
2939
|
+
return null;
|
|
2940
|
+
}
|
|
2941
|
+
if (retryError?.response) {
|
|
2942
|
+
results.push(`🐟 水鱼: ❌ API请求失败: ${retryError.response.status} ${retryError.response.statusText}`);
|
|
2943
|
+
return null;
|
|
2944
|
+
}
|
|
2945
|
+
results.push(`🐟 水鱼: ❌ 上传失败: ${retryError?.message || '未知错误'}`);
|
|
2946
|
+
return null;
|
|
2947
|
+
}
|
|
2808
2948
|
}
|
|
2809
|
-
|
|
2810
|
-
|
|
2949
|
+
else {
|
|
2950
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
2951
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
2952
|
+
return '✅ 重新绑定成功!请重新执行 /maiua 上传操作。';
|
|
2953
|
+
}
|
|
2954
|
+
if (error?.code === 'ECONNABORTED' || String(error?.message || '').includes('timeout')) {
|
|
2955
|
+
results.push('🐟 水鱼: ❌ 上传超时,请稍后再试一次。');
|
|
2956
|
+
return null;
|
|
2957
|
+
}
|
|
2958
|
+
if (error?.response) {
|
|
2959
|
+
results.push(`🐟 水鱼: ❌ API请求失败: ${error.response.status} ${error.response.statusText}`);
|
|
2960
|
+
return null;
|
|
2961
|
+
}
|
|
2962
|
+
results.push(`🐟 水鱼: ❌ 上传失败: ${error?.message || '未知错误'}`);
|
|
2811
2963
|
return null;
|
|
2812
2964
|
}
|
|
2813
|
-
results.push(`🐟 水鱼: ❌ 上传失败: ${error?.message || '未知错误'}`);
|
|
2814
|
-
return null;
|
|
2815
2965
|
}
|
|
2816
2966
|
})();
|
|
2817
2967
|
if (fishAbort) {
|
|
@@ -2821,7 +2971,20 @@ function apply(ctx, config) {
|
|
|
2821
2971
|
const lxnsAbort = await (async () => {
|
|
2822
2972
|
try {
|
|
2823
2973
|
await waitForQueue(session);
|
|
2824
|
-
|
|
2974
|
+
let lxResult = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, qrTextResult.qrText, finalLxnsCode);
|
|
2975
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
2976
|
+
if (qrTextResult.fromCache && !lxResult.UploadStatus && (lxResult.msg?.includes('二维码') || lxResult.msg?.includes('qr_text') || lxResult.msg?.includes('无效'))) {
|
|
2977
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
2978
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
2979
|
+
if (retryQrText.error) {
|
|
2980
|
+
const taskIdInfo = lxResult.task_id ? `\n任务ID: ${lxResult.task_id}` : '';
|
|
2981
|
+
results.push(`❄️ 落雪: ❌ 上传失败:${lxResult.msg || '未知错误'}\n获取新二维码失败:${retryQrText.error}${taskIdInfo}`);
|
|
2982
|
+
return null;
|
|
2983
|
+
}
|
|
2984
|
+
// 在调用API前加入队列
|
|
2985
|
+
await waitForQueue(session);
|
|
2986
|
+
lxResult = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, finalLxnsCode);
|
|
2987
|
+
}
|
|
2825
2988
|
if (!lxResult.UploadStatus) {
|
|
2826
2989
|
if (lxResult.msg === '该账号下存在未完成的任务') {
|
|
2827
2990
|
results.push('❄️ 落雪: ⚠️ 当前账号已有未完成的B50任务,请稍后再试,无需重复上传。');
|
|
@@ -2844,20 +3007,64 @@ function apply(ctx, config) {
|
|
|
2844
3007
|
return null;
|
|
2845
3008
|
}
|
|
2846
3009
|
catch (error) {
|
|
2847
|
-
|
|
2848
|
-
if (
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
3010
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
3011
|
+
if (qrTextResult.fromCache) {
|
|
3012
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
3013
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
3014
|
+
if (retryQrText.error) {
|
|
3015
|
+
results.push(`❄️ 落雪: ❌ 获取二维码失败:${retryQrText.error}`);
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
// 在调用API前加入队列
|
|
3019
|
+
await waitForQueue(session);
|
|
3020
|
+
try {
|
|
3021
|
+
const lxResult = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, finalLxnsCode);
|
|
3022
|
+
if (!lxResult.UploadStatus) {
|
|
3023
|
+
if (lxResult.msg === '该账号下存在未完成的任务') {
|
|
3024
|
+
results.push('❄️ 落雪: ⚠️ 当前账号已有未完成的B50任务,请稍后再试,无需重复上传。');
|
|
3025
|
+
return null;
|
|
3026
|
+
}
|
|
3027
|
+
const taskIdInfo = lxResult.task_id ? `\n任务ID: ${lxResult.task_id}` : '';
|
|
3028
|
+
results.push(`❄️ 落雪: ❌ 上传失败:${lxResult.msg || '未知错误'}${taskIdInfo}`);
|
|
3029
|
+
return null;
|
|
3030
|
+
}
|
|
3031
|
+
scheduleLxB50Notification(session, lxResult.task_id);
|
|
3032
|
+
results.push(`❄️ 落雪: ✅ B50任务已提交!\n任务ID: ${lxResult.task_id}\n请耐心等待任务完成,预计1-10分钟`);
|
|
3033
|
+
return null;
|
|
3034
|
+
}
|
|
3035
|
+
catch (retryError) {
|
|
3036
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, retryError, rebindTimeout);
|
|
3037
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
3038
|
+
return '✅ 重新绑定成功!请重新执行 /maiua 上传操作。';
|
|
3039
|
+
}
|
|
3040
|
+
if (retryError?.code === 'ECONNABORTED' || String(retryError?.message || '').includes('timeout')) {
|
|
3041
|
+
results.push('❄️ 落雪: ❌ 上传超时,请稍后再试一次。');
|
|
3042
|
+
return null;
|
|
3043
|
+
}
|
|
3044
|
+
if (retryError?.response) {
|
|
3045
|
+
results.push(`❄️ 落雪: ❌ API请求失败: ${retryError.response.status} ${retryError.response.statusText}`);
|
|
3046
|
+
return null;
|
|
3047
|
+
}
|
|
3048
|
+
results.push(`❄️ 落雪: ❌ 上传失败: ${retryError?.message || '未知错误'}`);
|
|
3049
|
+
return null;
|
|
3050
|
+
}
|
|
2854
3051
|
}
|
|
2855
|
-
|
|
2856
|
-
|
|
3052
|
+
else {
|
|
3053
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
3054
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
3055
|
+
return '✅ 重新绑定成功!请重新执行 /maiua 上传操作。';
|
|
3056
|
+
}
|
|
3057
|
+
if (error?.code === 'ECONNABORTED' || String(error?.message || '').includes('timeout')) {
|
|
3058
|
+
results.push('❄️ 落雪: ❌ 上传超时,请稍后再试一次。');
|
|
3059
|
+
return null;
|
|
3060
|
+
}
|
|
3061
|
+
if (error?.response) {
|
|
3062
|
+
results.push(`❄️ 落雪: ❌ API请求失败: ${error.response.status} ${error.response.statusText}`);
|
|
3063
|
+
return null;
|
|
3064
|
+
}
|
|
3065
|
+
results.push(`❄️ 落雪: ❌ 上传失败: ${error?.message || '未知错误'}`);
|
|
2857
3066
|
return null;
|
|
2858
3067
|
}
|
|
2859
|
-
results.push(`❄️ 落雪: ❌ 上传失败: ${error?.message || '未知错误'}`);
|
|
2860
|
-
return null;
|
|
2861
3068
|
}
|
|
2862
3069
|
})();
|
|
2863
3070
|
if (lxnsAbort) {
|
|
@@ -3060,18 +3267,18 @@ function apply(ctx, config) {
|
|
|
3060
3267
|
// 使用新API获取收藏品(需要qr_text)
|
|
3061
3268
|
const machineInfo = config.machineInfo;
|
|
3062
3269
|
let result;
|
|
3270
|
+
let usedCache = qrTextResult.fromCache === true;
|
|
3063
3271
|
try {
|
|
3064
3272
|
result = await api.getItem(machineInfo.regionId, machineInfo.regionName, machineInfo.clientId, machineInfo.placeId, machineInfo.placeName, parseInt(itemId, 10), itemKind, 1, // item_stock: 1
|
|
3065
3273
|
qrTextResult.qrText);
|
|
3066
3274
|
}
|
|
3067
3275
|
catch (error) {
|
|
3068
|
-
//
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
//
|
|
3072
|
-
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
3276
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
3277
|
+
if (usedCache) {
|
|
3278
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
3279
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
3073
3280
|
if (retryQrText.error) {
|
|
3074
|
-
return `❌
|
|
3281
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
3075
3282
|
}
|
|
3076
3283
|
// 在调用API前加入队列
|
|
3077
3284
|
await waitForQueue(session);
|
|
@@ -3079,19 +3286,58 @@ function apply(ctx, config) {
|
|
|
3079
3286
|
retryQrText.qrText);
|
|
3080
3287
|
}
|
|
3081
3288
|
else {
|
|
3082
|
-
|
|
3289
|
+
// 如果API返回失败,可能需要重新绑定
|
|
3290
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
3291
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
3292
|
+
// 重新绑定成功,重试获取收藏品
|
|
3293
|
+
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
3294
|
+
if (retryQrText.error) {
|
|
3295
|
+
return `❌ 重新绑定后获取二维码失败:${retryQrText.error}`;
|
|
3296
|
+
}
|
|
3297
|
+
// 在调用API前加入队列
|
|
3298
|
+
await waitForQueue(session);
|
|
3299
|
+
result = await api.getItem(machineInfo.regionId, machineInfo.regionName, machineInfo.clientId, machineInfo.placeId, machineInfo.placeName, parseInt(itemId, 10), itemKind, 1, // item_stock: 1
|
|
3300
|
+
retryQrText.qrText);
|
|
3301
|
+
}
|
|
3302
|
+
else {
|
|
3303
|
+
throw error;
|
|
3304
|
+
}
|
|
3083
3305
|
}
|
|
3084
3306
|
}
|
|
3085
3307
|
if (!result.UserAllStatus || !result.LoginStatus || !result.LogoutStatus) {
|
|
3086
|
-
//
|
|
3087
|
-
if (!result.QrStatus || result.LoginStatus === false) {
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3308
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
3309
|
+
if (usedCache && (!result.QrStatus || result.LoginStatus === false)) {
|
|
3310
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
3311
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
3312
|
+
if (retryQrText.error) {
|
|
3313
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
3314
|
+
}
|
|
3315
|
+
// 在调用API前加入队列
|
|
3316
|
+
await waitForQueue(session);
|
|
3317
|
+
result = await api.getItem(machineInfo.regionId, machineInfo.regionName, machineInfo.clientId, machineInfo.placeId, machineInfo.placeName, parseInt(itemId, 10), itemKind, 1, // item_stock: 1
|
|
3318
|
+
retryQrText.qrText);
|
|
3319
|
+
if (!result.UserAllStatus || !result.LoginStatus || !result.LogoutStatus) {
|
|
3320
|
+
if (!result.QrStatus || result.LoginStatus === false) {
|
|
3321
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
3322
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
3323
|
+
return `✅ 重新绑定成功!请重新执行发收藏品操作。`;
|
|
3324
|
+
}
|
|
3325
|
+
return `❌ 发放收藏品失败:服务器返回未成功\n重新绑定失败:${rebindResult.error || '未知错误'}`;
|
|
3326
|
+
}
|
|
3327
|
+
return '❌ 发放收藏品失败:服务器返回未成功,请确认是否已在短时间内多次执行发收藏品指令或稍后再试或点击获取二维码刷新账号后再试。';
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
else {
|
|
3331
|
+
// 如果返回失败,可能需要重新绑定
|
|
3332
|
+
if (!result.QrStatus || result.LoginStatus === false) {
|
|
3333
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
3334
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
3335
|
+
return `✅ 重新绑定成功!请重新执行发收藏品操作。`;
|
|
3336
|
+
}
|
|
3337
|
+
return `❌ 发放收藏品失败:服务器返回未成功\n重新绑定失败:${rebindResult.error || '未知错误'}`;
|
|
3091
3338
|
}
|
|
3092
|
-
return
|
|
3339
|
+
return '❌ 发放收藏品失败:服务器返回未成功,请确认是否已在短时间内多次执行发收藏品指令或稍后再试或点击获取二维码刷新账号后再试。';
|
|
3093
3340
|
}
|
|
3094
|
-
return '❌ 发放收藏品失败:服务器返回未成功,请确认是否已在短时间内多次执行发收藏品指令或稍后再试或点击获取二维码刷新账号后再试。';
|
|
3095
3341
|
}
|
|
3096
3342
|
return `✅ 已为 ${maskUserId(binding.maiUid)} 发放收藏品${proxyTip}\n类型: ${selectedType?.label}\nID: ${itemId}`;
|
|
3097
3343
|
}
|
|
@@ -3464,41 +3710,76 @@ function apply(ctx, config) {
|
|
|
3464
3710
|
await waitForQueue(session);
|
|
3465
3711
|
// 上传落雪B50(使用新API,需要qr_text)
|
|
3466
3712
|
let result;
|
|
3713
|
+
let usedCache = qrTextResult.fromCache === true;
|
|
3467
3714
|
try {
|
|
3468
3715
|
result = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, qrTextResult.qrText, finalLxnsCode);
|
|
3469
3716
|
}
|
|
3470
3717
|
catch (error) {
|
|
3471
|
-
//
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
//
|
|
3475
|
-
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
3718
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
3719
|
+
if (usedCache) {
|
|
3720
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
3721
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
3476
3722
|
if (retryQrText.error) {
|
|
3477
|
-
return `❌
|
|
3723
|
+
return `❌ 获取二维码失败:${retryQrText.error}`;
|
|
3478
3724
|
}
|
|
3479
3725
|
// 在调用API前加入队列
|
|
3480
3726
|
await waitForQueue(session);
|
|
3481
3727
|
result = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, finalLxnsCode);
|
|
3482
3728
|
}
|
|
3483
3729
|
else {
|
|
3484
|
-
|
|
3730
|
+
// 如果API返回失败,可能需要重新绑定
|
|
3731
|
+
const failureResult = await handleApiFailure(session, ctx, api, binding, config, error, rebindTimeout);
|
|
3732
|
+
if (failureResult.rebindResult && failureResult.rebindResult.success && failureResult.rebindResult.newBinding) {
|
|
3733
|
+
// 重新绑定成功,重试上传
|
|
3734
|
+
const retryQrText = await getQrText(session, ctx, api, failureResult.rebindResult.newBinding, config, rebindTimeout);
|
|
3735
|
+
if (retryQrText.error) {
|
|
3736
|
+
return `❌ 重新绑定后获取二维码失败:${retryQrText.error}`;
|
|
3737
|
+
}
|
|
3738
|
+
// 在调用API前加入队列
|
|
3739
|
+
await waitForQueue(session);
|
|
3740
|
+
result = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, finalLxnsCode);
|
|
3741
|
+
}
|
|
3742
|
+
else {
|
|
3743
|
+
throw error;
|
|
3744
|
+
}
|
|
3485
3745
|
}
|
|
3486
3746
|
}
|
|
3487
3747
|
if (!result.UploadStatus) {
|
|
3488
|
-
|
|
3489
|
-
|
|
3748
|
+
// 如果使用了缓存且失败,尝试重新获取SGID
|
|
3749
|
+
if (usedCache && (result.msg?.includes('二维码') || result.msg?.includes('qr_text') || result.msg?.includes('无效'))) {
|
|
3750
|
+
logger.info('使用缓存的SGID失败,尝试重新获取SGID');
|
|
3751
|
+
const retryQrText = await getQrText(session, ctx, api, binding, config, rebindTimeout, undefined, false); // 禁用缓存,强制重新输入
|
|
3752
|
+
if (retryQrText.error) {
|
|
3753
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
3754
|
+
return `❌ 上传失败:${result.msg || '未知错误'}\n获取新二维码失败:${retryQrText.error}${taskIdInfo}`;
|
|
3755
|
+
}
|
|
3756
|
+
// 在调用API前加入队列
|
|
3757
|
+
await waitForQueue(session);
|
|
3758
|
+
result = await api.uploadLxB50(machineInfo.regionId, machineInfo.clientId, machineInfo.placeId, retryQrText.qrText, finalLxnsCode);
|
|
3759
|
+
if (!result.UploadStatus) {
|
|
3760
|
+
if (result.msg === '该账号下存在未完成的任务') {
|
|
3761
|
+
return '⚠️ 当前账号已有未完成的落雪B50任务,请耐心等待任务完成,预计1-10分钟,无需重复上传。';
|
|
3762
|
+
}
|
|
3763
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
3764
|
+
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
3765
|
+
}
|
|
3490
3766
|
}
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3767
|
+
else {
|
|
3768
|
+
if (result.msg === '该账号下存在未完成的任务') {
|
|
3769
|
+
return '⚠️ 当前账号已有未完成的落雪B50任务,请耐心等待任务完成,预计1-10分钟,无需重复上传。';
|
|
3770
|
+
}
|
|
3771
|
+
// 如果返回失败,可能需要重新绑定
|
|
3772
|
+
if (result.msg?.includes('二维码') || result.msg?.includes('qr_text') || result.msg?.includes('无效')) {
|
|
3773
|
+
const rebindResult = await promptForRebind(session, ctx, api, binding, config, rebindTimeout);
|
|
3774
|
+
if (rebindResult.success && rebindResult.newBinding) {
|
|
3775
|
+
return `✅ 重新绑定成功!请重新执行上传操作。`;
|
|
3776
|
+
}
|
|
3777
|
+
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
3778
|
+
return `❌ 上传失败:${result.msg || '未知错误'}\n重新绑定失败:${rebindResult.error || '未知错误'}${taskIdInfo}`;
|
|
3496
3779
|
}
|
|
3497
3780
|
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
3498
|
-
return `❌ 上传失败:${result.msg || '未知错误'}
|
|
3781
|
+
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
3499
3782
|
}
|
|
3500
|
-
const taskIdInfo = result.task_id ? `\n任务ID: ${result.task_id}` : '';
|
|
3501
|
-
return `❌ 上传失败:${result.msg || '未知错误'}${taskIdInfo}`;
|
|
3502
3783
|
}
|
|
3503
3784
|
scheduleLxB50Notification(session, result.task_id);
|
|
3504
3785
|
return `✅ 落雪B50上传任务已提交!\n任务ID: ${result.task_id}\n\n请耐心等待任务完成,预计1-10分钟`;
|