dsh-qq-moony 0.4.0 → 0.5.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 +11 -0
- package/README.md +3 -1
- package/client.js +80 -50
- package/index.js +15 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.5.0 — 2026-10-25
|
|
4
|
+
|
|
5
|
+
装完之后不再一片红:缺什么会自己说出来。
|
|
6
|
+
|
|
7
|
+
**新增**
|
|
8
|
+
- 体检:设置页顶部检查三件事——QQ NT 装没装、NapCat 找不找得到、能不能连上;缺哪样就列出来,写清去哪儿下、哪几步
|
|
9
|
+
- 状态接口多返回 `qqnt` / `napcat` 两个字段
|
|
10
|
+
|
|
11
|
+
**为什么不能一条命令全装**
|
|
12
|
+
QQ NT 是几百兆的客户端(要管理员权限),NapCat 要往 QQ 进程里注入(要匹配版本)——npm 包装不下这两样。插件能做的是:缺东西的时候说清楚缺什么,而不是让人装完盯着一片红发呆。
|
|
13
|
+
|
|
3
14
|
## 0.4.0 — 2026-10-25
|
|
4
15
|
|
|
5
16
|
群聊从"只回 @"变成"会参与聊天"。
|
package/README.md
CHANGED
|
@@ -64,7 +64,9 @@ NapCat 是接管整个 QQ 客户端的行为——消息收发、登录态、空
|
|
|
64
64
|
|
|
65
65
|
## 三、设置页(名字叫「QQ嗦嗨嗨」)
|
|
66
66
|
|
|
67
|
-
装完重启 DSH,设置里会多一项 **QQ
|
|
67
|
+
装完重启 DSH,设置里会多一项 **QQ嗦嗨嗨**。
|
|
68
|
+
|
|
69
|
+
**顶上一块是体检**:QQ NT 装没装、NapCat 找不找得到、能不能连上。缺哪样它就列哪样,写明去哪儿下、哪几步——不用盯着一片红猜。
|
|
68
70
|
|
|
69
71
|
- **连接状态**:在线没有、登录的是谁、今天发了多少、上限多少
|
|
70
72
|
- **主动说话**:开关(点一下即时保存)
|
package/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
2
|
id: 'dsh-qq-moony',
|
|
3
3
|
factory(require) {
|
|
4
4
|
const React = require('react');
|
|
@@ -100,61 +100,91 @@
|
|
|
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
|
-
|
|
133
|
+
const 值 = 草稿 ?? 从状态取();
|
|
131
134
|
await 改({
|
|
132
|
-
everyMinMin: Number(
|
|
133
|
-
everyMinMax: Number(
|
|
134
|
-
perHour: Number(
|
|
135
|
-
perDay: Number(
|
|
136
|
-
qzoneMinMin: Number(
|
|
137
|
-
qzoneMinMax: Number(
|
|
138
|
-
qzonePrompt: String(
|
|
139
|
-
groupWhitelist: String(
|
|
140
|
-
groupContextSize: Number(
|
|
141
|
-
groupEveryMinMin: Number(
|
|
142
|
-
groupEveryMinMax: Number(
|
|
143
|
-
groupActiveWindowMin: Number(
|
|
144
|
-
groupCooldownMin: Number(
|
|
145
|
-
groupPerDay: Number(
|
|
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
|
|
154
|
+
if (状态 === null) {
|
|
152
155
|
return h('div', { style: { padding: '8px 0', opacity: 0.6 } }, 错 || '读状态中…');
|
|
153
156
|
}
|
|
154
157
|
|
|
158
|
+
const 值 = 草稿 ?? 从状态取();
|
|
159
|
+
const 缺口 = [];
|
|
160
|
+
if (!状态.qqnt) 缺口.push('没找到 QQ NT —— 去 im.qq.com 装新版(9.9.x)。老版 9.7 注不进去,这是死条件。');
|
|
161
|
+
if (!状态.napcat) 缺口.push('没找到 NapCat —— 去 github.com/NapNeko/NapCatQQ 下 Shell 版,解压后把 napCatDir 指过去。');
|
|
162
|
+
if (状态.qqnt && 状态.napcat && !状态.online)
|
|
163
|
+
缺口.push('QQ NT 和 NapCat 都在,但连不上 —— 检查 NapCat 启没启、3000 端口、token 三样。');
|
|
164
|
+
|
|
155
165
|
return h(
|
|
156
166
|
'div',
|
|
157
167
|
null,
|
|
168
|
+
缺口.length > 0
|
|
169
|
+
? h(
|
|
170
|
+
'div',
|
|
171
|
+
{
|
|
172
|
+
style: {
|
|
173
|
+
...卡片,
|
|
174
|
+
flexDirection: 'column',
|
|
175
|
+
alignItems: 'stretch',
|
|
176
|
+
gap: '6px',
|
|
177
|
+
borderColor: 'var(--dsw-alias-warning-1, #d99b2b)',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
h(
|
|
181
|
+
'div',
|
|
182
|
+
{ style: { ...标题, color: 'var(--dsw-alias-warning-1, #d99b2b)' } },
|
|
183
|
+
'还差几步才能用',
|
|
184
|
+
),
|
|
185
|
+
缺口.map((行, i) => h('div', { key: i, style: 说明 }, `${i + 1}. ${行}`)),
|
|
186
|
+
)
|
|
187
|
+
: null,
|
|
158
188
|
h(
|
|
159
189
|
'div',
|
|
160
190
|
{ style: { ...卡片 } },
|
|
@@ -178,7 +208,7 @@
|
|
|
178
208
|
'div',
|
|
179
209
|
null,
|
|
180
210
|
h('div', { style: 标题 }, '主动说话'),
|
|
181
|
-
h('div', { style: 说明 }, `开着它才会自己找你,大约每 ${
|
|
211
|
+
h('div', { style: 说明 }, `开着它才会自己找你,大约每 ${值.everyMinMin}–${值.everyMinMax} 分钟有机会开口一次;关掉就只回不发`),
|
|
182
212
|
),
|
|
183
213
|
h(开关, { 开: 状态.proactive, 点: () => 改({ proactive: !状态.proactive }) }),
|
|
184
214
|
),
|
|
@@ -208,7 +238,7 @@
|
|
|
208
238
|
h('input', {
|
|
209
239
|
type: 'number',
|
|
210
240
|
min: 5,
|
|
211
|
-
value:
|
|
241
|
+
value: 值.everyMinMin,
|
|
212
242
|
onChange: (e) => 数字('everyMinMin', Number(e.target.value)),
|
|
213
243
|
style: { ...输入框, width: '78px' },
|
|
214
244
|
}),
|
|
@@ -216,7 +246,7 @@
|
|
|
216
246
|
h('input', {
|
|
217
247
|
type: 'number',
|
|
218
248
|
min: 5,
|
|
219
|
-
value:
|
|
249
|
+
value: 值.everyMinMax,
|
|
220
250
|
onChange: (e) => 数字('everyMinMax', Number(e.target.value)),
|
|
221
251
|
style: { ...输入框, width: '78px' },
|
|
222
252
|
}),
|
|
@@ -235,7 +265,7 @@
|
|
|
235
265
|
type: 'number',
|
|
236
266
|
min: 1,
|
|
237
267
|
max: 200,
|
|
238
|
-
value:
|
|
268
|
+
value: 值.perHour,
|
|
239
269
|
onChange: (e) => 数字('perHour', Number(e.target.value)),
|
|
240
270
|
style: 输入框,
|
|
241
271
|
}),
|
|
@@ -253,7 +283,7 @@
|
|
|
253
283
|
type: 'number',
|
|
254
284
|
min: 1,
|
|
255
285
|
max: 1000,
|
|
256
|
-
value:
|
|
286
|
+
value: 值.perDay,
|
|
257
287
|
onChange: (e) => 数字('perDay', Number(e.target.value)),
|
|
258
288
|
style: 输入框,
|
|
259
289
|
}),
|
|
@@ -279,7 +309,7 @@
|
|
|
279
309
|
),
|
|
280
310
|
h('input', {
|
|
281
311
|
type: 'text',
|
|
282
|
-
value:
|
|
312
|
+
value: 值.groupWhitelist,
|
|
283
313
|
placeholder: '群号白名单,空格或逗号分隔;空着 = 群聊不生效',
|
|
284
314
|
onChange: (e) => 数字('groupWhitelist', e.target.value),
|
|
285
315
|
style: { ...输入框, width: '100%', boxSizing: 'border-box' },
|
|
@@ -292,7 +322,7 @@
|
|
|
292
322
|
type: 'number',
|
|
293
323
|
min: 5,
|
|
294
324
|
max: 100,
|
|
295
|
-
value:
|
|
325
|
+
value: 值.groupContextSize,
|
|
296
326
|
onChange: (e) => 数字('groupContextSize', Number(e.target.value)),
|
|
297
327
|
style: { ...输入框, width: '70px' },
|
|
298
328
|
}),
|
|
@@ -300,7 +330,7 @@
|
|
|
300
330
|
h('input', {
|
|
301
331
|
type: 'number',
|
|
302
332
|
min: 2,
|
|
303
|
-
value:
|
|
333
|
+
value: 值.groupEveryMinMin,
|
|
304
334
|
onChange: (e) => 数字('groupEveryMinMin', Number(e.target.value)),
|
|
305
335
|
style: { ...输入框, width: '70px' },
|
|
306
336
|
}),
|
|
@@ -308,7 +338,7 @@
|
|
|
308
338
|
h('input', {
|
|
309
339
|
type: 'number',
|
|
310
340
|
min: 2,
|
|
311
|
-
value:
|
|
341
|
+
value: 值.groupEveryMinMax,
|
|
312
342
|
onChange: (e) => 数字('groupEveryMinMax', Number(e.target.value)),
|
|
313
343
|
style: { ...输入框, width: '70px' },
|
|
314
344
|
}),
|
|
@@ -316,7 +346,7 @@
|
|
|
316
346
|
h('input', {
|
|
317
347
|
type: 'number',
|
|
318
348
|
min: 1,
|
|
319
|
-
value:
|
|
349
|
+
value: 值.groupActiveWindowMin,
|
|
320
350
|
onChange: (e) => 数字('groupActiveWindowMin', Number(e.target.value)),
|
|
321
351
|
style: { ...输入框, width: '70px' },
|
|
322
352
|
}),
|
|
@@ -329,7 +359,7 @@
|
|
|
329
359
|
h('input', {
|
|
330
360
|
type: 'number',
|
|
331
361
|
min: 1,
|
|
332
|
-
value:
|
|
362
|
+
value: 值.groupCooldownMin,
|
|
333
363
|
onChange: (e) => 数字('groupCooldownMin', Number(e.target.value)),
|
|
334
364
|
style: { ...输入框, width: '70px' },
|
|
335
365
|
}),
|
|
@@ -337,7 +367,7 @@
|
|
|
337
367
|
h('input', {
|
|
338
368
|
type: 'number',
|
|
339
369
|
min: 1,
|
|
340
|
-
value:
|
|
370
|
+
value: 值.groupPerDay,
|
|
341
371
|
onChange: (e) => 数字('groupPerDay', Number(e.target.value)),
|
|
342
372
|
style: { ...输入框, width: '70px' },
|
|
343
373
|
}),
|
|
@@ -363,7 +393,7 @@
|
|
|
363
393
|
),
|
|
364
394
|
h('textarea', {
|
|
365
395
|
rows: 3,
|
|
366
|
-
value:
|
|
396
|
+
value: 值.qzonePrompt,
|
|
367
397
|
placeholder: '例:一周发一次,写点最近的感受,两三句,不要提具体的人和地点',
|
|
368
398
|
onChange: (e) => 数字('qzonePrompt', e.target.value),
|
|
369
399
|
style: {
|
|
@@ -387,7 +417,7 @@
|
|
|
387
417
|
h('input', {
|
|
388
418
|
type: 'number',
|
|
389
419
|
min: 10,
|
|
390
|
-
value:
|
|
420
|
+
value: 值.qzoneMinMin,
|
|
391
421
|
onChange: (e) => 数字('qzoneMinMin', Number(e.target.value)),
|
|
392
422
|
style: { ...输入框, width: '78px' },
|
|
393
423
|
}),
|
|
@@ -395,7 +425,7 @@
|
|
|
395
425
|
h('input', {
|
|
396
426
|
type: 'number',
|
|
397
427
|
min: 10,
|
|
398
|
-
value:
|
|
428
|
+
value: 值.qzoneMinMax,
|
|
399
429
|
onChange: (e) => 数字('qzoneMinMax', Number(e.target.value)),
|
|
400
430
|
style: { ...输入框, width: '78px' },
|
|
401
431
|
}),
|
package/index.js
CHANGED
|
@@ -120,6 +120,19 @@ export function apply(ctx, 配置) {
|
|
|
120
120
|
|
|
121
121
|
ctx.logger?.info?.(`qq-moony: 接到 ${c.baseUrl}(限额 ${c.perHour}/时、${c.perDay}/天)`);
|
|
122
122
|
|
|
123
|
+
/** 体检:QQ NT 装没装、NapCat 在不在——缺东西的时候要能说清缺什么。 */
|
|
124
|
+
function 体检() {
|
|
125
|
+
const 候选 = [
|
|
126
|
+
'C:/Program Files/Tencent/QQNT/QQ.exe',
|
|
127
|
+
'C:/Program Files (x86)/Tencent/QQNT/QQ.exe',
|
|
128
|
+
join(homedir(), 'AppData/Local/Programs/QQNT/QQ.exe'),
|
|
129
|
+
'D:/Tencent/QQNT/QQ.exe',
|
|
130
|
+
];
|
|
131
|
+
const qqnt = 候选.some((p) => existsSync(p));
|
|
132
|
+
const napcat = Boolean(c.napCatDir) && existsSync(join(c.napCatDir, 'launcher-user.bat'));
|
|
133
|
+
return { qqnt, napcat };
|
|
134
|
+
}
|
|
135
|
+
|
|
123
136
|
/** DSH 起来时顺手看一眼 NapCat:没跑就自己拉起来(免扫码,用 -q 快速登录)。 */
|
|
124
137
|
async function 确认NapCat在跑() {
|
|
125
138
|
if (c.autoStartNapCat === false) return;
|
|
@@ -658,6 +671,8 @@ export function apply(ctx, 配置) {
|
|
|
658
671
|
ok: true,
|
|
659
672
|
online: 在线,
|
|
660
673
|
nickname: 昵称,
|
|
674
|
+
qqnt: 体检().qqnt,
|
|
675
|
+
napcat: 体检().napcat,
|
|
661
676
|
uin: Number(c.uin ?? 0),
|
|
662
677
|
proactive: Boolean(c.proactive),
|
|
663
678
|
autoReply: Boolean(c.autoReply),
|