dsh-qqbot-expands 0.4.1 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/index.js +37 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -17,6 +17,7 @@ DeepSeek Harness(DSH)插件:**在 QQ 官方机器人插件 `@tencent-conne
17
17
  - **不读取无权限内容**:平台不下发的消息不抓取,群聊全量消息需要群主在群里开启对应权限后才生效;
18
18
  - **不收集、不上传数据**:所有状态只落在本机 `~/.dsh-qqbot/`,不向任何第三方回传;
19
19
  - **文件读取需管理员授权**:非管理员发送的图片/文件默认拦截,必须管理员明确同意后才读取;
20
+ - **设置接口需认证**:HTTP 接口 `/qqbot-expands/settings`(读写管理员 openid、语音/绘图密钥等)不对外裸开——每个请求先过宿主的 `ctx.connection.admit()`,未通过返回 401/403;宿主没有 `connection` 服务时该接口干脆不注册(失败关闭),不会退化成匿名可写;
20
21
  - 使用前请确认你的机器人已按 QQ 开放平台要求完成注册、审核,并在群主/管理员授权范围内使用。
21
22
 
22
23
  如果平台规则与本文冲突,以 QQ 开放平台规则为准。
package/index.js CHANGED
@@ -1390,16 +1390,51 @@ async function handleSettingsRoute(rt, req, res) {
1390
1390
  sendJson(res, 200, { ok: true, ...settingsSnapshot(rt) })
1391
1391
  }
1392
1392
 
1393
+ /** 设置接口的准入:交给宿主 Connection 校验签名凭据与活 Peer,缺服务时失败关闭。 */
1394
+ function admitSettingsRequest(connection, req, res) {
1395
+ if (!connection || typeof connection.admit !== 'function') {
1396
+ // fail closed:没有 connection 服务就不给读写配置的入口
1397
+ sendJson(res, 403, { ok: false, error: '设置接口不可用:宿主未提供 connection 服务' })
1398
+ return false
1399
+ }
1400
+ let admission
1401
+ try {
1402
+ admission = connection.admit({ headers: req.headers ?? {} })
1403
+ } catch (err) {
1404
+ log('设置接口认证异常:' + (err?.message ?? err))
1405
+ sendJson(res, 401, { ok: false, error: '认证失败' })
1406
+ return false
1407
+ }
1408
+ const rejection = admission?.rejection
1409
+ if (rejection !== undefined) {
1410
+ sendJson(res, rejection, { ok: false, error: rejection === 403 ? 'forbidden' : 'unauthorized' })
1411
+ return false
1412
+ }
1413
+ if (!admission?.peer) {
1414
+ sendJson(res, 401, { ok: false, error: 'unauthorized' })
1415
+ return false
1416
+ }
1417
+ return true
1418
+ }
1419
+
1393
1420
  function registerSettingsRoutes(ctx, rt) {
1394
1421
  const inject = ctx.inject
1395
1422
  if (typeof inject !== 'function') return
1396
1423
  inject.call(ctx, ['webServer'], (scoped) => {
1397
1424
  const webServer = scoped.webServer
1398
1425
  if (!webServer || typeof webServer.register !== 'function') return
1426
+ const connection = typeof scoped.get === 'function' ? scoped.get('connection') : undefined
1427
+ if (!connection || typeof connection.admit !== 'function') {
1428
+ log('未提供 connection 服务,设置接口不注册(不以无认证方式开放)')
1429
+ return
1430
+ }
1399
1431
  const dispose = webServer.register({
1400
1432
  kind: 'exact',
1401
1433
  path: '/qqbot-expands/settings',
1402
- handler: (req, res) => { void handleSettingsRoute(rt, req, res) },
1434
+ handler: (req, res) => {
1435
+ if (!admitSettingsRequest(connection, req, res)) return
1436
+ void handleSettingsRoute(rt, req, res)
1437
+ },
1403
1438
  })
1404
1439
  scoped.effect(() => dispose, 'qqbot-expands.settings-routes')
1405
1440
  })
@@ -2292,7 +2327,7 @@ function buildTools(ctx, rt) {
2292
2327
  // ─────────────────────────── 入口 ───────────────────────────
2293
2328
 
2294
2329
  // 仅供单测使用(不参与运行时)
2295
- export const __test = { createRuntime, resolveConfig, tickGreeting, greetingSummary, handleSettingsRoute, settingsSnapshot }
2330
+ export const __test = { createRuntime, resolveConfig, tickGreeting, greetingSummary, handleSettingsRoute, settingsSnapshot, admitSettingsRequest }
2296
2331
 
2297
2332
  export async function apply(ctx, config) {
2298
2333
  const resolved = resolveConfig(config)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-qqbot-expands",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "QQ 官方机器人插件(@tencent-connect/dsh-qqbot)的功能拓展 bundle:群聊频控、私聊问候、表情包、语音、绘图与统一设置页。",
6
6
  "main": "./index.js",