catpaw-drive-core 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +207 -82
- package/dist/rex-build.cjs +1 -0
- package/dist/rex-build.d.ts +4 -0
- package/dist/rex-build.js +1 -0
- package/examples/drive-core-module/README.md +16 -0
- package/examples/drive-core-module/build.mjs +20 -0
- package/examples/drive-core-module/package.json +8 -0
- package/examples/drive-core-module/runtime.js +41 -0
- package/package.json +12 -15
- package/dist/drive-core.global.js +0 -1
- package/dist/index.cjs +0 -1
- package/dist/index.d.ts +0 -51
- package/dist/index.js +0 -1
package/README.md
CHANGED
|
@@ -1,124 +1,249 @@
|
|
|
1
|
-
# catpaw-drive-core
|
|
1
|
+
# catpaw-drive-core 1.0.0:Rex 外部模块开发接入指南
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
新模块使用 `catpaw-drive-core/rex-build`。npm 包在 Node.js 构建时生成网盘引擎表达式,嵌入最终 Rex 单文件;Rex 执行时直接使用宿主的词法 `Widget`,无需安装 npm、联网下载 core 或执行 eval。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
开发者负责自己的资源来源:网站搜索、详情、分享地址和网站登录。引擎负责九盘分享解析、目录、分集匹配、取链、播放头、通用网盘账号与配置。**安装 core 不会自动获得某个网站的资源搜索接口。**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
适用版本:npm 包 **1.0.0**,内置 Rex 引擎标识 **2.2.4**。唯一代码入口为 `/rex-build`。旧 SDK 根入口、浏览器全局文件及 createDriveCore API 已删除;直接 import/require 包根路径会报不支持。包版本以 npm/package.json 为准,`engineVersion` 为引擎版本。
|
|
8
|
+
|
|
9
|
+
## 1. 安装与构建
|
|
10
|
+
|
|
11
|
+
需要 Node.js 18+;CatPaw 自身工程构建要求 Node.js 22+。请锁定版本并提交 lockfile:
|
|
8
12
|
|
|
9
13
|
```sh
|
|
10
|
-
npm install catpaw-drive-core@
|
|
14
|
+
npm install --save-dev --save-exact catpaw-drive-core@1.0.0
|
|
11
15
|
```
|
|
12
16
|
|
|
17
|
+
构建脚本使用 ESM:
|
|
18
|
+
|
|
13
19
|
```js
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
namespace: '
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// 共享账号入口由调用方选择,核心通过 getConfig 获取只读快照。
|
|
23
|
-
getConfig() {
|
|
24
|
-
try {
|
|
25
|
-
const raw = Widget.sharedCache.get('catpaw.drive-accounts.v1', 'credentials');
|
|
26
|
-
return typeof raw === 'string' ? JSON.parse(raw) : null;
|
|
27
|
-
} catch { return null; }
|
|
28
|
-
},
|
|
20
|
+
import {renderRexEngine, engineVersion} from 'catpaw-drive-core/rex-build';
|
|
21
|
+
|
|
22
|
+
const expression = renderRexEngine({
|
|
23
|
+
namespace: 'example.demo.pan',
|
|
24
|
+
linkPrefix: 'demopan:',
|
|
25
|
+
idPrefix: 'demo-pan-',
|
|
26
|
+
title: '我的网盘资源',
|
|
27
|
+
site: 'https://example.invalid', // 换成自己网站的实际 origin
|
|
29
28
|
});
|
|
29
|
+
// expression 是 JavaScript 表达式字符串,构建时写入脚本,不要 JSON.stringify(expression)。
|
|
30
|
+
const output = 'var WidgetMetadata = ' + JSON.stringify(metadata) + ';\n'
|
|
31
|
+
+ 'var DriveEngine = ' + expression + ';\n'
|
|
32
|
+
+ runtimeSource;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
CommonJS 同样可用:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
const {renderRexEngine} = require('catpaw-drive-core/rex-build');
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
配置约束:
|
|
42
|
+
|
|
43
|
+
| 字段 | 规则与作用 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| namespace | 仅小写字母、数字、点;每个模块唯一,用于本模块原引擎的缓存命名空间 |
|
|
46
|
+
| linkPrefix | **七个小写字母加冒号,总长度 8**,例如 `demopan:`;每个模块唯一 |
|
|
47
|
+
| idPrefix | 仅小写字母和连字符,例如 `demo-pan-` |
|
|
48
|
+
| title | 模块显示标题;对外作者信息由外层 WidgetMetadata 设置 |
|
|
49
|
+
| site | 自己网站 origin;示例占位域名不能作为真实搜索服务 |
|
|
30
50
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
对外发布后保持 metadata.id、namespace、linkPrefix、idPrefix 稳定,保留历史链接。外层只声明一份自己的 `WidgetMetadata`,不要再追加全盘模块元数据。生成引擎中的元数据在 IIFE 内部。不要把词法 `Widget` 改为依赖 `globalThis.Widget`。
|
|
52
|
+
|
|
53
|
+
npm 包随附完整示例 `examples/drive-core-module/`。复制到独立工程后执行 `npm install && npm run build`,产物是 `dist/demo.js`。示例由使用者输入片名、年份和分享地址,可搜索、展示分集及从 TMDB 匹配播放;它没有虚构的网站 API。接入实际网站时替换其 discovery。
|
|
54
|
+
|
|
55
|
+
## 2. 必须注册 TMDB 资源入口
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
var WidgetMetadata = {
|
|
59
|
+
id: 'example.demo.pan', title: '我的网盘资源', author: 'YourName',
|
|
60
|
+
version: '1.0.0', requiredVersion: '0.0.1', detailCacheDuration: 1800,
|
|
61
|
+
globalParams: [],
|
|
62
|
+
search: {title: '搜索', functionName: 'search', params: [
|
|
63
|
+
{name: 'keyword', title: '关键词', type: 'input', value: ''}
|
|
64
|
+
]},
|
|
65
|
+
modules: [{
|
|
66
|
+
id: 'loadResource', title: '加载网盘资源', functionName: 'loadResource',
|
|
67
|
+
type: 'stream', cacheDuration: 0, params: []
|
|
68
|
+
}]
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Rex 从 NightFrame / TMDB 进入影视时调用 `loadResource(params)`。只实现 `search`、`loadDetail` 或普通 list 入口,无法完成自动资源加载。模块必须启用;最终打包文件必须包含全局 `loadResource` 函数。
|
|
73
|
+
|
|
74
|
+
典型输入(原样透传宿主其他字段及 signal):
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
{
|
|
78
|
+
title: '三体', seriesName: '三体', type: 'tv', year: 2023,
|
|
79
|
+
tmdbId: 204541, season: 1, episode: 15
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
电影使用 `type: 'movie'`;剧集必须有有效 episode,season 缺省为 1。不要补成其他剧集,也不要仅凭关键词接受年份冲突的资源。
|
|
84
|
+
|
|
85
|
+
## 3. 运行时引擎 API
|
|
86
|
+
|
|
87
|
+
`DriveEngine` 为前述表达式的运行结果;它没有 npm import。以下为 1.0.0 的公开接入方法:
|
|
88
|
+
|
|
89
|
+
| 方法 | 作用 |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| bind(params) | **每个 search / loadDetail / loadResource 调用开始时执行**,绑定参数并读取当前账号;不要仅在初始化时调用 |
|
|
92
|
+
| parseShare({url, password?, note?}) | 有效时返回标准分享描述,无效返回 null;由引擎识别网盘及提取码 |
|
|
93
|
+
| enabled(provider) | 当前通用开关是否允许该盘 |
|
|
94
|
+
| encode(info) / decode(link) / isLink(link) | 生成、读取和识别本模块持久链接;不要自行拼接编码格式 |
|
|
95
|
+
| matchesSiteTitle(title, params) | 校验网站片名与本次目标 |
|
|
96
|
+
| prepareDirectoryIdentity(year, params) | **异步**年份/季度身份判断,返回 boolean;false 时舍弃该候选 |
|
|
97
|
+
| candidateLimit() | 当前每盘候选数量配置 |
|
|
98
|
+
| loadDetail(link) | detail 链接返回详情及 episodeItems;play 链接返回带 videoUrl/headers 的播放项数组 |
|
|
99
|
+
| loadResource(params, discovery?) | 资源匹配和取链,返回包含 url 的资源数组;原样返回以保留头、画质和字幕等字段 |
|
|
100
|
+
| owner() | 当前资源匹配任务的取消/截止时间上下文 |
|
|
101
|
+
| request(spec, requestFn, owner) | 在该上下文内调度网站请求,限制 timeoutMs 并检查失效 |
|
|
102
|
+
| clear() | 原引擎目录/相关缓存清理入口;网站自身缓存需开发者一起清理 |
|
|
103
|
+
|
|
104
|
+
provider 为 `quark`、`baidu`、`115`、`uc`、`123`、`xunlei`、`guangya`、`yidong`、`tianyi`。
|
|
105
|
+
|
|
106
|
+
详情跳转应保留引擎生成的分集 link,播放时重新解析为新鲜 URL;不要把临时下载地址当永久历史链接,不要丢弃 `headers` / `customHeaders`。分集封面可由网站适配器补齐 coverUrl、posterPath、backdropPath。
|
|
107
|
+
|
|
108
|
+
### 网站 discovery 契约
|
|
109
|
+
|
|
110
|
+
`engine.isLink(params.link)` 为 true 时走已有网盘链接;其余 TMDB 调用**必须传入 discovery**。遗漏时会进入引擎原全盘搜索路径,不能将自己的网站 origin 当作该协议接口。
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
async function loadResource(params = {}) {
|
|
114
|
+
DriveEngine.bind(params);
|
|
115
|
+
if (DriveEngine.isLink(params.link)) return DriveEngine.loadResource(params);
|
|
116
|
+
const discovery = {
|
|
117
|
+
identity: 'my-site:v1:public', // 域名/站点账户身份改变时也要改变;不要放明文凭据
|
|
118
|
+
async search(query) {
|
|
119
|
+
// 由你实现 websiteSearch;网站请求在 engine.owner() 的预算中执行。
|
|
120
|
+
const titles = await websiteSearch(query.keyword, DriveEngine.owner());
|
|
121
|
+
const rows = [];
|
|
122
|
+
for (const item of titles) {
|
|
123
|
+
if (!DriveEngine.matchesSiteTitle(item.title, query)) continue;
|
|
124
|
+
if (!await DriveEngine.prepareDirectoryIdentity(item.year, query)) continue;
|
|
125
|
+
for (const ref of item.shareReferences) {
|
|
126
|
+
if (!DriveEngine.enabled(ref.provider)) continue;
|
|
127
|
+
rows.push({
|
|
128
|
+
id: item.id + ':' + ref.id, cpSiteCardId: item.id,
|
|
129
|
+
type: 'url', title: item.title, provider: ref.provider,
|
|
130
|
+
link: DriveEngine.encode({action:'detail', title:item.title,
|
|
131
|
+
site:origin, shares:[], siteRef:ref.id})
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return rows;
|
|
136
|
+
},
|
|
137
|
+
async read(row) {
|
|
138
|
+
const info = DriveEngine.decode(row.link);
|
|
139
|
+
const url = await websiteShareUrl(info.siteRef, DriveEngine.owner());
|
|
140
|
+
const share = DriveEngine.parseShare({url});
|
|
141
|
+
if (!share || share.provider !== row.provider) return null;
|
|
142
|
+
return {action:'detail', title:info.title, site:origin, shares:[share]};
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
return DriveEngine.loadResource(params, discovery);
|
|
42
146
|
}
|
|
43
147
|
```
|
|
44
148
|
|
|
45
|
-
|
|
149
|
+
上面 `websiteSearch`、`websiteShareUrl`、`origin` 由具体网站实现,不能直接运行;包内分享示例无需这些占位函数。`cpSiteCardId` 标识同一个网站影视条目,`id` 区分分享。search 返回未取分享的候选,read 在引擎调度时再解引用;保持原网站顺序,不要先 Promise.all 获取所有分享、预先转存或预先取全部播放地址。
|
|
46
150
|
|
|
47
|
-
|
|
151
|
+
网站请求形态:
|
|
48
152
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
153
|
+
```js
|
|
154
|
+
const response = await DriveEngine.request(
|
|
155
|
+
{url, method:'GET', timeoutMs:10000},
|
|
156
|
+
spec => Widget.http.request(spec),
|
|
157
|
+
DriveEngine.owner()
|
|
158
|
+
);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
此处需要宿主支持 `Widget.http.request` 且正确实现 timeoutMs。只有 get/post 的宿主需自己映射参数和响应,不能盲目替换为 fetch。网站请求默认不要携带网盘 Cookie。网站登录、验证码和站点限流属于网站适配器职责。
|
|
56
162
|
|
|
57
|
-
|
|
163
|
+
## 4. 直接使用 CatPaw 通用配置
|
|
58
164
|
|
|
59
|
-
|
|
165
|
+
正式通用域:
|
|
60
166
|
|
|
61
|
-
|
|
167
|
+
```js
|
|
168
|
+
const raw = Widget.sharedCache.get('catpaw.drive-accounts.v1', 'credentials');
|
|
169
|
+
```
|
|
62
170
|
|
|
63
|
-
|
|
171
|
+
返回值为**同步 JSON 字符串**,未保存或宿主不支持时可能缺失或抛错。它不是对象,也不是 Promise。完整示例字符串解析后的内容如下(所有凭据都是占位值):
|
|
64
172
|
|
|
65
173
|
```json
|
|
66
174
|
{
|
|
67
175
|
"schemaVersion": 1,
|
|
68
176
|
"revision": 1,
|
|
69
|
-
"quarkCookie": "",
|
|
70
|
-
"baiduCookie": "",
|
|
71
|
-
"cookie115": "",
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"tianyiCookie": "",
|
|
75
|
-
"
|
|
177
|
+
"quarkCookie": "QUARK_COOKIE",
|
|
178
|
+
"baiduCookie": "BDUSS=BAIDU_COOKIE",
|
|
179
|
+
"cookie115": "UID=115_COOKIE",
|
|
180
|
+
"xunleiAuth": "{\"accessToken\":\"XUNLEI_ACCESS\",\"refreshToken\":\"XUNLEI_REFRESH\",\"deviceId\":\"XUNLEI_DEVICE\"}",
|
|
181
|
+
"guangyaAuth": "{\"accessToken\":\"GUANGYA_ACCESS\",\"refreshToken\":\"GUANGYA_REFRESH\",\"deviceId\":\"GUANGYA_DEVICE\"}",
|
|
182
|
+
"tianyiCookie": "TIANYI_COOKIE",
|
|
183
|
+
"quarkQuality": "auto",
|
|
184
|
+
"resourceCategory": "",
|
|
185
|
+
"maxShareCandidates": "2",
|
|
186
|
+
"indexTimeoutSeconds": "10",
|
|
187
|
+
"driveQuarkEnabled": "enabled",
|
|
188
|
+
"driveBaiduEnabled": "enabled",
|
|
189
|
+
"driveUcEnabled": "enabled",
|
|
190
|
+
"drive115Enabled": "enabled",
|
|
191
|
+
"drive123Enabled": "enabled",
|
|
192
|
+
"driveXunleiEnabled": "disabled",
|
|
193
|
+
"driveGuangyaEnabled": "disabled",
|
|
194
|
+
"driveYidongEnabled": "disabled",
|
|
195
|
+
"driveTianyiEnabled": "disabled",
|
|
196
|
+
"transferAutoCleanup": "disabled",
|
|
197
|
+
"candidateFailureFallback": "enabled"
|
|
76
198
|
}
|
|
77
199
|
```
|
|
78
200
|
|
|
79
|
-
|
|
201
|
+
即 `raw === JSON.stringify(上面对象)`。**光鸭、迅雷 UI 各有三个独立输入字段,但共享快照仍分别只用 guangyaAuth / xunleiAuth 一个字符串承载整套凭据。** 不是六个顶层字段,也不是两个对象。只填访问令牌时可为原始令牌字符串;历史 JSON 凭据可能含其他字段,应原样保留。外层 JSON.parse 一次后,只有要查看套内字段时才尝试再次解析 Auth 字符串。
|
|
80
202
|
|
|
81
|
-
|
|
203
|
+
| 配置 | 值与默认行为 |
|
|
204
|
+
| --- | --- |
|
|
205
|
+
| schemaVersion / revision | 数字 1 / 正安全整数;revision 随发布共享配置更新,不作为时间戳 |
|
|
206
|
+
| 六个账号字段 | 字符串;空字符串表示未配置。UC、123、移动当前使用免登录路径,没有对应 Cookie 输入 |
|
|
207
|
+
| 九盘 Enabled | 字符串 `enabled` / `disabled`;夸克、百度、115、UC、123 默认开,其余默认关 |
|
|
208
|
+
| quarkQuality | `auto` / `origin` / `transcode`,默认 auto |
|
|
209
|
+
| resourceCategory | `''` / `8k` / `4k` / `1080p` / `other`,仅控制展示分类,不提升视频分辨率 |
|
|
210
|
+
| maxShareCandidates | 字符串 `1` / `2` / `3` / `5`,默认 `2` |
|
|
211
|
+
| indexTimeoutSeconds | 5~30 的整数字符串,默认 `10`;保留10秒预算,不通过重构自动延长 |
|
|
212
|
+
| candidateFailureFallback | enabled / disabled,默认 enabled;提取失败时每盘最多候补一次 |
|
|
213
|
+
| transferAutoCleanup | enabled / disabled,默认 disabled;开启会清理夸克、迅雷、光鸭超2小时未用的转存文件,并清空对应账号整个回收站 |
|
|
82
214
|
|
|
83
|
-
|
|
215
|
+
`renderRexEngine` 已包含读取、校验、继承及失效处理,通常只需 `bind(params)`;**不要再手动 JSON.parse 后覆盖 params 所有字段**,否则容易破坏本地覆盖规则及配置变更检查。
|
|
84
216
|
|
|
85
|
-
|
|
217
|
+
需要仅接入共享配置、继续用自己网盘实现的模块,可以只读此 JSON,但必须自己实现字段校验、缺失处理、账号变更导致的缓存/在途任务失效和全部网盘协议。诊断时只展示“已配置/未配置”与 revision,不打印 raw、Cookie、令牌或带提取码的内部链接。读取后验证 schemaVersion、revision;不支持的 schema 应报不支持,不能当作其他账号格式继续取链。
|
|
86
218
|
|
|
87
|
-
|
|
219
|
+
使用者步骤:安装正式“猫 · 通用配置”→填写账号和开关→执行“保存/更新共享配置”,或搜索 **“保存账号”**。仅保存输入表单不代表已发布共享快照。共享范围是当前 Rex 宿主环境;不保证自动跨设备同步。外部模块不能覆盖作者的共享配置,只读继承即可。
|
|
88
220
|
|
|
89
|
-
|
|
90
|
-
|---|---|
|
|
91
|
-
| `bind(params)` | 绑定当前模块配置和账号 |
|
|
92
|
-
| `enabled(provider)` | 查询网盘开关 |
|
|
93
|
-
| `parseShare({url,password?,note?})` | 识别分享;失败返回 null |
|
|
94
|
-
| `encode(descriptor)` / `decode(link)` | 编解码当前引擎资源描述 |
|
|
95
|
-
| `isLink(link)` | 判断是否当前资源链接前缀 |
|
|
96
|
-
| `loadDetail(link)` | 读取分享目录和分集;播放描述可能返回资源数组 |
|
|
97
|
-
| `loadResource(params, discovery?)` | 解析播放资源;自动选集可传 seriesName、type、year、season、episode |
|
|
98
|
-
| `clear()` | 清理当前模块的目录缓存 |
|
|
99
|
-
| `candidateLimit()` | 查询当前候选档位 |
|
|
100
|
-
| `matchesSiteTitle(title, params)` | 使用共享标题匹配规则 |
|
|
101
|
-
| `prepareDirectoryIdentity(year, params)` | 准备可信年份信息 |
|
|
102
|
-
| `owner()` / `request(spec, request, owner?)` | 网站适配器共享当前预算与取消检查 |
|
|
221
|
+
### 本地覆盖与 Beta 隔离
|
|
103
222
|
|
|
104
|
-
|
|
223
|
+
示例默认只使用共享账号。若需要本模块覆盖,在 metadata 添加 `credentialSource`(shared/local)及与通用配置同名的输入项,原样传给 `bind(params)`。
|
|
105
224
|
|
|
106
|
-
|
|
225
|
+
- `shared`:普通 Cookie 本地非空优先,空值继承共享。
|
|
226
|
+
- 光鸭本地三项 `guangyaAuth` / `guangyaRefreshToken` / `guangyaDeviceId`,迅雷本地三项 `xunleiAuth` / `xunleiRefreshToken` / `xunleiDeviceId`:任一非空就以**整套本地值**为准,不能与共享字段逐项混合;三项全空才继承共享。
|
|
227
|
+
- `credentialSource:'local'`:不继承共享账号,但通用网盘开关仍生效,不应据此承诺所有配置隔离。
|
|
228
|
+
- Beta 共享域是 `catpaw.beta.drive-accounts.v1`,与正式域分开。1.0.0 通用 renderer 默认正式域;CatPaw 的 Beta 构建另有整体身份/命名空间变换。仅改 namespace 不会自动切换共享账号域,外部模块不要擅自同时读取两域或静默回退。
|
|
107
229
|
|
|
108
|
-
|
|
230
|
+
## 5. 行为保持与迁移范围
|
|
109
231
|
|
|
110
|
-
-
|
|
111
|
-
- `search(params)`:返回含 `title`、`provider` 和 `link` 的候选条目;link 可用 `core.encode(descriptor)` 生成。
|
|
112
|
-
- `read(row, params)`:返回包含 title、shares 的 `action: 'detail'` 描述或 null。
|
|
232
|
+
1.0.0 的 `/rex-build` 来自原 Rex 引擎,保留词法 Widget、原缓存语义、账号读取、链接、转存目录、取消检查及资源匹配预算。仅按作者要求移除固定日历使用期限;令牌和临时播放地址的自然过期仍有效。
|
|
113
233
|
|
|
114
|
-
|
|
234
|
+
引擎继续使用原转存目录策略(含 `ftv-cache`),不承诺每个 namespace 都独占远端文件夹。namespace 隔离模块本地键,通用账号跨模块共享。不要随意修改输出字符串里的存储键、目录、并发、排序和函数位置。
|
|
115
235
|
|
|
116
|
-
|
|
236
|
+
`renderDriveModule(siteId, template)` 供 CatPaw 已有站点的固定槽位迁移,接受的布局限定于包内快照;**它不是外部新网站注册接口**。外部新开发使用 renderRexEngine。将旧模块改为新引擎时,需迁移其旧 link/缓存契约;不能假设任意旧模块的 id、链接和行为会自动兼容。
|
|
117
237
|
|
|
118
|
-
|
|
238
|
+
已有17个 CatPaw Beta 的整文件输出与冻结原版逐字节比对通过(仅移除日历期限)。同一引擎已在 NightFrame → TMDB《嫁金钗》S1E15 展示资源卡片并播放验证。该证据覆盖这些模块和当时网络条件;外部网站适配器仍需验证自己的搜索、账号和真实播放。
|
|
119
239
|
|
|
120
|
-
|
|
240
|
+
## 6. 发布前检查
|
|
121
241
|
|
|
122
|
-
|
|
242
|
+
1. 独立目录安装锁定的公共 npm 包,构建单文件;不要依赖 CatPaw 私有源码或工作区路径。
|
|
243
|
+
2. Rex 中启用模块并保存正式通用配置;先用 UC 免登录分享验证目录,再验证自己的网盘账号。
|
|
244
|
+
3. 验证搜索→详情→分集→播放;重新进入运行环境后旧分集 link 仍能取新 URL,播放头保留。
|
|
245
|
+
4. 从 NightFrame / TMDB 进入同名同年份影视,验证电影及剧集季集,确认真正调用 stream loadResource;错误片名、年份、季集不出错误资源。
|
|
246
|
+
5. 验证10秒预算、取消、切账号、禁用网盘、改通用配置、清缓存、冷/热目录、分享失效等场景;不得把全部异常吞成空数组。
|
|
247
|
+
6. 保留既有模块身份和资源下载地址,原安装项更新。以后升级 core 时重新生成并比较产物;npm 升级本身不会修改已安装的 Rex 单文件。
|
|
123
248
|
|
|
124
|
-
|
|
249
|
+
包以混淆产物公开分发,无 source map;混淆不等同于加密,也不应用来隐藏凭据。当前 package.json 沿用 `UNLICENSED`,公开下载不等同于授予开源许可,外部分发授权请与作者确认。
|