@zaofan/dsh-qqbot 1.10.26 → 1.10.27

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/README.md CHANGED
@@ -73,8 +73,94 @@ QQ 官方**没有开放踢人接口**,所以这一块走"你自己的 QQ 号 +
73
73
 
74
74
  ![群管理·审批放行成功效果](docs/screenshots/group-admin-approval-chat.png)
75
75
 
76
+ 图⑥:**插件市场**——两列卡片、封面图、版本号、安装/更新/卸载一键搞定(数据来自扩展索引仓库,支持填代理解决墙内访问);
77
+ 图⑦:**扩展包面板**——每个包下面直接列出它带的工具和 `/斜杠命令`,点「设置」还能配自定义参数。
78
+
79
+ ![插件市场(卡片网格 / 封面 / 一键安装更新)](docs/images/market.png)
80
+
81
+ ![扩展包面板(工具与斜杠命令按包分组展示)](docs/images/packs.png)
82
+
83
+ 图⑧:**设置中心**——50 个内置扩展一览,每个都能单独开关、点齿轮改配置;
84
+ 图⑨:**扩展自注册设置面板**——扩展用 `qqbotSettingsPage` 声明 schema,面板自动渲染出表单,值存成 JSON 供扩展读取。
85
+
86
+ ![设置中心(内置扩展一览与单条开关)](docs/images/settings-center.png)
87
+
88
+ ![扩展自注册设置面板(声明式 schema 自动渲染)](docs/images/ext-settings.png)
89
+
90
+ ---
91
+
92
+
76
93
  ---
77
94
 
95
+ ## 📦 扩展包与插件市场:把你的扩展分享给别人
96
+
97
+ 单个 `.mjs` 是「扩展文件」,**一个目录就是一个「扩展包」** —— 可以带工具、斜杠命令、封面、版本号,装进别人的面板里就是一张卡片。
98
+
99
+ 市场索引在独立仓库:[**zaofan-make/dsh-qqbot-plugins**](https://github.com/zaofan-make/dsh-qqbot-plugins)。
100
+
101
+ ### 目录结构
102
+
103
+ ```
104
+ packs/你的插件id/ ← id 只能用字母数字-_(它就是安装后的目录名)
105
+ qqbot-pack.json ← 元信息,必填
106
+ cover.png ← 可选,卡片封面(自动探测 cover.png/jpg/webp/gif)
107
+ tools/xxx.mjs ← 可选,给 AI 调用的工具
108
+ commands/yyy.mjs ← 可选,/斜杠命令
109
+ ```
110
+
111
+ `qqbot-pack.json`:
112
+
113
+ ```json
114
+ {
115
+ "name": "实用小工具",
116
+ "author": "你的名字",
117
+ "version": "1.0.0",
118
+ "description": "一句话说明,会显示在卡片上",
119
+ "homepage": "https://github.com/你/你的仓库",
120
+ "tags": ["工具", "日常"]
121
+ }
122
+ ```
123
+
124
+ `name` / `author` / `version` 必填,其余可选。
125
+
126
+ ### 上传流程(不需要 token,也不会冲突)
127
+
128
+ ```bash
129
+ # 1. fork + clone
130
+ git clone https://github.com/<你>/dsh-qqbot-plugins.git
131
+
132
+ # 2. 只加你自己的目录
133
+ mkdir -p packs/my-pack/tools packs/my-pack/commands
134
+ # 写 qqbot-pack.json、tools/*.mjs、commands/*.mjs
135
+
136
+ # 3. 提 PR
137
+ ```
138
+
139
+ **不要改 `index.json`** —— 它由 GitHub Action 自动生成:
140
+
141
+ - 提 PR → 自动跑检查(manifest 字段、`node --check` 语法、禁二进制、`inputSchema` 格式)
142
+ - 合并到 main → Action 扫描 `packs/*/qqbot-pack.json`,重建索引(**顺便把文件清单和封面也扫出来**,你不用手写)
143
+ - 两个人同时提 PR **也不会冲突**,因为各自只加自己的目录
144
+
145
+ ### ⚠️ 最容易踩的坑:`inputSchema` 不是标准 JSON Schema
146
+
147
+ ```js
148
+ // ✅ 对:dsh 的扁平写法,属性名 → 类型描述
149
+ export default {
150
+ name: 'pick_one',
151
+ description: '从列表里随机挑一个',
152
+ inputSchema: {
153
+ options: { type: 'array', items: { type: 'string' }, description: '候选选项' },
154
+ },
155
+ run: async (args) => ({ ok: true, msg: '选中:' + args.options[0] }),
156
+ }
157
+
158
+ // ❌ 错:包成标准 JSON Schema,注册时会被拒
159
+ // inputSchema: { type: 'object', properties: { options: {...} } }
160
+ // → unsupported JSON schema: parameters.type must be a value schema object
161
+ ```
162
+
163
+ 命令的契约也不一样:工具用 **`run`**,命令用 **`handler`**(返回字符串)。
78
164
 
79
165
  ---
80
166
 
@@ -646,55 +732,55 @@ AI 侧的工具叫 **`qq_group_admin`**:
646
732
  - **不常驻**:拿到凭据立刻关;等扫码最多留 5 分钟;宿主退出时会一起带走(不留孤儿进程)
647
733
  - 凭据只存在你自己的机器上,仓库里不含任何凭据
648
734
 
649
- ## ♻️ 撤回消息与自动撤回(v1.10.11+)
650
-
651
- 机器人**是群管理员**时,可以撤回**普通成员**的消息(官方窗口 2 分钟,超时就撤不了,这是平台限制)。
652
-
653
- ### 三个工具
654
-
655
- | 工具 | 作用 |
656
- | --- | --- |
657
- | `group_recall` | 撤某人最近一条 / 群里最近一条 / 指定 message_id |
658
- | `group_msg_search` | 按关键词或类型搜台账(**含机器人自己发的**),返回 message_id |
659
- | `group_recall_batch` | 批量撤(给 msg_ids,或给关键词/类型让它自己挑)+ 可选批量禁言发送者 |
660
-
661
- `gid` 是**可选**的:不传 = 当前会话所在的群;要撤别的群(机器人也是那个群的管理员)才传。
662
-
663
- ### 自动撤回(设置面板 → 🔨 锤子 → ♻️ 自动撤回)
664
-
665
- 命中关键词或附件类型 → 消息**一进来就撤**,不等 AI。配置项 `groupAdmin.autoRecall`:
666
-
667
- ```yaml
668
- autoRecall:
669
- enabled: true
670
- mode: keep # keep=仍进 AI(只撤消息);drop=连 AI 都收不到
671
- keywords: ["加我微信"]
672
- kinds: [] # text / image / voice / video / file,按附件类型命中
673
- muteSeconds: 0 # >0 时顺带禁言发送者
674
- dryRun: false # true = 只记日志、不真撤
675
- ```
676
-
677
- > **实现位置很关键**:挂在 **debounce 之前**的中间件里。
678
- > 写在 `bot.on('message')` 里会被 debounce 吃掉(它 consume 后自己调 `handleInbound`);
679
- > 写在 `handleInbound` 里又要等派发,等到了往往已过 2 分钟窗口 —— 两种都实测踩过。
680
-
681
- ## 📒 消息历史台账(v1.10.11+)
682
-
683
- ```
684
- {dataRoot}/.qqbot/msg-history/
685
- ├── _索引.txt # 目录 ↔ 群名 对照,方便人工辨认
686
- ├── group_<群openid>/
687
- │ ├── 群名.txt # 文件名就是群名
688
- │ └── 2026-10-20.jsonl # 一天一个文件
689
- └── c2c_<对方openid>/
690
- └── 2026-10-20.jsonl
691
- ```
692
-
693
- - 一行一条:`message_id` / 发送者 / 昵称 / 类型 / 正文摘要 / 时间 / 是否机器人
694
- - 默认保留 **7 天**(启动时 + 每 200 次写清理过期文件;目录空了自动删)
695
- - 入站与出站都记;`group_msg_search` / `group_recall*` 就是读它
696
- - 与引用补全用的 `.qqbot/msg-content.jsonl` **互不干扰**(后者只存被引用消息的正文与图片路径)
697
-
735
+ ## ♻️ 撤回消息与自动撤回(v1.10.11+)
736
+
737
+ 机器人**是群管理员**时,可以撤回**普通成员**的消息(官方窗口 2 分钟,超时就撤不了,这是平台限制)。
738
+
739
+ ### 三个工具
740
+
741
+ | 工具 | 作用 |
742
+ | --- | --- |
743
+ | `group_recall` | 撤某人最近一条 / 群里最近一条 / 指定 message_id |
744
+ | `group_msg_search` | 按关键词或类型搜台账(**含机器人自己发的**),返回 message_id |
745
+ | `group_recall_batch` | 批量撤(给 msg_ids,或给关键词/类型让它自己挑)+ 可选批量禁言发送者 |
746
+
747
+ `gid` 是**可选**的:不传 = 当前会话所在的群;要撤别的群(机器人也是那个群的管理员)才传。
748
+
749
+ ### 自动撤回(设置面板 → 🔨 锤子 → ♻️ 自动撤回)
750
+
751
+ 命中关键词或附件类型 → 消息**一进来就撤**,不等 AI。配置项 `groupAdmin.autoRecall`:
752
+
753
+ ```yaml
754
+ autoRecall:
755
+ enabled: true
756
+ mode: keep # keep=仍进 AI(只撤消息);drop=连 AI 都收不到
757
+ keywords: ["加我微信"]
758
+ kinds: [] # text / image / voice / video / file,按附件类型命中
759
+ muteSeconds: 0 # >0 时顺带禁言发送者
760
+ dryRun: false # true = 只记日志、不真撤
761
+ ```
762
+
763
+ > **实现位置很关键**:挂在 **debounce 之前**的中间件里。
764
+ > 写在 `bot.on('message')` 里会被 debounce 吃掉(它 consume 后自己调 `handleInbound`);
765
+ > 写在 `handleInbound` 里又要等派发,等到了往往已过 2 分钟窗口 —— 两种都实测踩过。
766
+
767
+ ## 📒 消息历史台账(v1.10.11+)
768
+
769
+ ```
770
+ {dataRoot}/.qqbot/msg-history/
771
+ ├── _索引.txt # 目录 ↔ 群名 对照,方便人工辨认
772
+ ├── group_<群openid>/
773
+ │ ├── 群名.txt # 文件名就是群名
774
+ │ └── 2026-10-20.jsonl # 一天一个文件
775
+ └── c2c_<对方openid>/
776
+ └── 2026-10-20.jsonl
777
+ ```
778
+
779
+ - 一行一条:`message_id` / 发送者 / 昵称 / 类型 / 正文摘要 / 时间 / 是否机器人
780
+ - 默认保留 **7 天**(启动时 + 每 200 次写清理过期文件;目录空了自动删)
781
+ - 入站与出站都记;`group_msg_search` / `group_recall*` 就是读它
782
+ - 与引用补全用的 `.qqbot/msg-content.jsonl` **互不干扰**(后者只存被引用消息的正文与图片路径)
783
+
698
784
  ## 🚫 无上下文模式(按会话省 token)
699
785
 
700
786
  让某个 QQ 会话**每轮只记得最近几条对话**,更早的历史自动折叠 —— 群聊省 token 利器。
@@ -728,28 +814,28 @@ autoRecall:
728
814
  ## License
729
815
 
730
816
  [MIT](./LICENSE)
731
-
732
- ---
733
-
734
- ## 正文图组:markdown 图片直接发
735
-
736
- DSH 前端会把**回复正文里的 markdown 图片**渲染成图;本插件把同一段文本**原样转发到 QQ** ——
737
- 本地路径会自动上传成 `qqbot-media` 引用(读文件头补真实宽高,配额满 100 张自动删最早),不需要调用任何工具。
738
-
739
- ```markdown
740
- ![干饭女王 #400px](D:/pics/a.jpg)
741
-
742
- 第一幕:本鲸宣布今晚不睡了
743
-
744
- ![何意味 #400px](D:/pics/b.jpg)
745
- ```
746
-
747
- **一行一张、连续几行就是图组**(小剧场 / 分镜 / 图文并排),QQ 侧按顺序渲染成一屏。
748
-
749
- | DSH 前端 | QQ 群 |
750
- | :---: | :---: |
751
- | ![DSH 前端显示](docs/images/dsh-md-images.png) | ![QQ 群显示](docs/images/qq-md-images.jpg) |
752
-
753
- 配合表情包库最顺手:`list_stickers` 搜到图 → 把本地路径写进正文 → 图组直接出来,比连发 `send_media` 更像翻漫画。
754
-
755
- 失败策略:图传不上去时会**原样留在文字里**(不阻断本条,不会吞掉正文)。
817
+
818
+ ---
819
+
820
+ ## 正文图组:markdown 图片直接发
821
+
822
+ DSH 前端会把**回复正文里的 markdown 图片**渲染成图;本插件把同一段文本**原样转发到 QQ** ——
823
+ 本地路径会自动上传成 `qqbot-media` 引用(读文件头补真实宽高,配额满 100 张自动删最早),不需要调用任何工具。
824
+
825
+ ```markdown
826
+ ![干饭女王 #400px](D:/pics/a.jpg)
827
+
828
+ 第一幕:本鲸宣布今晚不睡了
829
+
830
+ ![何意味 #400px](D:/pics/b.jpg)
831
+ ```
832
+
833
+ **一行一张、连续几行就是图组**(小剧场 / 分镜 / 图文并排),QQ 侧按顺序渲染成一屏。
834
+
835
+ | DSH 前端 | QQ 群 |
836
+ | :---: | :---: |
837
+ | ![DSH 前端显示](docs/images/dsh-md-images.png) | ![QQ 群显示](docs/images/qq-md-images.jpg) |
838
+
839
+ 配合表情包库最顺手:`list_stickers` 搜到图 → 把本地路径写进正文 → 图组直接出来,比连发 `send_media` 更像翻漫画。
840
+
841
+ 失败策略:图传不上去时会**原样留在文字里**(不阻断本条,不会吞掉正文)。