@chatluna/patchbay 0.1.8 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatluna/patchbay",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Cordis 4 patches for Koishi, Satori, Satori adapters and Cordis plugins, wired into yarn, pnpm or npm",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/patchbay.json CHANGED
@@ -61,6 +61,43 @@
61
61
  "cordis": "^4.0.0-rc.8"
62
62
  }
63
63
  },
64
+ {
65
+ "name": "@satorijs/adapter-discord",
66
+ "version": "4.6.3",
67
+ "description": "Keep literal markup in message text, decode rich embeds as elements and resolve the author of a DM delete",
68
+ "fixes": [
69
+ "ChatLunaLab/v2-mirror#147",
70
+ "ChatLunaLab/v2-mirror#150",
71
+ "ChatLunaLab/v2-mirror#158"
72
+ ]
73
+ },
74
+ {
75
+ "name": "@satorijs/adapter-qq",
76
+ "version": "4.14.1",
77
+ "description": "Decode official QQ group_openid targets, ARK cards, nested chat records and index-only quotes; keep absolute channel image URLs and literal markup in guild text",
78
+ "fixes": [
79
+ "ChatLunaLab/v2-mirror#84",
80
+ "ChatLunaLab/v2-mirror#93",
81
+ "ChatLunaLab/v2-mirror#134",
82
+ "ChatLunaLab/v2-mirror#135",
83
+ "ChatLunaLab/v2-mirror#136",
84
+ "ChatLunaLab/v2-mirror#139",
85
+ "ChatLunaLab/v2-mirror#225"
86
+ ]
87
+ },
88
+ {
89
+ "name": "@satorijs/adapter-telegram",
90
+ "version": "4.5.11",
91
+ "description": "Mention the bot by username, decode contacts, polls, dice, venues and video notes, scope albums and forum topics to their chat, and omit missing ids from uploads",
92
+ "fixes": [
93
+ "ChatLunaLab/v2-mirror#146",
94
+ "ChatLunaLab/v2-mirror#148",
95
+ "ChatLunaLab/v2-mirror#149",
96
+ "ChatLunaLab/v2-mirror#151",
97
+ "ChatLunaLab/v2-mirror#164",
98
+ "ChatLunaLab/v2-mirror#226"
99
+ ]
100
+ },
64
101
  {
65
102
  "name": "koishi-plugin-adapter-onebot",
66
103
  "version": "6.9.5",
@@ -0,0 +1,81 @@
1
+ diff --git a/lib/index.cjs b/lib/index.cjs
2
+ index c3cecb6..6eddf09 100644
3
+ --- a/lib/index.cjs
4
+ +++ b/lib/index.cjs
5
+ @@ -1259,22 +1259,30 @@ async function decodeMessage(bot, data, message, payload = message, details = tr
6
+ message.id = message.messageId = data.id;
7
+ message.content = "";
8
+ if (data.content) {
9
+ - message.content = data.content.replace(/<@[!&]?(.+?)>/g, (_, id) => {
10
+ - if (data.mention_roles.includes(id)) {
11
+ - return (0, import_core2.h)("at", { role: id }).toString();
12
+ + let last = 0;
13
+ + for (const match of data.content.matchAll(/<@([!&]?)(\d+)>|<(a?):(\w+):(\d+)>|<#(\d+)>|@everyone|@here/g)) {
14
+ + message.content += import_core2.h.escape(data.content.slice(last, match.index));
15
+ + last = match.index + match[0].length;
16
+ + const [token, kind, userId, animated, name, emojiId, channelId] = match;
17
+ + if (userId) {
18
+ + if (kind === "&" || data.mention_roles.includes(userId)) {
19
+ + message.content += (0, import_core2.h)("at", { role: userId });
20
+ + } else {
21
+ + const user = data.mentions?.find((u) => u.id === userId);
22
+ + message.content += import_core2.h.at(userId, { name: user?.username });
23
+ + }
24
+ + } else if (emojiId) {
25
+ + message.content += (0, import_core2.h)("face", { id: emojiId, name, animated: !!animated, platform }, [
26
+ + import_core2.h.image(`https://cdn.discordapp.com/emojis/${emojiId}.webp?quality=lossless`)
27
+ + ]);
28
+ + } else if (channelId) {
29
+ + const channel = data.mention_channels?.find((c) => c.id === channelId);
30
+ + message.content += import_core2.h.sharp(channelId, { name: channel?.name });
31
+ } else {
32
+ - const user = data.mentions?.find((u) => u.id === id || `${u.username}#${u.discriminator}` === id);
33
+ - return import_core2.h.at(id, { name: user?.username }).toString();
34
+ + message.content += (0, import_core2.h)("at", { type: token === "@everyone" ? "all" : "here" });
35
+ }
36
+ - }).replace(/<a?:(.*):(.+?)>/g, (_, name, id) => {
37
+ - const animated = _[1] === "a";
38
+ - return (0, import_core2.h)("face", { id, name, animated, platform }, [
39
+ - import_core2.h.image(`https://cdn.discordapp.com/emojis/${id}.webp?quality=lossless`)
40
+ - ]).toString();
41
+ - }).replace(/@everyone/g, () => (0, import_core2.h)("at", { type: "all" }).toString()).replace(/@here/g, () => (0, import_core2.h)("at", { type: "here" }).toString()).replace(/<#(.+?)>/g, (_, id) => {
42
+ - const channel = data.mention_channels?.find((c) => c.id === id);
43
+ - return import_core2.h.sharp(id, { name: channel?.name }).toString();
44
+ - });
45
+ + }
46
+ + message.content += import_core2.h.escape(data.content.slice(last));
47
+ }
48
+ if (data.sticker_items) {
49
+ message.content += data.sticker_items.map((s) => (0, import_core2.h)("sticker", {
50
+ @@ -1327,6 +1335,16 @@ async function decodeMessage(bot, data, message, payload = message, details = tr
51
+ }).join("");
52
+ }
53
+ for (const embed of data.embeds) {
54
+ + if (embed.title || embed.description || embed.fields?.length || embed.author?.name || embed.footer?.text) {
55
+ + message.content += (0, import_core2.h)("discord:embed", {
56
+ + type: embed.type,
57
+ + title: embed.title,
58
+ + url: embed.url,
59
+ + description: embed.description,
60
+ + author: embed.author?.name,
61
+ + footer: embed.footer?.text
62
+ + }, (embed.fields ?? []).map((field) => (0, import_core2.h)("field", { name: field.name, value: field.value, inline: field.inline })));
63
+ + }
64
+ if (embed.image) {
65
+ message.content += (0, import_core2.h)("img", { src: embed.image.url, proxy_url: embed.image.proxy_url });
66
+ }
67
+ @@ -1409,6 +1427,14 @@ async function adaptSession(bot, input) {
68
+ session.messageId = input.d.id;
69
+ session.channelId = input.d.channel_id;
70
+ setupMessageGuildId(session, input.d.guild_id);
71
+ + if (!input.d.guild_id) {
72
+ + try {
73
+ + const channel = await bot.internal.getChannel(input.d.channel_id);
74
+ + session.userId = channel.recipients?.[0]?.id;
75
+ + } catch (e) {
76
+ + bot.logger.warn("cannot resolve the author of a direct message deletion", e);
77
+ + }
78
+ + }
79
+ } else if (input.t === "MESSAGE_REACTION_ADD") {
80
+ session.type = "reaction-added";
81
+ setupReaction(session, input.d);
@@ -0,0 +1,111 @@
1
+ diff --git a/lib/index.cjs b/lib/index.cjs
2
+ index 4e1bd28..d722f5b 100644
3
+ --- a/lib/index.cjs
4
+ +++ b/lib/index.cjs
5
+ @@ -293,6 +293,7 @@ var decodeGuildMember = /* @__PURE__ */ __name((member) => ({
6
+ roles: member.roles?.map((id) => ({ id })),
7
+ joinedAt: new Date(member.joined_at).valueOf()
8
+ }), "decodeGuildMember");
9
+ +var attachmentUrl = /* @__PURE__ */ __name((url) => /^[a-z][a-z\d+.-]*:/i.test(url) ? url : "https://" + url.replace(/^\/\//, ""), "attachmentUrl");
10
+ var decodeGroupMessageContent = /* @__PURE__ */ __name((content, attachments = [], attachedFace = /* @__PURE__ */ new Set()) => {
11
+ const elements = [];
12
+ let lastIndex = 0;
13
+ @@ -306,7 +307,7 @@ var decodeGroupMessageContent = /* @__PURE__ */ __name((content, attachments = [
14
+ case 6: {
15
+ const imageAttachment = attachments[+faceId];
16
+ if (imageAttachment) {
17
+ - elements.push(import_core.h.image(imageAttachment.url, {
18
+ + elements.push(import_core.h.image(attachmentUrl(imageAttachment.url), {
19
+ width: imageAttachment.width,
20
+ height: imageAttachment.height
21
+ }));
22
+ @@ -341,20 +342,32 @@ var decodeAttachments = /* @__PURE__ */ __name((attachments, attachedFace = /* @
23
+ const elements = [];
24
+ for (const [index, attachment] of attachments.entries()) {
25
+ if (attachment.content_type === "file") {
26
+ - elements.push(import_core.h.file(attachment.url, {
27
+ + elements.push(import_core.h.file(attachmentUrl(attachment.url), {
28
+ filename: attachment.filename
29
+ }));
30
+ } else if (attachment.content_type.startsWith("image/")) {
31
+ if (attachedFace.has(index)) continue;
32
+ - elements.push(import_core.h.image(attachment.url, { width: attachment.width, height: attachment.height }));
33
+ + elements.push(import_core.h.image(attachmentUrl(attachment.url), { width: attachment.width, height: attachment.height }));
34
+ } else if (attachment.content_type === "voice") {
35
+ - elements.push(import_core.h.audio(attachment.url));
36
+ + elements.push(import_core.h.audio(attachmentUrl(attachment.url)));
37
+ } else if (attachment.content_type.startsWith("video")) {
38
+ - elements.push(import_core.h.video(attachment.url, { width: attachment.width, height: attachment.height }));
39
+ + elements.push(import_core.h.video(attachmentUrl(attachment.url), { width: attachment.width, height: attachment.height }));
40
+ }
41
+ }
42
+ return elements;
43
+ }, "decodeAttachments");
44
+ +var decodeElementContent = /* @__PURE__ */ __name((element) => {
45
+ + const attached = /* @__PURE__ */ new Set();
46
+ + return [
47
+ + ...decodeGroupMessageContent(element.content ?? "", element.attachments ?? [], attached),
48
+ + ...decodeAttachments(element.attachments ?? [], attached)
49
+ + ];
50
+ +}, "decodeElementContent");
51
+ +var decodeRecord = /* @__PURE__ */ __name((elements) => import_core.h("message", { forward: true }, elements.map((element) => import_core.h("message", {}, [
52
+ + ...element.author?.username ? [import_core.h("author", { name: element.author.username })] : [],
53
+ + ...decodeElementContent(element),
54
+ + ...element.msg_elements?.length ? [decodeRecord(element.msg_elements)] : []
55
+ +]))), "decodeRecord");
56
+ function decodeGroupMessage(bot, data, message = {}, payload = message) {
57
+ message.id = data.id;
58
+ const attachedFace = /* @__PURE__ */ new Set();
59
+ @@ -376,16 +389,22 @@ function decodeGroupMessage(bot, data, message = {}, payload = message) {
60
+ }, "text")
61
+ });
62
+ message.elements.push(...decodeAttachments(data.attachments ?? [], attachedFace));
63
+ - if (data.message_type === Message.Type.QUOTE) {
64
+ - const quoted = [];
65
+ - const quotedAttached = /* @__PURE__ */ new Set();
66
+ - quoted.push(...decodeGroupMessageContent(data.msg_elements[0].content, data.msg_elements[0].attachments ?? [], quotedAttached));
67
+ - quoted.push(...decodeAttachments(data.msg_elements[0].attachments ?? [], quotedAttached));
68
+ + const ark = data.ark_data ?? data.ark;
69
+ + if (+data.message_type === Message.Type.ARK && ark) {
70
+ + message.elements.push(import_core.h("json", { data: JSON.stringify(ark) }));
71
+ + }
72
+ + if (+data.message_type === 102 && data.msg_elements?.length) {
73
+ + message.elements.push(decodeRecord(data.msg_elements));
74
+ + }
75
+ + if (+data.message_type === Message.Type.QUOTE) {
76
+ + const quoted = data.msg_elements?.[0];
77
+ + const id = quoted?.msg_idx ?? data.message_scene?.ext?.find((item) => item.startsWith("ref_msg_idx="))?.slice("ref_msg_idx=".length);
78
+ message.quote = {
79
+ + ...id ? { id } : {},
80
+ member: {
81
+ - nick: data.msg_elements[0].author?.username
82
+ + nick: quoted?.author?.username
83
+ },
84
+ - elements: quoted
85
+ + elements: quoted ? decodeElementContent(quoted) : []
86
+ };
87
+ }
88
+ message.content = message.elements.join("");
89
+ @@ -395,7 +414,8 @@ function decodeGroupMessage(bot, data, message = {}, payload = message) {
90
+ date = data.timestamp.slice(0, data.timestamp.indexOf("m=")).trim().replace(/\+(\d{4}) CST/, "GMT+$1");
91
+ }
92
+ payload.timestamp = new Date(date).valueOf();
93
+ - payload.guild = data.group_id && { id: data.group_id };
94
+ + const groupId = data.group_id ?? data.group_openid;
95
+ + payload.guild = groupId && { id: groupId };
96
+ payload.user = { id: data.author.id, avatar: `https://q.qlogo.cn/qqapp/${bot.config.id}/${data.author.id}/640` };
97
+ if (data.author.username) payload.user.name = data.author.username;
98
+ if (data.author.member_role) payload.member = { roles: [{ id: data.author.member_role }] };
99
+ @@ -404,10 +424,10 @@ function decodeGroupMessage(bot, data, message = {}, payload = message) {
100
+ __name(decodeGroupMessage, "decodeGroupMessage");
101
+ async function decodeMessage(bot, data, message = {}, payload = message) {
102
+ message.id = message.messageId = data.id;
103
+ - message.content = (data.content ?? "").replace(/<@!(\d+)>/g, (_, $1) => import_core.h.at($1).toString());
104
+ + message.content = (data.content ?? "").split(/<@!(\d+)>/).map((part, index) => index % 2 ? import_core.h.at(part).toString() : import_core.h.escape(part)).join("");
105
+ const { attachments = [] } = data;
106
+ if (attachments.length && !/\s$/.test(message.content)) message.content += " ";
107
+ - message.content = attachments.filter(({ content_type }) => content_type.startsWith("image")).reduce((content, attachment) => content + import_core.h.image("https://" + attachment.url), message.content);
108
+ + message.content = attachments.filter(({ content_type }) => content_type.startsWith("image")).reduce((content, attachment) => content + import_core.h.image(attachmentUrl(attachment.url)), message.content);
109
+ message.elements = import_core.h.parse(message.content);
110
+ message.elements = import_core.h.transform(message.elements, {
111
+ text: /* @__PURE__ */ __name((attrs) => import_core.h.unescape(attrs.content), "text")
@@ -0,0 +1,125 @@
1
+ diff --git a/lib/index.cjs b/lib/index.cjs
2
+ index 01364de..27e76a5 100644
3
+ --- a/lib/index.cjs
4
+ +++ b/lib/index.cjs
5
+ @@ -244,10 +244,11 @@ async function handleUpdate(update, bot) {
6
+ session.content = command + session.content.slice(group.length);
7
+ } else if (message) {
8
+ if (update.message?.media_group_id) {
9
+ - if (!mediaGroupMap.has(update.message.media_group_id)) {
10
+ - mediaGroupMap.set(update.message.media_group_id, [/* @__PURE__ */ new Date(), []]);
11
+ + const groupKey = `${bot.selfId}:${update.message.chat.id}:${update.message.media_group_id}`;
12
+ + if (!mediaGroupMap.has(groupKey)) {
13
+ + mediaGroupMap.set(groupKey, [/* @__PURE__ */ new Date(), []]);
14
+ }
15
+ - const [, updates] = mediaGroupMap.get(update.message.media_group_id);
16
+ + const [, updates] = mediaGroupMap.get(groupKey);
17
+ session.type = update.message || update.channel_post ? "message" : "message-updated";
18
+ await decodeMessage(bot, message, session.event.message = {}, session.event);
19
+ updates.push({
20
+ @@ -255,10 +256,10 @@ async function handleUpdate(update, bot) {
21
+ elements: session.event.message.elements
22
+ });
23
+ const thisUpdateTime = /* @__PURE__ */ new Date();
24
+ - mediaGroupMap.set(update.message.media_group_id, [thisUpdateTime, updates]);
25
+ + mediaGroupMap.set(groupKey, [thisUpdateTime, updates]);
26
+ await new Promise((resolve) => setTimeout(resolve, 1200));
27
+ - if (mediaGroupMap.get(update.message.media_group_id)[0] === thisUpdateTime) {
28
+ - mediaGroupMap.delete(update.message.media_group_id);
29
+ + if (mediaGroupMap.get(groupKey)[0] === thisUpdateTime) {
30
+ + mediaGroupMap.delete(groupKey);
31
+ session.event.message.elements = updates.sort((a, b) => a.id - b.id).reduce((acc, cur) => acc.concat(cur.elements), []);
32
+ session.event.message.content = session.event.message.elements.join("");
33
+ session.event.message.id = Math.min(...updates.map((e) => e.id)).toString();
34
+ @@ -310,7 +311,7 @@ async function handleUpdate(update, bot) {
35
+ name: data.chat.title
36
+ };
37
+ session.event.channel = {
38
+ - id: data.is_topic_message ? data.message_thread_id.toString() : data.chat.id.toString(),
39
+ + id: data.is_topic_message ? `${data.chat.id}:${data.message_thread_id}` : data.chat.id.toString(),
40
+ type: import_core.Universal.Channel.Type.TEXT
41
+ };
42
+ }
43
+ @@ -366,7 +367,7 @@ async function decodeMessage(bot, data, message, payload = message) {
44
+ if (attr.includes("code")) ele = (0, import_core.h)("code", {}, ele);
45
+ if (attr.includes("pre")) ele = (0, import_core.h)("pre", {}, ele);
46
+ if (attr.includes("spoiler")) ele = (0, import_core.h)("spl", {}, ele);
47
+ - if (attr.includes("mention")) ele = (0, import_core.h)("at", { name: content.slice(1) });
48
+ + if (attr.includes("mention")) ele = content.slice(1) === bot.user?.name ? (0, import_core.h)("at", { id: bot.selfId, name: content.slice(1) }) : (0, import_core.h)("at", { name: content.slice(1) });
49
+ if (url) ele = (0, import_core.h)("a", { href: url }, ele);
50
+ if (user) ele = (0, import_core.h)("at", { id: user.id, name: user.username }, ele);
51
+ if (content === "\n") ele = (0, import_core.h)("br");
52
+ @@ -394,7 +395,15 @@ async function decodeMessage(bot, data, message, payload = message) {
53
+ segments.push((0, import_core.h)(type, attrs));
54
+ }, "addResource");
55
+ if (data.location) {
56
+ - segments.push((0, import_core.h)("location", { lat: data.location.latitude, lon: data.location.longitude }));
57
+ + segments.push((0, import_core.h)("location", { lat: data.location.latitude, lon: data.location.longitude, title: data.venue?.title, address: data.venue?.address }));
58
+ + } else if (data.contact) {
59
+ + const { contact } = data;
60
+ + segments.push((0, import_core.h)("telegram:contact", { name: [contact.first_name, contact.last_name].filter(Boolean).join(" "), phone: contact.phone_number, id: contact.user_id?.toString() }));
61
+ + } else if (data.poll) {
62
+ + const { poll } = data;
63
+ + segments.push((0, import_core.h)("telegram:poll", { question: poll.question, type: poll.type, multiple: poll.allows_multiple_answers, closed: poll.is_closed }, poll.options.map((option) => (0, import_core.h)("option", { text: option.text, votes: option.voter_count }))));
64
+ + } else if (data.dice) {
65
+ + segments.push((0, import_core.h)("telegram:dice", { emoji: data.dice.emoji, value: data.dice.value }));
66
+ } else if (data.photo) {
67
+ const photo = data.photo.sort((s1, s2) => s2.file_size - s1.file_size)[0];
68
+ segments.push((0, import_core.h)("img", await bot.$getFileFromId(photo.file_id)));
69
+ @@ -419,6 +428,8 @@ async function decodeMessage(bot, data, message, payload = message) {
70
+ await addResource("img", data.animation);
71
+ } else if (data.video) {
72
+ await addResource("video", data.video);
73
+ + } else if (data.video_note) {
74
+ + await addResource("video", data.video_note);
75
+ } else if (data.document) {
76
+ await addResource("file", data.document);
77
+ } else if (data.audio) {
78
+ @@ -442,7 +453,7 @@ async function decodeMessage(bot, data, message, payload = message) {
79
+ };
80
+ payload.member = {};
81
+ payload.channel = {
82
+ - id: data.is_topic_message ? data.message_thread_id.toString() : data.chat.id.toString(),
83
+ + id: data.is_topic_message ? `${data.chat.id}:${data.message_thread_id}` : data.chat.id.toString(),
84
+ type: import_core.Universal.Channel.Type.TEXT
85
+ };
86
+ }
87
+ @@ -461,9 +472,12 @@ var TelegramMessageEncoder = class extends import_core2.MessageEncoder {
88
+ mode = "default";
89
+ rows = [];
90
+ async prepare() {
91
+ - const chat_id = this.session.guildId || this.channelId;
92
+ + const [chat, thread] = this.channelId.split(":");
93
+ + const chat_id = thread ? chat : this.session.guildId || this.channelId;
94
+ this.payload = { chat_id, parse_mode: "html", caption: "" };
95
+ - if (this.session.guildId && this.channelId !== this.session.guildId) {
96
+ + if (thread) {
97
+ + this.payload.message_thread_id = +thread;
98
+ + } else if (this.session.guildId && this.channelId !== this.session.guildId) {
99
+ this.payload.message_thread_id = +this.channelId;
100
+ }
101
+ }
102
+ @@ -564,8 +578,8 @@ var TelegramMessageEncoder = class extends import_core2.MessageEncoder {
103
+ formData.append("chat_id", this.payload.chat_id);
104
+ formData.append("caption", this.payload.caption);
105
+ formData.append("parse_mode", this.payload.parse_mode);
106
+ - formData.append("reply_to_message_id", this.payload.reply_to_message_id);
107
+ - formData.append("message_thread_id", this.payload.message_thread_id);
108
+ + if (this.payload.reply_to_message_id !== undefined) formData.append("reply_to_message_id", this.payload.reply_to_message_id);
109
+ + if (this.payload.message_thread_id !== undefined) formData.append("message_thread_id", this.payload.message_thread_id);
110
+ formData.append("has_spoiler", files[0].element.attrs.spoiler ? "true" : "false");
111
+ formData.append(dataKey, "attach://" + files[0].filename);
112
+ formData.append(files[0].filename, new Blob([files[0].data], { type: files[0].mime }), files[0].filename);
113
+ @@ -874,10 +888,12 @@ var TelegramBot = class _TelegramBot extends import_core5.Bot {
114
+ this.online();
115
+ }
116
+ async deleteMessage(chat_id, message_id) {
117
+ + chat_id = chat_id.split(":")[0];
118
+ message_id = +message_id;
119
+ await this.internal.deleteMessage({ chat_id, message_id });
120
+ }
121
+ async editMessage(chat_id, message_id, content) {
122
+ + chat_id = chat_id.split(":")[0];
123
+ message_id = +message_id;
124
+ const payload = {
125
+ chat_id,