# QQBot Connector

[![npm version](https://img.shields.io/npm/v/@tencent-connect/qqbot-connector.svg)](https://www.npmjs.com/package/@tencent-connect/qqbot-connector)

QQ 机器人扫码连接 SDK，在控制台展示二维码，用户使用手机 QQ 扫码后自动获取机器人的 AppID 与 AppSecret。

默认情况下扫码页面会将接入方统一显示为"第三方机器人"。如需在扫码页面展示你的平台名称，或有其他商务合作需求，请通过邮件与我们联系：qq_bot_api@tencent.com。

## 系统要求

- Node.js >= 18.0.0

## 安装

```bash
npm install @tencent-connect/qqbot-connector
```

## 快速开始

### Promise 风格

始终在控制台打印二维码，扫码后返回凭据：

```ts
import { qrConnect } from '@tencent-connect/qqbot-connector';

try {
  const [{ appId, appSecret }] = await qrConnect();
  console.log('绑定成功！');
  console.log('AppID:', appId);
  console.log('AppSecret:', appSecret);
} catch (err) {
  console.error('绑定失败:', err.message);
}
```

### 回调风格

通过 `displayQrCodeToConsole` 控制是否在控制台打印二维码，`onQrDisplayed` 始终会在轮询开始前回调二维码 URL：

```ts
import { startQrConnect } from '@tencent-connect/qqbot-connector';

// 不打印二维码到控制台，通过 onQrDisplayed 自行处理 URL
const stop = startQrConnect({
  onSuccess([{ appId, appSecret }]) {
    console.log('绑定成功！');
    console.log('AppID:', appId);
    console.log('AppSecret:', appSecret);
  },
  onFailure(err) {
    console.error('绑定失败:', err.message);
  },
  onQrDisplayed(url) {
    // 始终回调，可自行生成二维码图片、发送给用户等
    console.log('二维码链接:', url);
  },
  onQrExpired() {
    console.log('二维码已过期，正在刷新…');
  },
}, {
  displayQrCodeToConsole: false,
});

// 需要取消时调用 stop()
// stop();
```

## API

### `qrConnect(options?): Promise<QrConnectCredentials[]>`

在控制台展示二维码并等待扫码，返回 Promise。

此模式下始终在控制台打印二维码（`displayQrCodeToConsole` 固定为 `true`，不可关闭）。如需自行处理二维码 URL 而不打印，请使用回调风格的 `startQrConnect`。

**参数：**

| 名称 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `options.source` | `string` | `''` | 接入平台标识，留空则显示为"第三方机器人" |
| `options.signal` | `AbortSignal` | — | 外部取消信号 |

**返回值：**

```ts
interface QrConnectCredentials {
  appId: string;
  appSecret: string;
}
```

> **注意：** 绑定成功后返回的凭据类型是 `QrConnectCredentials[]` 数组。目前扫码仅支持绑定单个 QQ 机器人（数组长度为 1），未来可能会拓展支持同时绑定多个 QQ 机器人，建议业务侧提前做好对数组的遍历处理，以便后续平滑升级。

### `startQrConnect(callbacks, options?): () => void`

轮询等待扫码结果（回调风格）。返回一个 `stop` 函数，调用后可中止流程。

二维码过期后会自动刷新并重新轮询，直到用户扫码成功或主动取消。无论 `displayQrCodeToConsole` 为何值，`onQrDisplayed` 都会在轮询开始前回调二维码 URL，供业务自行展示。

**callbacks：**

| 名称 | 类型 | 说明 |
|------|------|------|
| `onSuccess` | `(credentials: QrConnectCredentials[]) => void` | 扫码成功回调 |
| `onFailure` | `(error: Error) => void` | 失败或取消回调 |
| `onQrDisplayed?` | `(url: string) => void` | 二维码 URL 就绪，轮询开始前始终触发 |
| `onQrExpired?` | `() => void` | 二维码已过期，即将刷新（可选） |

**options：**

| 名称 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `options.displayQrCodeToConsole` | `boolean` | `true` | 是否在控制台打印二维码 |
| `options.source` | `string` | `''` | 接入平台标识，留空则显示为"第三方机器人" |
| `options.signal` | `AbortSignal` | — | 外部取消信号 |

### 取消支持

两种取消方式：

```ts
// 方式一：使用返回的 stop 函数
const stop = startQrConnect({ ... });
stop();

// 方式二：使用 AbortController
const ac = new AbortController();
qrConnect({ signal: ac.signal }).catch(console.error);
ac.abort();
```

## 协助与反馈

如在使用过程中遇到问题，欢迎前往以下地址查阅已有议题或提交新问题：

https://github.com/tencent-connect/openclaw-qqbot/issues
