diff --git a/README.md b/README.md index 50e4043..65dd946 100644 --- a/README.md +++ b/README.md @@ -465,11 +465,13 @@ NODE_ENV=production | `/config list` | 查看所有存储桶配置 | | `/config add <名称> ` | 添加存储桶配置 | | `/config remove <名称>` | 删除存储桶配置 | +| `/config rename <旧名称> <新名称>` | 重命名存储桶(自动更新引用) | | `/config set <键路径> <值>` | 修改配置项 | **示例:** ```bash /config add mybucket xxxxxx yyyyyy my-bucket z0 https://cdn.example.com +/config rename old-bucket new-bucket /config remove mybucket ``` @@ -480,10 +482,12 @@ NODE_ENV=production | `/path list` | 查看所有预设路径 | | `/path add <名称> <路径>` | 添加预设路径 | | `/path remove <名称>` | 删除预设路径 | +| `/path rename <旧名称> <新名称>` | 重命名路径(自动更新引用) | **示例:** ```bash /path add backup /backup/ +/path rename old-path new-path /path add ipa /ipa/gamehall_jinxian2.ipa /path remove backup ``` @@ -493,13 +497,15 @@ NODE_ENV=production | 命令 | 说明 | |------|------| | `/profile list` | 查看所有上传配置模板 | -| `/profile add <名称> <存储桶> [路径键名]` | 添加上传配置模板 | +| `/profile add <名称> <存储桶> [路径]` | 添加上传配置模板 | | `/profile remove <名称>` | 删除上传配置模板 | +| `/profile rename <旧名称> <新名称>` | 重命名配置模板 | **示例:** ```bash /profile add 默认上传 default /profile add IPA 上传 default ipa +/profile rename old-profile new-profile /profile remove IPA 上传 ``` diff --git a/src/index.js b/src/index.js index b8b8708..d50f586 100644 --- a/src/index.js +++ b/src/index.js @@ -617,8 +617,56 @@ async function handleConfigCommandV2(message, content, feishu, uploader) { msg_type: 'text', content: { text: `✅ 已设置 ${keyPath} = ${value}` } }); + } else if (subCommand === 'rename' || subCommand === 'mv') { + // /config rename <旧名称> <新名称> + if (args.length < 2) { + throw new Error('用法:/config rename <旧名称> <新名称>\n示例:/config rename old-bucket new-bucket'); + } + const oldName = args[0]; + const newName = args.slice(1).join(' '); + + if (!fullConfig.buckets[oldName]) { + const availableBuckets = Object.keys(fullConfig.buckets).join(', '); + throw new Error(`存储桶 "${oldName}" 不存在\n可用存储桶:${availableBuckets || '无'}`); + } + + if (fullConfig.buckets[newName]) { + throw new Error(`存储桶 "${newName}" 已存在,请先删除或选择其他名称`); + } + + // 不允许重命名 default 存储桶 + if (oldName === 'default') { + throw new Error('不能重命名 default 存储桶'); + } + + // 复制配置到新名称 + fullConfig.buckets[newName] = fullConfig.buckets[oldName]; + delete fullConfig.buckets[oldName]; + + // 更新引用此存储桶的上传配置 + let updatedProfiles = 0; + if (fullConfig.uploadProfiles) { + for (const profile of Object.values(fullConfig.uploadProfiles)) { + if (profile.bucket === oldName) { + profile.bucket = newName; + updatedProfiles++; + } + } + } + + fs.writeFileSync(configPath, JSON.stringify(fullConfig, null, 2)); + + let msg = `✅ 已重命名存储桶:**${oldName}** → **${newName}**`; + if (updatedProfiles > 0) { + msg += `\n\n📌 同时更新了 ${updatedProfiles} 个引用此存储桶的上传配置`; + } + + await feishu.sendMessage(chatId, { + msg_type: 'text', + content: { text: msg } + }); } else { - throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove, set`); + throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove, rename, set`); } } catch (error) { await feishu.sendMessage(chatId, { @@ -692,8 +740,58 @@ async function handlePathCommandV2(message, content, feishu) { msg_type: 'text', content: { text: `✅ 已删除预设路径:**${name}**` } }); + } else if (subCommand === 'rename' || subCommand === 'mv') { + // /path rename <旧名称> <新名称> + if (args.length < 2) { + throw new Error('用法:/path rename <旧名称> <新名称>\n示例:/path rename old-path new-path'); + } + const oldName = args[0]; + const newName = args.slice(1).join(' '); + + if (!fullConfig.uploadPaths || !fullConfig.uploadPaths[oldName]) { + const availablePaths = Object.keys(fullConfig.uploadPaths || {}).join(', '); + throw new Error(`预设路径 "${oldName}" 不存在\n可用路径:${availablePaths || '无'}`); + } + + if (fullConfig.uploadPaths && fullConfig.uploadPaths[newName]) { + throw new Error(`预设路径 "${newName}" 已存在,请先删除或选择其他名称`); + } + + // 检查是否有上传配置引用此路径 + const profiles = fullConfig.uploadProfiles || {}; + const referencedBy = Object.entries(profiles) + .filter(([_, config]) => config.path === oldName) + .map(([pname, _]) => pname); + + // 复制配置到新名称 + fullConfig.uploadPaths = fullConfig.uploadPaths || {}; + fullConfig.uploadPaths[newName] = fullConfig.uploadPaths[oldName]; + delete fullConfig.uploadPaths[oldName]; + + // 更新引用此路径的上传配置 + let updatedProfiles = 0; + if (referencedBy.length > 0) { + for (const profile of Object.values(fullConfig.uploadProfiles)) { + if (profile.path === oldName) { + profile.path = newName; + updatedProfiles++; + } + } + } + + fs.writeFileSync(configPath, JSON.stringify(fullConfig, null, 2)); + + let msg = `✅ 已重命名预设路径:**${oldName}** → **${newName}**`; + if (updatedProfiles > 0) { + msg += `\n\n📌 同时更新了 ${updatedProfiles} 个引用此路径的上传配置`; + } + + await feishu.sendMessage(chatId, { + msg_type: 'text', + content: { text: msg } + }); } else { - throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove`); + throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove, rename`); } } catch (error) { await feishu.sendMessage(chatId, { @@ -780,8 +878,34 @@ async function handleProfileCommandV2(message, content, feishu) { msg_type: 'text', content: { text: `✅ 已删除上传配置:**${name}**` } }); + } else if (subCommand === 'rename' || subCommand === 'mv') { + // /profile rename <旧名称> <新名称> + if (args.length < 2) { + throw new Error('用法:/profile rename <旧名称> <新名称>\n示例:/profile rename old-profile new-profile'); + } + const oldName = args[0]; + const newName = args.slice(1).join(' '); + + if (!fullConfig.uploadProfiles || !fullConfig.uploadProfiles[oldName]) { + const availableProfiles = Object.keys(fullConfig.uploadProfiles || {}).join(', '); + throw new Error(`上传配置 "${oldName}" 不存在\n可用配置:${availableProfiles || '无'}`); + } + + if (fullConfig.uploadProfiles && fullConfig.uploadProfiles[newName]) { + throw new Error(`上传配置 "${newName}" 已存在,请先删除或选择其他名称`); + } + + // 复制配置到新名称 + fullConfig.uploadProfiles[newName] = fullConfig.uploadProfiles[oldName]; + delete fullConfig.uploadProfiles[oldName]; + + fs.writeFileSync(configPath, JSON.stringify(fullConfig, null, 2)); + await feishu.sendMessage(chatId, { + msg_type: 'text', + content: { text: `✅ 已重命名上传配置:**${oldName}** → **${newName}**` } + }); } else { - throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove`); + throw new Error(`未知命令:${subCommand}\n可用命令:list, add, remove, rename`); } } catch (error) { await feishu.sendMessage(chatId, { @@ -823,7 +947,7 @@ async function handleHelpCommandV2(chatId, feishu) { tag: 'div', text: { tag: 'lark_md', - content: '**⚙️ 存储桶配置 (/config)**\n\n• `/config list` - 查看所有存储桶配置\n• `/config add <名称> ` - 添加存储桶\n• `/config remove <名称>` - 删除存储桶\n• `/config set <键路径> <值>` - 修改配置项\n\n**示例:**\n`/config add mybucket xxxxxx yyyyyy my-bucket z0 https://cdn.example.com`' + content: '**⚙️ 存储桶配置 (/config 或 /qc)**\n\n• `/config list` - 查看所有存储桶配置\n• `/config add <名称> ` - 添加存储桶\n• `/config remove <名称>` - 删除存储桶\n• `/config rename <旧名称> <新名称>` - 重命名存储桶(自动更新引用)\n• `/config set <键路径> <值>` - 修改配置项\n\n**示例:**\n`/config add mybucket xxxxxx yyyyyy my-bucket z0 https://cdn.example.com`\n`/config rename old-bucket new-bucket`' } }, { @@ -833,7 +957,7 @@ async function handleHelpCommandV2(chatId, feishu) { tag: 'div', text: { tag: 'lark_md', - content: '**📁 预设路径 (/path)**\n\n• `/path list` - 查看所有预设路径\n• `/path add <名称> <路径>` - 添加预设路径\n• `/path remove <名称>` - 删除预设路径\n\n**示例:**\n`/path add backup /backup/`\n`/path add ipa /ipa/gamehall_jinxian2.ipa`' + content: '**📁 预设路径 (/path)**\n\n• `/path list` - 查看所有预设路径\n• `/path add <名称> <路径>` - 添加预设路径\n• `/path remove <名称>` - 删除预设路径\n• `/path rename <旧名称> <新名称>` - 重命名路径(自动更新引用)\n\n**示例:**\n`/path add backup /backup/`\n`/path rename old-path new-path`' } }, { @@ -843,7 +967,7 @@ async function handleHelpCommandV2(chatId, feishu) { tag: 'div', text: { tag: 'lark_md', - content: '**📤 上传配置 (/profile)**\n\n• `/profile list` - 查看所有上传配置模板\n• `/profile add <名称> <存储桶> [路径键名]` - 添加上传配置\n• `/profile remove <名称>` - 删除上传配置\n\n**示例:**\n`/profile add 默认上传 default`\n`/profile add IPA 上传 default ipa`' + content: '**📤 上传配置 (/profile)**\n\n• `/profile list` - 查看所有上传配置模板\n• `/profile add <名称> <存储桶> [路径]` - 添加上传配置\n• `/profile remove <名称>` - 删除上传配置\n• `/profile rename <旧名称> <新名称>` - 重命名配置\n\n**示例:**\n`/profile add 默认上传 default`\n`/profile add IPA 上传 default ipa`\n`/profile rename old-profile new-profile`' } }, {