@alemonjs/qq-bot 2.1.34 → 2.1.35

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
@@ -116,7 +116,7 @@ export default async () => {
116
116
 
117
117
  ### 流程
118
118
 
119
- 1. 启动适配器(默认 WebSocket 模式),终端输出授权二维码与链接,并在**运行目录**保存二维码图片(`qqbot-login-qr.png`,二维码刷新时自动覆盖);
119
+ 1. 启动适配器(默认 WebSocket 模式),通过 CBP 输出授权二维码与链接;二维码图片由 CBP/UI 统一处理;
120
120
  2. 使用**手机 QQ**(开放平台上该机器人的管理者账号)扫描二维码(终端直接扫,或打开保存的图片扫),并在页面中确认授权;
121
121
  3. 适配器自动轮询授权结果,平台下发的凭证在本地解密(AES-256-GCM,密钥不落盘);
122
122
  4. `app_id` 与 `secret` 自动写入 `alemon.config.yaml` 的 `qq-bot` 节(保留文件中已有的注释与原格式),随后立即连接,无需重启。
@@ -134,7 +134,7 @@ export default async () => {
134
134
  | 事项 | 说明 |
135
135
  | -------- | ------------------------------------------------------------------------------------------------ |
136
136
  | 触发条件 | 配置中未填写 `app_id`/`secret`,且未配置 `bots`(WebSocket 模式) |
137
- | 二维码 | 终端出码 + 图片保存到运行目录(`qqbot-login-qr.png`),过期自动刷新(最多 3 次),总超时 10 分钟 |
137
+ | 二维码 | CBP 统一输出,过期自动刷新(最多 3 次),总超时 10 分钟 |
138
138
  | 凭证安全 | AppSecret 全程密文传输、本地解密,密钥仅存内存不落盘 |
139
139
  | 失败处理 | 超时 / 刷新次数用尽 / 授权取消时跳过连接并输出日志,可重启重试或手动配置 |
140
140
  | Webhook | Webhook 模式(配置 `route`/`port`/`ws`)不触发扫码流程,需自行填写完整配置 |
@@ -31,7 +31,7 @@ const bootstrap = async () => {
31
31
  activeRegistry = registry;
32
32
  if (!hasConfiguredCredentials()) {
33
33
  logger.info("[qq-bot] 未检测到 app_id/secret 配置,进入扫码登录流程");
34
- const result = await qrLogin({ onQRCode: (qrBuffer, url, _qrImagePath, loginId, refresh) => {
34
+ const result = await qrLogin({ onQRCode: (qrBuffer, url, loginId, refresh) => {
35
35
  loginStatus = {
36
36
  state: "awaiting_qrcode",
37
37
  type: "qrcode",
@@ -35,14 +35,14 @@ type QRLoginOptions = {
35
35
  pollInterval?: number;
36
36
  /** 注入门户请求(测试用) */
37
37
  request?: PortalRequest;
38
- /** 二维码生成回调(默认同时终端出码并保存图片到运行目录) */
39
- onQRCode?: (qrBuffer: Buffer, url: string, qrImagePath: string | undefined, loginId: string, refresh: number) => void | Promise<void>;
38
+ /** 二维码生成回调;图片由回调方或 CBP 统一处理,不在适配器运行目录落盘 */
39
+ onQRCode?: (qrBuffer: Buffer, url: string, loginId: string, refresh: number) => void | Promise<void>;
40
40
  /** 状态变化回调 */
41
41
  onStatus?: (message: string) => void | Promise<void>;
42
42
  };
43
43
  /**
44
44
  * 扫码登录流程:
45
- * 创建绑定任务 → 终端出码并保存二维码图片到运行目录 → 轮询授权结果 → 解密 AppSecret。
45
+ * 创建绑定任务 → 生成二维码并通过回调交给 CBP/UI → 轮询授权结果 → 解密 AppSecret。
46
46
  * 成功返回 { appId, clientSecret, userOpenid };超时/失败/刷新次数用尽返回 null
47
47
  */
48
48
  declare const qrLogin: (options?: QRLoginOptions) => Promise<QRLoginResult | null>;
@@ -2,7 +2,7 @@ import { getConfig, logger } from "alemonjs";
2
2
  import axios from "axios";
3
3
  import { createDecipheriv, randomBytes } from "node:crypto";
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
- import { dirname, join } from "node:path";
5
+ import { dirname } from "node:path";
6
6
  import QRCode from "qrcode";
7
7
  import YAML from "yaml";
8
8
 
@@ -51,7 +51,7 @@ const buildConnectUrl = (taskId) => {
51
51
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
52
52
  /**
53
53
  * 扫码登录流程:
54
- * 创建绑定任务 → 终端出码并保存二维码图片到运行目录 → 轮询授权结果 → 解密 AppSecret。
54
+ * 创建绑定任务 → 生成二维码并通过回调交给 CBP/UI → 轮询授权结果 → 解密 AppSecret。
55
55
  * 成功返回 { appId, clientSecret, userOpenid };超时/失败/刷新次数用尽返回 null
56
56
  */
57
57
  const qrLogin = async (options = {}) => {
@@ -70,7 +70,6 @@ const qrLogin = async (options = {}) => {
70
70
  return null;
71
71
  }
72
72
  const url = buildConnectUrl(taskId);
73
- let qrImagePath = null;
74
73
  let qrBuffer = null;
75
74
  try {
76
75
  qrBuffer = await QRCode.toBuffer(url, {
@@ -78,12 +77,10 @@ const qrLogin = async (options = {}) => {
78
77
  width: 320,
79
78
  margin: 2
80
79
  });
81
- qrImagePath = join(process.cwd(), "qqbot-login-qr.png");
82
- writeFileSync(qrImagePath, qrBuffer);
83
80
  } catch (err) {
84
- logger.warn(`[qq-bot] 二维码图片保存失败:${err?.message ?? err}`);
81
+ logger.warn(`[qq-bot] 二维码生成失败:${err?.message ?? err}`);
85
82
  }
86
- if (qrBuffer && onQRCode) await onQRCode(qrBuffer, url, qrImagePath ?? void 0, taskId, refresh);
83
+ if (qrBuffer && onQRCode) await onQRCode(qrBuffer, url, taskId, refresh);
87
84
  await onStatus?.("请使用手机 QQ 扫描二维码并确认授权");
88
85
  logger.warn("[qq-bot] 注意:扫码授权完成后平台将重置机器人密钥,旧密钥会立即失效;若该机器人已在其他实例中运行,请更新其配置");
89
86
  while (Date.now() < deadline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alemonjs/qq-bot",
3
- "version": "2.1.34",
3
+ "version": "2.1.35",
4
4
  "description": "QQ官方平台",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
@@ -97,5 +97,5 @@
97
97
  "type": "git",
98
98
  "url": "https://github.com/lemonade-lab/alemonjs.git"
99
99
  },
100
- "gitHead": "8e6c0d91889ff7926fc7bc58ac8dc664c8f721ea"
101
- }
100
+ "gitHead": "c6aa5616afe091a37610dad22fbb2d2618d943b8"
101
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2013-present, Yuxi (Evan) You
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
13
- all 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
21
- THE SOFTWARE.