diff --git a/src/index.ts b/src/index.ts index 75c6797..1c49c39 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,13 +10,14 @@ import { reuploadCommands } from './_reupload'; import * as BuildConfig from './constants'; import { parseLog } from './logs'; import { getLatestMinecraftVersion } from './utils/remoteVersions'; +import { expandDiscordLink } from './utils/resolveMessage'; import { membersCommand } from './commands/members'; import { starsCommand } from './commands/stars'; import { modrinthCommand } from './commands/modrinth'; import { tagsCommand } from './commands/tags'; import { jokeCommand } from './commands/joke'; -import { roryCommand } from "./commands/rory"; +import { roryCommand } from './commands/rory'; import random from 'just-random'; import { green, bold, yellow, cyan } from 'kleur/colors'; @@ -87,12 +88,12 @@ client.once('ready', async () => { `${random(BuildConfig.ETA_MESSAGES)} <:pofat:1031701005559144458>` ); } - const log = await parseLog(e.content); if (log != null) { e.reply({ embeds: [log] }); return; } + await expandDiscordLink(e); }); }); @@ -121,7 +122,7 @@ client.on('interactionCreate', async (interaction) => { await tagsCommand(interaction); } else if (commandName === 'joke') { await jokeCommand(interaction); - } else if (commandName === "rory") { + } else if (commandName === 'rory') { await roryCommand(interaction); } } diff --git a/src/utils/resolveMessage.ts b/src/utils/resolveMessage.ts new file mode 100644 index 0000000..a7bb38b --- /dev/null +++ b/src/utils/resolveMessage.ts @@ -0,0 +1,93 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + Colors, + EmbedBuilder, + type Message, + ThreadChannel, +} from 'discord.js'; + +function findFirstImage(message: Message): string | undefined { + const result = message.attachments.find((attach) => { + return attach.contentType?.startsWith('image/'); + }); + if (result == undefined) { + return undefined; + } else { + return result.url; + } +} + +export async function expandDiscordLink(message: Message): Promise { + const re = + /(https?:\/\/)?(?:canary\.|ptb\.)?discord(?:app)?\.com\/channels\/(?\d+)\/(?\d+)\/(?\d+)/g; + + const results = message.content.matchAll(re); + + let n = 0; + + for (const r of results) { + if (n >= 3) + break; // only process three previews + + if (r.groups == undefined && r.groups.server_id != message.guildId) + continue; // do not let the bot leak messages from one server to another + + const channel = await message.guild?.channels.fetch( + r.groups.channel_id + ); + + if (!channel || !channel.isTextBased()) + continue; + + if (channel instanceof ThreadChannel) { + if (!channel.parent?.members?.some((user) => user.id == message.author.id)) + continue; // do not reveal a message to a user who can't see it + } else { + if (!channel.members?.some((user) => user.id == message.author.id)) + continue; // do not reveal a message to a user who can't see it + } + + try { + const messageToShow = await channel.messages.fetch(r.groups.message_id); + + const builder = new EmbedBuilder() + .setAuthor({ + name: `${messageToShow.author.username}#${messageToShow.author.discriminator}`, + iconURL: messageToShow.author.displayAvatarURL(), + }) + .setColor(Colors.Aqua) + .setTimestamp(messageToShow.createdTimestamp) + .setFooter({ text: `#${messageToShow.channel.name}`}) + if (messageToShow.content) { + builder.setDescription(messageToShow.content); + } + if (messageToShow.attachments.size > 0) { + let attachmentsString = ''; + messageToShow.attachments.forEach((value) => { + attachmentsString += `[${value.name}](${value.url}) `; + }); + + builder.addFields({ name: 'Attachments', value: attachmentsString }); + + const firstImage = findFirstImage(messageToShow); + if (firstImage != undefined) { + builder.setImage(firstImage); + } + } + + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel('Jump to original message') + .setStyle(ButtonStyle.Link) + .setURL(messageToShow.url) + ); + + await message.reply({ embeds: [builder], components: [row], allowedMentions: {repliedUser: false}}); + n++; + } catch (e) { + console.error(e); + } + } +}