dsh-qq-moony 0.5.2 → 0.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.6.0 — 2026-10-25
4
+
5
+ 有人报告"装上了但一直连不上、还反复自己重启",根因是两个 bug 叠在一起:
6
+
7
+ - **修:配置优先级反了。** README 写的是"本地 config.json 优先",代码里却是包的 patch 排在最后、压掉了本地文件——用户改的端口和 token 从来没生效过。现在顺序是 `默认 < patch < 本地文件`。
8
+ - **修:端口被别的服务占着时白折腾。** 原来只看"请求通不通",有人机器上 3000 早被别的网页服务占了(回的是 `{"code":90004,"message":"资源不存在"}`),插件误判成 NapCat 挂了,于是反复拉起、每次白等一分钟。现在探活区分三种:`ok` / `foreign`(端口被占)/ `down`,被占时不自动拉起,设置页直接说"3000 被别的服务占了,换个端口或者把它挪开"。
9
+
10
+ **给改装的人**:如果 3000 上有别的东西,改 `baseUrl`(比如 `http://127.0.0.1:3010`),同时把 NapCat 的 OneBot HTTP 端口也改成一�样。
3
11
  ## 0.5.2 — 2026-10-25
4
12
 
5
13
  - 拉起 NapCat 时不再弹黑窗口:改成生成 VBS、用 `wscript` 静默执行(`windowsHide` 对批处理无效)
package/client.js CHANGED
@@ -159,7 +159,9 @@ window.__ModuleLoader__.load({
159
159
  const 缺口 = [];
160
160
  if (!状态.qqnt) 缺口.push('没找到 QQ NT —— 去 im.qq.com 装新版(9.9.x)。老版 9.7 注不进去,这是死条件。');
161
161
  if (!状态.napcat) 缺口.push('没找到 NapCat —— 去 github.com/NapNeko/NapCatQQ 下 Shell 版,解压后把 napCatDir 指过去。');
162
- if (状态.qqnt && 状态.napcat && !状态.online)
162
+ if (状态.portState === 'foreign')
163
+ 缺口.push('端口上坐着的不是 NapCat —— 3000 被别的服务占了。换个端口(改 baseUrl),或者把那个服务挪开。');
164
+ else if (状态.qqnt && 状态.napcat && !状态.online)
163
165
  缺口.push('QQ NT 和 NapCat 都在,但连不上 —— 检查 NapCat 启没启、3000 端口、token 三样。');
164
166
 
165
167
  return h(
package/index.js CHANGED
@@ -114,7 +114,7 @@ const 工具输出 = (字段, 渲染) => ({
114
114
  });
115
115
 
116
116
  export function apply(ctx, 配置) {
117
- const c = { ...默认配置, ...读取本地配置(), ...(配置 ?? {}) };
117
+ const c = { ...默认配置, ...(配置 ?? {}), ...读取本地配置() };
118
118
  const 账本 = join(家目录(), 'sent.log');
119
119
  const 收件箱 = join(家目录(), 'inbox.jsonl');
120
120
 
@@ -133,22 +133,40 @@ export function apply(ctx, 配置) {
133
133
  return { qqnt, napcat };
134
134
  }
135
135
 
136
- /** DSH 起来时顺手看一眼 NapCat:没跑就自己拉起来(免扫码,用 -q 快速登录)。 */
137
- async function 确认NapCat在跑() {
138
- if (c.autoStartNapCat === false) return;
139
- const 探活 = async () => {
136
+ /** 探活:区分「NapCat 在」「端口被别的服务占了」「根本没起来」三种情况。 */
137
+ async function 探NapCat() {
138
+ try {
139
+ const 头 = c.token ? { Authorization: `Bearer ${c.token}` } : {};
140
+ const r = await fetch(`${c.baseUrl}/get_login_info`, { headers: 头, signal: AbortSignal.timeout(4000) });
141
+ const 文本 = await r.text();
142
+ let 体 = null;
140
143
  try {
141
- const 头 = c.token ? { Authorization: `Bearer ${c.token}` } : {};
142
- const r = await fetch(`${c.baseUrl}/get_login_info`, { headers: 头, signal: AbortSignal.timeout(4000) });
143
- return r.ok;
144
+ 体 = JSON.parse(文本);
144
145
  } catch {
145
- return false;
146
+ /* 不是 JSON,多半是别的服务 */
146
147
  }
147
- };
148
- if (await 探活()) {
148
+ if (r.ok && 体?.status === 'ok') return 'ok';
149
+ // 有东西在应答,但不是 OneBot——端口被别的程序占了
150
+ return 体 ? 'foreign' : 'foreign';
151
+ } catch {
152
+ return 'down';
153
+ }
154
+ }
155
+
156
+ /** DSH 起来时顺手看一眼 NapCat:没跑就自己拉起来(免扫码,用 -q 快速登录)。 */
157
+ async function 确认NapCat在跑() {
158
+ if (c.autoStartNapCat === false) return;
159
+
160
+ const 状态 = await 探NapCat();
161
+ if (状态 === 'ok') {
149
162
  记调试('NapCat 已经在跑,不用拉');
150
163
  return;
151
164
  }
165
+ if (状态 === 'foreign') {
166
+ // 端口上坐着别的程序:这时候去拉起 NapCat 只会白折腾
167
+ 记调试(`${c.baseUrl} 上应答的不是 NapCat(多半被别的服务占了),不自动拉起`);
168
+ return;
169
+ }
152
170
  const 目录 = c.napCatDir || '';
153
171
  const 号码 = String(c.qqUin || c.uin || '');
154
172
  if (!目录 || !号码) {
@@ -179,7 +197,7 @@ export function apply(ctx, 配置) {
179
197
  // 给它一点时间登录,最多等一分钟
180
198
  for (let i = 0; i < 30; i += 1) {
181
199
  await new Promise((r) => setTimeout(r, 2000));
182
- if (await 探活()) {
200
+ if ((await 探NapCat()) === 'ok') {
183
201
  记调试(`NapCat 起来了(等了约 ${(i + 1) * 2} 秒)`);
184
202
  return;
185
203
  }
@@ -668,16 +686,20 @@ export function apply(ctx, 配置) {
668
686
  const 记录 = 读账(账本);
669
687
  let 在线 = false;
670
688
  let 昵称 = '';
671
- try {
672
- const r = await 调('get_login_info', {});
673
- 在线 = true;
674
- 昵称 = String(r.data?.nickname ?? '');
675
- } catch {
676
- /* 离线就报离线 */
689
+ 在线 = (await 探NapCat()) === 'ok';
690
+ if (在线) {
691
+ try {
692
+ const r = await 调('get_login_info', {});
693
+ 昵称 = String(r.data?.nickname ?? '');
694
+ } catch {
695
+ /* 探到了但取名字失败,别当离线 */
696
+ }
677
697
  }
698
+ const 端口状态 = 在线 ? 'ok' : await 探NapCat();
678
699
  发json(res, 200, {
679
700
  ok: true,
680
701
  online: 在线,
702
+ portState: 端口状态,
681
703
  nickname: 昵称,
682
704
  qqnt: 体检().qqnt,
683
705
  napcat: 体检().napcat,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-qq-moony",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "把 QQ 小号接进 DeepSeek Harness:收发消息、发表情包、发 QQ 空间说说、参与群聊,能自己找话题,自带启动与限速防封。",
5
5
  "keywords": [
6
6
  "dsh",