dsh-qq-moony 0.5.1 → 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 +18 -0
- package/README.md +1 -1
- package/client.js +3 -1
- package/index.js +51 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
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 端口也改成一�样。
|
|
11
|
+
## 0.5.2 — 2026-10-25
|
|
12
|
+
|
|
13
|
+
- 拉起 NapCat 时不再弹黑窗口:改成生成 VBS、用 `wscript` 静默执行(`windowsHide` 对批处理无效)
|
|
14
|
+
- README 补一句:自启是静默的,不用留一个控制台窗口在那儿
|
|
15
|
+
|
|
16
|
+
## 0.5.1 — 2026-10-25
|
|
17
|
+
|
|
18
|
+
- 修:点「保存更改」之后设置页会空白——草稿被清空、新值还没回来那一瞬没有可显示的值
|
|
19
|
+
- 现在每个字段都有兜底:草稿为空就用服务端返回的值
|
|
20
|
+
|
|
3
21
|
## 0.5.0 — 2026-10-25
|
|
4
22
|
|
|
5
23
|
装完之后不再一片红:缺什么会自己说出来。
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ dsh plugin add dsh-qq-moony
|
|
|
40
40
|
- *接消息*:白名单里的群,被 @ 才应。
|
|
41
41
|
- *参与聊天*:每群记着最近三十条,隔 8–20 分钟给一次"要不要插一句"的机会,把这现场交给它判断,接不住就什么都不发。冷场(五分钟没人说话)不开口;同群冷却十分钟;群里一天最多二十条。
|
|
42
42
|
|
|
43
|
-
**打开 DSH 就自带 NapCat。** 启动时探一下 3000 端口,没通就用 `-q` 快速登录把 NapCat
|
|
43
|
+
**打开 DSH 就自带 NapCat。** 启动时探一下 3000 端口,没通就用 `-q` 快速登录把 NapCat 拉起来——免扫码,几秒上线。**而且是静默的**:插件生成一个 VBS 用 `wscript` 起,不会弹黑窗口(`windowsHide` 对批处理不管用,这是唯一可靠的办法)。
|
|
44
44
|
|
|
45
45
|
---
|
|
46
46
|
|
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 (状态.
|
|
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
|
-
/**
|
|
137
|
-
async function
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
146
|
+
/* 不是 JSON,多半是别的服务 */
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
-
|
|
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 (!目录 || !号码) {
|
|
@@ -156,14 +174,22 @@ export function apply(ctx, 配置) {
|
|
|
156
174
|
return;
|
|
157
175
|
}
|
|
158
176
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
177
|
+
// 用 VBS 起,窗口不弹出来(cmd 的隐藏参数对批处理不管用)
|
|
178
|
+
const 启动脚本 = join(家目录(), 'start-napcat.vbs');
|
|
179
|
+
mkdirSync(家目录(), { recursive: true });
|
|
180
|
+
const 批处理 = join(目录, 'launcher-user.bat');
|
|
181
|
+
const vbs =
|
|
182
|
+
`Set sh = CreateObject("WScript.Shell")\r\n` +
|
|
183
|
+
`sh.Run "cmd /c ""${批处理}"" -q ${号码}", 0, False\r\n`;
|
|
184
|
+
// .vbs 用 UTF-16LE + BOM,中文路径才认
|
|
185
|
+
writeFileSync(启动脚本, Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(vbs, 'utf16le')]));
|
|
186
|
+
const 子 = spawn('wscript.exe', [启动脚本], {
|
|
161
187
|
detached: true,
|
|
162
188
|
stdio: 'ignore',
|
|
163
189
|
windowsHide: true,
|
|
164
190
|
});
|
|
165
191
|
子.unref();
|
|
166
|
-
记调试(`NapCat
|
|
192
|
+
记调试(`NapCat 没在跑,已静默拉起(${目录},-q ${号码})`);
|
|
167
193
|
} catch (e) {
|
|
168
194
|
记调试(`拉 NapCat 失败:${e?.message ?? e}`);
|
|
169
195
|
return;
|
|
@@ -171,7 +197,7 @@ export function apply(ctx, 配置) {
|
|
|
171
197
|
// 给它一点时间登录,最多等一分钟
|
|
172
198
|
for (let i = 0; i < 30; i += 1) {
|
|
173
199
|
await new Promise((r) => setTimeout(r, 2000));
|
|
174
|
-
if (await
|
|
200
|
+
if ((await 探NapCat()) === 'ok') {
|
|
175
201
|
记调试(`NapCat 起来了(等了约 ${(i + 1) * 2} 秒)`);
|
|
176
202
|
return;
|
|
177
203
|
}
|
|
@@ -660,16 +686,20 @@ export function apply(ctx, 配置) {
|
|
|
660
686
|
const 记录 = 读账(账本);
|
|
661
687
|
let 在线 = false;
|
|
662
688
|
let 昵称 = '';
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
689
|
+
在线 = (await 探NapCat()) === 'ok';
|
|
690
|
+
if (在线) {
|
|
691
|
+
try {
|
|
692
|
+
const r = await 调('get_login_info', {});
|
|
693
|
+
昵称 = String(r.data?.nickname ?? '');
|
|
694
|
+
} catch {
|
|
695
|
+
/* 探到了但取名字失败,别当离线 */
|
|
696
|
+
}
|
|
669
697
|
}
|
|
698
|
+
const 端口状态 = 在线 ? 'ok' : await 探NapCat();
|
|
670
699
|
发json(res, 200, {
|
|
671
700
|
ok: true,
|
|
672
701
|
online: 在线,
|
|
702
|
+
portState: 端口状态,
|
|
673
703
|
nickname: 昵称,
|
|
674
704
|
qqnt: 体检().qqnt,
|
|
675
705
|
napcat: 体检().napcat,
|