nonebot-plugin-douyin-notify 0.1.0__tar.gz

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 (24) hide show
  1. nonebot_plugin_douyin_notify-0.1.0/LICENSE +22 -0
  2. nonebot_plugin_douyin_notify-0.1.0/PKG-INFO +240 -0
  3. nonebot_plugin_douyin_notify-0.1.0/README.md +209 -0
  4. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/__init__.py +48 -0
  5. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/commands.py +207 -0
  6. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/config.py +34 -0
  7. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/database.py +685 -0
  8. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/jobs.py +221 -0
  9. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/models.py +131 -0
  10. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/paths.py +37 -0
  11. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/permissions.py +48 -0
  12. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/pipeline.py +142 -0
  13. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/providers/__init__.py +20 -0
  14. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/providers/base.py +19 -0
  15. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/providers/browser.py +744 -0
  16. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/providers/parser.py +191 -0
  17. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/renderer.py +174 -0
  18. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/resources/live.html +39 -0
  19. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/resources/login.html +62 -0
  20. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/resources/video.html +40 -0
  21. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/resources/web.html +368 -0
  22. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/selectors.py +57 -0
  23. nonebot_plugin_douyin_notify-0.1.0/nonebot_plugin_douyin_notify/web.py +647 -0
  24. nonebot_plugin_douyin_notify-0.1.0/pyproject.toml +143 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mengbingnaixi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.1
2
+ Name: nonebot-plugin-douyin-notify
3
+ Version: 0.1.0
4
+ Summary: Douyin video and live notifications for NoneBot2 and OneBot V11
5
+ Keywords: nonebot2,nonebot,douyin,onebot,qq
6
+ Author: mengbingnaixi
7
+ License: MIT
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Framework :: AsyncIO
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Communications :: Chat
17
+ Project-URL: Homepage, https://github.com/mengbingnaixi/nonebot-plugin-douyin-notify
18
+ Project-URL: Repository, https://github.com/mengbingnaixi/nonebot-plugin-douyin-notify
19
+ Project-URL: Documentation, https://github.com/mengbingnaixi/nonebot-plugin-douyin-notify#readme
20
+ Project-URL: Issues, https://github.com/mengbingnaixi/nonebot-plugin-douyin-notify/issues
21
+ Requires-Python: <4.0,>=3.10
22
+ Requires-Dist: nonebot2[fastapi]>=2.5.0
23
+ Requires-Dist: nonebot-adapter-onebot>=2.4.6
24
+ Requires-Dist: nonebot-plugin-apscheduler>=0.5.0
25
+ Requires-Dist: nonebot-plugin-localstore>=0.7.4
26
+ Requires-Dist: aiosqlite>=0.20.0
27
+ Requires-Dist: jinja2>=3.1.4
28
+ Requires-Dist: playwright>=1.45.0
29
+ Requires-Dist: python-multipart>=0.0.9
30
+ Description-Content-Type: text/markdown
31
+
32
+ # nonebot-plugin-douyin-notify
33
+
34
+ 基于 NoneBot2、OneBot V11 和 Playwright 的抖音视频/直播订阅推送插件。插件使用固定的无头 Chromium 打开公开抖音页面,复用抖音网页自身产生的请求获取账号、作品和直播状态,并将新内容渲染为图片卡片推送到 QQ 群。
35
+
36
+ > 抖音网页接口不是公开稳定 API,页面结构、访问频率限制和安全验证策略可能随时变化。请仅处理公开信息,合理设置轮询间隔,并遵守平台条款、版权规则和个人信息保护要求。
37
+
38
+ ## 功能
39
+
40
+ - 订阅公开抖音用户的新视频、开播状态或两者
41
+ - 为每条群订阅分别配置 `@全体成员`、视频/直播自定义封面和渲染方案
42
+ - 同一作者只采集一次,再向多个订阅群分发
43
+ - 首次检查只建立基线,不补发历史作品或当前直播
44
+ - 按作品、直播场次、机器人和群持久化去重
45
+ - 固定使用无头 Chromium,不支持切换为可见浏览器
46
+ - 受管理令牌保护的 Web 控制台
47
+ - 在 Web 中扫码登录并操作抖音官方二次验证页面
48
+ - 视频/直播 PNG 卡片渲染,失败时自动回退为文本消息
49
+ - 按群或按订阅用户、按视频/直播选择模板、字体、主色和辅色
50
+ - 主题色支持在单色与双色渐变之间切换
51
+ - 上传自定义 UTF-8 HTML 模板、字体和 PNG/JPEG/WebP 封面并实时预览
52
+
53
+ ## 安装
54
+
55
+ ```bash
56
+ nb plugin install nonebot-plugin-douyin-notify
57
+ playwright install chromium
58
+ ```
59
+
60
+ 也可以使用 pip:
61
+
62
+ ```bash
63
+ pip install nonebot-plugin-douyin-notify
64
+ playwright install chromium
65
+ ```
66
+
67
+ NoneBot 必须使用 FastAPI 驱动并加载 OneBot V11 适配器:
68
+
69
+ ```dotenv
70
+ DRIVER=~fastapi+~httpx+~websockets
71
+ ```
72
+
73
+ ```toml
74
+ [tool.nonebot]
75
+ plugins = ["nonebot_plugin_douyin_notify"]
76
+
77
+ [tool.nonebot.adapters]
78
+ nonebot-adapter-onebot = [
79
+ { name = "OneBot V11", module_name = "nonebot.adapters.onebot.v11" },
80
+ ]
81
+ ```
82
+
83
+ ## 配置
84
+
85
+ 插件零配置可加载,但 Web 管理默认关闭。启用 Web 时应配置高强度随机令牌,并通过防火墙、反向代理或内网限制访问范围。
86
+
87
+ ```dotenv
88
+ # 相对路径以 NoneBot 工作目录为基准;Windows 也推荐使用正斜杠
89
+ DOUYIN_NOTIFY_DATA="E:/BotData/douyin-notify"
90
+ DOUYIN_NOTIFY_POLL_INTERVAL=120
91
+ DOUYIN_NOTIFY_REQUEST_CONCURRENCY=1
92
+ DOUYIN_NOTIFY_PAGE_TIMEOUT=45000
93
+ DOUYIN_NOTIFY_PAGE_SETTLE_MS=2500
94
+ DOUYIN_NOTIFY_OPERATION_TIMEOUT=90
95
+ DOUYIN_NOTIFY_LOGIN_TIMEOUT=900
96
+ DOUYIN_NOTIFY_COOKIE=
97
+ DOUYIN_NOTIFY_BROWSER_CHANNEL=
98
+ DOUYIN_NOTIFY_BROWSER_EXECUTABLE_PATH=
99
+ DOUYIN_NOTIFY_NOTIFY_LIVE_END=false
100
+ DOUYIN_NOTIFY_AUTO_FOLLOW=false
101
+
102
+ DOUYIN_NOTIFY_WEB_ENABLED=true
103
+ DOUYIN_NOTIFY_WEB_PATH=/douyin-notify
104
+ DOUYIN_NOTIFY_WEB_TOKEN=请替换为高强度随机令牌
105
+ DOUYIN_NOTIFY_WEB_PUBLIC_URL=https://bot.example.com/douyin-notify
106
+ DOUYIN_NOTIFY_RENDER_WIDTH=620
107
+ DOUYIN_NOTIFY_RENDER_TIMEOUT=20000
108
+ ```
109
+
110
+ | 配置 | 默认值 | 说明 |
111
+ | --- | --- | --- |
112
+ | `DOUYIN_NOTIFY_DATA` | LocalStore 数据目录 | 数据库、浏览器会话、模板、字体和封面的资源根目录;不存在时自动创建 |
113
+ | `DOUYIN_NOTIFY_POLL_INTERVAL` | `120` | 作者检查间隔,最低 30 秒;可在 Web 中调整 |
114
+ | `DOUYIN_NOTIFY_REQUEST_CONCURRENCY` | `1` | 同时检查的作者数,范围 1 至 8 |
115
+ | `DOUYIN_NOTIFY_PAGE_TIMEOUT` | `45000` | 页面和接口等待超时,单位毫秒 |
116
+ | `DOUYIN_NOTIFY_PAGE_SETTLE_MS` | `2500` | 页面加载后的额外等待时间 |
117
+ | `DOUYIN_NOTIFY_OPERATION_TIMEOUT` | `90` | 单次账号读取总超时,单位秒 |
118
+ | `DOUYIN_NOTIFY_LOGIN_TIMEOUT` | `900` | Web 登录会话有效期,单位秒 |
119
+ | `DOUYIN_NOTIFY_COOKIE` | 空 | 可选的私有抖音网页版 Cookie |
120
+ | `DOUYIN_NOTIFY_BROWSER_CHANNEL` | 空 | Chromium 通道,例如 `msedge` |
121
+ | `DOUYIN_NOTIFY_BROWSER_EXECUTABLE_PATH` | 空 | 自定义 Chromium 可执行文件 |
122
+ | `DOUYIN_NOTIFY_NOTIFY_LIVE_END` | `false` | 是否推送下播卡片 |
123
+ | `DOUYIN_NOTIFY_AUTO_FOLLOW` | `false` | 新建订阅时是否使用插件已登录的抖音账号关注作者;可在 Web 中调整 |
124
+ | `DOUYIN_NOTIFY_WEB_ENABLED` | `false` | 是否启用 Web 控制台 |
125
+ | `DOUYIN_NOTIFY_WEB_PATH` | `/douyin-notify` | Web 路径 |
126
+ | `DOUYIN_NOTIFY_WEB_TOKEN` | 空 | Web 管理令牌;启用 Web 时应显式配置 |
127
+ | `DOUYIN_NOTIFY_WEB_PUBLIC_URL` | 空 | 反向代理后的公开地址,预留给部署集成 |
128
+ | `DOUYIN_NOTIFY_RENDER_WIDTH` | `620` | 渲染浏览器的 CSS 视口宽度;PNG 使用 2 倍设备像素比输出 |
129
+ | `DOUYIN_NOTIFY_RENDER_TIMEOUT` | `20000` | 单次卡片渲染超时,单位毫秒 |
130
+
131
+ `DOUYIN_NOTIFY_DATA` 的作用与其他插件常见的 `*_PATH` 资源路径配置相同。可以填写带引号的绝对路径,例如 Windows 下的 `DOUYIN_NOTIFY_DATA="E:/BotData/douyin-notify"`,也可以填写 `DOUYIN_NOTIFY_DATA="./data/nonebot_plugin_douyin_notify"`。相对路径以 NoneBot 当前工作目录为基准。
132
+
133
+ 配置的根目录及其父目录即使尚不存在,插件也会在加载时自动创建,并同时准备以下内容:
134
+
135
+ ```text
136
+ douyin-notify/
137
+ ├── subscription.sqlite3
138
+ ├── browser-profile/
139
+ ├── covers/
140
+ ├── fonts/
141
+ └── templates/
142
+ ```
143
+
144
+ 其中 `subscription.sqlite3` 会在数据库初始化时生成。插件只使用自己的 `browser-profile/`,不会读取系统 Chrome、Edge 或其他浏览器的 Cookie、密码和配置。运行 NoneBot 的系统用户必须对所配置路径具有写入权限;如果路径指向已有文件或无权写入的位置,系统仍会报告配置错误。
145
+
146
+ ## Web 控制台
147
+
148
+ 启用后访问:
149
+
150
+ ```text
151
+ http://<NoneBot 地址>:<端口>/douyin-notify/
152
+ ```
153
+
154
+ 控制台包含机器人连接和轮询设置、QQ群扫描、订阅增删、订阅用户设置、立即检查、抖音登录、二次验证操作、渲染方案、资源上传和实时预览。
155
+
156
+ 订阅列表中每位作者都有独立设置按钮。`@全体成员` 按“机器人、QQ群、作者”保存;封面、模板、字体、主色、辅色和渐变开关按视频与直播分别保存。未设置的项目继承群级渲染方案,自定义封面为空时使用抖音接口返回的封面,不再打开直播间截图。机器人需要具备相应群权限才能成功发送 `@全体成员`。
157
+
158
+ “订阅时自动关注”默认关闭。启用后,从受管理令牌保护的 Web 控制台新建订阅会尝试关注作者;通过 QQ 命令新建订阅时,只有 NoneBot 超级用户可以触发关注,普通群主或群管理员仍可保存订阅,但不会修改登录抖音账号的关注列表。更新已有订阅不会重复关注。
159
+
160
+ 自动关注只操作抖音官方作者主页上的“关注”按钮,并在页面显示“已关注”后才报告成功。未登录、按钮未确认或触发安全验证时,订阅仍会保存,并返回自动关注失败提示;安全验证必须在 Web 登录区按抖音官方流程人工完成。
161
+
162
+ 管理令牌验证成功后写入 `HttpOnly`、`SameSite=Strict` Cookie。令牌不要提交到仓库、截图、Issue、商店提交表单或聊天记录。生产环境建议通过 HTTPS 反向代理访问。
163
+
164
+ ## 登录与二次验证
165
+
166
+ 插件始终运行无头浏览器。Web 登录区显示插件专用 Chromium 的实时截图,并把人工点击、拖动和键盘输入转发到该抖音官方页面。因此扫码、短信输入、普通点击确认和需要人工拖动的页面可以在 Web 中完成。
167
+
168
+ 插件不会识别验证码、自动求解滑块、模拟人脸、绕过设备验证或调用非官方验证服务。手机 App 出现确认或人脸验证时,仍需在手机端按抖音官方流程完成。登录成功后会话保存在插件数据目录,轮询和后续重启会继续复用。
169
+
170
+ ## QQ 命令
171
+
172
+ 默认命令前缀取决于 NoneBot 配置,以下以 `/` 为例。
173
+
174
+ | 命令 | 说明 | 权限 |
175
+ | --- | --- | --- |
176
+ | `/douyin subscribe <链接> [video\|live\|all]` | 添加或更新订阅 | 群主、管理员、超管 |
177
+ | `/douyin unsubscribe <用户ID\|序号>` | 取消订阅 | 群主、管理员、超管 |
178
+ | `/douyin list` | 查看本群订阅 | 所有人 |
179
+ | `/douyin check <用户ID\|序号>` | 立即检查指定作者 | 群主、管理员、超管 |
180
+ | `/douyin clear` | 清空本群订阅 | 群主、管理员、超管 |
181
+ | `/douyin help` | 查看帮助 | 所有人 |
182
+
183
+ 登录命令已移除,登录只在受保护的 Web 控制台中进行。命令支持中文别名:`订阅`、`取消`、`列表`、`检查`、`清空`、`帮助`。
184
+
185
+ ## 自定义渲染
186
+
187
+ 内置 `video.html` 和 `live.html` 模板使用 Jinja2 沙箱渲染。上传模板必须为 UTF-8 HTML,并包含唯一的卡片根节点:
188
+
189
+ ```html
190
+ <article id="douyin-card">
191
+ <h1>{{ event.title }}</h1>
192
+ <p>{{ event.author_name }}</p>
193
+ </article>
194
+ ```
195
+
196
+ | 字段 | 内容 |
197
+ | --- | --- |
198
+ | `event.kind.value` | `video` 或 `live` |
199
+ | `event.author_name` | 作者昵称 |
200
+ | `event.author_avatar` | 作者头像 URL |
201
+ | `event.title` | 视频描述或直播标题 |
202
+ | `event.cover_url` | 封面 URL |
203
+ | `event.published_text` | 北京时间格式化发布时间 |
204
+ | `event.url` | 官方内容链接 |
205
+ | `accent_color` | Web 中选择的主色 |
206
+ | `gradient_color` | Web 中选择的辅色 |
207
+ | `theme_background` | 渐变开启时为双色渐变,关闭时为主色纯色 |
208
+
209
+ 模板外部请求只允许抖音图片域名和 QQ 群头像域名,渲染上下文关闭 JavaScript。字体支持 `.ttf`、`.otf`、`.woff` 和 `.woff2`;自定义封面支持 `.png`、`.jpg`、`.jpeg` 和 `.webp`,并校验文件头。单个上传文件最大 10 MiB。
210
+
211
+ 渲染器使用 `device_scale_factor=2` 生成高像素密度 PNG。内置模板的 CSS 卡片尺寸为 `576 × 431`,最终图片为 `1152 × 862 px`;自定义模板也会按其 `#douyin-card` 尺寸以 2 倍像素输出。
212
+
213
+ ## 数据与隐私
214
+
215
+ - 数据库:`subscription.sqlite3`
216
+ - 抖音浏览器状态:`browser-profile/`
217
+ - 自定义模板:`templates/`
218
+ - 自定义字体:`fonts/`
219
+ - 自定义封面:`covers/`
220
+ - 日志不会输出 Cookie、动态签名、管理令牌或完整接口请求 URL
221
+ - 删除群订阅后,无其他群引用的作者状态会自动清理
222
+
223
+ ## 开发
224
+
225
+ ```bash
226
+ pdm install
227
+ pdm run playwright install chromium
228
+ pdm run format
229
+ pdm run test
230
+ pdm run python -m build
231
+ ```
232
+ ## 鸣谢
233
+
234
+ - [NoneBot2](https://nonebot.dev/) — Python 异步聊天机器人框架
235
+
236
+ ---
237
+
238
+ ## License
239
+
240
+ MIT License
@@ -0,0 +1,209 @@
1
+ # nonebot-plugin-douyin-notify
2
+
3
+ 基于 NoneBot2、OneBot V11 和 Playwright 的抖音视频/直播订阅推送插件。插件使用固定的无头 Chromium 打开公开抖音页面,复用抖音网页自身产生的请求获取账号、作品和直播状态,并将新内容渲染为图片卡片推送到 QQ 群。
4
+
5
+ > 抖音网页接口不是公开稳定 API,页面结构、访问频率限制和安全验证策略可能随时变化。请仅处理公开信息,合理设置轮询间隔,并遵守平台条款、版权规则和个人信息保护要求。
6
+
7
+ ## 功能
8
+
9
+ - 订阅公开抖音用户的新视频、开播状态或两者
10
+ - 为每条群订阅分别配置 `@全体成员`、视频/直播自定义封面和渲染方案
11
+ - 同一作者只采集一次,再向多个订阅群分发
12
+ - 首次检查只建立基线,不补发历史作品或当前直播
13
+ - 按作品、直播场次、机器人和群持久化去重
14
+ - 固定使用无头 Chromium,不支持切换为可见浏览器
15
+ - 受管理令牌保护的 Web 控制台
16
+ - 在 Web 中扫码登录并操作抖音官方二次验证页面
17
+ - 视频/直播 PNG 卡片渲染,失败时自动回退为文本消息
18
+ - 按群或按订阅用户、按视频/直播选择模板、字体、主色和辅色
19
+ - 主题色支持在单色与双色渐变之间切换
20
+ - 上传自定义 UTF-8 HTML 模板、字体和 PNG/JPEG/WebP 封面并实时预览
21
+
22
+ ## 安装
23
+
24
+ ```bash
25
+ nb plugin install nonebot-plugin-douyin-notify
26
+ playwright install chromium
27
+ ```
28
+
29
+ 也可以使用 pip:
30
+
31
+ ```bash
32
+ pip install nonebot-plugin-douyin-notify
33
+ playwright install chromium
34
+ ```
35
+
36
+ NoneBot 必须使用 FastAPI 驱动并加载 OneBot V11 适配器:
37
+
38
+ ```dotenv
39
+ DRIVER=~fastapi+~httpx+~websockets
40
+ ```
41
+
42
+ ```toml
43
+ [tool.nonebot]
44
+ plugins = ["nonebot_plugin_douyin_notify"]
45
+
46
+ [tool.nonebot.adapters]
47
+ nonebot-adapter-onebot = [
48
+ { name = "OneBot V11", module_name = "nonebot.adapters.onebot.v11" },
49
+ ]
50
+ ```
51
+
52
+ ## 配置
53
+
54
+ 插件零配置可加载,但 Web 管理默认关闭。启用 Web 时应配置高强度随机令牌,并通过防火墙、反向代理或内网限制访问范围。
55
+
56
+ ```dotenv
57
+ # 相对路径以 NoneBot 工作目录为基准;Windows 也推荐使用正斜杠
58
+ DOUYIN_NOTIFY_DATA="E:/BotData/douyin-notify"
59
+ DOUYIN_NOTIFY_POLL_INTERVAL=120
60
+ DOUYIN_NOTIFY_REQUEST_CONCURRENCY=1
61
+ DOUYIN_NOTIFY_PAGE_TIMEOUT=45000
62
+ DOUYIN_NOTIFY_PAGE_SETTLE_MS=2500
63
+ DOUYIN_NOTIFY_OPERATION_TIMEOUT=90
64
+ DOUYIN_NOTIFY_LOGIN_TIMEOUT=900
65
+ DOUYIN_NOTIFY_COOKIE=
66
+ DOUYIN_NOTIFY_BROWSER_CHANNEL=
67
+ DOUYIN_NOTIFY_BROWSER_EXECUTABLE_PATH=
68
+ DOUYIN_NOTIFY_NOTIFY_LIVE_END=false
69
+ DOUYIN_NOTIFY_AUTO_FOLLOW=false
70
+
71
+ DOUYIN_NOTIFY_WEB_ENABLED=true
72
+ DOUYIN_NOTIFY_WEB_PATH=/douyin-notify
73
+ DOUYIN_NOTIFY_WEB_TOKEN=请替换为高强度随机令牌
74
+ DOUYIN_NOTIFY_WEB_PUBLIC_URL=https://bot.example.com/douyin-notify
75
+ DOUYIN_NOTIFY_RENDER_WIDTH=620
76
+ DOUYIN_NOTIFY_RENDER_TIMEOUT=20000
77
+ ```
78
+
79
+ | 配置 | 默认值 | 说明 |
80
+ | --- | --- | --- |
81
+ | `DOUYIN_NOTIFY_DATA` | LocalStore 数据目录 | 数据库、浏览器会话、模板、字体和封面的资源根目录;不存在时自动创建 |
82
+ | `DOUYIN_NOTIFY_POLL_INTERVAL` | `120` | 作者检查间隔,最低 30 秒;可在 Web 中调整 |
83
+ | `DOUYIN_NOTIFY_REQUEST_CONCURRENCY` | `1` | 同时检查的作者数,范围 1 至 8 |
84
+ | `DOUYIN_NOTIFY_PAGE_TIMEOUT` | `45000` | 页面和接口等待超时,单位毫秒 |
85
+ | `DOUYIN_NOTIFY_PAGE_SETTLE_MS` | `2500` | 页面加载后的额外等待时间 |
86
+ | `DOUYIN_NOTIFY_OPERATION_TIMEOUT` | `90` | 单次账号读取总超时,单位秒 |
87
+ | `DOUYIN_NOTIFY_LOGIN_TIMEOUT` | `900` | Web 登录会话有效期,单位秒 |
88
+ | `DOUYIN_NOTIFY_COOKIE` | 空 | 可选的私有抖音网页版 Cookie |
89
+ | `DOUYIN_NOTIFY_BROWSER_CHANNEL` | 空 | Chromium 通道,例如 `msedge` |
90
+ | `DOUYIN_NOTIFY_BROWSER_EXECUTABLE_PATH` | 空 | 自定义 Chromium 可执行文件 |
91
+ | `DOUYIN_NOTIFY_NOTIFY_LIVE_END` | `false` | 是否推送下播卡片 |
92
+ | `DOUYIN_NOTIFY_AUTO_FOLLOW` | `false` | 新建订阅时是否使用插件已登录的抖音账号关注作者;可在 Web 中调整 |
93
+ | `DOUYIN_NOTIFY_WEB_ENABLED` | `false` | 是否启用 Web 控制台 |
94
+ | `DOUYIN_NOTIFY_WEB_PATH` | `/douyin-notify` | Web 路径 |
95
+ | `DOUYIN_NOTIFY_WEB_TOKEN` | 空 | Web 管理令牌;启用 Web 时应显式配置 |
96
+ | `DOUYIN_NOTIFY_WEB_PUBLIC_URL` | 空 | 反向代理后的公开地址,预留给部署集成 |
97
+ | `DOUYIN_NOTIFY_RENDER_WIDTH` | `620` | 渲染浏览器的 CSS 视口宽度;PNG 使用 2 倍设备像素比输出 |
98
+ | `DOUYIN_NOTIFY_RENDER_TIMEOUT` | `20000` | 单次卡片渲染超时,单位毫秒 |
99
+
100
+ `DOUYIN_NOTIFY_DATA` 的作用与其他插件常见的 `*_PATH` 资源路径配置相同。可以填写带引号的绝对路径,例如 Windows 下的 `DOUYIN_NOTIFY_DATA="E:/BotData/douyin-notify"`,也可以填写 `DOUYIN_NOTIFY_DATA="./data/nonebot_plugin_douyin_notify"`。相对路径以 NoneBot 当前工作目录为基准。
101
+
102
+ 配置的根目录及其父目录即使尚不存在,插件也会在加载时自动创建,并同时准备以下内容:
103
+
104
+ ```text
105
+ douyin-notify/
106
+ ├── subscription.sqlite3
107
+ ├── browser-profile/
108
+ ├── covers/
109
+ ├── fonts/
110
+ └── templates/
111
+ ```
112
+
113
+ 其中 `subscription.sqlite3` 会在数据库初始化时生成。插件只使用自己的 `browser-profile/`,不会读取系统 Chrome、Edge 或其他浏览器的 Cookie、密码和配置。运行 NoneBot 的系统用户必须对所配置路径具有写入权限;如果路径指向已有文件或无权写入的位置,系统仍会报告配置错误。
114
+
115
+ ## Web 控制台
116
+
117
+ 启用后访问:
118
+
119
+ ```text
120
+ http://<NoneBot 地址>:<端口>/douyin-notify/
121
+ ```
122
+
123
+ 控制台包含机器人连接和轮询设置、QQ群扫描、订阅增删、订阅用户设置、立即检查、抖音登录、二次验证操作、渲染方案、资源上传和实时预览。
124
+
125
+ 订阅列表中每位作者都有独立设置按钮。`@全体成员` 按“机器人、QQ群、作者”保存;封面、模板、字体、主色、辅色和渐变开关按视频与直播分别保存。未设置的项目继承群级渲染方案,自定义封面为空时使用抖音接口返回的封面,不再打开直播间截图。机器人需要具备相应群权限才能成功发送 `@全体成员`。
126
+
127
+ “订阅时自动关注”默认关闭。启用后,从受管理令牌保护的 Web 控制台新建订阅会尝试关注作者;通过 QQ 命令新建订阅时,只有 NoneBot 超级用户可以触发关注,普通群主或群管理员仍可保存订阅,但不会修改登录抖音账号的关注列表。更新已有订阅不会重复关注。
128
+
129
+ 自动关注只操作抖音官方作者主页上的“关注”按钮,并在页面显示“已关注”后才报告成功。未登录、按钮未确认或触发安全验证时,订阅仍会保存,并返回自动关注失败提示;安全验证必须在 Web 登录区按抖音官方流程人工完成。
130
+
131
+ 管理令牌验证成功后写入 `HttpOnly`、`SameSite=Strict` Cookie。令牌不要提交到仓库、截图、Issue、商店提交表单或聊天记录。生产环境建议通过 HTTPS 反向代理访问。
132
+
133
+ ## 登录与二次验证
134
+
135
+ 插件始终运行无头浏览器。Web 登录区显示插件专用 Chromium 的实时截图,并把人工点击、拖动和键盘输入转发到该抖音官方页面。因此扫码、短信输入、普通点击确认和需要人工拖动的页面可以在 Web 中完成。
136
+
137
+ 插件不会识别验证码、自动求解滑块、模拟人脸、绕过设备验证或调用非官方验证服务。手机 App 出现确认或人脸验证时,仍需在手机端按抖音官方流程完成。登录成功后会话保存在插件数据目录,轮询和后续重启会继续复用。
138
+
139
+ ## QQ 命令
140
+
141
+ 默认命令前缀取决于 NoneBot 配置,以下以 `/` 为例。
142
+
143
+ | 命令 | 说明 | 权限 |
144
+ | --- | --- | --- |
145
+ | `/douyin subscribe <链接> [video\|live\|all]` | 添加或更新订阅 | 群主、管理员、超管 |
146
+ | `/douyin unsubscribe <用户ID\|序号>` | 取消订阅 | 群主、管理员、超管 |
147
+ | `/douyin list` | 查看本群订阅 | 所有人 |
148
+ | `/douyin check <用户ID\|序号>` | 立即检查指定作者 | 群主、管理员、超管 |
149
+ | `/douyin clear` | 清空本群订阅 | 群主、管理员、超管 |
150
+ | `/douyin help` | 查看帮助 | 所有人 |
151
+
152
+ 登录命令已移除,登录只在受保护的 Web 控制台中进行。命令支持中文别名:`订阅`、`取消`、`列表`、`检查`、`清空`、`帮助`。
153
+
154
+ ## 自定义渲染
155
+
156
+ 内置 `video.html` 和 `live.html` 模板使用 Jinja2 沙箱渲染。上传模板必须为 UTF-8 HTML,并包含唯一的卡片根节点:
157
+
158
+ ```html
159
+ <article id="douyin-card">
160
+ <h1>{{ event.title }}</h1>
161
+ <p>{{ event.author_name }}</p>
162
+ </article>
163
+ ```
164
+
165
+ | 字段 | 内容 |
166
+ | --- | --- |
167
+ | `event.kind.value` | `video` 或 `live` |
168
+ | `event.author_name` | 作者昵称 |
169
+ | `event.author_avatar` | 作者头像 URL |
170
+ | `event.title` | 视频描述或直播标题 |
171
+ | `event.cover_url` | 封面 URL |
172
+ | `event.published_text` | 北京时间格式化发布时间 |
173
+ | `event.url` | 官方内容链接 |
174
+ | `accent_color` | Web 中选择的主色 |
175
+ | `gradient_color` | Web 中选择的辅色 |
176
+ | `theme_background` | 渐变开启时为双色渐变,关闭时为主色纯色 |
177
+
178
+ 模板外部请求只允许抖音图片域名和 QQ 群头像域名,渲染上下文关闭 JavaScript。字体支持 `.ttf`、`.otf`、`.woff` 和 `.woff2`;自定义封面支持 `.png`、`.jpg`、`.jpeg` 和 `.webp`,并校验文件头。单个上传文件最大 10 MiB。
179
+
180
+ 渲染器使用 `device_scale_factor=2` 生成高像素密度 PNG。内置模板的 CSS 卡片尺寸为 `576 × 431`,最终图片为 `1152 × 862 px`;自定义模板也会按其 `#douyin-card` 尺寸以 2 倍像素输出。
181
+
182
+ ## 数据与隐私
183
+
184
+ - 数据库:`subscription.sqlite3`
185
+ - 抖音浏览器状态:`browser-profile/`
186
+ - 自定义模板:`templates/`
187
+ - 自定义字体:`fonts/`
188
+ - 自定义封面:`covers/`
189
+ - 日志不会输出 Cookie、动态签名、管理令牌或完整接口请求 URL
190
+ - 删除群订阅后,无其他群引用的作者状态会自动清理
191
+
192
+ ## 开发
193
+
194
+ ```bash
195
+ pdm install
196
+ pdm run playwright install chromium
197
+ pdm run format
198
+ pdm run test
199
+ pdm run python -m build
200
+ ```
201
+ ## 鸣谢
202
+
203
+ - [NoneBot2](https://nonebot.dev/) — Python 异步聊天机器人框架
204
+
205
+ ---
206
+
207
+ ## License
208
+
209
+ MIT License
@@ -0,0 +1,48 @@
1
+ from nonebot import get_driver, require
2
+ from nonebot.plugin import PluginMetadata
3
+
4
+ require("nonebot_plugin_localstore")
5
+ require("nonebot_plugin_apscheduler")
6
+
7
+ from .config import Config, plugin_config # noqa: E402
8
+ from .database import repository # noqa: E402
9
+ from .jobs import install_jobs, load_runtime_config # noqa: E402
10
+ from .providers import douyin_provider # noqa: E402
11
+ from .renderer import renderer # noqa: E402
12
+ from .web import install_web # noqa: E402
13
+
14
+ __plugin_meta__ = PluginMetadata(
15
+ name="抖音视频与直播订阅",
16
+ description="将抖音用户的新视频和开播状态推送到 QQ 群",
17
+ usage=(
18
+ "使用 /douyin help 查看帮助;通过受保护的 Web 管理页配置登录、订阅、"
19
+ "渲染方案和资源"
20
+ ),
21
+ type="application",
22
+ homepage="https://github.com/mengbingnaixi/nonebot-plugin-douyin-notify",
23
+ config=Config,
24
+ supported_adapters={"~onebot.v11"},
25
+ extra={},
26
+ )
27
+
28
+ driver = get_driver()
29
+
30
+
31
+ @driver.on_startup
32
+ async def _startup() -> None:
33
+ await repository.initialize()
34
+ await load_runtime_config()
35
+ install_jobs()
36
+
37
+
38
+ @driver.on_shutdown
39
+ async def _shutdown() -> None:
40
+ await douyin_provider.close()
41
+ await renderer.close()
42
+
43
+
44
+ from . import commands as commands # noqa: E402,F401
45
+
46
+ install_web()
47
+
48
+ __all__ = ["Config", "commands", "plugin_config"]