diff --git a/.gitignore b/.gitignore index 83f9014..0ff39a4 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,9 @@ dist # TernJS port file .tern-port +# IDE config +.idea/ + +# other +.DS_Store config.json \ No newline at end of file diff --git a/scripts/register.js b/scripts/register.js index c7f904a..cc58dad 100644 --- a/scripts/register.js +++ b/scripts/register.js @@ -9,6 +9,36 @@ const commands = [ { name: "snipe", description: "Shows the last deleted message from a specified channel!", + options: [ + { + type: 7, // text channel + name: "channel", + description: "The channel to snipe", + }, + ], + }, + { + name: "editsnipe", + description: "Shows the last edited message from a specified channel!", + options: [ + { + type: 7, // text channel + name: "channel", + description: "The channel to snipe", + }, + ], + }, + { + name: "reactionsnipe", + description: + "Shows the last removed reaction from a specified channel!", + options: [ + { + type: 7, // text channel + name: "channel", + description: "The channel to snipe", + }, + ], }, ]; diff --git a/src/index.js b/src/index.js index d9b97e5..18db68b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,26 +1,83 @@ const { Client, Intents, MessageEmbed } = require("discord.js"); const client = new Client({ - intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES], + intents: [ + Intents.FLAGS.GUILDS, + Intents.FLAGS.GUILD_MESSAGES, + Intents.FLAGS.GUILD_MESSAGE_REACTIONS, + ], + partials: ["MESSAGE", "REACTION", "USER"], }); const { token } = require("../config.json"); const snipes = {}; +const editSnipes = {}; +const reactionSnipes = {}; + +const formatEmoji = (emoji) => { + return !emoji.id || emoji.available + ? emoji.toString() // bot has access or unicode emoji + : `[:${emoji.name}:](${emoji.url})`; // bot cannot use the emoji +}; client.on("ready", () => { console.log(`[sniper] :: Logged in as ${client.user.tag}.`); }); client.on("messageDelete", async (message) => { - snipes[message.guild.id] = { + if (message.partial) return; // content is null + + snipes[message.channel.id] = { author: message.author, content: message.content, createdAt: message.createdTimestamp, }; }); +client.on("messageUpdate", async (oldMessage, newMessage) => { + if (oldMessage.partial) return; // content is null + + editSnipes[oldMessage.channel.id] = { + author: oldMessage.author, + content: oldMessage.content, + createdAt: newMessage.editedTimestamp, + }; +}); + +client.on("messageReactionRemove", async (reaction, user) => { + if (reaction.partial) reaction = await reaction.fetch(); + + reactionSnipes[reaction.message.channel.id] = { + user: user, + emoji: reaction.emoji, + messageURL: reaction.message.url, + createdAt: Date.now(), + }; +}); + client.on("interactionCreate", async (interaction) => { - if (interaction.isCommand() && interaction.commandName === "snipe") { - const snipe = snipes[interaction.guildId]; + if (!interaction.isCommand()) return; + + const channel = + interaction.options.getChannel("channel") || interaction.channel; + + if (interaction.commandName === "snipe") { + const snipe = snipes[channel.id]; + + await interaction.reply( + snipe + ? { + embeds: [ + new MessageEmbed() + .setDescription(snipe.content) + .setAuthor(snipe.author.tag) + .setFooter(`#${channel.name}`) + .setTimestamp(snipe.createdAt), + ], + } + : "There's nothing to snipe!" + ); + } else if (interaction.commandName === "editsnipe") { + const snipe = editSnipes[channel.id]; await interaction.reply( snipe @@ -29,6 +86,27 @@ client.on("interactionCreate", async (interaction) => { new MessageEmbed() .setDescription(snipe.content) .setAuthor(snipe.author.tag) + .setFooter(`#${channel.name}`) + .setTimestamp(snipe.createdAt), + ], + } + : "There's nothing to snipe!" + ); + } else if (interaction.commandName === "reactionsnipe") { + const snipe = reactionSnipes[channel.id]; + + await interaction.reply( + snipe + ? { + embeds: [ + new MessageEmbed() + .setDescription( + `reacted with ${formatEmoji( + snipe.emoji + )} on [this message](${snipe.messageURL})` + ) + .setAuthor(snipe.user.tag) + .setFooter(`#${channel.name}`) .setTimestamp(snipe.createdAt), ], }