@alemonjs/bubble 2.1.0-alpha.9 → 2.1.1
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/lib/format.d.ts +4 -0
- package/lib/format.js +81 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +153 -39
- package/lib/sdk/instance.js +9 -9
- package/lib/sdk/types.d.ts +7 -0
- package/lib/send.js +115 -77
- package/package.json +1 -1
package/lib/format.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DataEnums, DataMarkDown } from 'alemonjs';
|
|
2
|
+
export declare const markdownToBubbleText: (items: DataMarkDown["value"]) => string;
|
|
3
|
+
export declare const markdownRawToBubbleText: (raw: string) => string;
|
|
4
|
+
export declare const dataEnumToBubbleText: (item: DataEnums) => string;
|
package/lib/format.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const markdownToBubbleText = (items) => {
|
|
2
|
+
return items
|
|
3
|
+
.map(item => {
|
|
4
|
+
switch (item.type) {
|
|
5
|
+
case 'MD.text':
|
|
6
|
+
return item.value;
|
|
7
|
+
case 'MD.title':
|
|
8
|
+
return `# ${item.value}\n`;
|
|
9
|
+
case 'MD.subtitle':
|
|
10
|
+
return `## ${item.value}\n`;
|
|
11
|
+
case 'MD.bold':
|
|
12
|
+
return `**${item.value}**`;
|
|
13
|
+
case 'MD.italic':
|
|
14
|
+
case 'MD.italicStar':
|
|
15
|
+
return `*${item.value}*`;
|
|
16
|
+
case 'MD.strikethrough':
|
|
17
|
+
return `~~${item.value}~~`;
|
|
18
|
+
case 'MD.link': {
|
|
19
|
+
const v = item.value;
|
|
20
|
+
return `[${v.text}](${v.url})`;
|
|
21
|
+
}
|
|
22
|
+
case 'MD.image':
|
|
23
|
+
return ``;
|
|
24
|
+
case 'MD.list':
|
|
25
|
+
return (item.value
|
|
26
|
+
.map(li => {
|
|
27
|
+
if (typeof li.value === 'object') {
|
|
28
|
+
return `${li.value.index}. ${li.value.text ?? ''}`;
|
|
29
|
+
}
|
|
30
|
+
return `- ${li.value}`;
|
|
31
|
+
})
|
|
32
|
+
.join('\n') + '\n');
|
|
33
|
+
case 'MD.blockquote':
|
|
34
|
+
return `> ${item.value}\n`;
|
|
35
|
+
case 'MD.divider':
|
|
36
|
+
return '\n————————\n';
|
|
37
|
+
case 'MD.newline':
|
|
38
|
+
return '\n';
|
|
39
|
+
case 'MD.code': {
|
|
40
|
+
const lang = item?.options?.language || '';
|
|
41
|
+
return `\`\`\`${lang}\n${item.value}\n\`\`\`\n`;
|
|
42
|
+
}
|
|
43
|
+
case 'MD.mention':
|
|
44
|
+
if (item.value === 'everyone') {
|
|
45
|
+
return '<@everyone>';
|
|
46
|
+
}
|
|
47
|
+
return `<@${item.value ?? ''}>`;
|
|
48
|
+
case 'MD.content':
|
|
49
|
+
return item.value;
|
|
50
|
+
case 'MD.button': {
|
|
51
|
+
const options = item?.options;
|
|
52
|
+
const autoEnter = options?.autoEnter ?? false;
|
|
53
|
+
const label = typeof item.value === 'object' ? item.value.title : item.value;
|
|
54
|
+
const command = options?.data || label;
|
|
55
|
+
return `<btn variant="borderless" command="${command}" enter="${String(autoEnter)}" >${label}</btn> `;
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
return String(item?.value ?? '');
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.join('');
|
|
62
|
+
};
|
|
63
|
+
const markdownRawToBubbleText = (raw) => {
|
|
64
|
+
return raw;
|
|
65
|
+
};
|
|
66
|
+
const dataEnumToBubbleText = (item) => {
|
|
67
|
+
switch (item.type) {
|
|
68
|
+
case 'MarkdownOriginal':
|
|
69
|
+
return markdownRawToBubbleText(String(item.value));
|
|
70
|
+
case 'Attachment':
|
|
71
|
+
return `[附件${item.options?.filename ? ': ' + item.options.filename : ''}]`;
|
|
72
|
+
case 'Audio':
|
|
73
|
+
return '[音频]';
|
|
74
|
+
case 'Video':
|
|
75
|
+
return '[视频]';
|
|
76
|
+
default:
|
|
77
|
+
return '';
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { dataEnumToBubbleText, markdownRawToBubbleText, markdownToBubbleText };
|
package/lib/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export { OpCode } from './sdk/wss.types';
|
|
|
7
7
|
export type { BUBBLEOptions, HelloPayload, SubscribePayload } from './sdk/wss.types';
|
|
8
8
|
export * from './hook';
|
|
9
9
|
export { type Options } from './config';
|
|
10
|
-
declare const
|
|
11
|
-
export default
|
|
10
|
+
declare const _default: () => any;
|
|
11
|
+
export default _default;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BubbleClient } from './sdk/wss.js';
|
|
2
|
-
import { cbpPlatform, createResult, ResultCode } from 'alemonjs';
|
|
2
|
+
import { definePlatform, cbpPlatform, createResult, ResultCode } from 'alemonjs';
|
|
3
3
|
import { getMaster, platform } from './config.js';
|
|
4
4
|
import { CDN_URL } from './sdk/api.js';
|
|
5
5
|
export { BubbleAPI as API, API_URL, GATEWAY_URL } from './sdk/api.js';
|
|
@@ -13,11 +13,21 @@ const main = () => {
|
|
|
13
13
|
const cbp = cbpPlatform(url);
|
|
14
14
|
const client = new BubbleClient();
|
|
15
15
|
void client.connect();
|
|
16
|
+
let botId = '';
|
|
17
|
+
client
|
|
18
|
+
.getMe()
|
|
19
|
+
.then(res => {
|
|
20
|
+
botId = String(res?.id ?? '');
|
|
21
|
+
})
|
|
22
|
+
.catch(() => { });
|
|
16
23
|
const createUserAvatar = (_UserId, avatar) => {
|
|
24
|
+
if (!avatar) {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
17
27
|
return `${CDN_URL}/${avatar}`;
|
|
18
28
|
};
|
|
19
29
|
client.on('MESSAGE_CREATE', event => {
|
|
20
|
-
if (event.author?.is_bot) {
|
|
30
|
+
if (event.author?.is_bot || event.author?.isBot) {
|
|
21
31
|
return;
|
|
22
32
|
}
|
|
23
33
|
const atUsers = [];
|
|
@@ -48,8 +58,8 @@ const main = () => {
|
|
|
48
58
|
OpenId: UserId,
|
|
49
59
|
MessageId: String(event.id),
|
|
50
60
|
MessageText: msg,
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
BotId: botId,
|
|
62
|
+
_tag: 'message.create',
|
|
53
63
|
value: event
|
|
54
64
|
};
|
|
55
65
|
cbp.send(e);
|
|
@@ -70,8 +80,118 @@ const main = () => {
|
|
|
70
80
|
OpenId: UserId,
|
|
71
81
|
MessageId: String(event.id),
|
|
72
82
|
MessageText: event.content,
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
BotId: botId,
|
|
84
|
+
_tag: 'private.message.create',
|
|
85
|
+
value: event
|
|
86
|
+
};
|
|
87
|
+
cbp.send(e);
|
|
88
|
+
});
|
|
89
|
+
client.on('MESSAGE_UPDATE', event => {
|
|
90
|
+
const UserId = String(event.authorId);
|
|
91
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
92
|
+
const UserAvatar = createUserAvatar(UserId, event?.author?.avatar);
|
|
93
|
+
const e = {
|
|
94
|
+
name: 'message.update',
|
|
95
|
+
Platform: platform,
|
|
96
|
+
GuildId: String(event.channelId || ''),
|
|
97
|
+
ChannelId: String(event.channelId || ''),
|
|
98
|
+
SpaceId: String(event.channelId || ''),
|
|
99
|
+
UserId: UserId,
|
|
100
|
+
UserKey,
|
|
101
|
+
UserName: event?.author?.username,
|
|
102
|
+
UserAvatar: UserAvatar,
|
|
103
|
+
IsMaster: isMaster,
|
|
104
|
+
IsBot: false,
|
|
105
|
+
MessageId: String(event.id),
|
|
106
|
+
BotId: botId,
|
|
107
|
+
_tag: 'MESSAGE_UPDATE',
|
|
108
|
+
value: event
|
|
109
|
+
};
|
|
110
|
+
cbp.send(e);
|
|
111
|
+
});
|
|
112
|
+
client.on('MESSAGE_DELETE', event => {
|
|
113
|
+
const e = {
|
|
114
|
+
name: 'message.delete',
|
|
115
|
+
Platform: platform,
|
|
116
|
+
GuildId: String(event.guild_id || ''),
|
|
117
|
+
ChannelId: String(event.channel_id || ''),
|
|
118
|
+
SpaceId: String(event.channel_id || ''),
|
|
119
|
+
MessageId: String(event.id),
|
|
120
|
+
BotId: botId,
|
|
121
|
+
_tag: 'MESSAGE_DELETE',
|
|
122
|
+
value: event
|
|
123
|
+
};
|
|
124
|
+
cbp.send(e);
|
|
125
|
+
});
|
|
126
|
+
client.on('DM_MESSAGE_UPDATE', event => {
|
|
127
|
+
const UserId = String(event.authorId);
|
|
128
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
129
|
+
const UserAvatar = createUserAvatar(UserId, event?.author?.avatar);
|
|
130
|
+
const e = {
|
|
131
|
+
name: 'private.message.update',
|
|
132
|
+
Platform: platform,
|
|
133
|
+
UserId: UserId,
|
|
134
|
+
UserKey,
|
|
135
|
+
UserName: event?.author?.username,
|
|
136
|
+
UserAvatar: UserAvatar,
|
|
137
|
+
IsMaster: isMaster,
|
|
138
|
+
IsBot: false,
|
|
139
|
+
MessageId: String(event.id),
|
|
140
|
+
BotId: botId,
|
|
141
|
+
_tag: 'DM_MESSAGE_UPDATE',
|
|
142
|
+
value: event
|
|
143
|
+
};
|
|
144
|
+
cbp.send(e);
|
|
145
|
+
});
|
|
146
|
+
client.on('DM_MESSAGE_DELETE', event => {
|
|
147
|
+
const e = {
|
|
148
|
+
name: 'private.message.delete',
|
|
149
|
+
Platform: platform,
|
|
150
|
+
MessageId: String(event.id),
|
|
151
|
+
BotId: botId,
|
|
152
|
+
_tag: 'DM_MESSAGE_DELETE',
|
|
153
|
+
value: event
|
|
154
|
+
};
|
|
155
|
+
cbp.send(e);
|
|
156
|
+
});
|
|
157
|
+
client.on('GUILD_MEMBER_ADD', event => {
|
|
158
|
+
const UserId = String(event.user_id || event.user?.id || '');
|
|
159
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
160
|
+
const e = {
|
|
161
|
+
name: 'member.add',
|
|
162
|
+
Platform: platform,
|
|
163
|
+
GuildId: String(event.guild_id || ''),
|
|
164
|
+
ChannelId: '',
|
|
165
|
+
SpaceId: String(event.guild_id || ''),
|
|
166
|
+
UserId: UserId,
|
|
167
|
+
UserKey,
|
|
168
|
+
UserName: event.user?.username ?? event.nickname,
|
|
169
|
+
IsMaster: isMaster,
|
|
170
|
+
IsBot: false,
|
|
171
|
+
MessageId: '',
|
|
172
|
+
BotId: botId,
|
|
173
|
+
_tag: 'GUILD_MEMBER_ADD',
|
|
174
|
+
value: event
|
|
175
|
+
};
|
|
176
|
+
cbp.send(e);
|
|
177
|
+
});
|
|
178
|
+
client.on('GUILD_MEMBER_REMOVE', event => {
|
|
179
|
+
const UserId = String(event.user_id || event.user?.id || '');
|
|
180
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
181
|
+
const e = {
|
|
182
|
+
name: 'member.remove',
|
|
183
|
+
Platform: platform,
|
|
184
|
+
GuildId: String(event.guild_id || ''),
|
|
185
|
+
ChannelId: '',
|
|
186
|
+
SpaceId: String(event.guild_id || ''),
|
|
187
|
+
UserId: UserId,
|
|
188
|
+
UserKey,
|
|
189
|
+
UserName: event.user?.username ?? event.nickname,
|
|
190
|
+
IsMaster: isMaster,
|
|
191
|
+
IsBot: false,
|
|
192
|
+
MessageId: '',
|
|
193
|
+
BotId: botId,
|
|
194
|
+
_tag: 'GUILD_MEMBER_REMOVE',
|
|
75
195
|
value: event
|
|
76
196
|
};
|
|
77
197
|
cbp.send(e);
|
|
@@ -91,10 +211,10 @@ const main = () => {
|
|
|
91
211
|
},
|
|
92
212
|
use: {
|
|
93
213
|
send: async (event, val) => {
|
|
94
|
-
if (val.length
|
|
214
|
+
if (!val || val.length <= 0) {
|
|
95
215
|
return [];
|
|
96
216
|
}
|
|
97
|
-
const tag = event.
|
|
217
|
+
const tag = event._tag;
|
|
98
218
|
if (tag === 'message.create') {
|
|
99
219
|
const ChannelId = String(event.value.channelId || '');
|
|
100
220
|
const res = await sendToRoom(client, { channel_id: ChannelId, message_id: String(event.value.id || '') }, val);
|
|
@@ -114,9 +234,9 @@ const main = () => {
|
|
|
114
234
|
},
|
|
115
235
|
mention: e => {
|
|
116
236
|
const event = e.value;
|
|
117
|
-
const MessageMention = event.mentions.map(item => {
|
|
237
|
+
const MessageMention = (event.mentions || []).map(item => {
|
|
118
238
|
const UserId = item.id;
|
|
119
|
-
const avatar =
|
|
239
|
+
const avatar = item.avatar;
|
|
120
240
|
const UserAvatar = createUserAvatar(UserId, avatar);
|
|
121
241
|
const [isMaster, UserKey] = getMaster(UserId);
|
|
122
242
|
return {
|
|
@@ -135,7 +255,21 @@ const main = () => {
|
|
|
135
255
|
};
|
|
136
256
|
const onactions = async (data, consume) => {
|
|
137
257
|
try {
|
|
138
|
-
if (data.action === '
|
|
258
|
+
if (data.action === 'me.info') {
|
|
259
|
+
const res = await client.getMe();
|
|
260
|
+
const UserId = String(res.id);
|
|
261
|
+
const [isMaster, UserKey] = getMaster(UserId);
|
|
262
|
+
const user = {
|
|
263
|
+
UserId: UserId,
|
|
264
|
+
UserName: res.name,
|
|
265
|
+
IsBot: true,
|
|
266
|
+
IsMaster: isMaster,
|
|
267
|
+
UserAvatar: '',
|
|
268
|
+
UserKey: UserKey
|
|
269
|
+
};
|
|
270
|
+
consume([createResult(ResultCode.Ok, '请求完成', user)]);
|
|
271
|
+
}
|
|
272
|
+
else if (data.action === 'message.send') {
|
|
139
273
|
const event = data.payload.event;
|
|
140
274
|
const paramFormat = data.payload.params.format;
|
|
141
275
|
const res = await api.use.send(event, paramFormat);
|
|
@@ -158,6 +292,9 @@ const main = () => {
|
|
|
158
292
|
const res = await api.use.mention(event);
|
|
159
293
|
consume([createResult(ResultCode.Ok, '请求完成', res)]);
|
|
160
294
|
}
|
|
295
|
+
else {
|
|
296
|
+
consume([createResult(ResultCode.Fail, '未知请求,请尝试升级版本', null)]);
|
|
297
|
+
}
|
|
161
298
|
}
|
|
162
299
|
catch (error) {
|
|
163
300
|
consume([createResult(ResultCode.Fail, '请求失败', error)]);
|
|
@@ -176,35 +313,12 @@ const main = () => {
|
|
|
176
313
|
consume([createResult(ResultCode.Fail, '请求失败', error)]);
|
|
177
314
|
}
|
|
178
315
|
}
|
|
316
|
+
else {
|
|
317
|
+
consume([createResult(ResultCode.Fail, '未知请求,请尝试升级版本', null)]);
|
|
318
|
+
}
|
|
179
319
|
};
|
|
180
320
|
cbp.onapis((data, consume) => void onapis(data, consume));
|
|
181
321
|
};
|
|
182
|
-
|
|
183
|
-
['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
|
|
184
|
-
process?.on?.(sig, () => {
|
|
185
|
-
logger.info?.(`[alemonjs][${sig}] 收到信号,正在关闭...`);
|
|
186
|
-
setImmediate(() => process.exit(0));
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
process?.on?.('exit', code => {
|
|
190
|
-
logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
|
|
191
|
-
});
|
|
192
|
-
process.on('message', msg => {
|
|
193
|
-
try {
|
|
194
|
-
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
195
|
-
if (data?.type === 'start') {
|
|
196
|
-
main();
|
|
197
|
-
}
|
|
198
|
-
else if (data?.type === 'stop') {
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
catch { }
|
|
203
|
-
});
|
|
204
|
-
if (process.send) {
|
|
205
|
-
process.send(JSON.stringify({ type: 'ready' }));
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
mainProcess();
|
|
322
|
+
var index = definePlatform({ main });
|
|
209
323
|
|
|
210
|
-
export { BubbleClient, CDN_URL,
|
|
324
|
+
export { BubbleClient, CDN_URL, index as default, platform };
|
package/lib/sdk/instance.js
CHANGED
|
@@ -79,15 +79,15 @@ const loggerError = err => {
|
|
|
79
79
|
message: err?.message
|
|
80
80
|
});
|
|
81
81
|
};
|
|
82
|
-
const createAxiosInstance = (service, options) => {
|
|
83
|
-
|
|
84
|
-
service(options)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
82
|
+
const createAxiosInstance = async (service, options) => {
|
|
83
|
+
try {
|
|
84
|
+
const res = await service(options);
|
|
85
|
+
return res?.data ?? {};
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
loggerError(err);
|
|
89
|
+
throw err?.response?.data ?? err;
|
|
90
|
+
}
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
export { createAxiosInstance };
|
package/lib/sdk/types.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export interface BaseMessage {
|
|
|
35
35
|
authorId?: string | number;
|
|
36
36
|
author: {
|
|
37
37
|
id: number;
|
|
38
|
+
isBot?: boolean;
|
|
38
39
|
is_bot?: boolean;
|
|
39
40
|
avatar?: string | null;
|
|
40
41
|
username: string;
|
|
@@ -110,5 +111,11 @@ export interface FileQuota {
|
|
|
110
111
|
}
|
|
111
112
|
export interface BubbleEventMap {
|
|
112
113
|
MESSAGE_CREATE: MessageCreateEvent;
|
|
114
|
+
MESSAGE_UPDATE: MessageUpdateEvent;
|
|
115
|
+
MESSAGE_DELETE: MessageDeleteEvent;
|
|
113
116
|
DM_MESSAGE_CREATE: DmMessageCreateEvent;
|
|
117
|
+
DM_MESSAGE_UPDATE: MessageUpdateEvent;
|
|
118
|
+
DM_MESSAGE_DELETE: MessageDeleteEvent;
|
|
119
|
+
GUILD_MEMBER_ADD: GuildMemberEvent;
|
|
120
|
+
GUILD_MEMBER_REMOVE: GuildMemberEvent;
|
|
114
121
|
}
|
package/lib/send.js
CHANGED
|
@@ -1,10 +1,101 @@
|
|
|
1
1
|
import { createResult, ResultCode } from 'alemonjs';
|
|
2
2
|
import { readFileSync } from 'fs';
|
|
3
|
+
import { dataEnumToBubbleText } from './format.js';
|
|
3
4
|
|
|
4
5
|
const ImageURLToBuffer = async (url) => {
|
|
5
6
|
const arrayBuffer = await fetch(url).then(res => res.arrayBuffer());
|
|
6
7
|
return Buffer.from(arrayBuffer);
|
|
7
8
|
};
|
|
9
|
+
const buildBubbleMdContent = (mdAndButtons) => {
|
|
10
|
+
let contentMd = '';
|
|
11
|
+
if (mdAndButtons && mdAndButtons.length > 0) {
|
|
12
|
+
mdAndButtons.forEach(item => {
|
|
13
|
+
if (item.type === 'Markdown' && typeof item.value !== 'string') {
|
|
14
|
+
const md = item.value;
|
|
15
|
+
const map = {
|
|
16
|
+
'MD.title': value => `# ${value}`,
|
|
17
|
+
'MD.subtitle': value => `## ${value}`,
|
|
18
|
+
'MD.text': value => `${value} `,
|
|
19
|
+
'MD.bold': value => `**${value}** `,
|
|
20
|
+
'MD.divider': () => '\n————————\n',
|
|
21
|
+
'MD.italic': value => `_${value}_ `,
|
|
22
|
+
'MD.italicStar': value => `*${value}* `,
|
|
23
|
+
'MD.strikethrough': value => `~~${value}~~ `,
|
|
24
|
+
'MD.blockquote': value => `\n> ${value}`,
|
|
25
|
+
'MD.newline': () => '\n',
|
|
26
|
+
'MD.link': value => `[🔗${value.text}](${value.url}) `,
|
|
27
|
+
'MD.image': value => `\n\n`,
|
|
28
|
+
'MD.mention': (value, options) => {
|
|
29
|
+
const { belong } = options || {};
|
|
30
|
+
if (value === 'everyone' || value === 'all' || value === '' || typeof value !== 'string') {
|
|
31
|
+
return '<@everyone> ';
|
|
32
|
+
}
|
|
33
|
+
if (belong === 'user') {
|
|
34
|
+
return `<@${value}> `;
|
|
35
|
+
}
|
|
36
|
+
else if (belong === 'channel') {
|
|
37
|
+
return `<#${value}> `;
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
},
|
|
41
|
+
'MD.button': (value, options) => {
|
|
42
|
+
const autoEnter = options?.autoEnter ?? false;
|
|
43
|
+
const label = typeof value === 'object' ? value.title : value;
|
|
44
|
+
const command = options?.data || label;
|
|
45
|
+
return `<btn variant="borderless" command="${command}" enter="${String(autoEnter)}" >${label}</btn> `;
|
|
46
|
+
},
|
|
47
|
+
'MD.content': value => `${value}`
|
|
48
|
+
};
|
|
49
|
+
md.forEach(line => {
|
|
50
|
+
if (map[line.type]) {
|
|
51
|
+
const value = 'value' in line ? line.value : undefined;
|
|
52
|
+
const options = 'options' in line ? line.options : {};
|
|
53
|
+
contentMd += map[line.type](value, options);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (line.type === 'MD.list') {
|
|
57
|
+
const listStr = line.value.map(listItem => {
|
|
58
|
+
if (typeof listItem.value === 'object') {
|
|
59
|
+
return `\n${listItem.value.index}. ${listItem.value.text}`;
|
|
60
|
+
}
|
|
61
|
+
return `\n- ${listItem.value}`;
|
|
62
|
+
});
|
|
63
|
+
contentMd += `${listStr.join('')}\n`;
|
|
64
|
+
}
|
|
65
|
+
else if (line.type === 'MD.code') {
|
|
66
|
+
const language = line?.options?.language || '';
|
|
67
|
+
contentMd += `\n\`\`\`${language}\n${line.value}\n\`\`\`\n`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const value = line['value'] || '';
|
|
71
|
+
contentMd += String(value);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else if (item.type === 'BT.group' && item.value.length > 0 && typeof item.value !== 'string') {
|
|
76
|
+
contentMd += `<box classWind="mt-2" variant="borderless" >${item.value
|
|
77
|
+
?.map(row => {
|
|
78
|
+
const val = row.value;
|
|
79
|
+
if (val.length === 0) {
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
return `<flex>${val
|
|
83
|
+
.map(button => {
|
|
84
|
+
const value = button?.value || {};
|
|
85
|
+
const options = button.options;
|
|
86
|
+
const autoEnter = options?.autoEnter ?? false;
|
|
87
|
+
const label = value;
|
|
88
|
+
const command = options?.data || label;
|
|
89
|
+
return `<btn command="${command}" enter="${String(autoEnter)}" >${label}</btn>`;
|
|
90
|
+
})
|
|
91
|
+
.join('')}</flex>`;
|
|
92
|
+
})
|
|
93
|
+
.join('')}</box>`;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return contentMd;
|
|
98
|
+
};
|
|
8
99
|
const sendToRoom = async (client, param, val) => {
|
|
9
100
|
try {
|
|
10
101
|
if (!val || val.length <= 0) {
|
|
@@ -15,6 +106,9 @@ const sendToRoom = async (client, param, val) => {
|
|
|
15
106
|
const messageId = param?.message_id ? String(param?.message_id) : undefined;
|
|
16
107
|
const images = val.filter(item => item.type === 'Image' || item.type === 'ImageURL' || item.type === 'ImageFile');
|
|
17
108
|
const mdAndButtons = val.filter(item => item.type === 'Markdown' || item.type === 'BT.group');
|
|
109
|
+
const nativeTypes = new Set(['Image', 'ImageURL', 'ImageFile', 'Markdown', 'BT.group', 'Mention', 'Text', 'Link']);
|
|
110
|
+
const unsupportedItems = val.filter(item => !nativeTypes.has(item.type));
|
|
111
|
+
const fallbackText = unsupportedItems.map(item => dataEnumToBubbleText(item)).filter(Boolean).join('\n');
|
|
18
112
|
const content = val
|
|
19
113
|
.filter(item => item.type === 'Mention' || item.type === 'Text' || item.type === 'Link')
|
|
20
114
|
.map(item => {
|
|
@@ -51,6 +145,8 @@ const sendToRoom = async (client, param, val) => {
|
|
|
51
145
|
return '';
|
|
52
146
|
})
|
|
53
147
|
.join('');
|
|
148
|
+
const contentMd = buildBubbleMdContent(mdAndButtons);
|
|
149
|
+
const finalContent = [content, contentMd, fallbackText].filter(Boolean).join('\n');
|
|
54
150
|
if (images.length > 0) {
|
|
55
151
|
let bufferData = null;
|
|
56
152
|
for (let i = 0; i < images.length; i++) {
|
|
@@ -59,7 +155,20 @@ const sendToRoom = async (client, param, val) => {
|
|
|
59
155
|
}
|
|
60
156
|
const item = images[i];
|
|
61
157
|
if (item.type === 'Image') {
|
|
62
|
-
|
|
158
|
+
if (Buffer.isBuffer(item.value)) {
|
|
159
|
+
bufferData = item.value;
|
|
160
|
+
}
|
|
161
|
+
else if (item.value.startsWith('http://') || item.value.startsWith('https://')) {
|
|
162
|
+
const res = await ImageURLToBuffer(item.value);
|
|
163
|
+
bufferData = res;
|
|
164
|
+
}
|
|
165
|
+
else if (item.value.startsWith('base64://')) {
|
|
166
|
+
const base64Str = item.value.slice(9);
|
|
167
|
+
bufferData = Buffer.from(base64Str, 'base64');
|
|
168
|
+
}
|
|
169
|
+
else if (item.value.startsWith('file://')) {
|
|
170
|
+
bufferData = readFileSync(item.value.slice(7));
|
|
171
|
+
}
|
|
63
172
|
}
|
|
64
173
|
else if (item.type === 'ImageURL') {
|
|
65
174
|
const res = await ImageURLToBuffer(item.value);
|
|
@@ -76,7 +185,7 @@ const sendToRoom = async (client, param, val) => {
|
|
|
76
185
|
}
|
|
77
186
|
if (channelId) {
|
|
78
187
|
const res = await client.sendMessage(channelId, {
|
|
79
|
-
content:
|
|
188
|
+
content: finalContent,
|
|
80
189
|
type: 'image',
|
|
81
190
|
attachments: [fileAttachment]
|
|
82
191
|
});
|
|
@@ -84,7 +193,7 @@ const sendToRoom = async (client, param, val) => {
|
|
|
84
193
|
}
|
|
85
194
|
if (threadId) {
|
|
86
195
|
const res = await client.sendDm(threadId, {
|
|
87
|
-
content:
|
|
196
|
+
content: finalContent,
|
|
88
197
|
type: 'image',
|
|
89
198
|
attachments: [fileAttachment]
|
|
90
199
|
});
|
|
@@ -92,84 +201,13 @@ const sendToRoom = async (client, param, val) => {
|
|
|
92
201
|
}
|
|
93
202
|
return [createResult(ResultCode.Ok, '完成', null)];
|
|
94
203
|
}
|
|
95
|
-
|
|
96
|
-
if (mdAndButtons && mdAndButtons.length > 0) {
|
|
97
|
-
mdAndButtons.forEach(item => {
|
|
98
|
-
if (item.type === 'Markdown') {
|
|
99
|
-
const md = item.value;
|
|
100
|
-
md.forEach(line => {
|
|
101
|
-
if (line.type === 'MD.text') {
|
|
102
|
-
contentMd += line.value;
|
|
103
|
-
}
|
|
104
|
-
else if (line.type === 'MD.blockquote') {
|
|
105
|
-
contentMd += `\n> ${line.value}`;
|
|
106
|
-
}
|
|
107
|
-
else if (line.type === 'MD.bold') {
|
|
108
|
-
contentMd += `**${line.value}**`;
|
|
109
|
-
}
|
|
110
|
-
else if (line.type === 'MD.italic') {
|
|
111
|
-
contentMd += `*${line.value}*`;
|
|
112
|
-
}
|
|
113
|
-
else if (line.type === 'MD.divider') {
|
|
114
|
-
contentMd += '\n---\n';
|
|
115
|
-
}
|
|
116
|
-
else if (line.type === 'MD.image') {
|
|
117
|
-
contentMd += `\n\n`;
|
|
118
|
-
}
|
|
119
|
-
else if (line.type === 'MD.link') {
|
|
120
|
-
contentMd += `[${line.value}](${line.value})`;
|
|
121
|
-
}
|
|
122
|
-
else if (line.type === 'MD.list') {
|
|
123
|
-
const listStr = line.value.map(listItem => {
|
|
124
|
-
if (typeof listItem.value === 'object') {
|
|
125
|
-
return `\n${listItem.value.index}. ${listItem.value.text}`;
|
|
126
|
-
}
|
|
127
|
-
return `\n- ${listItem.value}`;
|
|
128
|
-
});
|
|
129
|
-
contentMd += `${listStr}\n`;
|
|
130
|
-
}
|
|
131
|
-
else if (line.type === 'MD.newline') {
|
|
132
|
-
contentMd += '\n';
|
|
133
|
-
}
|
|
134
|
-
else if (line.type === 'MD.code') {
|
|
135
|
-
const language = line?.options?.language || '';
|
|
136
|
-
contentMd += `\n\`\`\`${language}\n${line.value}\n\`\`\`\n`;
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
const value = line['value'] || '';
|
|
140
|
-
contentMd += String(value);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
else if (item.type === 'BT.group' && item.value.length > 0) {
|
|
145
|
-
contentMd += `<box classWind="mt-2" variant="borderless" >${item.value
|
|
146
|
-
?.map(row => {
|
|
147
|
-
const val = row.value;
|
|
148
|
-
if (val.length === 0) {
|
|
149
|
-
return '';
|
|
150
|
-
}
|
|
151
|
-
return `<flex>${val
|
|
152
|
-
.map(button => {
|
|
153
|
-
const value = button.value;
|
|
154
|
-
const options = button.options;
|
|
155
|
-
const autoEnter = options?.autoEnter ?? false;
|
|
156
|
-
const label = typeof value === 'object' ? value.title : value;
|
|
157
|
-
const command = options?.data || label;
|
|
158
|
-
return `<btn command="${command}" enter="${String(autoEnter)}" >${label}</btn>`;
|
|
159
|
-
})
|
|
160
|
-
.join('')}</flex>`;
|
|
161
|
-
})
|
|
162
|
-
.join('')}</box>`;
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
if ((content && content.length > 0) || (contentMd && contentMd.length > 0)) {
|
|
204
|
+
if (finalContent && finalContent.length > 0) {
|
|
167
205
|
if (channelId) {
|
|
168
|
-
const res = await client.sendMessage(channelId, { content:
|
|
206
|
+
const res = await client.sendMessage(channelId, { content: finalContent, type: 'text' });
|
|
169
207
|
return [createResult(ResultCode.Ok, '完成', res)];
|
|
170
208
|
}
|
|
171
209
|
if (threadId) {
|
|
172
|
-
const res = await client.sendDm(threadId, { content:
|
|
210
|
+
const res = await client.sendDm(threadId, { content: finalContent, type: 'text' });
|
|
173
211
|
return [createResult(ResultCode.Ok, '完成', res)];
|
|
174
212
|
}
|
|
175
213
|
return [createResult(ResultCode.Ok, '完成', null)];
|