dsh-qq-moony 0.5.0 → 0.5.2

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,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.5.2 — 2026-10-25
4
+
5
+ - 拉起 NapCat 时不再弹黑窗口:改成生成 VBS、用 `wscript` 静默执行(`windowsHide` 对批处理无效)
6
+ - README 补一句:自启是静默的,不用留一个控制台窗口在那儿
7
+
8
+ ## 0.5.1 — 2026-10-25
9
+
10
+ - 修:点「保存更改」之后设置页会空白——草稿被清空、新值还没回来那一瞬没有可显示的值
11
+ - 现在每个字段都有兜底:草稿为空就用服务端返回的值
12
+
3
13
  ## 0.5.0 — 2026-10-25
4
14
 
5
15
  装完之后不再一片红:缺什么会自己说出来。
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
@@ -100,58 +100,62 @@ window.__ModuleLoader__.load({
100
100
  const [草稿, 设草稿] = React.useState(null);
101
101
  const [脏, 设脏] = React.useState(false);
102
102
 
103
+ // 草稿没建起来之前,先用状态里的值兜底——省得"保存"之后闪回空白
104
+ const 从状态取 = () => ({
105
+ everyMinMin: 状态?.everyMinMin ?? 45,
106
+ everyMinMax: 状态?.everyMinMax ?? 90,
107
+ perHour: 状态?.perHour ?? 20,
108
+ perDay: 状态?.perDay ?? 60,
109
+ qzoneMinMin: 状态?.qzoneMinMin ?? 120,
110
+ qzoneMinMax: 状态?.qzoneMinMax ?? 240,
111
+ qzonePrompt: 状态?.qzonePrompt ?? '',
112
+ groupWhitelist: (状态?.groupWhitelist ?? []).join(' '),
113
+ groupContextSize: 状态?.groupContextSize ?? 30,
114
+ groupEveryMinMin: 状态?.groupEveryMinMin ?? 8,
115
+ groupEveryMinMax: 状态?.groupEveryMinMax ?? 20,
116
+ groupActiveWindowMin: 状态?.groupActiveWindowMin ?? 5,
117
+ groupCooldownMin: 状态?.groupCooldownMin ?? 10,
118
+ groupPerDay: 状态?.groupPerDay ?? 20,
119
+ });
120
+
103
121
  React.useEffect(() => {
104
122
  if (状态 && 草稿 === null) {
105
- 设草稿({
106
- everyMinMin: 状态.everyMinMin ?? 45,
107
- everyMinMax: 状态.everyMinMax ?? 90,
108
- perHour: 状态.perHour ?? 20,
109
- perDay: 状态.perDay ?? 60,
110
- qzoneMinMin: 状态.qzoneMinMin ?? 120,
111
- qzoneMinMax: 状态.qzoneMinMax ?? 240,
112
- qzonePrompt: 状态.qzonePrompt ?? '',
113
- groupWhitelist: (状态.groupWhitelist ?? []).join(' '),
114
- groupContextSize: 状态.groupContextSize ?? 30,
115
- groupEveryMinMin: 状态.groupEveryMinMin ?? 8,
116
- groupEveryMinMax: 状态.groupEveryMinMax ?? 20,
117
- groupActiveWindowMin: 状态.groupActiveWindowMin ?? 5,
118
- groupCooldownMin: 状态.groupCooldownMin ?? 10,
119
- groupPerDay: 状态.groupPerDay ?? 20,
120
- });
123
+ 设草稿(从状态取());
121
124
  }
122
125
  }, [状态, 草稿]);
123
126
 
124
- const 数字 = (键, 值) => {
125
- 设草稿((旧) => ({ ...(旧 ?? {}), [键]: 值 }));
127
+ const 数字 = (键, 新值) => {
128
+ 设草稿((旧) => ({ ...(旧 ?? 从状态取()), [键]: 新值 }));
126
129
  设脏(true);
127
130
  };
128
131
 
129
132
  const 保存 = async () => {
130
- if (!草稿) return;
133
+ const 值 = 草稿 ?? 从状态取();
131
134
  await 改({
132
- everyMinMin: Number(草稿.everyMinMin),
133
- everyMinMax: Number(草稿.everyMinMax),
134
- perHour: Number(草稿.perHour),
135
- perDay: Number(草稿.perDay),
136
- qzoneMinMin: Number(草稿.qzoneMinMin),
137
- qzoneMinMax: Number(草稿.qzoneMinMax),
138
- qzonePrompt: String(草稿.qzonePrompt ?? ''),
139
- groupWhitelist: String(草稿.groupWhitelist ?? ''),
140
- groupContextSize: Number(草稿.groupContextSize),
141
- groupEveryMinMin: Number(草稿.groupEveryMinMin),
142
- groupEveryMinMax: Number(草稿.groupEveryMinMax),
143
- groupActiveWindowMin: Number(草稿.groupActiveWindowMin),
144
- groupCooldownMin: Number(草稿.groupCooldownMin),
145
- groupPerDay: Number(草稿.groupPerDay),
135
+ everyMinMin: Number(值.everyMinMin),
136
+ everyMinMax: Number(值.everyMinMax),
137
+ perHour: Number(值.perHour),
138
+ perDay: Number(值.perDay),
139
+ qzoneMinMin: Number(值.qzoneMinMin),
140
+ qzoneMinMax: Number(值.qzoneMinMax),
141
+ qzonePrompt: String(值.qzonePrompt ?? ''),
142
+ groupWhitelist: String(值.groupWhitelist ?? ''),
143
+ groupContextSize: Number(值.groupContextSize),
144
+ groupEveryMinMin: Number(值.groupEveryMinMin),
145
+ groupEveryMinMax: Number(值.groupEveryMinMax),
146
+ groupActiveWindowMin: Number(值.groupActiveWindowMin),
147
+ groupCooldownMin: Number(值.groupCooldownMin),
148
+ groupPerDay: Number(值.groupPerDay),
146
149
  });
147
150
  设脏(false);
148
151
  设草稿(null);
149
152
  };
150
153
 
151
- if (状态 === null || 草稿 === null) {
154
+ if (状态 === null) {
152
155
  return h('div', { style: { padding: '8px 0', opacity: 0.6 } }, 错 || '读状态中…');
153
156
  }
154
157
 
158
+ const 值 = 草稿 ?? 从状态取();
155
159
  const 缺口 = [];
156
160
  if (!状态.qqnt) 缺口.push('没找到 QQ NT —— 去 im.qq.com 装新版(9.9.x)。老版 9.7 注不进去,这是死条件。');
157
161
  if (!状态.napcat) 缺口.push('没找到 NapCat —— 去 github.com/NapNeko/NapCatQQ 下 Shell 版,解压后把 napCatDir 指过去。');
@@ -204,7 +208,7 @@ window.__ModuleLoader__.load({
204
208
  'div',
205
209
  null,
206
210
  h('div', { style: 标题 }, '主动说话'),
207
- h('div', { style: 说明 }, `开着它才会自己找你,大约每 ${草稿.everyMinMin}–${草稿.everyMinMax} 分钟有机会开口一次;关掉就只回不发`),
211
+ h('div', { style: 说明 }, `开着它才会自己找你,大约每 ${值.everyMinMin}–${值.everyMinMax} 分钟有机会开口一次;关掉就只回不发`),
208
212
  ),
209
213
  h(开关, { 开: 状态.proactive, 点: () => 改({ proactive: !状态.proactive }) }),
210
214
  ),
@@ -234,7 +238,7 @@ window.__ModuleLoader__.load({
234
238
  h('input', {
235
239
  type: 'number',
236
240
  min: 5,
237
- value: 草稿.everyMinMin,
241
+ value: 值.everyMinMin,
238
242
  onChange: (e) => 数字('everyMinMin', Number(e.target.value)),
239
243
  style: { ...输入框, width: '78px' },
240
244
  }),
@@ -242,7 +246,7 @@ window.__ModuleLoader__.load({
242
246
  h('input', {
243
247
  type: 'number',
244
248
  min: 5,
245
- value: 草稿.everyMinMax,
249
+ value: 值.everyMinMax,
246
250
  onChange: (e) => 数字('everyMinMax', Number(e.target.value)),
247
251
  style: { ...输入框, width: '78px' },
248
252
  }),
@@ -261,7 +265,7 @@ window.__ModuleLoader__.load({
261
265
  type: 'number',
262
266
  min: 1,
263
267
  max: 200,
264
- value: 草稿.perHour,
268
+ value: 值.perHour,
265
269
  onChange: (e) => 数字('perHour', Number(e.target.value)),
266
270
  style: 输入框,
267
271
  }),
@@ -279,7 +283,7 @@ window.__ModuleLoader__.load({
279
283
  type: 'number',
280
284
  min: 1,
281
285
  max: 1000,
282
- value: 草稿.perDay,
286
+ value: 值.perDay,
283
287
  onChange: (e) => 数字('perDay', Number(e.target.value)),
284
288
  style: 输入框,
285
289
  }),
@@ -305,7 +309,7 @@ window.__ModuleLoader__.load({
305
309
  ),
306
310
  h('input', {
307
311
  type: 'text',
308
- value: 草稿.groupWhitelist,
312
+ value: 值.groupWhitelist,
309
313
  placeholder: '群号白名单,空格或逗号分隔;空着 = 群聊不生效',
310
314
  onChange: (e) => 数字('groupWhitelist', e.target.value),
311
315
  style: { ...输入框, width: '100%', boxSizing: 'border-box' },
@@ -318,7 +322,7 @@ window.__ModuleLoader__.load({
318
322
  type: 'number',
319
323
  min: 5,
320
324
  max: 100,
321
- value: 草稿.groupContextSize,
325
+ value: 值.groupContextSize,
322
326
  onChange: (e) => 数字('groupContextSize', Number(e.target.value)),
323
327
  style: { ...输入框, width: '70px' },
324
328
  }),
@@ -326,7 +330,7 @@ window.__ModuleLoader__.load({
326
330
  h('input', {
327
331
  type: 'number',
328
332
  min: 2,
329
- value: 草稿.groupEveryMinMin,
333
+ value: 值.groupEveryMinMin,
330
334
  onChange: (e) => 数字('groupEveryMinMin', Number(e.target.value)),
331
335
  style: { ...输入框, width: '70px' },
332
336
  }),
@@ -334,7 +338,7 @@ window.__ModuleLoader__.load({
334
338
  h('input', {
335
339
  type: 'number',
336
340
  min: 2,
337
- value: 草稿.groupEveryMinMax,
341
+ value: 值.groupEveryMinMax,
338
342
  onChange: (e) => 数字('groupEveryMinMax', Number(e.target.value)),
339
343
  style: { ...输入框, width: '70px' },
340
344
  }),
@@ -342,7 +346,7 @@ window.__ModuleLoader__.load({
342
346
  h('input', {
343
347
  type: 'number',
344
348
  min: 1,
345
- value: 草稿.groupActiveWindowMin,
349
+ value: 值.groupActiveWindowMin,
346
350
  onChange: (e) => 数字('groupActiveWindowMin', Number(e.target.value)),
347
351
  style: { ...输入框, width: '70px' },
348
352
  }),
@@ -355,7 +359,7 @@ window.__ModuleLoader__.load({
355
359
  h('input', {
356
360
  type: 'number',
357
361
  min: 1,
358
- value: 草稿.groupCooldownMin,
362
+ value: 值.groupCooldownMin,
359
363
  onChange: (e) => 数字('groupCooldownMin', Number(e.target.value)),
360
364
  style: { ...输入框, width: '70px' },
361
365
  }),
@@ -363,7 +367,7 @@ window.__ModuleLoader__.load({
363
367
  h('input', {
364
368
  type: 'number',
365
369
  min: 1,
366
- value: 草稿.groupPerDay,
370
+ value: 值.groupPerDay,
367
371
  onChange: (e) => 数字('groupPerDay', Number(e.target.value)),
368
372
  style: { ...输入框, width: '70px' },
369
373
  }),
@@ -389,7 +393,7 @@ window.__ModuleLoader__.load({
389
393
  ),
390
394
  h('textarea', {
391
395
  rows: 3,
392
- value: 草稿.qzonePrompt,
396
+ value: 值.qzonePrompt,
393
397
  placeholder: '例:一周发一次,写点最近的感受,两三句,不要提具体的人和地点',
394
398
  onChange: (e) => 数字('qzonePrompt', e.target.value),
395
399
  style: {
@@ -413,7 +417,7 @@ window.__ModuleLoader__.load({
413
417
  h('input', {
414
418
  type: 'number',
415
419
  min: 10,
416
- value: 草稿.qzoneMinMin,
420
+ value: 值.qzoneMinMin,
417
421
  onChange: (e) => 数字('qzoneMinMin', Number(e.target.value)),
418
422
  style: { ...输入框, width: '78px' },
419
423
  }),
@@ -421,7 +425,7 @@ window.__ModuleLoader__.load({
421
425
  h('input', {
422
426
  type: 'number',
423
427
  min: 10,
424
- value: 草稿.qzoneMinMax,
428
+ value: 值.qzoneMinMax,
425
429
  onChange: (e) => 数字('qzoneMinMax', Number(e.target.value)),
426
430
  style: { ...输入框, width: '78px' },
427
431
  }),
package/index.js CHANGED
@@ -156,14 +156,22 @@ export function apply(ctx, 配置) {
156
156
  return;
157
157
  }
158
158
  try {
159
- const 子 = spawn('cmd.exe', ['/c', 'launcher-user.bat', '-q', 号码], {
160
- cwd: 目录,
159
+ // 用 VBS 起,窗口不弹出来(cmd 的隐藏参数对批处理不管用)
160
+ const 启动脚本 = join(家目录(), 'start-napcat.vbs');
161
+ mkdirSync(家目录(), { recursive: true });
162
+ const 批处理 = join(目录, 'launcher-user.bat');
163
+ const vbs =
164
+ `Set sh = CreateObject("WScript.Shell")\r\n` +
165
+ `sh.Run "cmd /c ""${批处理}"" -q ${号码}", 0, False\r\n`;
166
+ // .vbs 用 UTF-16LE + BOM,中文路径才认
167
+ writeFileSync(启动脚本, Buffer.concat([Buffer.from([0xff, 0xfe]), Buffer.from(vbs, 'utf16le')]));
168
+ const 子 = spawn('wscript.exe', [启动脚本], {
161
169
  detached: true,
162
170
  stdio: 'ignore',
163
171
  windowsHide: true,
164
172
  });
165
173
  子.unref();
166
- 记调试(`NapCat 没在跑,已拉起(${目录},-q ${号码})`);
174
+ 记调试(`NapCat 没在跑,已静默拉起(${目录},-q ${号码})`);
167
175
  } catch (e) {
168
176
  记调试(`拉 NapCat 失败:${e?.message ?? e}`);
169
177
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-qq-moony",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "把 QQ 小号接进 DeepSeek Harness:收发消息、发表情包、发 QQ 空间说说、参与群聊,能自己找话题,自带启动与限速防封。",
5
5
  "keywords": [
6
6
  "dsh",