@zhin.js/adapter-qq 2.0.11 → 3.0.0
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/CHANGELOG.md +10 -0
- package/README.md +117 -9
- package/lib/adapter.d.ts +4 -1
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +12 -1
- package/lib/adapter.js.map +1 -1
- package/lib/bot.d.ts +14 -1
- package/lib/bot.d.ts.map +1 -1
- package/lib/bot.js +145 -17
- package/lib/bot.js.map +1 -1
- package/lib/gateway-config.d.ts +14 -0
- package/lib/gateway-config.d.ts.map +1 -0
- package/lib/gateway-config.js +32 -0
- package/lib/gateway-config.js.map +1 -0
- package/lib/group-at-normalize.d.ts +8 -0
- package/lib/group-at-normalize.d.ts.map +1 -0
- package/lib/group-at-normalize.js +71 -0
- package/lib/group-at-normalize.js.map +1 -0
- package/lib/inbound-normalize.d.ts +11 -0
- package/lib/inbound-normalize.d.ts.map +1 -0
- package/lib/inbound-normalize.js +47 -0
- package/lib/inbound-normalize.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +37 -17
- package/lib/index.js.map +1 -1
- package/lib/outbound-markdown.d.ts +12 -0
- package/lib/outbound-markdown.d.ts.map +1 -0
- package/lib/outbound-markdown.js +78 -0
- package/lib/outbound-markdown.js.map +1 -0
- package/lib/outbound-media.d.ts +9 -0
- package/lib/outbound-media.d.ts.map +1 -0
- package/lib/outbound-media.js +50 -0
- package/lib/outbound-media.js.map +1 -0
- package/lib/sdk-version.d.ts +8 -0
- package/lib/sdk-version.d.ts.map +1 -0
- package/lib/sdk-version.js +19 -0
- package/lib/sdk-version.js.map +1 -0
- package/lib/types.d.ts +22 -0
- package/lib/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/adapter.ts +18 -1
- package/src/bot.ts +176 -18
- package/src/gateway-config.ts +48 -0
- package/src/group-at-normalize.ts +78 -0
- package/src/inbound-normalize.ts +57 -0
- package/src/index.ts +39 -17
- package/src/outbound-markdown.ts +93 -0
- package/src/outbound-media.ts +57 -0
- package/src/sdk-version.ts +21 -0
- package/src/types.ts +22 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QQ 官方出站媒体归一化。
|
|
3
|
+
* qq-official-bot 的 formatMediaData 对 data.url 直接当远程 URL 上传;
|
|
4
|
+
* base64:// / data:...;base64 须走 data.file 才会解析为 file_data。
|
|
5
|
+
*/
|
|
6
|
+
import type { MessageElement, MessageSegment, SendContent } from "zhin.js";
|
|
7
|
+
|
|
8
|
+
const MEDIA_TYPES = new Set(["image", "audio", "video", "file"]);
|
|
9
|
+
|
|
10
|
+
function isMessageSegment(seg: MessageElement): seg is MessageSegment {
|
|
11
|
+
return typeof seg.type === "string";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isRemoteUrl(value: string): boolean {
|
|
15
|
+
return /^https?:\/\//i.test(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isInlineBase64(value: string): boolean {
|
|
19
|
+
return value.startsWith("base64://") || /^data:[^/]+\/[^;]+;base64,/i.test(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resolveMediaFile(data: Record<string, unknown>): string | undefined {
|
|
23
|
+
const url = typeof data.url === "string" ? data.url : undefined;
|
|
24
|
+
const file = typeof data.file === "string" ? data.file : undefined;
|
|
25
|
+
const base64 = typeof data.base64 === "string" ? data.base64 : undefined;
|
|
26
|
+
|
|
27
|
+
if (file && !isRemoteUrl(file)) return file;
|
|
28
|
+
if (url && isInlineBase64(url)) return url;
|
|
29
|
+
if (url && !isRemoteUrl(url) && (url.startsWith("file://") || url.startsWith("/"))) return url;
|
|
30
|
+
if (base64) return base64.startsWith("base64://") ? base64 : `base64://${base64}`;
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function normalizeMediaSegment(seg: MessageSegment): MessageSegment {
|
|
35
|
+
if (!MEDIA_TYPES.has(seg.type)) return seg;
|
|
36
|
+
|
|
37
|
+
const data = { ...seg.data } as Record<string, unknown>;
|
|
38
|
+
const file = resolveMediaFile(data);
|
|
39
|
+
if (!file) return seg;
|
|
40
|
+
|
|
41
|
+
delete data.url;
|
|
42
|
+
delete data.base64;
|
|
43
|
+
data.file = file;
|
|
44
|
+
return { type: seg.type, data } as MessageSegment;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** 将 Zhin 出站 image/base64 段转为 qq-official-bot 可识别的 file 字段 */
|
|
48
|
+
export function normalizeOutboundMedia(content: SendContent): SendContent {
|
|
49
|
+
if (typeof content === "string") return content;
|
|
50
|
+
if (!Array.isArray(content)) {
|
|
51
|
+
return isMessageSegment(content) ? normalizeMediaSegment(content) : content;
|
|
52
|
+
}
|
|
53
|
+
return content.map((item) => {
|
|
54
|
+
if (typeof item === "string") return item;
|
|
55
|
+
return isMessageSegment(item) ? normalizeMediaSegment(item) : item;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import adapterPkg from "../package.json" with { type: "json" };
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
function readDepVersion(dep: string): string {
|
|
7
|
+
try {
|
|
8
|
+
return (require(`${dep}/package.json`) as { version: string }).version;
|
|
9
|
+
} catch {
|
|
10
|
+
return "unknown";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** HTTP header name for outbound QQ API requests. */
|
|
15
|
+
export const SDK_VERSION_HEADER = "x-sdk-version";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Composite SDK identity: Zhin adapter + underlying qq-official-bot.
|
|
19
|
+
* Example: `zhin-adapter-qq/v2.0.11+qq-official-bot/v1.2.1`
|
|
20
|
+
*/
|
|
21
|
+
export const SDK_VERSION = `zhin-adapter-qq/v${adapterPkg.version}+qq-official-bot/v${readDepVersion("qq-official-bot")}`;
|
package/src/types.ts
CHANGED
|
@@ -14,6 +14,28 @@ export type QQBotConfig<
|
|
|
14
14
|
context: "qq";
|
|
15
15
|
name: string;
|
|
16
16
|
data_dir?: string;
|
|
17
|
+
/**
|
|
18
|
+
* middleware 模式:挂在 host-router 的回调路径(默认 `/qq/webhook`,完整 URL 为 `{host}:8086/qq/webhook`,无 `/api` 前缀)。
|
|
19
|
+
* webhook 独立端口模式:使用 qq-official-bot 的 `path` 字段。
|
|
20
|
+
*/
|
|
21
|
+
webhookPath?: string;
|
|
22
|
+
/**
|
|
23
|
+
* 自定义 access token 接口(完整 URL)。
|
|
24
|
+
* 默认 `https://bots.qq.com/app/getAppAccessToken`;代理或私有部署时可覆盖。
|
|
25
|
+
*/
|
|
26
|
+
accessTokenUrl?: string;
|
|
27
|
+
/**
|
|
28
|
+
* 自定义 gateway 接口(完整 URL 或相对路径,如 `/gateway/bot`)。
|
|
29
|
+
* 响应中的 `url` 为 WebSocket 地址;**仅 `mode: websocket` 入站时使用**。
|
|
30
|
+
*/
|
|
31
|
+
gatewayUrl?: string;
|
|
32
|
+
/**
|
|
33
|
+
* AI 出站是否转为 QQ Markdown(`msg_type=2`)。
|
|
34
|
+
* - `auto`(默认):正文含 Markdown 语法时转换
|
|
35
|
+
* - `true`:纯文本也走 Markdown
|
|
36
|
+
* - `false`:保持纯文本
|
|
37
|
+
*/
|
|
38
|
+
outboundMarkdown?: boolean | "auto";
|
|
17
39
|
};
|
|
18
40
|
|
|
19
41
|
export interface QQBot<
|