(msg: Api.Message)
| 642 | // 节点名称折叠列表 |
| 643 | if (nodeInfo.names && nodeInfo.names.length > 0) { |
| 644 | const nameList = nodeInfo.names.map((n: string) => htmlEscape(n)).join('\n'); |
| 645 | seg.push(blockquoteTag(`📋 节点列表 (${nodeInfo.names.length}个)\n${nameList}`)); |
| 646 | } |
| 647 | } else { |
| 648 | seg.push(`(未能解析节点列表)`); |
| 649 | } |
| 650 | |
| 651 | reports.push(seg.join('\n')); |
| 652 | } |
| 653 | |
| 654 | let resultText = reports.join(separator); |
| 655 | const statsText = `\n📈 ${boldTag('统计:')} ✅有效:${stats.有效} | ⚠️耗尽:${stats.耗尽} | ❌过期:${stats.过期} | ❓失败:${stats.失败}`; |
| 656 | |
| 657 | if (urls.length > 1) resultText += statsText; |
| 658 | |
| 659 | if (isTxtOutput) { |
| 660 | const dateStr = dayjs().format('YYYYMMDD_HHmmss'); |
| 661 | const fileName = `subinfo_report_${dateStr}.txt`; |
| 662 | const fileContent = resultText; |
| 663 | const fileBuffer = Buffer.from(fileContent, 'utf-8') as Buffer & { name?: string }; |
| 664 | fileBuffer.name = fileName; |
| 665 | |
| 666 | try { |
| 667 | await client.sendFile(msg.chatId!, { file: fileBuffer, caption: `✅ 订阅查询报告 (共 ${urls.length} 个链接)\n${statsText.trim()}` }); |
| 668 | await msg.delete(); |
| 669 | } catch (e) { |
| 670 | const preview = isTxtOutput |
| 671 | ? splitLongMessage(resultText, 1024)[0] |
| 672 | : htmlEscape(splitLongMessage(resultText, 1024)[0]); |
| 673 | await msg.edit({ text: `❌ 发送TXT文件失败,请检查权限。\n\n部分内容:\n${preview}`, parseMode: 'html' }); |
| 674 | } |
| 675 | } else { |
| 676 | const messageParts = splitLongMessage(resultText, 4090); |
| 677 | await msg.edit({ text: messageParts[0], parseMode: "html", linkPreview: false }); |
| 678 | for (let i = 1; i < messageParts.length; i++) { |
| 679 | await client.sendMessage(msg.chatId!, { message: messageParts[i], parseMode: "html", replyTo: msg.id }); |
| 680 | } |
| 681 | } |
| 682 | } |
| 683 | |
| 684 | // --- 简洁模式处理器 (.cha) --- |
| 685 | async handleCha(msg: Api.Message): Promise<void> { |
| 686 | const client = await getGlobalClient(); |
| 687 | await msg.edit({ text: "⏳ 正在查询订阅信息..." }); |
| 688 | |
| 689 | const myText = (msg.text ?? '').trim(); |
| 690 | let parts = myText.split(/\s+/).slice(1); |
| 691 | |
| 692 | const isTxtOutput = parts.length > 0 && parts[0].toLowerCase() === 'txt'; |
| 693 | const cleanParts = isTxtOutput ? parts.slice(1) : parts; |
| 694 | |
| 695 | let sourceText = ''; |
| 696 | if (msg.replyToMsgId) { |
| 697 | try { |
| 698 | const replyMsg = await safeGetReplyMessage(msg); |
| 699 | if (replyMsg) sourceText = (replyMsg.text ?? '') + ' ' + ((replyMsg as any).caption ?? ''); |
| 700 | } catch { /* 忽略 */ } |
| 701 | } |
nothing calls this directly
no test coverage detected