feat: 添加 rename 重命名功能

- /config rename <旧名称> <新名称> - 重命名存储桶
  - 自动更新引用此存储桶的上传配置
  - 禁止重命名 default 存储桶
  - 检查新名称是否已存在

- /path rename <旧名称> <新名称> - 重命名预设路径
  - 自动更新引用此路径的上传配置
  - 检查新名称是否已存在

- /profile rename <旧名称> <新名称> - 重命名上传配置
  - 检查新名称是否已存在

- 更新帮助卡片和 README.md 文档
- 支持带空格的名称(如 'IPA 上传')
This commit is contained in:
饭团
2026-03-15 00:36:03 +08:00
parent 257d52c1a8
commit 79112210d4
2 changed files with 137 additions and 7 deletions

View File

@@ -465,11 +465,13 @@ NODE_ENV=production
| `/config list` | 查看所有存储桶配置 |
| `/config add <名称> <accessKey> <secretKey> <bucket> <region> <domain>` | 添加存储桶配置 |
| `/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 上传
```

View File

@@ -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 <名称> <accessKey> <secretKey> <bucket> <region> <domain>` - 添加存储桶\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 <名称> <AK> <SK> <bucket> <region> <domain>` - 添加存储桶\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`'
}
},
{