@karinjs/adapter-qqbot 1.2.8 → 1.2.10
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/config/comment/config.json +3 -0
- package/config/config/config.yaml +53 -0
- package/lib/cli/pr.d.ts +2 -0
- package/lib/cli/pr.js +73 -0
- package/lib/core/adapter/adapter.d.ts +91 -0
- package/lib/core/adapter/adapter.js +144 -0
- package/lib/core/adapter/handler.d.ts +49 -0
- package/lib/core/adapter/handler.js +140 -0
- package/lib/core/adapter/markdown.d.ts +38 -0
- package/lib/core/adapter/markdown.js +220 -0
- package/lib/core/adapter/normal.d.ts +30 -0
- package/lib/core/adapter/normal.js +263 -0
- package/lib/core/api/index.d.ts +167 -0
- package/lib/core/api/index.js +180 -0
- package/lib/core/api/sign.d.ts +22 -0
- package/lib/core/api/sign.js +40 -0
- package/lib/core/api/types.d.ts +236 -0
- package/lib/core/event/conver.d.ts +10 -0
- package/lib/core/event/conver.js +57 -0
- package/lib/core/event/index.d.ts +9 -0
- package/lib/core/event/index.js +98 -0
- package/lib/core/event/message.d.ts +27 -0
- package/lib/core/event/message.js +95 -0
- package/lib/core/event/notice.d.ts +50 -0
- package/lib/core/event/notice.js +133 -0
- package/lib/{types/event.d.ts → core/event/types.d.ts} +255 -14
- package/lib/core/internal/axios.d.ts +25 -0
- package/lib/core/internal/axios.js +46 -0
- package/lib/core/internal/sign.d.ts +22 -0
- package/lib/core/internal/sign.js +40 -0
- package/lib/core/webhook/c2c.d.ts +2 -0
- package/lib/core/webhook/c2c.js +14 -0
- package/lib/core/webhook/http.d.ts +2 -0
- package/lib/core/webhook/http.js +35 -0
- package/lib/core/webhook/index.d.ts +17 -0
- package/lib/core/webhook/index.js +87 -0
- package/lib/core/webhook/ws.d.ts +2 -0
- package/lib/core/webhook/ws.js +79 -0
- package/lib/index.d.ts +1 -3
- package/lib/index.js +5 -7
- package/lib/root.d.ts +5 -0
- package/lib/root.js +9 -0
- package/lib/types/config.d.ts +53 -0
- package/lib/utils/common.d.ts +75 -61
- package/lib/utils/common.js +190 -202
- package/lib/utils/config.d.ts +5 -130
- package/lib/utils/config.js +50 -172
- package/lib/utils/dir.d.ts +1 -5
- package/lib/utils/dir.js +1 -10
- package/lib/utils/index.d.ts +4 -3
- package/lib/utils/index.js +4 -3
- package/package.json +41 -23
- package/config/config.yaml +0 -69
- package/lib/core/api.d.ts +0 -166
- package/lib/core/api.js +0 -429
- package/lib/core/index.d.ts +0 -92
- package/lib/core/index.js +0 -343
- package/lib/core/intents.d.ts +0 -6
- package/lib/core/intents.js +0 -57
- package/lib/core/markdown.d.ts +0 -23
- package/lib/core/markdown.js +0 -265
- package/lib/types/index.d.ts +0 -3
- package/lib/types/index.js +0 -3
- package/lib/types/media.d.ts +0 -100
- package/lib/types/message.d.ts +0 -85
- /package/lib/{types/event.js → core/api/types.js} +0 -0
- /package/lib/{types/media.js → core/event/types.js} +0 -0
- /package/lib/types/{message.js → config.js} +0 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import FormData from 'form-data';
|
|
2
|
+
import { handleUrl, qrs, textToButton } from '@/utils/common';
|
|
3
|
+
import { common, fileToUrl, buttonHandle } from 'node-karin';
|
|
4
|
+
import { AdapterQQBot } from '@/core/adapter/adapter';
|
|
5
|
+
/** markdown */
|
|
6
|
+
export class AdapterQQBotMarkdown extends AdapterQQBot {
|
|
7
|
+
_config;
|
|
8
|
+
markdown;
|
|
9
|
+
constructor(QQBot, markdown, config) {
|
|
10
|
+
super(QQBot);
|
|
11
|
+
this.markdown = markdown;
|
|
12
|
+
this._config = config;
|
|
13
|
+
}
|
|
14
|
+
async srcReply(e, elements) {
|
|
15
|
+
const list = await buttonHandle(e.msg, { e });
|
|
16
|
+
return this.sendMsg(e.contact, [...elements, ...list]);
|
|
17
|
+
}
|
|
18
|
+
async sendMsg(contact, elements, retryCount) {
|
|
19
|
+
if (contact.scene === 'direct' || contact.scene === 'guild') {
|
|
20
|
+
return this.sendGuildMsg(contact, elements, retryCount);
|
|
21
|
+
}
|
|
22
|
+
else if (contact.scene === 'group' || contact.scene === 'friend') {
|
|
23
|
+
return this.sendQQMsg(contact, elements, retryCount);
|
|
24
|
+
}
|
|
25
|
+
throw new Error('不支持的消息类型');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 处理文本 将文本中的链接转为二维码
|
|
29
|
+
* @param text 文本
|
|
30
|
+
* @returns 处理后的文本和二维码 二维码为不带`base64://`的字符串
|
|
31
|
+
*/
|
|
32
|
+
async hendleText(text) {
|
|
33
|
+
const urls = handleUrl(text);
|
|
34
|
+
if (!urls.length)
|
|
35
|
+
return { text, qr: null };
|
|
36
|
+
urls.forEach((url) => {
|
|
37
|
+
text = text.replace(new RegExp(url, 'g'), '[请扫码查看]');
|
|
38
|
+
});
|
|
39
|
+
const list = await qrs(urls);
|
|
40
|
+
if (list.length === 1)
|
|
41
|
+
return { text, qr: list[0] };
|
|
42
|
+
const result = await common.mergeImage(list, 3);
|
|
43
|
+
return { text, qr: result.base64 };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 发送QQ私聊、群聊消息
|
|
47
|
+
* @param contact 联系人
|
|
48
|
+
* @param elements 消息元素
|
|
49
|
+
* @param retryCount 重试次数
|
|
50
|
+
*/
|
|
51
|
+
async sendQQMsg(contact, elements, retryCount) {
|
|
52
|
+
const list = this.initList('qq');
|
|
53
|
+
/** 上传富媒体的目标 */
|
|
54
|
+
const target = contact.scene === 'friend' ? 'user' : 'group';
|
|
55
|
+
for (const v of elements) {
|
|
56
|
+
if (v.type === 'text') {
|
|
57
|
+
const { text, buttons } = textToButton(v.text, contact.scene === 'friend');
|
|
58
|
+
list.content.push(text);
|
|
59
|
+
if (buttons)
|
|
60
|
+
list.button.push(...buttons);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (v.type === 'at') {
|
|
64
|
+
if (contact.scene === 'friend')
|
|
65
|
+
continue;
|
|
66
|
+
list.content.push(v.targetId === 'all' ? '<qqbot-at-everyone />' : `<qqbot-at-user id="${v.targetId}" />`);
|
|
67
|
+
}
|
|
68
|
+
if (v.type === 'image') {
|
|
69
|
+
list.image.push(v.file);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (v.type === 'pasmsg') {
|
|
73
|
+
if (v.source === 'event')
|
|
74
|
+
list.pasmsg.type = 'event';
|
|
75
|
+
list.pasmsg.msg_id = v.id;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (v.type === 'keyboard') {
|
|
79
|
+
list.keyboard.push(v);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (v.type === 'button') {
|
|
83
|
+
list.button.push(v);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (v.type === 'markdown') {
|
|
87
|
+
list.markdown.push(v);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (v.type === 'markdownTpl') {
|
|
91
|
+
list.markdownTpl.push(v);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (v.type === 'video' || v.type === 'record') {
|
|
95
|
+
let url;
|
|
96
|
+
if (v.file.startsWith('http')) {
|
|
97
|
+
url = v.file;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const data = await fileToUrl(v.type, v.file, `${v.type}.${v.type === 'record' ? 'mp3' : 'mp4'}`);
|
|
101
|
+
url = data.url;
|
|
102
|
+
}
|
|
103
|
+
const res = await this.super.uploadMedia(target, contact.peer, v.type, url, false);
|
|
104
|
+
list.list.push(this.super.QQdMsgOptions('media', res.file_info));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
this.logger('debug', `[QQBot][${v.type}] 不支持发送的消息类型`);
|
|
108
|
+
}
|
|
109
|
+
/** 处理被动消息 */
|
|
110
|
+
const pasmsg = (() => {
|
|
111
|
+
if (!list.pasmsg.msg_id)
|
|
112
|
+
return () => '';
|
|
113
|
+
list.pasmsg.msg_seq++;
|
|
114
|
+
if (list.pasmsg.type === 'msg') {
|
|
115
|
+
return (item) => {
|
|
116
|
+
item.msg_seq = list.pasmsg.msg_seq;
|
|
117
|
+
item.msg_id = list.pasmsg.msg_id;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return (item) => {
|
|
121
|
+
item.msg_seq = list.pasmsg.msg_seq;
|
|
122
|
+
item.event_id = list.pasmsg.msg_id;
|
|
123
|
+
};
|
|
124
|
+
})();
|
|
125
|
+
/** 发送消息 */
|
|
126
|
+
const send = (() => {
|
|
127
|
+
if (contact.scene === 'friend') {
|
|
128
|
+
return (peer, item) => this.super.sendFriendMsg(peer, item);
|
|
129
|
+
}
|
|
130
|
+
return (peer, item) => this.super.sendGroupMsg(peer, item);
|
|
131
|
+
})();
|
|
132
|
+
return this.markdown('qq', this, list, contact, pasmsg, send);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 发送频道消息
|
|
136
|
+
* @param contact 联系人
|
|
137
|
+
* @param elements 消息元素
|
|
138
|
+
* @param retryCount 重试次数
|
|
139
|
+
*/
|
|
140
|
+
async sendGuildMsg(contact, elements, retryCount) {
|
|
141
|
+
const list = this.initList('guild');
|
|
142
|
+
for (const v of elements) {
|
|
143
|
+
if (v.type === 'text') {
|
|
144
|
+
const { text, buttons } = textToButton(v.text, contact.scene === 'direct');
|
|
145
|
+
list.content.push(text);
|
|
146
|
+
if (buttons)
|
|
147
|
+
list.button.push(...buttons);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (v.type === 'image') {
|
|
151
|
+
list.image.push(v.file);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (v.type === 'at') {
|
|
155
|
+
if (contact.scene === 'guild') {
|
|
156
|
+
list.content.push(v.targetId === 'all' ? '<qqbot-at-everyone />' : `<qqbot-at-user id="${v.targetId}" />`);
|
|
157
|
+
}
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (v.type === 'pasmsg') {
|
|
161
|
+
if (v.source === 'event')
|
|
162
|
+
list.pasmsg.type = 'event';
|
|
163
|
+
list.pasmsg.msg_id = v.id;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (v.type === 'reply') {
|
|
167
|
+
list.reply.message_id = v.messageId;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (v.type === 'face') {
|
|
171
|
+
list.content.push(`<emoji:${v.id}>`);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (v.type === 'keyboard') {
|
|
175
|
+
list.keyboard.push(v);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (v.type === 'button') {
|
|
179
|
+
list.button.push(v);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (v.type === 'markdown') {
|
|
183
|
+
list.markdown.push(v);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (v.type === 'markdownTpl') {
|
|
187
|
+
list.markdownTpl.push(v);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
this.logger('debug', `[QQBot][${v.type}] 不支持发送的消息类型`);
|
|
191
|
+
}
|
|
192
|
+
/** 发送消息 */
|
|
193
|
+
const send = (() => {
|
|
194
|
+
if (contact.scene === 'guild') {
|
|
195
|
+
return (peer, subPeer, item) => this.super.sendChannelMsg(subPeer, item);
|
|
196
|
+
}
|
|
197
|
+
return (peer, subPeer, item) => this.super.sendDmsMsg(peer, item);
|
|
198
|
+
})();
|
|
199
|
+
/** 处理被动消息 */
|
|
200
|
+
const pasmsg = (() => {
|
|
201
|
+
if (!list.pasmsg.msg_id)
|
|
202
|
+
return () => '';
|
|
203
|
+
if (list.pasmsg.type === 'msg') {
|
|
204
|
+
return (item) => {
|
|
205
|
+
if (item instanceof FormData) {
|
|
206
|
+
return item.append('msg_id', list.pasmsg.msg_id);
|
|
207
|
+
}
|
|
208
|
+
item.msg_id = list.pasmsg.msg_id;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return (item) => {
|
|
212
|
+
if (item instanceof FormData) {
|
|
213
|
+
return item.append('event_id', list.pasmsg.msg_id);
|
|
214
|
+
}
|
|
215
|
+
item.event_id = list.pasmsg.msg_id;
|
|
216
|
+
};
|
|
217
|
+
})();
|
|
218
|
+
return this.markdown('guild', this, list, contact, pasmsg, send);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AdapterQQBot } from '@/core/adapter/adapter';
|
|
2
|
+
import type { Contact, ElementTypes, Message, SendMsgResults } from 'node-karin';
|
|
3
|
+
/** 正常发送消息 */
|
|
4
|
+
export declare class AdapterQQBotNormal extends AdapterQQBot {
|
|
5
|
+
srcReply(e: Message, elements: ElementTypes[]): Promise<SendMsgResults>;
|
|
6
|
+
sendMsg(contact: Contact, elements: Array<ElementTypes>, retryCount?: number): Promise<SendMsgResults>;
|
|
7
|
+
/**
|
|
8
|
+
* 处理文本 将文本中的链接转为二维码
|
|
9
|
+
* @param text 文本
|
|
10
|
+
* @returns 处理后的文本和二维码 二维码为不带`base64://`的字符串
|
|
11
|
+
*/
|
|
12
|
+
hendleText(text: string): Promise<{
|
|
13
|
+
text: string;
|
|
14
|
+
qr: string | null;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* 发送QQ私聊、群聊消息
|
|
18
|
+
* @param contact 联系人
|
|
19
|
+
* @param elements 消息元素
|
|
20
|
+
* @param retryCount 重试次数
|
|
21
|
+
*/
|
|
22
|
+
sendQQMsg(contact: Contact<'friend'> | Contact<'group'>, elements: Array<ElementTypes>, retryCount?: number): Promise<SendMsgResults>;
|
|
23
|
+
/**
|
|
24
|
+
* 发送频道消息
|
|
25
|
+
* @param contact 联系人
|
|
26
|
+
* @param elements 消息元素
|
|
27
|
+
* @param retryCount 重试次数
|
|
28
|
+
*/
|
|
29
|
+
sendGuildMsg(contact: Contact<'guild' | 'direct'>, elements: Array<ElementTypes>, retryCount?: number): Promise<SendMsgResults>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import FormData from 'form-data';
|
|
2
|
+
import { handleUrl, qrs } from '@/utils/common';
|
|
3
|
+
import { common, fileToUrl, } from 'node-karin';
|
|
4
|
+
import { AdapterQQBot } from '@/core/adapter/adapter';
|
|
5
|
+
/** 正常发送消息 */
|
|
6
|
+
export class AdapterQQBotNormal extends AdapterQQBot {
|
|
7
|
+
async srcReply(e, elements) {
|
|
8
|
+
return this.sendMsg(e.contact, elements);
|
|
9
|
+
}
|
|
10
|
+
async sendMsg(contact, elements, retryCount) {
|
|
11
|
+
if (contact.scene === 'direct' || contact.scene === 'guild') {
|
|
12
|
+
return this.sendGuildMsg(contact, elements, retryCount);
|
|
13
|
+
}
|
|
14
|
+
else if (contact.scene === 'group' || contact.scene === 'friend') {
|
|
15
|
+
return this.sendQQMsg(contact, elements, retryCount);
|
|
16
|
+
}
|
|
17
|
+
throw new Error('不支持的消息类型');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 处理文本 将文本中的链接转为二维码
|
|
21
|
+
* @param text 文本
|
|
22
|
+
* @returns 处理后的文本和二维码 二维码为不带`base64://`的字符串
|
|
23
|
+
*/
|
|
24
|
+
async hendleText(text) {
|
|
25
|
+
const urls = handleUrl(text);
|
|
26
|
+
if (!urls.length)
|
|
27
|
+
return { text, qr: null };
|
|
28
|
+
urls.forEach((url) => {
|
|
29
|
+
text = text.replace(new RegExp(url, 'g'), '[请扫码查看]');
|
|
30
|
+
});
|
|
31
|
+
const list = await qrs(urls);
|
|
32
|
+
if (list.length === 1)
|
|
33
|
+
return { text, qr: list[0] };
|
|
34
|
+
const result = await common.mergeImage(list, 3);
|
|
35
|
+
return { text, qr: result.base64 };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 发送QQ私聊、群聊消息
|
|
39
|
+
* @param contact 联系人
|
|
40
|
+
* @param elements 消息元素
|
|
41
|
+
* @param retryCount 重试次数
|
|
42
|
+
*/
|
|
43
|
+
async sendQQMsg(contact, elements, retryCount) {
|
|
44
|
+
const list = this.initList('qq');
|
|
45
|
+
/** 上传富媒体的目标 */
|
|
46
|
+
const target = contact.scene === 'friend' ? 'user' : 'group';
|
|
47
|
+
for (const v of elements) {
|
|
48
|
+
if (v.type === 'text') {
|
|
49
|
+
const { text, qr } = await this.hendleText(v.text);
|
|
50
|
+
list.content.push(text);
|
|
51
|
+
if (qr)
|
|
52
|
+
list.image.push(qr);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (v.type === 'image') {
|
|
56
|
+
list.image.push(v.file);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (v.type === 'pasmsg') {
|
|
60
|
+
if (v.source === 'event')
|
|
61
|
+
list.pasmsg.type = 'event';
|
|
62
|
+
list.pasmsg.msg_id = v.id;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (v.type === 'keyboard') {
|
|
66
|
+
list.keyboard.push(v);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (v.type === 'button') {
|
|
70
|
+
list.button.push(v);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (v.type === 'markdown') {
|
|
74
|
+
list.markdown.push(v);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (v.type === 'markdownTpl') {
|
|
78
|
+
list.markdownTpl.push(v);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (v.type === 'video' || v.type === 'record') {
|
|
82
|
+
let url;
|
|
83
|
+
if (v.file.startsWith('http')) {
|
|
84
|
+
url = v.file;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const data = await fileToUrl(v.type, v.file, `${v.type}.${v.type === 'record' ? 'mp3' : 'mp4'}`);
|
|
88
|
+
url = data.url;
|
|
89
|
+
}
|
|
90
|
+
const res = await this.super.uploadMedia(target, contact.peer, v.type, url, false);
|
|
91
|
+
list.list.push(this.super.QQdMsgOptions('media', res.file_info));
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
this.logger('debug', `[QQBot][${v.type}] 不支持发送的消息类型`);
|
|
95
|
+
}
|
|
96
|
+
if (list.content.length) {
|
|
97
|
+
list.list.unshift(this.super.QQdMsgOptions('text', list.content.join('')));
|
|
98
|
+
}
|
|
99
|
+
for (const url of list.image) {
|
|
100
|
+
const base64 = await common.base64(url);
|
|
101
|
+
const result = await this.super.uploadMedia(target, contact.peer, 'image', base64, false);
|
|
102
|
+
list.list.push(this.super.QQdMsgOptions('media', result.file_info));
|
|
103
|
+
}
|
|
104
|
+
/** 处理Markdown、按钮 */
|
|
105
|
+
list.markdownToButton('qq', list);
|
|
106
|
+
/** 返回值 */
|
|
107
|
+
const rawData = this.initSendMsgResults();
|
|
108
|
+
/** 处理被动消息 */
|
|
109
|
+
const pasmsg = (() => {
|
|
110
|
+
if (!list.pasmsg.msg_id)
|
|
111
|
+
return () => '';
|
|
112
|
+
list.pasmsg.msg_seq++;
|
|
113
|
+
if (list.pasmsg.type === 'msg') {
|
|
114
|
+
return (item) => {
|
|
115
|
+
item.msg_seq = list.pasmsg.msg_seq;
|
|
116
|
+
item.msg_id = list.pasmsg.msg_id;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return (item) => {
|
|
120
|
+
item.msg_seq = list.pasmsg.msg_seq;
|
|
121
|
+
item.event_id = list.pasmsg.msg_id;
|
|
122
|
+
};
|
|
123
|
+
})();
|
|
124
|
+
/** 发送消息 */
|
|
125
|
+
const send = (() => {
|
|
126
|
+
if (contact.scene === 'friend') {
|
|
127
|
+
return (peer, item) => this.super.sendFriendMsg(peer, item);
|
|
128
|
+
}
|
|
129
|
+
return (peer, item) => this.super.sendGroupMsg(peer, item);
|
|
130
|
+
})();
|
|
131
|
+
if (!list.list.length) {
|
|
132
|
+
list.list.push(this.super.QQdMsgOptions('text', '不支持发送的消息类型'));
|
|
133
|
+
}
|
|
134
|
+
for (const item of list.list) {
|
|
135
|
+
pasmsg(item);
|
|
136
|
+
const res = await send(contact.peer, item);
|
|
137
|
+
rawData.rawData.push(res);
|
|
138
|
+
}
|
|
139
|
+
return this.handleResponse(rawData);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 发送频道消息
|
|
143
|
+
* @param contact 联系人
|
|
144
|
+
* @param elements 消息元素
|
|
145
|
+
* @param retryCount 重试次数
|
|
146
|
+
*/
|
|
147
|
+
async sendGuildMsg(contact, elements, retryCount) {
|
|
148
|
+
const list = this.initList('guild');
|
|
149
|
+
for (const v of elements) {
|
|
150
|
+
if (v.type === 'text') {
|
|
151
|
+
const { text, qr } = await this.hendleText(v.text);
|
|
152
|
+
list.content.push(text);
|
|
153
|
+
if (qr)
|
|
154
|
+
list.image.push(qr);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (v.type === 'image') {
|
|
158
|
+
v.file.startsWith('http') ? list.imageUrls.push(v.file) : list.imageFiles.push(v.file);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (v.type === 'at') {
|
|
162
|
+
if (contact.scene === 'guild')
|
|
163
|
+
list.content.push(v.targetId === 'all' ? '@everyone' : `<@${v.targetId}>`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (v.type === 'pasmsg') {
|
|
167
|
+
if (v.source === 'event')
|
|
168
|
+
list.pasmsg.type = 'event';
|
|
169
|
+
list.pasmsg.msg_id = v.id;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (v.type === 'reply') {
|
|
173
|
+
list.reply.message_id = v.messageId;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (v.type === 'face') {
|
|
177
|
+
list.content.push(`<emoji:${v.id}>`);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (v.type === 'keyboard') {
|
|
181
|
+
list.keyboard.push(v);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (v.type === 'button') {
|
|
185
|
+
list.button.push(v);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (v.type === 'markdown') {
|
|
189
|
+
list.markdown.push(v);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (v.type === 'markdownTpl') {
|
|
193
|
+
list.markdownTpl.push(v);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
this.logger('debug', `[QQBot][${v.type}] 不支持发送的消息类型`);
|
|
197
|
+
}
|
|
198
|
+
/** 情况较为复杂... */
|
|
199
|
+
if (list.content.length) {
|
|
200
|
+
if (list.imageUrls.length) {
|
|
201
|
+
const url = list.imageUrls.shift();
|
|
202
|
+
list.list.unshift(this.super.GuildMsgOptions('text', list.content.join(''), url));
|
|
203
|
+
}
|
|
204
|
+
if (list.imageFiles.length) {
|
|
205
|
+
const buffer = await common.buffer(list.imageFiles.shift());
|
|
206
|
+
const formData = new FormData();
|
|
207
|
+
formData.append('content', list.content.join(''));
|
|
208
|
+
formData.append('file_image', buffer);
|
|
209
|
+
list.list.unshift(formData);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
list.list.unshift(this.super.GuildMsgOptions('text', list.content.join('')));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
for (const url of list.imageUrls) {
|
|
216
|
+
list.list.push(this.super.GuildMsgOptions('image', url));
|
|
217
|
+
}
|
|
218
|
+
for (const file of list.imageFiles) {
|
|
219
|
+
const buffer = await common.buffer(file);
|
|
220
|
+
const formData = new FormData();
|
|
221
|
+
formData.append('file_image', buffer);
|
|
222
|
+
list.list.push(formData);
|
|
223
|
+
}
|
|
224
|
+
/** 处理Markdown、按钮 */
|
|
225
|
+
list.markdownToButton('guild', list);
|
|
226
|
+
const rawData = this.initSendMsgResults();
|
|
227
|
+
/** 发送消息 */
|
|
228
|
+
const send = (() => {
|
|
229
|
+
if (contact.scene === 'guild') {
|
|
230
|
+
return (peer, subPeer, item) => this.super.sendChannelMsg(subPeer, item);
|
|
231
|
+
}
|
|
232
|
+
return (peer, subPeer, item) => this.super.sendDmsMsg(peer, item);
|
|
233
|
+
})();
|
|
234
|
+
/** 处理被动消息 */
|
|
235
|
+
const pasmsg = (() => {
|
|
236
|
+
if (!list.pasmsg.msg_id)
|
|
237
|
+
return () => '';
|
|
238
|
+
if (list.pasmsg.type === 'msg') {
|
|
239
|
+
return (item) => {
|
|
240
|
+
if (item instanceof FormData) {
|
|
241
|
+
return item.append('msg_id', list.pasmsg.msg_id);
|
|
242
|
+
}
|
|
243
|
+
item.msg_id = list.pasmsg.msg_id;
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return (item) => {
|
|
247
|
+
if (item instanceof FormData) {
|
|
248
|
+
return item.append('event_id', list.pasmsg.msg_id);
|
|
249
|
+
}
|
|
250
|
+
item.event_id = list.pasmsg.msg_id;
|
|
251
|
+
};
|
|
252
|
+
})();
|
|
253
|
+
if (!list.list.length) {
|
|
254
|
+
list.list.push(this.super.GuildMsgOptions('text', '不支持发送的消息类型'));
|
|
255
|
+
}
|
|
256
|
+
for (const item of list.list) {
|
|
257
|
+
pasmsg(item);
|
|
258
|
+
const res = await send(contact.peer, contact.subPeer, item);
|
|
259
|
+
rawData.rawData.push(res);
|
|
260
|
+
}
|
|
261
|
+
return this.handleResponse(rawData);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import FormData from 'form-data';
|
|
2
|
+
import type { createAxiosInstance } from '@/core/internal/axios';
|
|
3
|
+
import type { Ark, DmsResponse, Embeds, GetMeResponse, Keyboard, Markdown, MediaType, Scene, SendGuildArkMessageRequest, SendGuildEmbedMessageRequest, SendGuildMarkdownMessageRequest, SendGuildMsg, SendGuildResponse, SendGuildTextMessageRequest, SendQQArkMessageRequest, SendQQMarkdownMessageRequest, SendQQMediaMessageRequest, SendQQMsg, SendQQMsgResponse, SendQQTextMessageRequest, UploadMediaResponse } from './types';
|
|
4
|
+
export declare class QQBotApi {
|
|
5
|
+
/** axios 实例 */
|
|
6
|
+
axios: ReturnType<typeof createAxiosInstance>;
|
|
7
|
+
constructor(axios: ReturnType<typeof createAxiosInstance>);
|
|
8
|
+
/**
|
|
9
|
+
* 发送get请求
|
|
10
|
+
* @param path 请求路径
|
|
11
|
+
* @returns 请求结果
|
|
12
|
+
*/
|
|
13
|
+
get<T>(path: string): Promise<T>;
|
|
14
|
+
/**
|
|
15
|
+
* 发送post请求
|
|
16
|
+
* @param path 请求路径
|
|
17
|
+
* @param options 请求数据
|
|
18
|
+
* @param headers 请求头
|
|
19
|
+
*/
|
|
20
|
+
post<T>(path: string, options?: {}, headers?: Record<string, string>): Promise<T>;
|
|
21
|
+
/**
|
|
22
|
+
* 处理请求错误
|
|
23
|
+
* @param error 错误信息
|
|
24
|
+
*/
|
|
25
|
+
handleError(path: string, options: any, error: any): void;
|
|
26
|
+
/**
|
|
27
|
+
* 发送单聊消息
|
|
28
|
+
* @param targetId 目标QQ用户的 openid
|
|
29
|
+
* @param options 消息参数
|
|
30
|
+
*/
|
|
31
|
+
sendFriendMsg(targetId: string, options: SendQQMsg): Promise<SendQQMsgResponse>;
|
|
32
|
+
/**
|
|
33
|
+
* 发送群聊消息
|
|
34
|
+
* @param targetId 目标QQ群的 openid
|
|
35
|
+
* @param options 消息参数
|
|
36
|
+
*/
|
|
37
|
+
sendGroupMsg(targetId: string, options: SendQQMsg): Promise<SendQQMsgResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* 构建QQBot文本消息参数
|
|
40
|
+
* @param content 消息文本内容
|
|
41
|
+
*/
|
|
42
|
+
QQdMsgOptions(type: 'text', content: string): SendQQTextMessageRequest;
|
|
43
|
+
/**
|
|
44
|
+
* 构建Markdown消息参数
|
|
45
|
+
* @param markdown Markdown文本内容
|
|
46
|
+
* @param keyboard 按钮
|
|
47
|
+
*/
|
|
48
|
+
QQdMsgOptions(type: 'markdown', markdown: Markdown, keyboard?: Keyboard): SendQQMarkdownMessageRequest;
|
|
49
|
+
/**
|
|
50
|
+
* 构建Ark消息参数
|
|
51
|
+
* @param ark Ark参数
|
|
52
|
+
*/
|
|
53
|
+
QQdMsgOptions(type: 'ark', ark: SendQQArkMessageRequest['ark']): SendQQArkMessageRequest;
|
|
54
|
+
/**
|
|
55
|
+
* 构建Media消息参数
|
|
56
|
+
* @param file 文件信息
|
|
57
|
+
*/
|
|
58
|
+
QQdMsgOptions(type: 'media', file: string): SendQQMediaMessageRequest;
|
|
59
|
+
/**
|
|
60
|
+
* 构建频道文本、文本图片消息参数
|
|
61
|
+
* @param type 消息类型
|
|
62
|
+
* @param content 消息内容
|
|
63
|
+
* @param image 图片url
|
|
64
|
+
*/
|
|
65
|
+
GuildMsgOptions(type: 'text', content: string, image?: string): SendGuildTextMessageRequest;
|
|
66
|
+
/**
|
|
67
|
+
* 构建图片消息参数
|
|
68
|
+
* @param type 消息类型
|
|
69
|
+
* @param image 图片url
|
|
70
|
+
*/
|
|
71
|
+
GuildMsgOptions(type: 'image', image: string): SendGuildTextMessageRequest;
|
|
72
|
+
/**
|
|
73
|
+
* 构建Embed消息参数
|
|
74
|
+
* @param type 消息类型
|
|
75
|
+
* @param embed Embed参数
|
|
76
|
+
*/
|
|
77
|
+
GuildMsgOptions(type: 'embed', embed: Embeds): SendGuildEmbedMessageRequest;
|
|
78
|
+
/**
|
|
79
|
+
* 构建Ark消息参数
|
|
80
|
+
* @param type 消息类型
|
|
81
|
+
* @param ark Ark参数
|
|
82
|
+
*/
|
|
83
|
+
GuildMsgOptions(type: 'ark', ark: Ark): SendGuildArkMessageRequest;
|
|
84
|
+
/**
|
|
85
|
+
* 构建Markdown消息参数
|
|
86
|
+
* @param type 消息类型
|
|
87
|
+
* @param markdown Markdown文本
|
|
88
|
+
*/
|
|
89
|
+
GuildMsgOptions(type: 'markdown', markdown: Markdown): SendGuildMarkdownMessageRequest;
|
|
90
|
+
/**
|
|
91
|
+
* 上传富媒体文件
|
|
92
|
+
* @param scene 上传场景
|
|
93
|
+
* @param targetId 目标id
|
|
94
|
+
* @param type 文件类型
|
|
95
|
+
* @param url 需要上传的文件的url
|
|
96
|
+
* @param srvSendMsg 是否发送消息
|
|
97
|
+
*/
|
|
98
|
+
uploadMedia(scene: Scene, targetId: string, type: MediaType, url: string, srvSendMsg?: boolean): Promise<UploadMediaResponse>;
|
|
99
|
+
/**
|
|
100
|
+
* 上传富媒体文件
|
|
101
|
+
* @param scene 上传场景
|
|
102
|
+
* @param targetId 目标id
|
|
103
|
+
* @param type 文件类型
|
|
104
|
+
* @param base64 需要上传的文件的base64编码
|
|
105
|
+
* @param srvSendMsg 是否发送消息
|
|
106
|
+
*/
|
|
107
|
+
uploadMedia(scene: Scene, targetId: string, type: MediaType, base64: string, srvSendMsg?: boolean): Promise<UploadMediaResponse>;
|
|
108
|
+
/**
|
|
109
|
+
* 单聊撤回消息
|
|
110
|
+
* @param type 场景类型
|
|
111
|
+
* @param targetId 目标QQ用户的openid
|
|
112
|
+
* @param messageId 消息id
|
|
113
|
+
*/
|
|
114
|
+
recallMsg(type: 'user', targetId: string, messageId: string): Promise<boolean>;
|
|
115
|
+
/**
|
|
116
|
+
* 群聊撤回消息
|
|
117
|
+
* @param type 场景类型
|
|
118
|
+
* @param targetId 目标QQ群的openid
|
|
119
|
+
* @param messageId 消息id
|
|
120
|
+
*/
|
|
121
|
+
recallMsg(type: 'group', targetId: string, messageId: string): Promise<boolean>;
|
|
122
|
+
/**
|
|
123
|
+
* 文字子频道撤回消息
|
|
124
|
+
* @param type 场景类型
|
|
125
|
+
* @param channelId 子频道的id
|
|
126
|
+
* @param messageId 消息id
|
|
127
|
+
* @param hidetip 是否隐藏提示小灰条,true 为隐藏,false 为显示。默认为false
|
|
128
|
+
*/
|
|
129
|
+
recallMsg(type: 'channels', channelId: string, messageId: string, hidetip?: boolean): Promise<boolean>;
|
|
130
|
+
/**
|
|
131
|
+
* 频道私信撤回消息
|
|
132
|
+
* @param type 场景类型
|
|
133
|
+
* @param guildId 频道的id
|
|
134
|
+
* @param messageId 消息id
|
|
135
|
+
* @param hidetip 是否隐藏提示小灰条,true 为隐藏,false 为显示。默认为false
|
|
136
|
+
*/
|
|
137
|
+
recallMsg(type: 'dms', guildId: string, messageId: string, hidetip?: boolean): Promise<boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* 发送文字子频道消息
|
|
140
|
+
* @param targetId 目标子频道的id
|
|
141
|
+
* @param options 消息参数
|
|
142
|
+
*/
|
|
143
|
+
sendChannelMsg(targetId: string, options: SendGuildMsg | FormData): Promise<SendGuildResponse>;
|
|
144
|
+
/**
|
|
145
|
+
* 直接发送频道消息
|
|
146
|
+
* @param guildID 频道的id
|
|
147
|
+
* @param options 消息参数
|
|
148
|
+
*/
|
|
149
|
+
sendDmsMsg(guildID: string, options: SendGuildMsg | FormData): Promise<SendGuildResponse>;
|
|
150
|
+
/**
|
|
151
|
+
* 发送频道私信消息
|
|
152
|
+
* @param targetId 目标的id
|
|
153
|
+
* @param srcGuildId 源频道的id
|
|
154
|
+
* @param options 消息参数
|
|
155
|
+
*/
|
|
156
|
+
sendDmsMsg(targetId: string, srcGuildId: string, options: SendGuildMsg | FormData): Promise<SendGuildResponse>;
|
|
157
|
+
/**
|
|
158
|
+
* 获取当前机器人详情
|
|
159
|
+
*/
|
|
160
|
+
getMe(): Promise<GetMeResponse>;
|
|
161
|
+
/**
|
|
162
|
+
* 创建私信会话
|
|
163
|
+
* @param recipientID 接受者id
|
|
164
|
+
* @param srcGuildID 源频道id
|
|
165
|
+
*/
|
|
166
|
+
dms(recipientID: string, srcGuildID: string): Promise<DmsResponse>;
|
|
167
|
+
}
|