镜像自地址
https://github.com/lhly/cloud-drive-renamer.git
已同步 2026-10-20 13:47:47 +08:00
feat(woozooo): 新增蓝奏云网盘支持
新增蓝奏云网盘适配,支持文件列表获取、重命名及域名注入; 更新相关文档、测试用例及多语言描述,将蓝奏云纳入支持平台。
这个提交包含在:
父节点
0f8e981589
当前提交
d32e5ef66c
14
README.md
14
README.md
@ -4,7 +4,7 @@
|
||||
|
||||
**一款覆盖多家主流网盘的文件批量重命名工具**
|
||||
|
||||
支持 115 网盘、123 云盘、阿里云盘、百度网盘、移动云盘、天翼云盘、夸克网盘、UC 网盘的智能化文件管理
|
||||
支持 115 网盘、123 云盘、阿里云盘、百度网盘、蓝奏云、移动云盘、天翼云盘、迅雷云盘、夸克网盘、UC 网盘的智能化文件管理
|
||||
|
||||
[](LICENSE)
|
||||
[](https://www.typescriptlang.org/)
|
||||
@ -36,8 +36,10 @@
|
||||
- **123 云盘** - 支持文件批量重命名和页面同步
|
||||
- **阿里云盘** - 支持文件批量重命名和页面同步
|
||||
- **百度网盘** - 支持文件批量重命名和页面同步
|
||||
- **蓝奏云** - 支持文件批量重命名和页面同步
|
||||
- **移动云盘** - 支持文件批量重命名和页面同步
|
||||
- **天翼云盘** - 支持文件批量重命名和页面同步
|
||||
- **迅雷云盘** - 支持文件批量重命名和页面同步
|
||||
- **夸克网盘** - 支持文件批量重命名和页面同步
|
||||
- **UC 网盘** - 支持文件批量重命名和页面同步
|
||||
|
||||
@ -411,7 +413,9 @@ src/
|
||||
│ ├── cmcc/ # 移动云盘适配器
|
||||
│ ├── esurfing/ # 天翼云盘适配器
|
||||
│ ├── quark/ # 夸克网盘适配器
|
||||
│ └── uc/ # UC 网盘适配器
|
||||
│ ├── uc/ # UC 网盘适配器
|
||||
│ ├── xunlei/ # 迅雷云盘适配器
|
||||
│ └── woozooo/ # 蓝奏云适配器
|
||||
├── rules/ # 重命名规则
|
||||
│ ├── base-rule.ts # 规则基类
|
||||
│ ├── rule-factory.ts # 规则工厂
|
||||
@ -817,16 +821,18 @@ A: 请在 GitHub Issues 中提交,包含:
|
||||
|
||||
### 当前版本 (v1.5.0) 🎉
|
||||
|
||||
**多平台版本正式发布!** 当前版本已覆盖 8 个网盘平台,并保留完整的规则引擎、预览、冲突检测、重试和页面同步能力:
|
||||
**多平台版本正式发布!** 当前版本已覆盖 10 个网盘平台,并保留完整的规则引擎、预览、冲突检测、重试和页面同步能力:
|
||||
|
||||
#### 🚀 核心功能增强
|
||||
- ✅ **8 个网盘平台支持**
|
||||
- ✅ **10 个网盘平台支持**
|
||||
- 115 网盘 - 支持文件批量重命名和页面同步
|
||||
- 123 云盘 - 支持文件批量重命名和页面同步
|
||||
- 阿里云盘 - 支持文件批量重命名和页面同步
|
||||
- 百度网盘 - 支持文件批量重命名和页面同步
|
||||
- 蓝奏云 - 支持文件批量重命名和页面同步
|
||||
- 移动云盘 - 支持文件批量重命名和页面同步
|
||||
- 天翼云盘 - 支持文件批量重命名和页面同步
|
||||
- 迅雷云盘 - 支持文件批量重命名和页面同步
|
||||
- 夸克网盘 - 支持文件批量重命名和页面同步
|
||||
- UC 网盘 - 支持文件批量重命名和页面同步
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"description": "Extension name"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Powerful batch renaming tool for Quark Drive, Aliyun Drive, and Baidu Cloud Drive",
|
||||
"message": "Powerful batch renaming tool for Quark Drive, Aliyun Drive, Baidu Cloud Drive, 115 Drive, 123Pan, CMCC Drive, Esurfing Cloud, Xunlei Drive, Lanzou Cloud, and UC Drive",
|
||||
"description": "Extension description"
|
||||
},
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"description": "扩展名称"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "强大的批量重命名工具,支持夸克网盘、阿里云盘、百度网盘文件批量重命名",
|
||||
"message": "强大的批量重命名工具,支持夸克网盘、阿里云盘、百度网盘、115网盘、123云盘、移动云盘、天翼云盘、迅雷云盘、蓝奏云、UC网盘文件批量重命名",
|
||||
"description": "扩展描述"
|
||||
},
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"description": "擴充功能名稱"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "強大的批次重新命名工具,支援夸克網盤、阿里雲盤、百度雲端硬碟檔案批次重新命名",
|
||||
"message": "強大的批次重新命名工具,支援夸克網盤、阿里雲盤、百度雲端硬碟、115網盤、123雲盤、移動雲盤、天翼雲盤、迅雷雲盤、藍奏雲、UC網盤檔案批次重新命名",
|
||||
"description": "擴充功能描述"
|
||||
},
|
||||
|
||||
|
||||
@ -239,6 +239,9 @@ The Extension requests access to the following websites:
|
||||
- `https://yun.139.com/*` - CMCC Drive pages
|
||||
- `https://personal-kd-njs.yun.139.com/*` - CMCC Drive API
|
||||
- `https://cloud.189.cn/*` - Esurfing Cloud pages and API
|
||||
- `https://pan.xunlei.com/*` - Xunlei Drive pages
|
||||
- `https://api-pan.xunlei.com/*` - Xunlei Drive API
|
||||
- `https://pc.woozooo.com/*` - Lanzou Cloud pages and API
|
||||
- `https://pan.quark.cn/*` - Quark Drive pages and API
|
||||
- `https://drive.uc.cn/*` - UC Drive pages
|
||||
- `https://pan.uc.cn/*` - UC Drive pages
|
||||
|
||||
@ -90,7 +90,7 @@ cd ..
|
||||
|
||||
2. **Summary(简短描述)**
|
||||
```
|
||||
支持 115、123、阿里、百度、移动、天翼、夸克、UC 网盘的批量重命名工具
|
||||
支持 115、123、阿里、百度、蓝奏、移动、天翼、迅雷、夸克、UC 网盘的批量重命名工具
|
||||
```
|
||||
|
||||
3. **Category(分类)**
|
||||
@ -217,7 +217,7 @@ cd ..
|
||||
|
||||
3. **Short description(简短描述)**
|
||||
```
|
||||
支持 115、123、阿里、百度、移动、天翼、夸克、UC 网盘的批量重命名工具
|
||||
支持 115、123、阿里、百度、蓝奏、移动、天翼、迅雷、夸克、UC 网盘的批量重命名工具
|
||||
```
|
||||
|
||||
4. **Long description(详细描述)**
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
- **英文**: CloudDrive Renamer
|
||||
|
||||
### 简短描述 (132字符以内)
|
||||
- **中文**: 支持 115、123、阿里、百度、移动、天翼、夸克、UC 网盘的批量重命名工具
|
||||
- **英文**: Batch rename files across 115 Drive, 123Pan, Aliyun, Baidu, CMCC, Esurfing, Quark, and UC Drive
|
||||
- **中文**: 支持 115、123、阿里、百度、蓝奏、移动、天翼、迅雷、夸克、UC 网盘的批量重命名工具
|
||||
- **英文**: Batch rename files across 115 Drive, 123Pan, Aliyun, Baidu, Lanzou, CMCC, Esurfing, Xunlei, Quark, and UC Drive
|
||||
|
||||
### 详细描述
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
• 123 云盘 - 支持文件批量重命名
|
||||
• 阿里云盘 - 支持文件批量重命名
|
||||
• 百度网盘 - 支持文件批量重命名
|
||||
• 蓝奏云 - 支持文件批量重命名
|
||||
• 移动云盘 - 支持文件批量重命名
|
||||
• 天翼云盘 - 支持文件批量重命名
|
||||
• 迅雷云盘 - 支持文件批量重命名
|
||||
• 夸克网盘 - 支持文件批量重命名
|
||||
• UC 网盘 - 支持文件批量重命名
|
||||
|
||||
@ -73,8 +75,10 @@ A powerful batch renaming tool for cloud drives, designed to enhance file manage
|
||||
• 123Pan - Batch rename support
|
||||
• Aliyun Drive - Batch rename support
|
||||
• Baidu Cloud Drive - Batch rename support
|
||||
• Lanzou Cloud - Batch rename support
|
||||
• CMCC Drive - Batch rename support
|
||||
• Esurfing Cloud - Batch rename support
|
||||
• Xunlei Drive - Batch rename support
|
||||
• Quark Drive - Batch rename support
|
||||
• UC Drive - Batch rename support
|
||||
|
||||
@ -155,6 +159,9 @@ This project is open-sourced under MIT License. Contributions and suggestions ar
|
||||
- https://yun.139.com/* - 移动云盘页面
|
||||
- https://personal-kd-njs.yun.139.com/* - 移动云盘 API
|
||||
- https://cloud.189.cn/* - 天翼云盘页面与 API
|
||||
- https://pan.xunlei.com/* - 迅雷云盘页面
|
||||
- https://api-pan.xunlei.com/* - 迅雷云盘 API
|
||||
- https://pc.woozooo.com/* - 蓝奏云页面与 API
|
||||
- https://pan.quark.cn/* - 夸克网盘页面与 API
|
||||
- https://drive.uc.cn/* - UC 网盘页面
|
||||
- https://pan.uc.cn/* - UC 网盘页面
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
- **英文**: CloudDrive Renamer
|
||||
|
||||
### 简短描述 (不超过150字符)
|
||||
- **中文**: 支持 115、123、阿里、百度、移动、天翼、夸克、UC 网盘的批量重命名工具
|
||||
- **英文**: Batch rename files across 115 Drive, 123Pan, Aliyun, Baidu, CMCC, Esurfing, Quark, and UC Drive
|
||||
- **中文**: 支持 115、123、阿里、百度、蓝奏、移动、天翼、迅雷、夸克、UC 网盘的批量重命名工具
|
||||
- **英文**: Batch rename files across 115 Drive, 123Pan, Aliyun, Baidu, Lanzou, CMCC, Esurfing, Xunlei, Quark, and UC Drive
|
||||
|
||||
### 完整描述
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
• 123 云盘 - 支持文件批量重命名
|
||||
• 阿里云盘 - 支持文件批量重命名
|
||||
• 百度网盘 - 支持文件批量重命名
|
||||
• 蓝奏云 - 支持文件批量重命名
|
||||
• 移动云盘 - 支持文件批量重命名
|
||||
• 天翼云盘 - 支持文件批量重命名
|
||||
• 迅雷云盘 - 支持文件批量重命名
|
||||
• 夸克网盘 - 支持文件批量重命名
|
||||
• UC 网盘 - 支持文件批量重命名
|
||||
|
||||
@ -96,8 +98,10 @@ A powerful batch renaming tool for cloud drives, designed to enhance file manage
|
||||
• 123Pan - Batch rename support
|
||||
• Aliyun Drive - Batch rename support
|
||||
• Baidu Cloud Drive - Batch rename support
|
||||
• Lanzou Cloud - Batch rename support
|
||||
• CMCC Drive - Batch rename support
|
||||
• Esurfing Cloud - Batch rename support
|
||||
• Xunlei Drive - Batch rename support
|
||||
• Quark Drive - Batch rename support
|
||||
• UC Drive - Batch rename support
|
||||
|
||||
@ -169,12 +173,12 @@ Edge Add-ons允许添加搜索关键词以提高扩展的可发现性。
|
||||
|
||||
**推荐关键词(英文)**:
|
||||
```
|
||||
rename, batch rename, file rename, cloud drive, cloud storage, 115 drive, 123pan, aliyun drive, baidu cloud, quark drive, file management, bulk rename, batch operations, productivity
|
||||
rename, batch rename, file rename, cloud drive, cloud storage, 115 drive, 123pan, aliyun drive, baidu cloud, lanzou cloud, xunlei drive, quark drive, file management, bulk rename, batch operations, productivity
|
||||
```
|
||||
|
||||
**推荐关键词(中文)**:
|
||||
```
|
||||
重命名, 批量重命名, 文件重命名, 云盘, 网盘, 115网盘, 123云盘, 阿里云盘, 百度网盘, 移动云盘, 天翼云盘, 夸克网盘, UC网盘, 文件管理, 批量操作, 效率工具
|
||||
重命名, 批量重命名, 文件重命名, 云盘, 网盘, 115网盘, 123云盘, 阿里云盘, 百度网盘, 蓝奏云, 移动云盘, 天翼云盘, 迅雷云盘, 夸克网盘, UC网盘, 文件管理, 批量操作, 效率工具
|
||||
```
|
||||
|
||||
**关键词策略说明**:
|
||||
@ -244,6 +248,9 @@ rename, batch rename, file rename, cloud drive, cloud storage, 115 drive, 123pan
|
||||
| https://yun.139.com/* | 移动云盘 | 在移动云盘页面注入重命名工具界面 |
|
||||
| https://personal-kd-njs.yun.139.com/* | 移动云盘 API | 调用移动云盘 API 执行文件列表读取和重命名 |
|
||||
| https://cloud.189.cn/* | 天翼云盘 | 在天翼云盘页面注入界面并调用 API |
|
||||
| https://pan.xunlei.com/* | 迅雷云盘 | 在迅雷云盘页面注入重命名工具界面 |
|
||||
| https://api-pan.xunlei.com/* | 迅雷云盘 API | 调用迅雷云盘 API 执行文件列表读取和重命名 |
|
||||
| https://pc.woozooo.com/* | 蓝奏云 | 在蓝奏云页面注入界面并调用 API |
|
||||
| https://pan.quark.cn/* | 夸克网盘 | 在夸克网盘页面注入界面并调用 API |
|
||||
| https://drive.uc.cn/* | UC 网盘 | 在 UC 网盘页面注入重命名工具界面 |
|
||||
| https://pan.uc.cn/* | UC 网盘 | 支持 UC 网盘备用页面域名 |
|
||||
|
||||
@ -35,7 +35,7 @@ rename, batch rename, file rename, cloud drive, 115 drive, 123pan, aliyun drive,
|
||||
|
||||
虽然Edge主要使用英文关键词,但如果支持中文商店,可以考虑:
|
||||
```
|
||||
重命名, 批量重命名, 文件重命名, 云盘, 网盘, 115网盘, 123云盘, 阿里云盘, 百度网盘, 移动云盘, 天翼云盘, 夸克网盘, UC网盘, 文件管理, 批量操作, 效率工具
|
||||
重命名, 批量重命名, 文件重命名, 云盘, 网盘, 115网盘, 123云盘, 阿里云盘, 百度网盘, 蓝奏云, 移动云盘, 天翼云盘, 迅雷云盘, 夸克网盘, UC网盘, 文件管理, 批量操作, 效率工具
|
||||
```
|
||||
|
||||
### 关键词策略
|
||||
@ -399,7 +399,7 @@ rename, batch rename, file rename, cloud drive, 115 drive, 123pan, aliyun drive,
|
||||
|
||||
#### Short Description(简短描述)
|
||||
```
|
||||
支持 115、123、阿里、百度、移动、天翼、夸克、UC 网盘的批量重命名工具
|
||||
支持 115、123、阿里、百度、蓝奏、移动、天翼、迅雷、夸克、UC 网盘的批量重命名工具
|
||||
```
|
||||
|
||||
#### Long Description(详细描述)
|
||||
|
||||
@ -24,7 +24,8 @@
|
||||
"https://personal-kd-njs.yun.139.com/*",
|
||||
"https://cloud.189.cn/*",
|
||||
"https://pan.xunlei.com/*",
|
||||
"https://api-pan.xunlei.com/*"
|
||||
"https://api-pan.xunlei.com/*",
|
||||
"https://pc.woozooo.com/*"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "src/background/service-worker.ts",
|
||||
@ -113,6 +114,15 @@
|
||||
"src/content/index.ts"
|
||||
],
|
||||
"run_at": "document_idle"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://pc.woozooo.com/*"
|
||||
],
|
||||
"js": [
|
||||
"src/content/index.ts"
|
||||
],
|
||||
"run_at": "document_idle"
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
@ -130,7 +140,8 @@
|
||||
"src/adapters/123/page-script.js",
|
||||
"src/adapters/cmcc/page-script.js",
|
||||
"src/adapters/esurfing/page-script.js",
|
||||
"src/adapters/xunlei/page-script.js"
|
||||
"src/adapters/xunlei/page-script.js",
|
||||
"src/adapters/woozooo/page-script.js"
|
||||
],
|
||||
"matches": [
|
||||
"https://pan.quark.cn/*",
|
||||
@ -143,7 +154,8 @@
|
||||
"https://yun.123pan.cn/*",
|
||||
"https://yun.139.com/*",
|
||||
"https://cloud.189.cn/*",
|
||||
"https://pan.xunlei.com/*"
|
||||
"https://pan.xunlei.com/*",
|
||||
"https://pc.woozooo.com/*"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cloud-drive-renamer",
|
||||
"version": "1.5.0",
|
||||
"description": "云盘文件批量重命名工具,支持 115 网盘、123 云盘、阿里云盘、百度网盘、移动云盘、天翼云盘、迅雷云盘、夸克网盘、UC 网盘",
|
||||
"description": "云盘文件批量重命名工具,支持 115 网盘、123 云盘、阿里云盘、百度网盘、蓝奏云、移动云盘、天翼云盘、迅雷云盘、夸克网盘、UC 网盘",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "pnpm run sync:version && vite",
|
||||
@ -33,6 +33,8 @@
|
||||
"cmcc",
|
||||
"esurfing",
|
||||
"xunlei",
|
||||
"woozooo",
|
||||
"lanzou",
|
||||
"quark",
|
||||
"uc"
|
||||
],
|
||||
|
||||
@ -238,7 +238,7 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
|
||||
private applyRenameMappingToDomById(renameInfoById: Map<string, { oldName?: string; newName: string }>, root: ParentNode = document): number {
|
||||
let patched = 0;
|
||||
const nodes = Array.from(root.querySelectorAll('[data-file-id],[data-fid],[data-fileid],[data-row-key],[data-key],[data-id],[file_id]'));
|
||||
const nodes = Array.from(root.querySelectorAll('[data-file-id],[data-fid],[data-fileid],[data-row-key],[data-key],[data-id],[file_id],.f_tb[id^="f"]'));
|
||||
|
||||
for (const node of nodes) {
|
||||
const fileId =
|
||||
@ -248,13 +248,14 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
node.getAttribute('data-row-key') ||
|
||||
node.getAttribute('data-key') ||
|
||||
node.getAttribute('data-id') ||
|
||||
node.getAttribute('file_id');
|
||||
node.getAttribute('file_id') ||
|
||||
node.id?.match(/^f(\d+)$/)?.[1];
|
||||
if (!fileId) continue;
|
||||
|
||||
const info = renameInfoById.get(fileId);
|
||||
if (!info) continue;
|
||||
|
||||
const row = node.closest('tr,[role="row"],.ant-table-row,.document_table_list,.file-item,.list-item,li[rel="item"],li') || node;
|
||||
const row = node.closest('tr,[role="row"],.ant-table-row,.document_table_list,.f_tb,.file-item,.list-item,li[rel="item"],li') || node;
|
||||
patched += this.patchRowElement(row, info.oldName, info.newName);
|
||||
}
|
||||
|
||||
@ -265,7 +266,7 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
if (renameByOldName.size === 0) return 0;
|
||||
|
||||
let patched = 0;
|
||||
const nodes = Array.from(root.querySelectorAll('[class*="SourceListItem__name"],.touch-div,.document_table_list_name_text,.file-name,.filename,.name,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,[title],[aria-label]'));
|
||||
const nodes = Array.from(root.querySelectorAll('[class*="SourceListItem__name"],.f_name_title,.touch-div,.document_table_list_name_text,.file-name,.filename,.name,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,[title],[aria-label]'));
|
||||
for (const node of nodes) {
|
||||
for (const [oldName, newName] of renameByOldName.entries()) {
|
||||
patched += this.patchNameElement(node, oldName, newName);
|
||||
@ -275,7 +276,7 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
}
|
||||
|
||||
private patchRowElement(row: Element, oldName: string | undefined, newName: string): number {
|
||||
const preferredNameNode = row.querySelector('[class*="SourceListItem__name"],.touch-div,.document_table_list_name_text,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,.file-name,.filename,.name');
|
||||
const preferredNameNode = row.querySelector('[class*="SourceListItem__name"],.f_name_title,.touch-div,.document_table_list_name_text,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,.file-name,.filename,.name');
|
||||
if (preferredNameNode && oldName) {
|
||||
return this.patchStructuredNameWithinElement(preferredNameNode, oldName, newName);
|
||||
}
|
||||
@ -396,7 +397,7 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
const roots = new Set<ParentNode>();
|
||||
const ownerWindow = doc.defaultView ?? window;
|
||||
const NodeCtor = ownerWindow.Node;
|
||||
const rowSelector = 'tr,[role="row"],.ant-table-row,.document_table_list,.file-item,.list-item,li[rel="item"],li';
|
||||
const rowSelector = 'tr,[role="row"],.ant-table-row,.document_table_list,.f_tb,.file-item,.list-item,li[rel="item"],li';
|
||||
|
||||
const addNode = (node: Node | null) => {
|
||||
if (!node) return;
|
||||
@ -520,7 +521,7 @@ export abstract class SharedCloudDriveAdapter extends BasePlatformAdapter {
|
||||
|
||||
private findFilenameInRow(row: Element): string {
|
||||
return (
|
||||
row.querySelector('[class*="SourceListItem__name"],.touch-div,.document_table_list_name_text,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,.file-name,.filename,.name,[title]')?.textContent?.trim() ||
|
||||
row.querySelector('[class*="SourceListItem__name"],.f_name_title,.touch-div,.document_table_list_name_text,.table-file-name,.table-file-name-tooltip-host,.table-list-file-name,.file-name,.filename,.name,[title]')?.textContent?.trim() ||
|
||||
row.getAttribute('title') ||
|
||||
row.getAttribute('aria-label') ||
|
||||
''
|
||||
|
||||
156
src/adapters/woozooo/adapter.ts
普通文件
156
src/adapters/woozooo/adapter.ts
普通文件
@ -0,0 +1,156 @@
|
||||
import type { FileItem, PlatformConfig, PlatformName, RenameResult } from '../../types/platform';
|
||||
import { parseFileName } from '../../utils/helpers';
|
||||
import { SharedCloudDriveAdapter, type PageScriptAPI } from '../shared/shared-cloud-drive-adapter';
|
||||
import { getWoozoooPageScriptInjector } from './page-script-injector';
|
||||
|
||||
interface WoozoooFileItem {
|
||||
id?: string | number;
|
||||
name?: string;
|
||||
name_all?: string;
|
||||
size?: string | number;
|
||||
time?: string;
|
||||
}
|
||||
|
||||
interface WoozoooListResponse {
|
||||
zt?: string | number;
|
||||
info?: string | number | unknown[];
|
||||
text?: WoozoooFileItem[];
|
||||
dat?: unknown;
|
||||
}
|
||||
|
||||
interface WoozoooRenameResponse {
|
||||
zt?: string | number;
|
||||
info?: string;
|
||||
text?: unknown;
|
||||
dat?: unknown;
|
||||
}
|
||||
|
||||
export class WoozoooAdapter extends SharedCloudDriveAdapter {
|
||||
readonly platform: PlatformName = 'woozooo';
|
||||
|
||||
constructor(config?: Partial<PlatformConfig>) {
|
||||
super({ platform: 'woozooo', requestInterval: 800, maxRetries: 3, timeout: 30000, ...config });
|
||||
}
|
||||
|
||||
async getAllFiles(parentId?: string): Promise<FileItem[]> {
|
||||
const folderId = parentId ?? this.getCurrentFolderId();
|
||||
const uid = this.getUid();
|
||||
const vei = this.getVei();
|
||||
const files: FileItem[] = [];
|
||||
let page = 1;
|
||||
let hasMore = true;
|
||||
|
||||
while (hasMore) {
|
||||
const response = await this.callAPI('POST', `https://pc.woozooo.com/doupload.php?uid=${encodeURIComponent(uid)}`, {
|
||||
bodyMode: 'urlencoded',
|
||||
entries: [
|
||||
['task', '5'],
|
||||
['folder_id', folderId],
|
||||
['pg', String(page)],
|
||||
['vei', vei],
|
||||
],
|
||||
}) as WoozoooListResponse;
|
||||
|
||||
this.assertSuccessful(this.isSuccessful(response), response.zt, this.getErrorMessage(response, '蓝奏云列表获取失败'), response);
|
||||
if (!Array.isArray(response.text)) {
|
||||
throw new Error('蓝奏云列表获取失败: missing file list');
|
||||
}
|
||||
|
||||
files.push(...response.text.map((item) => this.toFileItem(item, folderId)));
|
||||
hasMore = String(response.info) !== '0' && response.text.length > 0;
|
||||
page += 1;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
async renameFile(fileId: string, newName: string): Promise<RenameResult> {
|
||||
return this.retryableRename(async () => {
|
||||
const response = await this.callAPI('POST', 'https://pc.woozooo.com/doupload.php', {
|
||||
bodyMode: 'urlencoded',
|
||||
entries: [
|
||||
['task', '46'],
|
||||
['file_id', fileId],
|
||||
['file_name', parseFileName(newName).name],
|
||||
['type', '2'],
|
||||
],
|
||||
}) as WoozoooRenameResponse;
|
||||
this.assertSuccessful(this.isSuccessful(response), response.zt, this.getErrorMessage(response, '蓝奏云重命名失败'), response);
|
||||
}, fileId, newName);
|
||||
}
|
||||
|
||||
protected getCurrentFolderId(): string {
|
||||
const doc = this.getFileFrameDocument();
|
||||
return doc?.querySelector<HTMLInputElement>('#folder_id_bibao')?.value || '-1';
|
||||
}
|
||||
|
||||
protected getPageScriptAPI(): PageScriptAPI {
|
||||
return getWoozoooPageScriptInjector();
|
||||
}
|
||||
|
||||
private toFileItem(item: WoozoooFileItem, parentId: string): FileItem {
|
||||
const name = item.name_all || item.name || '';
|
||||
const { ext } = parseFileName(name);
|
||||
return {
|
||||
id: String(item.id || ''),
|
||||
name,
|
||||
ext,
|
||||
parentId,
|
||||
size: Number(item.size ?? 0) || 0,
|
||||
mtime: this.normalizeTime(item.time),
|
||||
};
|
||||
}
|
||||
|
||||
private getFileFrameDocument(): Document | null {
|
||||
const frame = document.querySelector<HTMLIFrameElement>('#mainframe');
|
||||
try {
|
||||
return frame?.contentDocument || document;
|
||||
} catch {
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
||||
private getUid(): string {
|
||||
const frame = document.querySelector<HTMLIFrameElement>('#mainframe');
|
||||
const doc = this.getFileFrameDocument();
|
||||
const candidates = [frame?.src, doc?.location?.href, window.location.href];
|
||||
|
||||
for (const href of candidates) {
|
||||
if (!href) continue;
|
||||
try {
|
||||
const uid = new URL(href).searchParams.get('u');
|
||||
if (uid) return uid;
|
||||
} catch {
|
||||
// Ignore malformed or about:blank URLs and try the next source.
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getVei(): string {
|
||||
const win = this.getFileFrameWindow();
|
||||
const sources = [win && typeof win.more === 'function' ? String(win.more) : '', win && typeof win.folder === 'function' ? String(win.folder) : ''];
|
||||
for (const source of sources) {
|
||||
const match = source.match(/['"]vei['"]\s*:\s*['"]([^'"]+)['"]/);
|
||||
if (match?.[1]) return match[1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getFileFrameWindow(): (Window & typeof globalThis & { more?: unknown; folder?: unknown }) | null {
|
||||
const frame = document.querySelector<HTMLIFrameElement>('#mainframe');
|
||||
try {
|
||||
return (frame?.contentWindow as Window & typeof globalThis & { more?: unknown; folder?: unknown }) || window;
|
||||
} catch {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
|
||||
private isSuccessful(response: { zt?: string | number }): boolean {
|
||||
return String(response.zt) === '1';
|
||||
}
|
||||
|
||||
private getErrorMessage(response: { info?: unknown }, fallback: string): string {
|
||||
return typeof response.info === 'string' && response.info ? response.info : fallback;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import { CloudDrivePageScriptInjector } from '../shared/page-script-injector';
|
||||
|
||||
let instance: CloudDrivePageScriptInjector | null = null;
|
||||
|
||||
export function getWoozoooPageScriptInjector(): CloudDrivePageScriptInjector {
|
||||
if (!instance) {
|
||||
instance = new CloudDrivePageScriptInjector({
|
||||
requestType: 'WOOZOOO_API_REQUEST',
|
||||
responseType: 'WOOZOOO_API_RESPONSE',
|
||||
readyFlagName: '__WOOZOOO_PAGE_SCRIPT_READY__',
|
||||
datasetReadyKey: 'woozoooPageScriptReady',
|
||||
datasetTimestampKey: 'woozoooPageScriptTimestamp',
|
||||
logPrefix: 'Woozooo',
|
||||
});
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import { installCloudDrivePageScript, type PageScriptInstallOptions } from '../shared/page-script';
|
||||
|
||||
export const WOOZOOO_PAGE_SCRIPT_OPTIONS: PageScriptInstallOptions = {
|
||||
requestType: 'WOOZOOO_API_REQUEST',
|
||||
responseType: 'WOOZOOO_API_RESPONSE',
|
||||
readyFlagName: '__WOOZOOO_PAGE_SCRIPT_READY__',
|
||||
datasetReadyKey: 'woozoooPageScriptReady',
|
||||
datasetTimestampKey: 'woozoooPageScriptTimestamp',
|
||||
logPrefix: 'WoozoooPageScript',
|
||||
captureHeaders: [],
|
||||
};
|
||||
|
||||
installCloudDrivePageScript(WOOZOOO_PAGE_SCRIPT_OPTIONS);
|
||||
@ -10,6 +10,7 @@ import { Drive123Adapter } from '../adapters/123/adapter';
|
||||
import { CMCCAdapter } from '../adapters/cmcc/adapter';
|
||||
import { EsurfingAdapter } from '../adapters/esurfing/adapter';
|
||||
import { XunleiAdapter } from '../adapters/xunlei/adapter';
|
||||
import { WoozoooAdapter } from '../adapters/woozooo/adapter';
|
||||
import { storage } from '../utils/storage';
|
||||
import { STORAGE_KEYS } from '../types/stats';
|
||||
import { I18nService } from '../utils/i18n';
|
||||
@ -193,7 +194,7 @@ function cleanupOldInstances(): void {
|
||||
* 背景: @crxjs/vite-plugin 不支持在 manifest.json 中直接配置 world: "MAIN" 的 TypeScript 文件
|
||||
* 解决方案: 在 content script (ISOLATED world) 中动态创建 <script> 标签注入到页面
|
||||
*
|
||||
* @param platform - 平台名称 (aliyun/baidu/quark/uc/115/123/cmcc/esurfing)
|
||||
* @param platform - 平台名称 (aliyun/baidu/quark/uc/115/123/cmcc/esurfing/xunlei/woozooo)
|
||||
*/
|
||||
async function injectPageScriptToMainWorld(platform: PlatformName): Promise<void> {
|
||||
// ✅ 引用编译后的 .js 文件(Vite 会将 TypeScript 编译为 JavaScript)
|
||||
@ -273,6 +274,8 @@ function createPlatformAdapter(platform: PlatformName): PlatformAdapter {
|
||||
return new EsurfingAdapter();
|
||||
case 'xunlei':
|
||||
return new XunleiAdapter();
|
||||
case 'woozooo':
|
||||
return new WoozoooAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ const PLATFORM_LABELS: Record<PlatformName, string> = {
|
||||
cmcc: '移动云盘',
|
||||
esurfing: '天翼云盘',
|
||||
xunlei: '迅雷云盘',
|
||||
woozooo: '蓝奏云',
|
||||
};
|
||||
|
||||
function buildSummary(input: BuildLastFailureDiagnosticSnapshotInput): DiagnosticSummary {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"extName": "CloudDrive Renamer",
|
||||
"extDescription": "Powerful batch renaming tool for 115 Drive, 123Pan, Aliyun Drive, Baidu Cloud Drive, CMCC Drive, Esurfing Cloud, Xunlei Drive, Quark Drive, and UC Drive",
|
||||
"extDescription": "Powerful batch renaming tool for 115 Drive, 123Pan, Aliyun Drive, Baidu Cloud Drive, Lanzou Cloud, CMCC Drive, Esurfing Cloud, Xunlei Drive, Quark Drive, and UC Drive",
|
||||
"rename_dialog_title": "Batch Rename",
|
||||
"file_selector_title": "Batch Rename",
|
||||
"config_panel_title": "Configuration",
|
||||
@ -188,6 +188,7 @@
|
||||
"platform_cmcc": "CMCC Drive",
|
||||
"platform_esurfing": "Esurfing Cloud",
|
||||
"platform_xunlei": "Xunlei Drive",
|
||||
"platform_woozooo": "Lanzou Cloud",
|
||||
"popup_language_label": "Language",
|
||||
"toast_language_changed": "Language changed to $1",
|
||||
"toast_language_change_failed": "Failed to change language, please try again",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"extName": "云盘批量重命名工具",
|
||||
"extDescription": "强大的批量重命名工具,支持115网盘、123云盘、阿里云盘、百度网盘、移动云盘、天翼云盘、迅雷云盘、夸克网盘、UC网盘文件批量重命名",
|
||||
"extDescription": "强大的批量重命名工具,支持115网盘、123云盘、阿里云盘、百度网盘、蓝奏云、移动云盘、天翼云盘、迅雷云盘、夸克网盘、UC网盘文件批量重命名",
|
||||
"rename_dialog_title": "批量重命名",
|
||||
"file_selector_title": "批量重命名",
|
||||
"config_panel_title": "配置",
|
||||
@ -188,6 +188,7 @@
|
||||
"platform_cmcc": "移动云盘",
|
||||
"platform_esurfing": "天翼云盘",
|
||||
"platform_xunlei": "迅雷云盘",
|
||||
"platform_woozooo": "蓝奏云",
|
||||
"popup_language_label": "语言 / Language",
|
||||
"toast_language_changed": "语言已更改为$1",
|
||||
"toast_language_change_failed": "语言切换失败,请重试",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"extName": "雲端硬碟批次重新命名工具",
|
||||
"extDescription": "強大的批次重新命名工具,支援115網盤、123雲盤、阿里雲盤、百度雲端硬碟、移動雲盤、天翼雲盤、迅雷雲盤、夸克網盤、UC網盤檔案批次重新命名",
|
||||
"extDescription": "強大的批次重新命名工具,支援115網盤、123雲盤、阿里雲盤、百度雲端硬碟、藍奏雲、移動雲盤、天翼雲盤、迅雷雲盤、夸克網盤、UC網盤檔案批次重新命名",
|
||||
"rename_dialog_title": "批次重新命名",
|
||||
"file_selector_title": "批次重新命名",
|
||||
"config_panel_title": "設定",
|
||||
@ -188,6 +188,7 @@
|
||||
"platform_cmcc": "移動雲盤",
|
||||
"platform_esurfing": "天翼雲盤",
|
||||
"platform_xunlei": "迅雷雲盤",
|
||||
"platform_woozooo": "藍奏雲",
|
||||
"popup_language_label": "語言 / Language",
|
||||
"toast_language_changed": "語言已更改為$1",
|
||||
"toast_language_change_failed": "語言切換失敗,請重試",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 云盘平台类型
|
||||
*/
|
||||
export type PlatformName = 'quark' | 'aliyun' | 'baidu' | 'uc' | '115' | '123' | 'cmcc' | 'esurfing' | 'xunlei';
|
||||
export type PlatformName = 'quark' | 'aliyun' | 'baidu' | 'uc' | '115' | '123' | 'cmcc' | 'esurfing' | 'xunlei' | 'woozooo';
|
||||
|
||||
/**
|
||||
* 文件项接口
|
||||
|
||||
@ -123,6 +123,12 @@ export function detectPlatformFromUrl(url: string, pathname?: string): PlatformN
|
||||
return 'xunlei';
|
||||
}
|
||||
|
||||
// 蓝奏云
|
||||
if (url.includes('pc.woozooo.com')) {
|
||||
const pathToCheck = pathname ?? extractPathnameFromUrl(url);
|
||||
return pathToCheck === '/mydisk.php' ? 'woozooo' : null;
|
||||
}
|
||||
|
||||
// UC网盘
|
||||
if (url.includes('drive.uc.cn') || url.includes('pan.uc.cn')) {
|
||||
return 'uc';
|
||||
|
||||
@ -4,6 +4,7 @@ import { Drive123Adapter } from '../../../src/adapters/123/adapter';
|
||||
import { CMCCAdapter, md5 } from '../../../src/adapters/cmcc/adapter';
|
||||
import { EsurfingAdapter } from '../../../src/adapters/esurfing/adapter';
|
||||
import { XunleiAdapter } from '../../../src/adapters/xunlei/adapter';
|
||||
import { WoozoooAdapter } from '../../../src/adapters/woozooo/adapter';
|
||||
import { getDrive115PageScriptInjector } from '../../../src/adapters/115/page-script-injector';
|
||||
import { getDrive123PageScriptInjector } from '../../../src/adapters/123/page-script-injector';
|
||||
import { getCMCCPageScriptInjector } from '../../../src/adapters/cmcc/page-script-injector';
|
||||
@ -11,6 +12,8 @@ import { CMCC_PAGE_SCRIPT_OPTIONS } from '../../../src/adapters/cmcc/page-script
|
||||
import { getEsurfingPageScriptInjector } from '../../../src/adapters/esurfing/page-script-injector';
|
||||
import { getXunleiPageScriptInjector } from '../../../src/adapters/xunlei/page-script-injector';
|
||||
import { XUNLEI_PAGE_SCRIPT_OPTIONS } from '../../../src/adapters/xunlei/page-script';
|
||||
import { getWoozoooPageScriptInjector } from '../../../src/adapters/woozooo/page-script-injector';
|
||||
import { WOOZOOO_PAGE_SCRIPT_OPTIONS } from '../../../src/adapters/woozooo/page-script';
|
||||
|
||||
vi.mock('../../../src/adapters/115/page-script-injector', () => ({
|
||||
getDrive115PageScriptInjector: vi.fn(),
|
||||
@ -32,12 +35,17 @@ vi.mock('../../../src/adapters/xunlei/page-script-injector', () => ({
|
||||
getXunleiPageScriptInjector: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../../src/adapters/woozooo/page-script-injector', () => ({
|
||||
getWoozoooPageScriptInjector: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('missing platform adapters', () => {
|
||||
let mock115CallAPI: Mock;
|
||||
let mock123CallAPI: Mock;
|
||||
let mockCMCCCallAPI: Mock;
|
||||
let mockEsurfingCallAPI: Mock;
|
||||
let mockXunleiCallAPI: Mock;
|
||||
let mockWoozoooCallAPI: Mock;
|
||||
|
||||
beforeEach(() => {
|
||||
mock115CallAPI = vi.fn();
|
||||
@ -45,12 +53,14 @@ describe('missing platform adapters', () => {
|
||||
mockCMCCCallAPI = vi.fn();
|
||||
mockEsurfingCallAPI = vi.fn();
|
||||
mockXunleiCallAPI = vi.fn();
|
||||
mockWoozoooCallAPI = vi.fn();
|
||||
|
||||
vi.mocked(getDrive115PageScriptInjector).mockReturnValue({ callAPI: mock115CallAPI });
|
||||
vi.mocked(getDrive123PageScriptInjector).mockReturnValue({ callAPI: mock123CallAPI });
|
||||
vi.mocked(getCMCCPageScriptInjector).mockReturnValue({ callAPI: mockCMCCCallAPI });
|
||||
vi.mocked(getEsurfingPageScriptInjector).mockReturnValue({ callAPI: mockEsurfingCallAPI });
|
||||
vi.mocked(getXunleiPageScriptInjector).mockReturnValue({ callAPI: mockXunleiCallAPI });
|
||||
vi.mocked(getWoozoooPageScriptInjector).mockReturnValue({ callAPI: mockWoozoooCallAPI });
|
||||
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
@ -214,6 +224,73 @@ describe('missing platform adapters', () => {
|
||||
]));
|
||||
});
|
||||
|
||||
it('uses Woozooo APIs from the same-origin file iframe and preserves server-managed extensions', async () => {
|
||||
const adapter = new WoozoooAdapter({ requestInterval: 0 });
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.id = 'mainframe';
|
||||
iframe.src = 'https://pc.woozooo.com/mydisk.php?item=files&action=index&u=484561';
|
||||
document.body.appendChild(iframe);
|
||||
const frameDoc = iframe.contentDocument!;
|
||||
frameDoc.open();
|
||||
frameDoc.write(`
|
||||
<input id="folder_id_bibao" value="8006795" />
|
||||
<script>function more(folder_id){ $.ajax({ data: { 'task':5,'folder_id':folder_id,'pg':pgs,'vei':'B1VQUgNRAw9TBFdW' } }); }</script>
|
||||
`);
|
||||
frameDoc.close();
|
||||
|
||||
mockWoozoooCallAPI
|
||||
.mockResolvedValueOnce({
|
||||
zt: 1,
|
||||
info: 1,
|
||||
text: [{ id: '308207718', name: '未命名项目-图层 1.png', name_all: '未命名项目-图层 1.png', size: '246.6 K', time: '3 分钟前' }],
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
zt: 1,
|
||||
info: 1,
|
||||
text: [{ id: '308207716', name: '数字键盘.jpg', name_all: '数字键盘.jpg', size: '68.2 K', time: '3 分钟前' }],
|
||||
})
|
||||
.mockResolvedValueOnce({ zt: 1, info: 0, text: [] })
|
||||
.mockResolvedValueOnce({ zt: 1, info: '新名称' });
|
||||
|
||||
const files = await adapter.getAllFiles();
|
||||
const rename = await adapter.renameFile('308207718', '新名称.png');
|
||||
|
||||
expect(files).toHaveLength(2);
|
||||
expect(files[0]).toMatchObject({ id: '308207718', name: '未命名项目-图层 1.png', ext: '.png', parentId: '8006795', size: 0 });
|
||||
expect(files[1]).toMatchObject({ id: '308207716', name: '数字键盘.jpg', ext: '.jpg', parentId: '8006795', size: 0 });
|
||||
expect(rename).toEqual({ success: true, newName: '新名称.png' });
|
||||
expect(mockWoozoooCallAPI).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'POST',
|
||||
'https://pc.woozooo.com/doupload.php?uid=484561',
|
||||
{
|
||||
bodyMode: 'urlencoded',
|
||||
entries: [
|
||||
['task', '5'],
|
||||
['folder_id', '8006795'],
|
||||
['pg', '1'],
|
||||
['vei', 'B1VQUgNRAw9TBFdW'],
|
||||
],
|
||||
},
|
||||
30000
|
||||
);
|
||||
expect(mockWoozoooCallAPI).toHaveBeenNthCalledWith(
|
||||
4,
|
||||
'POST',
|
||||
'https://pc.woozooo.com/doupload.php',
|
||||
{
|
||||
bodyMode: 'urlencoded',
|
||||
entries: [
|
||||
['task', '46'],
|
||||
['file_id', '308207718'],
|
||||
['file_name', '新名称'],
|
||||
['type', '2'],
|
||||
],
|
||||
},
|
||||
30000
|
||||
);
|
||||
});
|
||||
|
||||
it('uses Xunlei APIs for listing and rename', async () => {
|
||||
const adapter = new XunleiAdapter({ requestInterval: 0 });
|
||||
Object.defineProperty(window, 'location', {
|
||||
@ -264,6 +341,10 @@ describe('missing platform adapters', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('uses no special captured headers for Woozooo page-script requests', () => {
|
||||
expect(WOOZOOO_PAGE_SCRIPT_OPTIONS.captureHeaders ?? []).toEqual([]);
|
||||
});
|
||||
|
||||
it('throws instead of returning an empty list when Xunlei list API fails', async () => {
|
||||
const adapter = new XunleiAdapter({ requestInterval: 0 });
|
||||
mockXunleiCallAPI.mockResolvedValue({ error: 'bad_request', error_description: 'list failed' });
|
||||
@ -567,6 +648,25 @@ describe('missing platform adapters', () => {
|
||||
expect(querySelectorAll).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('patches Woozooo iframe rows with f_name_title nodes after rename', async () => {
|
||||
const adapter = new WoozoooAdapter({ requestInterval: 0 });
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.id = 'mainframe';
|
||||
document.body.appendChild(iframe);
|
||||
const frameDoc = iframe.contentDocument!;
|
||||
frameDoc.body.innerHTML = `
|
||||
<div id="f308207718" class="f_tb">
|
||||
<div class="f_name"><span class="f_name_title" id="filename308207718">旧名称.png</span></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const result = await adapter.syncAfterRename([{ fileId: '308207718', oldName: '旧名称.png', newName: '新名称.png' }]);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.method).toBe('dom-patch');
|
||||
expect(frameDoc.querySelector('#filename308207718')?.textContent).toBe('新名称.png');
|
||||
});
|
||||
|
||||
it('patches visible rows for new adapters instead of reporting unsupported sync', async () => {
|
||||
document.body.innerHTML = `
|
||||
<table>
|
||||
|
||||
@ -45,6 +45,16 @@ describe('manifest platform matches', () => {
|
||||
expect(webAccessibleMatches).toContain('https://pan.xunlei.com/*');
|
||||
});
|
||||
|
||||
it('injects Woozooo UI on pc.woozooo.com and allows its same-origin API', () => {
|
||||
const manifest = loadManifest();
|
||||
const contentScriptMatches = manifest.content_scripts?.flatMap((script) => script.matches ?? []) ?? [];
|
||||
const webAccessibleMatches = manifest.web_accessible_resources?.flatMap((resource) => resource.matches ?? []) ?? [];
|
||||
|
||||
expect(manifest.host_permissions).toContain('https://pc.woozooo.com/*');
|
||||
expect(contentScriptMatches).toContain('https://pc.woozooo.com/*');
|
||||
expect(webAccessibleMatches).toContain('https://pc.woozooo.com/*');
|
||||
});
|
||||
|
||||
it('injects CMCC UI on yun.139.com and allows its API host', () => {
|
||||
const manifest = loadManifest();
|
||||
const contentScriptMatches = manifest.content_scripts?.flatMap((script) => script.matches ?? []) ?? [];
|
||||
|
||||
@ -242,6 +242,22 @@ describe('Platform Detection - Unified Utils', () => {
|
||||
expect(result).toBe('cmcc');
|
||||
});
|
||||
|
||||
it('should detect Woozooo Drive on the top-level file manager page', () => {
|
||||
const result = detectPlatformFromUrl(
|
||||
'https://pc.woozooo.com/mydisk.php',
|
||||
'/mydisk.php'
|
||||
);
|
||||
expect(result).toBe('woozooo');
|
||||
});
|
||||
|
||||
it('should detect Woozooo Drive on the same-origin file iframe page', () => {
|
||||
const result = detectPlatformFromUrl(
|
||||
'https://pc.woozooo.com/mydisk.php?item=files&action=index&u=484561',
|
||||
'/mydisk.php'
|
||||
);
|
||||
expect(result).toBe('woozooo');
|
||||
});
|
||||
|
||||
it('should detect Xunlei Drive', () => {
|
||||
const result = detectPlatformFromUrl(
|
||||
'https://pan.xunlei.com/',
|
||||
|
||||
@ -18,6 +18,7 @@ export default defineConfig({
|
||||
'page-script-cmcc': 'src/adapters/cmcc/page-script.ts',
|
||||
'page-script-esurfing': 'src/adapters/esurfing/page-script.ts',
|
||||
'page-script-xunlei': 'src/adapters/xunlei/page-script.ts',
|
||||
'page-script-woozooo': 'src/adapters/woozooo/page-script.ts',
|
||||
},
|
||||
output: {
|
||||
entryFileNames: (chunkInfo) => {
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户