(target)
| 3808 | } |
| 3809 | |
| 3810 | async function prepareShadowrocketNodeSwitch(target) { |
| 3811 | const resolved = await runCommand(shadowrocketNodeControlPath, ["resolve", target], { timeout: 8000, allowFailure: true }); |
| 3812 | if (resolved.status !== 0) { |
| 3813 | return { |
| 3814 | ok: false, |
| 3815 | summary: "Shadowrocket node resolve failed", |
| 3816 | reply: trimIMessageCommandOutput(`没找到这个节点:${target}\n${resolved.output.trim()}`) |
| 3817 | }; |
| 3818 | } |
| 3819 | const node = JSON.parse(resolved.output.trim()); |
| 3820 | const probe = await runCommand(shadowrocketNodeControlPath, ["probe-target", String(node.index || node.uuid)], { timeout: 8000, allowFailure: true }); |
| 3821 | state.proxy.pendingAction = { |
| 3822 | action: "switch-node", |
| 3823 | target: String(node.index || node.uuid), |
| 3824 | node, |
| 3825 | createdAt: Date.now() |
| 3826 | }; |
| 3827 | return { |
| 3828 | ok: true, |
| 3829 | summary: "Shadowrocket node switch confirmation required", |
| 3830 | reply: trimIMessageCommandOutput([ |
| 3831 | "准备切换 Shadowrocket 节点。", |
| 3832 | `目标:${node.index}. ${node.title}`, |
| 3833 | `类型:${node.type || "未知"},小火箭 ping:${node.ping ?? "未知"}`, |
| 3834 | `入口:${node.host || "未知"}:${node.port || "未知"}`, |
| 3835 | "", |
| 3836 | "准备阶段入口测速:", |
| 3837 | probe.output.trim() || "入口测速没有输出。", |
| 3838 | "", |
| 3839 | "注意:这里只测目标入口 TCP,不代表目标节点一定能访问 OpenAI/X/YouTube。", |
| 3840 | "确认切换请在 3 分钟内发送 /确认;不切换就发送 /取消。" |
| 3841 | ].join("\n")) |
| 3842 | }; |
| 3843 | } |
| 3844 | |
| 3845 | function trimIMessageCommandOutput(text, limit = 1600) { |
| 3846 | const value = String(text || "").trim(); |
no test coverage detected