diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js index c049f18..5778c02 100644 --- a/src/d2m/converters/message-to-event.js +++ b/src/d2m/converters/message-to-event.js @@ -630,6 +630,16 @@ async function messageToEvent(message, guild, options = {}, di) { message.content = `added a new emoji, ${message.content} :${name}:` } + // Send Klipy GIFs in customised form + let isKlipyGIF = false + let isOnlyKlipyGIF = false + if (message.embeds?.length === 1 && message.embeds[0].provider?.name === "Klipy" && message.embeds[0].video?.url) { + isKlipyGIF = true + if (message.content.match(/^https?:\/\/klipy\.com[^ \n]+$/)) { + isOnlyKlipyGIF = true + } + } + // Forwarded content appears first if (message.message_reference?.type === DiscordTypes.MessageReferenceType.Forward && message.message_snapshots?.length) { // Forwarded notice @@ -682,7 +692,7 @@ async function messageToEvent(message, guild, options = {}, di) { } // Then text content - if (message.content) { + if (message.content && !isOnlyKlipyGIF) { // Mentions scenario 3: scan the message content for written @mentions of matrix users. Allows for up to one space between @ and mention. let content = message.content if (options.scanTextForMentions !== false) { @@ -905,6 +915,20 @@ async function messageToEvent(message, guild, options = {}, di) { // Start building up a replica ("rep") of the embed in Discord-markdown format, which we will convert into both plaintext and formatted body at once const rep = new mxUtils.MatrixStringBuilder() + if (isKlipyGIF) { + rep.add("[GIF] ", "➿ ") + if (embed.title) { + rep.add(`${embed.title} ${embed.video.url}`, tag`${embed.title}`) + } else { + rep.add(embed.video.url) + } + + let {body, formatted_body: html} = rep.get() + html = `
${html}` + await addTextEvent(body, html, "m.text") + continue + } + // Provider if (embed.provider?.name && embed.provider.name !== "Tenor") { if (embed.provider.url) { diff --git a/src/d2m/converters/message-to-event.test.embeds.js b/src/d2m/converters/message-to-event.test.embeds.js index 4895993..cfb2f96 100644 --- a/src/d2m/converters/message-to-event.test.embeds.js +++ b/src/d2m/converters/message-to-event.test.embeds.js @@ -346,6 +346,18 @@ test("message2event embeds: tenor gif should show a video link without a provide }]) }) +test("message2event embeds: klipy gif should send in customised format", async t => { + const events = await messageToEvent(data.message_with_embeds.klipy_gif, data.guild.general, {}, {}) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "[GIF] Cute Corgi Waddle https://static.klipy.com/ii/d7aec6f6f171607374b2065c836f92f4/5b/5b/7ndEhcilPNKJ8O.mp4", + format: "org.matrix.custom.html", + formatted_body: "
➿ Cute Corgi Waddle", + "m.mentions": {} + }]) +}) + test("message2event embeds: if discord creates an embed preview for a discord channel link, don't copy that embed", async t => { const events = await messageToEvent(data.message_with_embeds.discord_server_included_punctuation_bad_discord, data.guild.general, {}, { api: { diff --git a/src/matrix/utils.js b/src/matrix/utils.js index b131510..d89c968 100644 --- a/src/matrix/utils.js +++ b/src/matrix/utils.js @@ -2,6 +2,7 @@ const assert = require("assert").strict const Ty = require("../types") +const {tag} = require("@cloudrac3r/html-template-tag") const passthrough = require("../passthrough") const {db} = passthrough @@ -72,7 +73,7 @@ class MatrixStringBuilder { */ add(body, formattedBody, condition = true) { if (condition) { - if (formattedBody == undefined) formattedBody = body + if (formattedBody == undefined) formattedBody = tag`${body}` this.body += body this.formattedBody += formattedBody } @@ -86,7 +87,7 @@ class MatrixStringBuilder { */ addLine(body, formattedBody, condition = true) { if (condition) { - if (formattedBody == undefined) formattedBody = body + if (formattedBody == undefined) formattedBody = tag`${body}` if (this.body.length && this.body.slice(-1) !== "\n") this.body += "\n" this.body += body const match = this.formattedBody.match(/<\/?([a-zA-Z]+[a-zA-Z0-9]*)[^>]*>\s*$/) @@ -103,7 +104,7 @@ class MatrixStringBuilder { */ addParagraph(body, formattedBody, condition = true) { if (condition) { - if (formattedBody == undefined) formattedBody = body + if (formattedBody == undefined) formattedBody = tag`${body}` if (this.body.length && this.body.slice(-1) !== "\n") this.body += "\n\n" this.body += body const match = formattedBody.match(/^<([a-zA-Z]+[a-zA-Z0-9]*)/) diff --git a/test/data.js b/test/data.js index 2205676..4854f6a 100644 --- a/test/data.js +++ b/test/data.js @@ -4916,6 +4916,69 @@ module.exports = { flags: 0, components: [] }, + klipy_gif: { + type: 0, + content: "https://klipy.com/gifs/cute-15", + mentions: [], + mention_roles: [], + attachments: [], + embeds: [ + { + type: "gifv", + url: "https://klipy.com/gifs/cute-15", + title: "Cute Corgi Waddle", + provider: { + name: "Klipy", + url: "https://klipy.com" + }, + thumbnail: { + url: "https://static.klipy.com/ii/d7aec6f6f171607374b2065c836f92f4/5b/5b/xHVF6sVV.webp", + proxy_url: "https://images-ext-1.discordapp.net/external/Z54QmlQflPPb6NoXikflBHGmttgRm3_jhzmcILXHhcA/https/static.klipy.com/ii/d7aec6f6f171607374b2065c836f92f4/5b/5b/xHVF6sVV.webp", + width: 277, + height: 498, + placeholder: "3gcGDAJV+WZYl3RpZ2gGeFBxBw==", + placeholder_version: 1, + flags: 0 + }, + video: { + url: "https://static.klipy.com/ii/d7aec6f6f171607374b2065c836f92f4/5b/5b/7ndEhcilPNKJ8O.mp4", + proxy_url: "https://images-ext-1.discordapp.net/external/xZspzkQPUKBa74pBhJDpBf3v2d3d0lC943xaB9_JnoM/https/static.klipy.com/ii/d7aec6f6f171607374b2065c836f92f4/5b/5b/7ndEhcilPNKJ8O.mp4", + width: 356, + height: 640, + placeholder: "3gcGDAJV+WZYl3RpZ2gGeFBxBw==", + placeholder_version: 1, + flags: 0 + }, + content_scan_version: 4 + } + ], + timestamp: "2026-02-03T11:11:50.070000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + id: "1468202316233707613", + channel_id: "1370776315266859131", + author: { + id: "304655299631906816", + username: "witterson", + avatar: "47ec94a1b2b4cc41ce0329b3575e9b66", + discriminator: "0", + public_flags: 0, + flags: 0, + banner: null, + accent_color: null, + global_name: "wit", + avatar_decoration_data: null, + collectibles: null, + display_name_styles: null, + banner_color: null, + clan: null, + primary_guild: null + }, + pinned: false, + mention_everyone: false, + tts: false + }, tenor_gif: { type: 0, content: "<@&1182745800661540927> get real https://tenor.com/view/get-real-gif-26176788",