@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 +21 -0
- package/README.md +79 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/qq-helpers.d.ts +39 -0
- package/dist/qq-helpers.d.ts.map +1 -0
- package/dist/qq-helpers.js +273 -0
- package/package.json +52 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|