dsh-napcat-keeper 2.8.0 → 2.8.1
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/CHANGELOG.md +21 -0
- package/README.md +40 -4
- package/lib/client.js +59 -3
- package/lib/index.js +610 -23
- package/package.json +2 -1
- package/scripts/selftest-companion.mjs +488 -0
- package/scripts/selftest-probe.mjs +6 -1
- package/scripts/smoke-client.mjs +68 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.8.1 — 认得出两个共存插件(dsh-onebot-qq 跟它的端口,dsh-qq-bridge 替它对端口)
|
|
4
|
+
- 2.8.0 解决了「反向 WS 下不再误判离线、不再无限重启」,但端口还是得你自己抄:`dsh-onebot-qq` 默认监听 `8643`,你 `onebotPort` 里填的却是 `3000`,那就一直「没客户端连进来」。
|
|
5
|
+
- 现在会读 `dsh-onebot-qq` 自己的配置:扫 `~/.dsh/profiles/*` 的 `package.json`(`dependencies` + `dsh.profile.bundles`)和 `cordis.patch.yml` / `cordis.yml` 里它那一段,得出「装没装 / 挂没挂 / 反向还是正向 / 监听哪个端口 / 有没有配令牌」。不认识 `!!js` 这类表达式,认不出的宁可当没配。
|
|
6
|
+
- **跟随(`companionFollow`,默认开)**:你填的端口**不通**、而它确实挂着反向 WS 时,自动改看它那个端口 —— 状态条写「端口 N(跟随 dsh-onebot-qq)」,日志说明「你填的 X 上没有服务,已跟随 Y」。你自己填的端口一旦通了,它绝不插手。
|
|
7
|
+
- 三种情况**不跟**,并在提示里说明为什么:它没挂进 profile(端口根本不会开)、它是正向模式(它自己去连 NapCat,不监听端口)、你把「跟随」关了。
|
|
8
|
+
- 设置页多一行「共存插件」:`dsh-onebot-qq 0.9.6 · 已启用 · 反向 WS :8643 · 令牌一致`;没装就写「没检测到」;它配了令牌而你这边填得不一样,会标 ⚠ 不一致。
|
|
9
|
+
- **新:把 `dsh-qq-bridge` 也认进来了**。它是「客户端」(拿 HTTP 去连 NapCat,再把消息接进 QQ),跟 `dsh-onebot-qq`(提供接口)正好相反,最容易崩的就是端口对不上。现在会读它的配置 —— 注意它**不在 profile 里**,摊在 `~/.dsh/qq-bridge-config.json`(中文键名 `NapCat` / `总开关` / `试运行` / `令牌` / `绑定`)。
|
|
10
|
+
- 交叉检查五种结论写进设置页新的「桥接插件」行 + `napcat_status`:**装了但没挂进 profile**(只在 `dependencies` 里,桥接根本没跑)/ **连的是反向 WS 端口**(HTTP 客户端敲 WebSocket 端口,必然 426 或 401)/ **端口对不上**(桥接端口 ≠ 本插件看到的 OneBot 端口)/ **总开关关着**(在跑但一句不发)/ **试运行中**(只记账)。全对得上就什么都不说。
|
|
11
|
+
- 这层检查只看配置,不碰桥接的进程、不改它的文件,纯提示。
|
|
12
|
+
- 两个插件共用同一套 profile 扫描(`profileHits`):挂载 = 在 `dsh.profile.bundles` 里,或 patch 里出现 `id: <bundle id>`;只装在 `dependencies` 而没进 bundles 的,一律判「装了但没挂」,不会假装它在生效。
|
|
13
|
+
- `napcat_status` 的 `companion` 改成 `{ onebot: …, bridge: … }`(这个字段上一版才加、没发布,直接换结构,不留旧形状)。
|
|
14
|
+
- `selftest:companion` 从 39 项扩到 **66 项**:新增桥接那一段 —— 地址抠端口、读中文配置、挂没挂、五种交叉检查各一条、未挂载优先于端口问题、以及 `probe` 会把检查结果一起带出来。`smoke-client` 加了 8 项桥接渲染断言(没装 / 装了在发 / 连错端口 / 总开关关着),共 52 项。
|
|
15
|
+
- 探测仍然**只走 HTTP + 系统连接表,不做 WebSocket 握手**:它的反向 WS 是「后来者顶掉前人」的,拿真令牌握手会把 NapCat 自己那条挤掉。
|
|
16
|
+
- **改:「跟随 dsh-onebot-qq」这一行不再是个摆设开关**。以前它在任何机器上都画出来、还默认勾着,可多数时候对面压根没挂进 profile,跟了也是白跟。现在它跟着探测结果走 —— 只有检测到 `dsh-onebot-qq` 装了、并且真挂进 profile(= 已启用)时才出现,且默认开;没装或只躺在 `dependencies` 里没挂载,这一行**整行不画**,`resolveConfig` 里值也直接按关算(`companionReady=false`),跟 `probe()` 里「没挂载就不跟」那条前提对齐。
|
|
17
|
+
- 你显式关过一次就一直是关:`resolveConfig` 只在存储/cordis 里**没有**这个键时才套用动态默认值,不会因为你升级或重启又偷偷掰回开。
|
|
18
|
+
- 配套挡住一个隐形的坑:设置页「保存」原本是把整份草稿全量发过去,界面上没画出来的项会带着旧值一起写进 `config.json`。现在只发真有变化的键,`saveAndApply` 那边也加了一道 —— 对面没启用时 `patch` 里就算带着 `companionFollow` 也不落盘,免得把用户以前的选择盖掉。
|
|
19
|
+
- `selftest:companion` 66 → **83 项**(新增 17 项:`companionReady` 三种组合、没装 / 装了没挂 / 挂了 profile 三种场景下的 `companionReady` 与 `companionFollow`、可用时默认开、以及「存了 false / cordis 写 false 都保持关」;`companionPublic` 那份瘦身结果也认;再加 `uiState` 每轮校准的两组断言);`smoke-client` 52 → **56 项**(没装不画这一行、挂了 profile 才画、没启用时不画、共存那行说明开关不会出现)。
|
|
20
|
+
- 面板每轮都来问一次状态,`uiState` 顺手按**最新**探测结果校准这一项:你把 `dsh-onebot-qq` 中途挂进 profile(或者摘掉),那一行立刻跟着出现 / 消失,值也跟着变,不用重启 DSH 等 `apply` 重跑(探测本身有 20 秒缓存,最多慢这么久)。
|
|
21
|
+
- `companionReady` 两种入参都吃:`detectCompanion()` 的完整结果(带 `found`)和 `companionPublic()` 的瘦身版(没有 `found`,只带 `version` / `profile` / `mounted`)—— 面板拿到的正是后面这种,早先只认 `found` 的话会一直判「不可用」。
|
|
22
|
+
- 顺带清掉一处历史脏值:`config.json` 里那条由整包保存写进去的 `"companionFollow": "false"` 已删除(删前备份到 `legacy/config.before-cf-default-fix.json`),所以这台机器一旦启用 `dsh-onebot-qq`,这一行会按新默认值出现并勾上。
|
|
23
|
+
|
|
3
24
|
## 2.8.0 — 认得出反向 WebSocket(和 dsh-onebot-qq 共存)
|
|
4
25
|
- **修的什么**:装了 `dsh-onebot-qq` 这类插件、把 NapCat 配成**反向 WebSocket** 连过来的机器上,本插件永远判「离线」,然后无限重启。原因是探测只用 HTTP 打 `get_login_info`,而反向 WS 的端口根本不吃 HTTP(换来 401 / 426);老代码只看返回的 body、不看 HTTP 状态码,于是把「端口明明在回话」当成「端口不通」→ 卡死判定 → 杀掉重拉 → 循环。
|
|
5
26
|
- 现在 `postOneBot` 会把 HTTP 状态码带回来,`probe()` 据此分清四种情况:能问到 `login_info`(普通 HTTP)、只收 WebSocket(反向 WS)、端口要求鉴权(多半是令牌不对)、端口没开。
|
package/README.md
CHANGED
|
@@ -217,15 +217,50 @@ NapCat 连 OneBot 有两条相反的路:
|
|
|
217
217
|
|
|
218
218
|
然后在 NapCat 那边把反向 WS 地址填成 `ws://127.0.0.1:<上面那个端口>`,令牌对上 `accessToken`。
|
|
219
219
|
|
|
220
|
+
### 装了 dsh-onebot-qq 的,端口可以不用自己填
|
|
221
|
+
|
|
222
|
+
从 2.8.x 起,本插件会去读 `dsh-onebot-qq` 自己的配置(profile 的 `package.json`、`cordis.patch.yml`/`cordis.yml` 里它那一段),知道它监听哪个端口、是反向还是正向、令牌配没配。于是:
|
|
223
|
+
|
|
224
|
+
- 你填的 `onebotPort` **能通**,就永远用你的 —— 它不会插嘴;
|
|
225
|
+
- 你填的端口**没人听**,而 `dsh-onebot-qq` 正开着反向 WS,就自动改看它那个端口(默认 `8643`),状态条会写「端口 N(跟随 dsh-onebot-qq)」,日志里也会说明「你填的 X 上没有服务,已跟随 Y」;
|
|
226
|
+
- 它没挂进 profile(只在 `dependencies` 里、没进 `dsh.profile.bundles`、patch 里也没它)→ 端口根本不会开,这时**不跟**,因为跟了也没用;
|
|
227
|
+
- 它是**正向**模式(它自己去连 NapCat,不监听端口)→ 也不跟,照常按你的端口 + `auto` 探;
|
|
228
|
+
- 它配了 `accessToken` 但你这边填的不一样 → 设置页「共存插件」那行会标 ⚠ 令牌不一致。
|
|
229
|
+
|
|
230
|
+
对照开关就是设置页那个「跟随 dsh-onebot-qq」(配置项 `companionFollow`)。它现在**跟着探测结果走**:只有检测到 `dsh-onebot-qq` 装了、并且真挂进 profile(= 已启用)时,这一行才会出现在设置页,且默认开;没装、或者只躺在 `dependencies` 里没挂载(那种情况端口根本不会开),这一行干脆不画,值也按关算 —— 免得上面那句「不跟」全靠猜。你要是自己关过,那就一直按关处理,不会因为它升级/重启又偷偷掰回开。设置页每轮刷新都会重算一遍,所以你中途把它挂上或者摘掉,那一行立刻跟着出现/消失,不用重启 DSH。
|
|
231
|
+
|
|
232
|
+
> 跟着它看端口的前提是它真的在跑。只装在 `dependencies` 里的,设置页「共存插件」那行会写「已安装但没挂进 profile(「跟随」那个开关不会出现)」,先去 profile 里把它挂上再说。
|
|
233
|
+
|
|
234
|
+
> 探测全程只用 HTTP + 系统连接表,**不做 WebSocket 握手**:`dsh-onebot-qq` 的反向 WS 是「后来者顶掉前人」的,拿真令牌去握手会把 NapCat 自己那条连接挤掉。
|
|
235
|
+
|
|
220
236
|
真等不来客户端时,插件也不会每轮都杀进程:先按 `stuckSec`(默认 420 秒)等,超时才**温和重拉**一次,最多两次;还不行就进 `reverse-giveup`,把「该去 NapCat 里改反向 WS 地址」写进日志和状态条,不再折磨那条链。
|
|
221
237
|
|
|
222
238
|
> 同一个端口没法既当 HTTP 接口又当反向 WS 服务 —— 谁先占着就听谁的。两样都想要,就给它们分两个端口。
|
|
223
239
|
|
|
240
|
+
### 装了 dsh-qq-bridge 的,插件会替你把端口对一遍
|
|
241
|
+
|
|
242
|
+
`dsh-onebot-qq` 提供的是**接口**(端口由它开,NapCat 连进去);`dsh-qq-bridge` 是**客户端**(它反过来拿 HTTP/WS 去连 NapCat,再把消息接到 QQ 聊天里)。两者对端口的要求正好相反,最容易崩的地方就一句话:**桥接里填的 `NapCat` 地址,必须是 NapCat 自己开着的那个 OneBot 端口。**
|
|
243
|
+
|
|
244
|
+
本插件会顺手读桥接的配置(`~/.dsh/qq-bridge-config.json`,它的配置不在 profile 里、摊在 `~/.dsh` 根上),然后拿自己看到的实际情况跟它比一比,结论写在设置页「桥接插件」那行:
|
|
245
|
+
|
|
246
|
+
| 看到的情况 | 结论 |
|
|
247
|
+
| --- | --- |
|
|
248
|
+
| 只在 `dependencies` 里、没进 `dsh.profile.bundles` | **装了但没挂进 profile** —— 桥接根本没跑 |
|
|
249
|
+
| 桥接指向的就是那个**反向 WS** 端口 | **连的是反向 WS 端口** —— 那里只收 WebSocket 握手,HTTP 客户端敲过去必然 426/401 |
|
|
250
|
+
| 桥接端口 ≠ 本插件看到的 OneBot 端口 | **端口对不上** —— 消息发不出去 |
|
|
251
|
+
| 桥接「总开关」是关的 | 在跑,但一句都不发 |
|
|
252
|
+
| 桥接开着「试运行」 | 只记账,不真发到 QQ |
|
|
253
|
+
| 以上都对得上 | 不吭声(对得上就没什么可说的) |
|
|
254
|
+
|
|
255
|
+
这层检查只看**配置**,不碰桥接的进程、不改它的文件,纯提示。想让它真发消息,还是得去桥接自己的设置页把总开关打开、把地址填对。
|
|
256
|
+
|
|
257
|
+
> 典型的踩坑组合:`dsh-onebot-qq` 开着反向 WS 占着 `8643`,桥接的 `NapCat` 又填成 `http://127.0.0.1:8643` —— 看着「端口明明通」,桥接就是一直不动。给 NapCat 另开一个 `httpServers` 端口(比如 `3000`)让桥接连,两边就都活了。
|
|
258
|
+
|
|
224
259
|
## 给 agent 用的三个工具
|
|
225
260
|
|
|
226
261
|
| 工具 | 作用 |
|
|
227
262
|
| --- | --- |
|
|
228
|
-
| `napcat_status` |
|
|
263
|
+
| `napcat_status` | 端口/登录态、进程链、二维码副本路径、桥接心跳、日志尾部,以及两个共存插件的状态(`dsh-onebot-qq` 装了没/挂了没/端口模式/令牌一致不,`dsh-qq-bridge` 装了没/挂了没/桥接端口对不对) |
|
|
229
264
|
| `napcat_restart` | 干净地杀掉整条链并重拉,然后等它上线 |
|
|
230
265
|
| `napcat_dedupe` | 只在真有重复链时才杀(没重复就什么都不做) |
|
|
231
266
|
|
|
@@ -244,6 +279,7 @@ NapCat 连 OneBot 有两条相反的路:
|
|
|
244
279
|
| `onebotPort` | `3000` | OneBot 端口。普通部署填 NapCat 里 `httpServers` 的端口;反向 WebSocket 部署填**反向 WS 服务**监听的端口 |
|
|
245
280
|
| `accessToken` | 空 | OneBot access token(跟 NapCat 或反向 WS 服务里填的一致) |
|
|
246
281
|
| `probeMode` | `auto` | 在线探测方式:`auto` 先按 HTTP 问、问不通再看是不是反向 WS;`http` 只认 HTTP 接口;`reverse` 只认反向 WebSocket;`process` 只看进程不碰端口 |
|
|
282
|
+
| `companionFollow` | `true` | 你填的端口不通时,是否跟随 `dsh-onebot-qq` 配的反向 WS 端口(详见「反向 WebSocket」那节);你自己填的端口一通,它就绝不插手。**这一项只在检测到 `dsh-onebot-qq` 装了且挂进 profile 时才出现、才默认开**,否则设置页不显示、值按关算 |
|
|
247
283
|
| `taskName` | 空(= 用 cscript,QQ 跟着 DSH 生灭) | 想脱离 DSH 才填计划任务名 |
|
|
248
284
|
| `autoCreateTask` | `false` | 填了 `taskName` 且任务不存在时自动创建 |
|
|
249
285
|
| `hideConsole` | `true` | 拉起时不显示黑框(用 wscript 壳藏窗口) |
|
|
@@ -304,7 +340,7 @@ npm run check:privacy # 只查隐私(发版前必跑)
|
|
|
304
340
|
|
|
305
341
|
**隐私体检**是发版前那道闸:把包里所有文本文件过一遍,找 Windows / Unix 家目录路径、邮箱、`ghp_` / `npm_` / `sk-` / `AKIA` 这类凭证、`Bearer` 后面的真串、DSH 会话 id,以及自测里那种 `launchAccount: '1234567890'` 的真实 QQ 号。命中就按 `文件:行` 列出来并返回非 0;确实是文档里必须留的示例,在那行末尾写 `check-privacy:ignore` 放过。占位写法(`C:/Users/你/…`、`C:/Users/x/…`)本来就放行。
|
|
306
342
|
|
|
307
|
-
|
|
343
|
+
另外几个自测,都不依赖本机路径,clone 下来就能跑:`npm run smoke:client`(把 `lib/client.js` 塞进假 React 渲染一遍)、`npm run selftest:scan`(造假树验扫盘判定)、`npm run selftest:save`(保存真的落到插件目录、误写的那份被认领回来)、`npm run selftest:probe`(本地起假服务器,验普通 HTTP / 反向 WS / 需要鉴权 / 端口没开四种判定)、`npm run selftest:companion`(造假 profile 与桥接配置,验 `dsh-onebot-qq` 的端口跟随和 `dsh-qq-bridge` 的交叉结论)、`npm run selftest:setup`(临时目录里真跑一遍 apply / 重跑 / undo)。
|
|
308
344
|
|
|
309
345
|
> **改这个插件的文件的规矩**:别用 `Get-Content` 读、`Set-Content -Encoding utf8` 写 —— PowerShell 5.1 会按 ANSI 读、再按 UTF-8 写,一趟往返中文全变乱码,BOM 还照写。用编辑器另存为「UTF-8 无 BOM」;非要脚本写,就走
|
|
310
346
|
> `[IO.File]::WriteAllText($path, $text, (New-Object System.Text.UTF8Encoding($false)))`。
|
|
@@ -367,13 +403,13 @@ DSH 自带的 pnpm 不捎带 git,Windows 上又默认没装,于是就卡在
|
|
|
367
403
|
| 填进去的 | 结果 |
|
|
368
404
|
| --- | --- |
|
|
369
405
|
| `dsh-napcat-keeper` | ✅ |
|
|
370
|
-
| `dsh-napcat-keeper@2.8.
|
|
406
|
+
| `dsh-napcat-keeper@2.8.1` | ✅(指定版本) |
|
|
371
407
|
| `dsh plugin --profile desktop add dsh-napcat-keeper` | ❌ 整条命令 |
|
|
372
408
|
| `add dsh-napcat-keeper` | ❌ 多了 `add` |
|
|
373
409
|
| `Dsh-napcat-keeper` | ❌ 大写 |
|
|
374
410
|
| `dsh-napcat-keeper。`、`dsh-napcat-keeper;` | ❌ 全角标点 |
|
|
375
411
|
|
|
376
|
-
改法就一句:**那一栏只填 `dsh-napcat-keeper`**(要指定版本就 `dsh-napcat-keeper@2.8.
|
|
412
|
+
改法就一句:**那一栏只填 `dsh-napcat-keeper`**(要指定版本就 `dsh-napcat-keeper@2.8.1`)。想跑命令行的话,得在终端里跑,
|
|
377
413
|
不是在输入框里跑。
|
|
378
414
|
|
|
379
415
|
## License
|
package/lib/client.js
CHANGED
|
@@ -130,6 +130,7 @@ window.__ModuleLoader__.load({
|
|
|
130
130
|
['accessToken', 'OneBot 访问令牌', '没设就留空;设了要跟 NapCat(或反向 WS 服务)里填的一致', 'password'],
|
|
131
131
|
['probeMode', '在线探测方式', '自动 = 先按 HTTP 接口问;端口只收 WebSocket 时会认成「反向 WS」。如果端口是 dsh-onebot-qq 这类反向 WS 服务在听(HTTP 换来 401/426、老被判离线),明确选「反向 WebSocket」最省事', 'select', false,
|
|
132
132
|
[['auto', '自动(推荐)'], ['http', '只认 HTTP 接口'], ['reverse', '反向 WebSocket'], ['process', '只看进程']]],
|
|
133
|
+
['companionFollow', '跟随 dsh-onebot-qq', '只在 dsh-onebot-qq 装了、并且真挂进 profile(= 已启用)时才出现这一行,可用时默认开。开着的话:你自己填的端口连不上时,自动改看它的反向 WS 端口(就是它监听的那个);填的端口一旦通了,还是用你的', 'bool'],
|
|
133
134
|
],
|
|
134
135
|
},
|
|
135
136
|
{
|
|
@@ -176,6 +177,35 @@ window.__ModuleLoader__.load({
|
|
|
176
177
|
return obj && Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : ''
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
/** 「共存插件」那行:dsh-onebot-qq 装没装、挂没挂、它监听哪个端口 */
|
|
181
|
+
function 共存描述(runtime) {
|
|
182
|
+
const c = runtime.companion
|
|
183
|
+
if (!c || !c.version) return '没检测到 dsh-onebot-qq(不装也不影响;装了它就会显示在这里)'
|
|
184
|
+
const 状态 = c.mounted ? '已启用' : '已安装但没挂进 profile(「跟随」那个开关不会出现)'
|
|
185
|
+
const 模式 = c.mode === 'reverse' ? '反向 WS :' + String(c.port) : '正向连 ' + String(c.url || '')
|
|
186
|
+
const 令牌 = runtime.companionTokenMatch === true
|
|
187
|
+
? ' · 令牌一致'
|
|
188
|
+
: runtime.companionTokenMatch === false
|
|
189
|
+
? ' · ⚠ 令牌不一致'
|
|
190
|
+
: ''
|
|
191
|
+
return 'dsh-onebot-qq ' + String(c.version) + ' · ' + 状态 + ' · ' + 模式 + 令牌
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** 「桥接插件」那行:dsh-qq-bridge 装没装、挂没挂、它连的端口对不对 */
|
|
195
|
+
function 桥接描述(runtime) {
|
|
196
|
+
const b = runtime && runtime.bridgePlugin
|
|
197
|
+
if (!b || !b.version) return '没检测到 dsh-qq-bridge(不装也不影响;装了它就会显示在这里)'
|
|
198
|
+
const 状态 = b.mounted ? '已启用' : '已安装但没挂进 profile'
|
|
199
|
+
const 开关 = !b.configKnown ? '没读到配置' : !b.enabled ? '总开关关着' : b.dryRun ? '试运行中' : '在发'
|
|
200
|
+
const 问题 =
|
|
201
|
+
b.check === 'bridge-hits-reverse'
|
|
202
|
+
? ' · ⚠ 连的是反向 WS 端口'
|
|
203
|
+
: b.check === 'port-mismatch'
|
|
204
|
+
? ' · ⚠ 端口和 NapCat 对不上'
|
|
205
|
+
: ''
|
|
206
|
+
return 'dsh-qq-bridge ' + String(b.version) + ' · ' + 状态 + ' · ' + 开关 + ' · 连 ' + String(b.napcatUrl || '') + 问题
|
|
207
|
+
}
|
|
208
|
+
|
|
179
209
|
function 状态条(runtime) {
|
|
180
210
|
if (!runtime) return null
|
|
181
211
|
const 在 = runtime.online
|
|
@@ -212,6 +242,10 @@ window.__ModuleLoader__.load({
|
|
|
212
242
|
? h('span', null, String(runtime.nickname || '') + '(' + String(runtime.userId || '') + ')')
|
|
213
243
|
: null,
|
|
214
244
|
h('span', { style: S.dim }, '探测:' + 模式名 + (runtime.portStatus ? ' · HTTP ' + String(runtime.portStatus) : '')),
|
|
245
|
+
runtime.portUsed
|
|
246
|
+
? h('span', { style: S.dim }, '端口 ' + String(runtime.portUsed) +
|
|
247
|
+
(runtime.followed ? '(跟随 dsh-onebot-qq)' : ''))
|
|
248
|
+
: null,
|
|
215
249
|
反向 ? h('span', { style: S.dim },
|
|
216
250
|
'客户端 ' + (runtime.clients === null || runtime.clients === undefined ? '查不到' : String(runtime.clients))) : null,
|
|
217
251
|
h('span', { style: S.dim }, '阶段:' + 阶段名),
|
|
@@ -245,7 +279,14 @@ window.__ModuleLoader__.load({
|
|
|
245
279
|
h('span', null, runtime.qr ? '最新一张 ' + String(runtime.qr.ageSec) + ' 秒前' : '还没有(没进扫码态)'),
|
|
246
280
|
h('span', { style: S.dim }, '桥接心跳'),
|
|
247
281
|
h('span', null, runtime.bridge && runtime.bridge.ageSec !== null ? String(runtime.bridge.ageSec) + ' 秒前' : '没读到'),
|
|
282
|
+
h('span', { style: S.dim }, '共存插件'),
|
|
283
|
+
h('span', null, 共存描述(runtime)),
|
|
284
|
+
h('span', { style: S.dim }, '桥接插件'),
|
|
285
|
+
h('span', { style: { wordBreak: 'break-all' } }, 桥接描述(runtime)),
|
|
248
286
|
),
|
|
287
|
+
runtime.bridgePlugin && runtime.bridgePlugin.note
|
|
288
|
+
? h('div', { style: { ...S.dim, marginTop: 4 } }, '桥接提示:' + String(runtime.bridgePlugin.note))
|
|
289
|
+
: null,
|
|
249
290
|
runtime.error ? h('div', { style: { ...S.bad, marginTop: 6 } }, '最近错误:' + String(runtime.error)) : null,
|
|
250
291
|
runtime.hint ? h('div', { style: { ...S.dim, marginTop: 4 } }, '提示:' + String(runtime.hint)) : null,
|
|
251
292
|
)
|
|
@@ -362,12 +403,27 @@ window.__ModuleLoader__.load({
|
|
|
362
403
|
)
|
|
363
404
|
}
|
|
364
405
|
|
|
365
|
-
|
|
406
|
+
// 「跟随 dsh-onebot-qq」只有在那插件装了、且挂进 profile(= 真启用)时才有意义:
|
|
407
|
+
// 没得跟的时候这一行整行不画,它的值也不参与「有没有改动」和保存。
|
|
408
|
+
const 跟随可开 = Boolean(
|
|
409
|
+
态 && 态.runtime
|
|
410
|
+
&& (态.runtime.companionReady === true || Boolean(态.runtime.companion && 态.runtime.companion.mounted)),
|
|
411
|
+
)
|
|
412
|
+
const 可写键 = (k) => k !== 'companionFollow' || 跟随可开
|
|
413
|
+
const 草键 = 全部键.filter(可写键)
|
|
414
|
+
|
|
415
|
+
const 脏 = Boolean(态 && 草 && 草键.some((k) => String(取(草, k)) !== String(取(态.config, k))))
|
|
366
416
|
|
|
367
417
|
const 存 = async () => {
|
|
368
418
|
if (!草 || 忙) return
|
|
369
419
|
set忙(true)
|
|
370
|
-
|
|
420
|
+
// 只发真有变化的键:界面上没画出来的项(比如这会儿不可用的 companionFollow),
|
|
421
|
+
// 草稿里带的是旧值/假值,整包发过去会把用户以前的选择盖掉。
|
|
422
|
+
const patch = {}
|
|
423
|
+
草键.forEach((k) => {
|
|
424
|
+
if (String(取(草, k)) !== String(取(态 && 态.config, k))) patch[k] = 取(草, k)
|
|
425
|
+
})
|
|
426
|
+
const r = await post('/save', { patch })
|
|
371
427
|
if (r) 装(r)
|
|
372
428
|
set说(r && r.config ? '设置已保存并生效' : '保存失败,看看日志')
|
|
373
429
|
set忙(false)
|
|
@@ -764,7 +820,7 @@ window.__ModuleLoader__.load({
|
|
|
764
820
|
: h('div', { key: g.group },
|
|
765
821
|
h('div', { style: S.h }, g.group),
|
|
766
822
|
g.note ? h('div', { style: { ...S.dim, marginBottom: 8 } }, g.note) : null,
|
|
767
|
-
g.items.map(渲染项),
|
|
823
|
+
g.items.filter((it) => it[0] !== 'companionFollow' || 跟随可开).map(渲染项),
|
|
768
824
|
)),
|
|
769
825
|
|
|
770
826
|
h('div', { style: S.h }, '日志'),
|