@napgram/utils 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 magisk317
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.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @napgram/utils
2
+
3
+ Utility functions for NapGram native plugins.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @napgram/utils
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import {
15
+ extractPlainText,
16
+ makeText,
17
+ makeAt,
18
+ makeReply,
19
+ makeImage,
20
+ parseUserId,
21
+ sleep,
22
+ randomChoice
23
+ } from '@napgram/utils';
24
+
25
+ // Extract plain text from message segments
26
+ const text = extractPlainText(event.message.segments);
27
+
28
+ // Create message segments
29
+ const segments = [
30
+ makeReply(event.message.id),
31
+ makeAt(event.sender.userId),
32
+ makeText(' Hello!'),
33
+ makeImage('https://example.com/image.png')
34
+ ];
35
+
36
+ await event.send(segments);
37
+
38
+ // Parse IDs
39
+ const { platform, id } = parseUserId('qq:u:123456');
40
+
41
+ // Utilities
42
+ await sleep(1000);
43
+ const choice = randomChoice(['a', 'b', 'c']);
44
+ ```
45
+
46
+ ## Subpath Exports
47
+
48
+ ```typescript
49
+ import { sendPoke } from '@napgram/utils/qq-helpers';
50
+ ```
51
+
52
+ ## API Reference
53
+
54
+ ### Message Segments
55
+
56
+ - `makeText(text)` - Create text segment
57
+ - `makeAt(userId, userName?)` - Create @mention segment
58
+ - `makeReply(messageId)` - Create reply segment
59
+ - `makeImage(url, file?)` - Create image segment
60
+ - `makeVideo(url, file?)` - Create video segment
61
+ - `makeAudio(url, file?)` - Create audio segment
62
+ - `makeFile(url, name?)` - Create file segment
63
+ - `makeFace(id)` - Create emoji segment
64
+
65
+ ### Parsers
66
+
67
+ - `extractPlainText(segments)` - Extract plain text
68
+ - `parseUserId(userId)` - Parse user ID (qq:u:xxx / tg:u:xxx)
69
+ - `parseGroupId(groupId)` - Parse group ID
70
+
71
+ ### Utilities
72
+
73
+ - `sleep(ms)` - Delay function
74
+ - `randomInt(min, max)` - Random integer
75
+ - `randomChoice(array)` - Random array element
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,77 @@
1
+ /**
2
+ * NapGram Plugin Utils
3
+ *
4
+ * Utility functions for NapGram native plugins
5
+ */
6
+ import type { MessageSegment } from '@napgram/core';
7
+ /**
8
+ * 提取消息片段中的纯文本
9
+ */
10
+ export declare function extractPlainText(segments: MessageSegment[]): string;
11
+ /**
12
+ * 创建文本片段
13
+ */
14
+ export declare function makeText(text: string): MessageSegment;
15
+ /**
16
+ * 创建 @某人 片段
17
+ */
18
+ export declare function makeAt(userId: string, userName?: string): MessageSegment;
19
+ /**
20
+ * 创建回复片段
21
+ */
22
+ export declare function makeReply(messageId: string): MessageSegment;
23
+ /**
24
+ * 创建图片片段
25
+ */
26
+ export declare function makeImage(url: string, file?: string): MessageSegment;
27
+ /**
28
+ * 创建视频片段
29
+ */
30
+ export declare function makeVideo(url: string, file?: string): MessageSegment;
31
+ /**
32
+ * 创建音频片段
33
+ */
34
+ export declare function makeAudio(url: string, file?: string): MessageSegment;
35
+ /**
36
+ * 创建文件片段
37
+ */
38
+ export declare function makeFile(url: string, name?: string): MessageSegment;
39
+ /**
40
+ * 创建表情片段
41
+ */
42
+ export declare function makeFace(id: string): MessageSegment;
43
+ /**
44
+ * 解析用户 ID
45
+ *
46
+ * @example
47
+ * parseUserId('qq:u:123456') // { platform: 'qq', id: '123456' }
48
+ * parseUserId('tg:u:789012') // { platform: 'tg', id: '789012' }
49
+ */
50
+ export declare function parseUserId(userId: string): {
51
+ platform: 'qq' | 'tg';
52
+ id: string;
53
+ };
54
+ /**
55
+ * 解析群组 ID
56
+ *
57
+ * @example
58
+ * parseGroupId('qq:g:123456') // { platform: 'qq', id: '123456' }
59
+ */
60
+ export declare function parseGroupId(groupId: string): {
61
+ platform: 'qq' | 'tg';
62
+ id: string;
63
+ };
64
+ /**
65
+ * 延迟函数
66
+ */
67
+ export declare function sleep(ms: number): Promise<void>;
68
+ /**
69
+ * 随机整数
70
+ */
71
+ export declare function randomInt(min: number, max: number): number;
72
+ /**
73
+ * 随机选择数组元素
74
+ */
75
+ export declare function randomChoice<T>(array: T[]): T;
76
+ export * from './qq-helpers';
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAKnE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAKrD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,CAKxE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAK3D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAKpE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAKpE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAKpE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAKnE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,CAKnD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAUjF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAUnF;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAE7C;AAGD,cAAc,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * NapGram Plugin Utils
3
+ *
4
+ * Utility functions for NapGram native plugins
5
+ */
6
+ /**
7
+ * 提取消息片段中的纯文本
8
+ */
9
+ export function extractPlainText(segments) {
10
+ return segments
11
+ .filter(seg => seg.type === 'text')
12
+ .map(seg => seg.data.text || '')
13
+ .join('');
14
+ }
15
+ /**
16
+ * 创建文本片段
17
+ */
18
+ export function makeText(text) {
19
+ return {
20
+ type: 'text',
21
+ data: { text }
22
+ };
23
+ }
24
+ /**
25
+ * 创建 @某人 片段
26
+ */
27
+ export function makeAt(userId, userName) {
28
+ return {
29
+ type: 'at',
30
+ data: { userId, userName }
31
+ };
32
+ }
33
+ /**
34
+ * 创建回复片段
35
+ */
36
+ export function makeReply(messageId) {
37
+ return {
38
+ type: 'reply',
39
+ data: { messageId }
40
+ };
41
+ }
42
+ /**
43
+ * 创建图片片段
44
+ */
45
+ export function makeImage(url, file) {
46
+ return {
47
+ type: 'image',
48
+ data: { url, file }
49
+ };
50
+ }
51
+ /**
52
+ * 创建视频片段
53
+ */
54
+ export function makeVideo(url, file) {
55
+ return {
56
+ type: 'video',
57
+ data: { url, file }
58
+ };
59
+ }
60
+ /**
61
+ * 创建音频片段
62
+ */
63
+ export function makeAudio(url, file) {
64
+ return {
65
+ type: 'audio',
66
+ data: { url, file }
67
+ };
68
+ }
69
+ /**
70
+ * 创建文件片段
71
+ */
72
+ export function makeFile(url, name) {
73
+ return {
74
+ type: 'file',
75
+ data: { url, name }
76
+ };
77
+ }
78
+ /**
79
+ * 创建表情片段
80
+ */
81
+ export function makeFace(id) {
82
+ return {
83
+ type: 'face',
84
+ data: { id }
85
+ };
86
+ }
87
+ /**
88
+ * 解析用户 ID
89
+ *
90
+ * @example
91
+ * parseUserId('qq:u:123456') // { platform: 'qq', id: '123456' }
92
+ * parseUserId('tg:u:789012') // { platform: 'tg', id: '789012' }
93
+ */
94
+ export function parseUserId(userId) {
95
+ const parts = userId.split(':');
96
+ if (parts.length < 3) {
97
+ throw new Error(`Invalid userId format: ${userId}`);
98
+ }
99
+ const platform = parts[0];
100
+ const id = parts.slice(2).join(':');
101
+ return { platform, id };
102
+ }
103
+ /**
104
+ * 解析群组 ID
105
+ *
106
+ * @example
107
+ * parseGroupId('qq:g:123456') // { platform: 'qq', id: '123456' }
108
+ */
109
+ export function parseGroupId(groupId) {
110
+ const parts = groupId.split(':');
111
+ if (parts.length < 3) {
112
+ throw new Error(`Invalid groupId format: ${groupId}`);
113
+ }
114
+ const platform = parts[0];
115
+ const id = parts.slice(2).join(':');
116
+ return { platform, id };
117
+ }
118
+ /**
119
+ * 延迟函数
120
+ */
121
+ export function sleep(ms) {
122
+ return new Promise(resolve => setTimeout(resolve, ms));
123
+ }
124
+ /**
125
+ * 随机整数
126
+ */
127
+ export function randomInt(min, max) {
128
+ return Math.floor(Math.random() * (max - min + 1)) + min;
129
+ }
130
+ /**
131
+ * 随机选择数组元素
132
+ */
133
+ export function randomChoice(array) {
134
+ return array[randomInt(0, array.length - 1)];
135
+ }
136
+ // QQ 交互 Helpers
137
+ export * from './qq-helpers';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * QQ 交互 Helper 函数
3
+ *
4
+ * 提供高级封装,避免插件重复实现逻辑
5
+ */
6
+ import type { MessageEvent } from '@napgram/core';
7
+ export interface QQInteractionResult {
8
+ success: boolean;
9
+ message: string;
10
+ data?: any;
11
+ }
12
+ /**
13
+ * 从回复消息或参数中解析目标 QQ 号
14
+ */
15
+ export declare function resolveTargetUser(event: MessageEvent, args: string[]): string | undefined;
16
+ /**
17
+ * 查找当前聊天绑定的 QQ 群
18
+ */
19
+ export declare function findBoundQQGroup(event: MessageEvent): {
20
+ qqGroupId?: string;
21
+ error?: string;
22
+ };
23
+ /**
24
+ * 戳一戳
25
+ */
26
+ export declare function sendPoke(event: MessageEvent, args: string[]): Promise<QQInteractionResult>;
27
+ /**
28
+ * 获取/设置群名片
29
+ */
30
+ export declare function handleNick(event: MessageEvent, args: string[]): Promise<QQInteractionResult>;
31
+ /**
32
+ * 点赞
33
+ */
34
+ export declare function sendLike(event: MessageEvent, args: string[]): Promise<QQInteractionResult>;
35
+ /**
36
+ * 群荣誉
37
+ */
38
+ export declare function getGroupHonor(event: MessageEvent, args: string[]): Promise<QQInteractionResult>;
39
+ //# sourceMappingURL=qq-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qq-helpers.d.ts","sourceRoot":"","sources":["../src/qq-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAuCzF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAoB5F;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC1B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,mBAAmB,CAAC,CAyD9B;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC5B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,mBAAmB,CAAC,CA4C9B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC1B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,mBAAmB,CAAC,CA4D9B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAC/B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,mBAAmB,CAAC,CAiD9B"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * QQ 交互 Helper 函数
3
+ *
4
+ * 提供高级封装,避免插件重复实现逻辑
5
+ */
6
+ /**
7
+ * 从回复消息或参数中解析目标 QQ 号
8
+ */
9
+ export function resolveTargetUser(event, args) {
10
+ let targetUin;
11
+ // 1. 尝试从回复消息中提取
12
+ if (event.raw?.replyToMessage) {
13
+ const repliedMsg = event.raw.replyToMessage;
14
+ const replyText = repliedMsg.text || '';
15
+ // A. 尝试从文本格式解析:昵称 (QQ号)
16
+ const match = replyText.match(/\((\d+)\)/);
17
+ if (match) {
18
+ targetUin = match[1];
19
+ }
20
+ // B. 尝试从 RichHeader 链接中解析
21
+ if (!targetUin && repliedMsg.entities) {
22
+ for (const entity of repliedMsg.entities) {
23
+ if (entity.type === 'text_link' && entity.url && entity.url.includes('/richHeader/')) {
24
+ const parts = entity.url.split('/');
25
+ const uin = parts.pop()?.split('?')[0]; // 去失 query params
26
+ if (uin && /^\d+$/.test(uin)) {
27
+ targetUin = uin;
28
+ break;
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ // 2. 从参数中获取
35
+ if (!targetUin && args.length > 0) {
36
+ // 参数可能是 QQ 号
37
+ const arg = args[0];
38
+ if (/^\d+$/.test(arg)) {
39
+ targetUin = arg;
40
+ }
41
+ }
42
+ return targetUin;
43
+ }
44
+ /**
45
+ * 查找当前聊天绑定的 QQ 群
46
+ */
47
+ export function findBoundQQGroup(event) {
48
+ // 只在 Telegram 端处理
49
+ if (event.platform !== 'tg') {
50
+ return { error: '此命令仅在 Telegram 端使用' };
51
+ }
52
+ // 检查 API 可用性
53
+ if (!event.instance || !event.instance.forwardPairs) {
54
+ return { error: 'Instance API 不可用' };
55
+ }
56
+ // 查找绑定
57
+ const forwardMap = event.instance.forwardPairs;
58
+ const pair = forwardMap.findByTG?.(event.channelId, event.threadId, true);
59
+ if (!pair) {
60
+ return { error: '❌ 当前聊天未绑定任何 QQ 群' };
61
+ }
62
+ return { qqGroupId: pair.qqRoomId.toString() };
63
+ }
64
+ /**
65
+ * 戳一戳
66
+ */
67
+ export async function sendPoke(event, args) {
68
+ // 查找绑定的 QQ 群
69
+ const { qqGroupId, error } = findBoundQQGroup(event);
70
+ if (error) {
71
+ return { success: false, message: error };
72
+ }
73
+ // 解析目标用户
74
+ const targetUin = resolveTargetUser(event, args);
75
+ if (!targetUin) {
76
+ return {
77
+ success: false,
78
+ message: `❌ 无法识别目标用户\n\n使用方式:\n• 回复目标用户消息:/poke\n• 直接指定:/poke 123456789`
79
+ };
80
+ }
81
+ // 检查 QQ API
82
+ if (!event.qq) {
83
+ return { success: false, message: '❌ QQ Client API 不可用' };
84
+ }
85
+ // 执行戳一戳
86
+ try {
87
+ if (event.qq.sendGroupPoke) {
88
+ await event.qq.sendGroupPoke(qqGroupId, targetUin);
89
+ }
90
+ else if (event.qq.callApi) {
91
+ const groupId = Number(qqGroupId);
92
+ const userId = Number(targetUin);
93
+ let lastError;
94
+ for (const method of ['send_group_poke', 'group_poke']) {
95
+ try {
96
+ await event.qq.callApi(method, { group_id: groupId, user_id: userId });
97
+ lastError = undefined;
98
+ break;
99
+ }
100
+ catch (error) {
101
+ lastError = error;
102
+ }
103
+ }
104
+ if (lastError) {
105
+ throw lastError;
106
+ }
107
+ }
108
+ else {
109
+ return { success: false, message: '❌ 当前QQ客户端不支持戳一戳功能' };
110
+ }
111
+ return {
112
+ success: true,
113
+ message: `👉 已戳一戳 ${targetUin}`
114
+ };
115
+ }
116
+ catch (error) {
117
+ return {
118
+ success: false,
119
+ message: '❌ 发送戳一戳失败'
120
+ };
121
+ }
122
+ }
123
+ /**
124
+ * 获取/设置群名片
125
+ */
126
+ export async function handleNick(event, args) {
127
+ // 查找绑定的 QQ 群
128
+ const { qqGroupId, error } = findBoundQQGroup(event);
129
+ if (error) {
130
+ return { success: false, message: error };
131
+ }
132
+ // 检查 QQ API
133
+ if (!event.qq) {
134
+ return { success: false, message: '❌ QQ Client API 不可用' };
135
+ }
136
+ const botUin = event.qq.uin.toString();
137
+ try {
138
+ if (args.length === 0) {
139
+ // 获取当前昵称
140
+ const memberInfo = await event.qq.getGroupMemberInfo?.(qqGroupId, botUin);
141
+ const card = memberInfo?.card || memberInfo?.nickname || '未设置';
142
+ return {
143
+ success: true,
144
+ message: `📝 当前群名片: \`${card}\`\n\n使用 \`/nick 新名片\` 修改`
145
+ };
146
+ }
147
+ else {
148
+ // 设置新昵称
149
+ const newCard = args.join(' ');
150
+ if (!event.qq.setGroupCard) {
151
+ return { success: false, message: '❌ 当前QQ客户端不支持修改群名片' };
152
+ }
153
+ await event.qq.setGroupCard(qqGroupId, botUin, newCard);
154
+ return {
155
+ success: true,
156
+ message: `✅ 已修改群名片为: \`${newCard}\``
157
+ };
158
+ }
159
+ }
160
+ catch (error) {
161
+ return {
162
+ success: false,
163
+ message: '❌ 获取/设置群名片失败'
164
+ };
165
+ }
166
+ }
167
+ /**
168
+ * 点赞
169
+ */
170
+ export async function sendLike(event, args) {
171
+ // 只在 Telegram 端处理
172
+ if (event.platform !== 'tg') {
173
+ return { success: false, message: '此命令仅在 Telegram 端使用' };
174
+ }
175
+ // 检查 QQ API
176
+ if (!event.qq) {
177
+ return { success: false, message: '❌ QQ Client API 不可用' };
178
+ }
179
+ // 解析参数:支持 /like QQ号 次数 或 /like 次数 QQ号
180
+ let targetUin;
181
+ let times = 1;
182
+ // 从回复消息中提取
183
+ if (event.raw?.replyToMessage) {
184
+ targetUin = resolveTargetUser(event, []);
185
+ // 第一个参数是次数
186
+ if (args.length > 0 && /^\d+$/.test(args[0])) {
187
+ times = Math.min(Math.max(parseInt(args[0]), 1), 10);
188
+ }
189
+ }
190
+ else {
191
+ // 从参数中解析
192
+ for (const arg of args) {
193
+ if (/^\d{5,}$/.test(arg)) {
194
+ // 长数字是 QQ 号
195
+ targetUin = arg;
196
+ }
197
+ else if (/^\d{1,2}$/.test(arg)) {
198
+ // 短数字是次数
199
+ times = Math.min(Math.max(parseInt(arg), 1), 10);
200
+ }
201
+ }
202
+ }
203
+ if (!targetUin) {
204
+ return {
205
+ success: false,
206
+ message: `❌ 无法识别目标用户\n\n使用方式:\n• 回复目标用户的消息:/like [次数]\n• 直接指定:/like 123456789 [次数]\n• 参数顺序可互换:/like 10 123456789`
207
+ };
208
+ }
209
+ // 执行点赞
210
+ try {
211
+ if (!event.qq.sendLike) {
212
+ return { success: false, message: '❌ 当前QQ客户端不支持点赞功能' };
213
+ }
214
+ await event.qq.sendLike(targetUin, times);
215
+ return {
216
+ success: true,
217
+ message: `✅ 已给 ${targetUin} 点赞 x${times}`
218
+ };
219
+ }
220
+ catch (error) {
221
+ return {
222
+ success: false,
223
+ message: `❌ 点赞失败:${error.message || error}`
224
+ };
225
+ }
226
+ }
227
+ /**
228
+ * 群荣誉
229
+ */
230
+ export async function getGroupHonor(event, args) {
231
+ // 查找绑定的 QQ 群
232
+ const { qqGroupId, error } = findBoundQQGroup(event);
233
+ if (error) {
234
+ return { success: false, message: error };
235
+ }
236
+ // 检查 QQ API
237
+ if (!event.qq) {
238
+ return { success: false, message: '❌ QQ Client API 不可用' };
239
+ }
240
+ const type = args[0] || 'all';
241
+ const validTypes = ['talkative', 'performer', 'legend', 'strong_newbie', 'emotion', 'all'];
242
+ if (!validTypes.includes(type)) {
243
+ return {
244
+ success: false,
245
+ message: `❌ 无效的类型:${type}\n\n可用类型:${validTypes.join(', ')}`
246
+ };
247
+ }
248
+ try {
249
+ if (!event.qq.getGroupHonorInfo) {
250
+ return { success: false, message: '❌ 当前QQ客户端不支持查询群荣誉' };
251
+ }
252
+ const honorInfo = await event.qq.getGroupHonorInfo(qqGroupId, type);
253
+ // 格式化输出(简化版)
254
+ let message = `🏆 群荣誉榜单\n\n`;
255
+ if (honorInfo && typeof honorInfo === 'object') {
256
+ message += JSON.stringify(honorInfo, null, 2);
257
+ }
258
+ else {
259
+ message += '暂无数据';
260
+ }
261
+ return {
262
+ success: true,
263
+ message,
264
+ data: honorInfo
265
+ };
266
+ }
267
+ catch (error) {
268
+ return {
269
+ success: false,
270
+ message: `❌ 查询群荣誉失败:${error.message || error}`
271
+ };
272
+ }
273
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@napgram/utils",
3
+ "version": "0.1.0",
4
+ "description": "Utility functions for NapGram native plugins",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./qq-helpers": {
15
+ "types": "./dist/qq-helpers.d.ts",
16
+ "import": "./dist/qq-helpers.js"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "LICENSE"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.json",
27
+ "clean": "rm -rf dist",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "keywords": [
31
+ "napgram",
32
+ "plugin",
33
+ "utils",
34
+ "helpers"
35
+ ],
36
+ "author": "NapLink",
37
+ "license": "MIT",
38
+ "dependencies": {
39
+ "@napgram/core": "workspace:*"
40
+ },
41
+ "devDependencies": {
42
+ "typescript": "^5.9.3"
43
+ },
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/NapGram/sdk.git",
47
+ "directory": "packages/utils"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ }
52
+ }