(msg: Api.Message, client: any, mode: "add" | "replace" = "add")
| 443 | break; |
| 444 | |
| 445 | case "set": |
| 446 | await this.setTarget(msg, args.slice(1).join(" ")); |
| 447 | break; |
| 448 | |
| 449 | case "info": |
| 450 | await this.showInfo(msg); |
| 451 | break; |
| 452 | |
| 453 | case "restart": |
| 454 | await this.restartSSH(msg); |
| 455 | break; |
| 456 | |
| 457 | default: |
| 458 | await msg.edit({ |
| 459 | text: `❓ 未知子命令,使用 <code>${mainPrefix}ssh help</code> 查看说明`, |
| 460 | parseMode: "html" |
| 461 | }); |
| 462 | } |
| 463 | } catch (error: any) { |
| 464 | console.error("[ssh] 执行失败:", error); |
| 465 | await msg.edit({ |
| 466 | text: `❌ <b>执行失败:</b> ${htmlEscape(error.message || "未知错误")}`, |
| 467 | parseMode: "html" |
| 468 | }); |
| 469 | } |
| 470 | } |
| 471 | |
| 472 | // 生成SSH密钥 |
| 473 | private async generateSSHKeys(msg: Api.Message, client: any, mode: "add" | "replace" = "add"): Promise<void> { |
| 474 | await msg.edit({ text: "🔄 正在生成SSH密钥对...", parseMode: "html" }); |
| 475 | |
| 476 | const timestamp = dayjs().format("YYYYMMDD_HHmmss"); |
| 477 | const workDir = path.join(createDirectoryInTemp("sshkey"), `keys_${timestamp}`); |
| 478 | const keyName = `ssh_key_${timestamp}`; |
| 479 | |
| 480 | try { |
| 481 | // 创建工作目录 |
| 482 | fs.mkdirSync(workDir, { recursive: true }); |
| 483 | |
| 484 | // 生成RSA密钥对 - 使用验证过的路径 |
| 485 | if (!validatePath(keyName)) { |
| 486 | throw new Error("密钥名称包含非法字符"); |
| 487 | } |
| 488 | const keyPath = path.join(workDir, keyName); |
| 489 | await execFileAsync("ssh-keygen", [ |
| 490 | "-t", "rsa", "-b", "4096", "-f", keyPath, "-N", "", "-C", `generated_${timestamp}`, |
| 491 | ]); |
| 492 | |
| 493 | // 读取密钥文件 |
| 494 | const privateKey = fs.readFileSync(keyPath, "utf-8"); |
| 495 | const publicKey = fs.readFileSync(`${keyPath}.pub`, "utf-8").trim(); |
| 496 | |
| 497 | // 验证公钥格式 |
| 498 | const keyParts = publicKey.split(/\s+/); |
| 499 | if (keyParts.length < 2 || !keyParts[0].startsWith('ssh-')) { |
| 500 | throw new Error("生成的公钥格式无效"); |
| 501 | } |
| 502 |
no test coverage detected