@zhin.js/adapter-onebot12 0.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/src/utils.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * OneBot 12 事件与 zhin Message 的转换、消息段转换
3
+ */
4
+ import type { SendContent } from 'zhin.js';
5
+ import type { OneBot12Event, OneBot12Segment } from './types.js';
6
+
7
+ /** 判断是否为消息事件(type=message) */
8
+ export function isMessageEvent(ev: OneBot12Event): ev is OneBot12Event & { message_id: string; message?: OneBot12Segment[] } {
9
+ return ev.type === 'message' && !!ev.message_id;
10
+ }
11
+
12
+ /** 从事件得到 zhin 场景 id:私聊 user_id,群 group_id,频道 channel_id 或 guild_id:channel_id */
13
+ export function getChannelId(ev: OneBot12Event): string {
14
+ if (ev.detail_type === 'private' && ev.user_id) return ev.user_id;
15
+ if (ev.detail_type === 'group' && ev.group_id) return ev.group_id;
16
+ if (ev.detail_type === 'channel' && ev.channel_id) {
17
+ return ev.guild_id ? `${ev.guild_id}:${ev.channel_id}` : ev.channel_id;
18
+ }
19
+ return '';
20
+ }
21
+
22
+ /** 从事件得到 channel 类型 */
23
+ export function getChannelType(ev: OneBot12Event): 'private' | 'group' {
24
+ if (ev.detail_type === 'private') return 'private';
25
+ return 'group';
26
+ }
27
+
28
+ /** 将 OneBot 12 消息事件转为 zhin Message 的 MessageBase 所需字段 */
29
+ export function formatOneBot12MessagePayload(
30
+ ev: OneBot12Event,
31
+ botName: string,
32
+ recallFn: (msgId: string) => Promise<void>,
33
+ replyFn: (channel: { id: string; type: 'group' | 'private' }, content: (string | { type: string; data?: Record<string, unknown> })[], quote?: boolean | string) => Promise<string>,
34
+ ): {
35
+ $id: string;
36
+ $adapter: 'onebot12';
37
+ $bot: string;
38
+ $channel: { id: string; type: 'group' | 'private' };
39
+ $sender: { id: string; name: string };
40
+ $content: Array<{ type: string; data: Record<string, unknown> }>;
41
+ $raw: string;
42
+ $timestamp: number;
43
+ $recall: () => Promise<void>;
44
+ $reply: (content: SendContent, quote?: boolean | string) => Promise<string>;
45
+ } {
46
+ const channelId = getChannelId(ev);
47
+ const channelType = getChannelType(ev);
48
+ const raw = ev.alt_message ?? (Array.isArray(ev.message) ? ev.message.map((s) => (s.type === 'text' ? (s.data?.text as string) ?? '' : '')).join('') : '');
49
+ const content = Array.isArray(ev.message)
50
+ ? ev.message.map((s) => ({ type: s.type, data: (s.data ?? {}) as Record<string, unknown> }))
51
+ : [{ type: 'text', data: { text: raw } }];
52
+ const senderId = ev.user_id ?? '';
53
+ const senderName = (ev as Record<string, unknown>)['user.name'] as string | undefined ?? (ev as Record<string, unknown>)['qq.nickname'] as string | undefined ?? senderId;
54
+
55
+ return {
56
+ $id: ev.message_id!,
57
+ $adapter: 'onebot12',
58
+ $bot: botName,
59
+ $channel: { id: channelId, type: channelType },
60
+ $sender: { id: senderId, name: senderName },
61
+ $content: content,
62
+ $raw: raw,
63
+ $timestamp: ev.time ?? 0,
64
+ $recall: () => recallFn(ev.message_id!),
65
+ $reply: (cnt: SendContent, quote?: boolean | string) =>
66
+ replyFn(
67
+ { id: channelId, type: channelType },
68
+ (Array.isArray(cnt) ? cnt : [cnt]) as (string | { type: string; data?: Record<string, unknown> })[],
69
+ quote,
70
+ ),
71
+ };
72
+ }
73
+
74
+ /** 将 zhin 的 content(segment 数组或字符串)转为 OneBot 12 message 段数组;简单实现仅 text */
75
+ export function contentToOb12Segments(content: SendContent): OneBot12Segment[] {
76
+ const arr = Array.isArray(content) ? content : [content];
77
+ const segs: OneBot12Segment[] = [];
78
+ for (const c of arr) {
79
+ if (typeof c === 'string') {
80
+ segs.push({ type: 'text', data: { text: c } });
81
+ } else if (c && typeof c === 'object' && 'type' in c) {
82
+ const el = c as { type: string; data?: Record<string, unknown> };
83
+ segs.push({ type: el.type, data: el.data ?? {} });
84
+ }
85
+ }
86
+ return segs.length ? segs : [{ type: 'text', data: { text: '' } }];
87
+ }