diff --git a/src/bot.ts b/src/bot.ts index 0990a3e23e05b4ea9ce19f5146bd47e9b083714f..b3759472e3063013da571b6691cda50e3aee65be 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -50,6 +50,7 @@ const MATRIX_ICON_URL = "https://matrix.org/_matrix/media/r0/download/matrix.org class ChannelLookupResult { public channel: Discord.TextChannel; public botUser: boolean; + public canSendEmbeds: boolean; } interface IThirdPartyLookupField { @@ -362,6 +363,7 @@ export class DiscordBot { const lookupResult = new ChannelLookupResult(); lookupResult.channel = channel as Discord.TextChannel; lookupResult.botUser = this.bot.user.id === client.user.id; + lookupResult.canSendEmbeds = client.user.bot; // only bots can send embeds return lookupResult; } throw new Error(`Channel "${room}" not found`); @@ -414,18 +416,55 @@ export class DiscordBot { } try { this.channelLock.set(chan.id); - if (!botUser) { - // NOTE: Don't send replies to discord if we are a puppet. + if (!roomLookup.canSendEmbeds) { + // NOTE: Don't send replies to discord if we are a puppet user. + let addText = ""; + if (embedSet.replyEmbed) { + for (const line of embedSet.replyEmbed.description!.split("\n")) { + addText += "\n> " + line; + } + } + msg = await chan.send(embed.description + addText, opts); + } else if (!botUser) { + if (embedSet.imageEmbed || embedSet.replyEmbed) { + let sendEmbed = new Discord.RichEmbed(); + if (embedSet.imageEmbed) { + if (!embedSet.replyEmbed) { + sendEmbed = embedSet.imageEmbed; + } else { + sendEmbed.setImage(embedSet.imageEmbed.image!.url); + } + } + if (embedSet.replyEmbed) { + if (!embedSet.imageEmbed) { + sendEmbed = embedSet.replyEmbed; + } else { + sendEmbed.addField("Replying to", embedSet.replyEmbed!.author!.name); + sendEmbed.addField("Reply text", embedSet.replyEmbed.description); + } + } + opts.embed = sendEmbed; + } msg = await chan.send(embed.description, opts); } else if (hook) { MetricPeg.get.remoteCall("hook.send"); + const embeds: Discord.RichEmbed[] = []; + if (embedSet.imageEmbed) { + embeds.push(embedSet.imageEmbed); + } + if (embedSet.replyEmbed) { + embeds.push(embedSet.replyEmbed); + } msg = await hook.send(embed.description, { avatarURL: embed!.author!.icon_url, - embeds: embedSet.replyEmbed ? [embedSet.replyEmbed] : undefined, + embeds, files: opts.file ? [opts.file] : undefined, username: embed!.author!.name, } as Discord.WebhookMessageOptions); } else { + if (embedSet.imageEmbed) { + embed.setImage(embedSet.imageEmbed.image!.url); + } if (embedSet.replyEmbed) { embed.addField("Replying to", embedSet.replyEmbed!.author!.name); embed.addField("Reply text", embedSet.replyEmbed.description); diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts index 762380ee024d3afa2b1cf140e0b0db4d4b85a849..26f94ee0c6df7ba3c37c9e2c91e4aa94239920d5 100644 --- a/src/matrixeventprocessor.ts +++ b/src/matrixeventprocessor.ts @@ -54,6 +54,7 @@ export class MatrixEventProcessorOpts { export interface IMatrixEventProcessorResult { messageEmbed: Discord.RichEmbed; replyEmbed?: Discord.RichEmbed; + imageEmbed?: Discord.RichEmbed; } export class MatrixEventProcessor { @@ -170,11 +171,13 @@ export class MatrixEventProcessor { const embedSet = await this.EventToEmbed(event, chan); const opts: Discord.MessageOptions = {}; - const file = await this.HandleAttachment(event, mxClient); + const file = await this.HandleAttachment(event, mxClient, roomLookup.canSendEmbeds); if (typeof(file) === "string") { embedSet.messageEmbed.description += " " + file; + } else if ((file as Discord.FileOptions).name && (file as Discord.FileOptions).attachment) { + opts.file = file as Discord.FileOptions; } else { - opts.file = file; + embedSet.imageEmbed = file as Discord.RichEmbed; } await this.discord.send(embedSet, opts, roomLookup, event); @@ -284,7 +287,11 @@ export class MatrixEventProcessor { }; } - public async HandleAttachment(event: IMatrixEvent, mxClient: MatrixClient): Promise<string|Discord.FileOptions> { + public async HandleAttachment( + event: IMatrixEvent, + mxClient: MatrixClient, + sendEmbeds: boolean = false, + ): Promise<string|Discord.FileOptions|Discord.RichEmbed> { if (!this.HasAttachment(event)) { return ""; } @@ -296,7 +303,7 @@ export class MatrixEventProcessor { if (!event.content.info) { // Fractal sends images without an info, which is technically allowed // but super unhelpful: https://gitlab.gnome.org/World/fractal/issues/206 - event.content.info = {size: 0}; + event.content.info = {mimetype: "", size: 0}; } if (!event.content.url) { @@ -317,6 +324,10 @@ export class MatrixEventProcessor { } as Discord.FileOptions; } } + if (sendEmbeds && event.content.info.mimetype.split("/")[0] === "image") { + return new Discord.RichEmbed() + .setImage(url); + } return `[${name}](${url})`; } diff --git a/test/test_matrixeventprocessor.ts b/test/test_matrixeventprocessor.ts index 43eb0c8a6cfc6b98eea212ef6b21193eb416a787..2af10cf8232b809ddb26a5c3336c26c1d8f1fde2 100644 --- a/test/test_matrixeventprocessor.ts +++ b/test/test_matrixeventprocessor.ts @@ -603,6 +603,22 @@ describe("MatrixEventProcessor", () => { } as IMatrixEvent, mxClient); expect(ret).equals("[filename.webm](https://localhost/8000000)"); }); + it("Should reply embeds on large info.size images if set", async () => { + const LARGE_FILE = 8000000; + const processor = createMatrixEventProcessor(); + const ret = await processor.HandleAttachment({ + content: { + body: "filename.jpg", + info: { + mimetype: "image/jpeg", + size: LARGE_FILE, + }, + msgtype: "m.image", + url: "mxc://localhost/8000000", + }, + } as IMatrixEvent, mxClient, true); + expect((ret as Discord.RichEmbed).image!.url).equals("https://localhost/8000000"); + }); it("Should handle stickers.", async () => { const processor = createMatrixEventProcessor(); const attachment = (await processor.HandleAttachment({