import 'dotenv/config' const TOKEN = process.env.TOKEN; const CLIENT_ID = process.env.CLIENT_ID; if (!TOKEN || !CLIENT_ID) { console.error(`No ${TOKEN ? "CLIENT_ID" : "TOKEN"} provided`); process.exit(); } import commands from "./commands.ts"; if (process.argv.includes("--register")) { const rest = new REST({ version: "10" }).setToken(TOKEN); try { console.log("refreshing slash commands..."); await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands }); console.log("OK"); } catch (error) { console.error(error); } process.exit(); } import { REST, Routes, Client, Partials, GatewayIntentBits, Events, TextChannel, Webhook, WebhookMessageCreateOptions, WebhookClient, } from "discord.js"; import { writeConfig, readConfig } from "./config.ts"; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.MessageContent, ], partials: [Partials.Message, Partials.Channel, Partials.Reaction], }); client.on("ready", () => { if (!client.user) { console.error("Failed to login"); process.exit(); } console.log(`Logged in as ${client.user.tag}!`); client.user.setActivity("for reactions"); }); import { Entry, Type } from "./entry.ts"; const entries: Entry[] = readConfig(); writeConfig(entries); client.on("interactionCreate", async (interaction) => { if (interaction.isChatInputCommand()) { if (interaction.commandName === "config") { const subcommand = interaction.options.getSubcommand(true); if (subcommand === "output") { const channel = interaction.options.getChannel("channel", true); try { await interaction.deferReply({ ephemeral: true, }); let entry = entries.find((entry) => entry.server === interaction.guildId); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } entry.output_channel = channel.id; writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `Set output to <#${channel.id}>`, }); } } else if (subcommand === "channels") { const channel = interaction.options.getChannel("channel", true); const mode = interaction.options.getString("add_remove", true); try { await interaction.deferReply({ ephemeral: true }); let entry = entries.find((entry) => entry.server === interaction.guildId); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } if (mode === "add") entry.channels.push(channel.id); else entry.channels = entry.channels.filter((c) => c !== channel.id); writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `Set to watch for reactions in <#${channel.id}>`, }); } } else if (subcommand === "channels_type") { const channel_type = interaction.options.getString("channels_type", true); try { await interaction.deferReply({ ephemeral: true }); let entry = entries.find((entry) => entry.server === interaction.guildId); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } entry.channel_type = channel_type as Type; writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `channel list type set to ${channel_type}`, ephemeral: true, }); } } else if (subcommand === "emojis") { const emoji = interaction.options.getString("emoji", true); const mode = interaction.options.getString("add_remove", true); try { await interaction.deferReply({ ephemeral: true }); let entry = entries.find( (entry) => entry.server === interaction.guildId ); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } if (mode === "add") entry.emojis.push(emoji); else entry.emojis = entry.emojis.filter((e) => e !== emoji); await writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `Set to watch for ${emoji}`, ephemeral: true, }); } } else if (subcommand === "emojis_type") { const emoji_type = interaction.options.getString("emojis_type", true); try { await interaction.deferReply({ ephemeral: true }); let entry = entries.find( (entry) => entry.server === interaction.guildId ); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } entry.emoji_type = emoji_type as Type; writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `emoji list type set to ${emoji_type}`, ephemeral: true, }); } } else if (subcommand === "count") { const count = interaction.options.getInteger("count", true); try { await interaction.deferReply({ ephemeral: true }); let entry = entries.find( (entry) => entry.server === interaction.guildId ); if (!entry) { entry = new Entry(interaction.guildId!); entries.push(entry); } entry.count = count; await writeConfig(entries); } catch (error) { console.error(error); } finally { await interaction.followUp({ content: `The number needed to trigger is now ${count}`, ephemeral: true, }); } } } } }); import awardEmbed from "./award_message.ts"; client.on(Events.MessageReactionAdd, async (reaction, user) => { if (reaction.partial) { try { await reaction.fetch(); } catch (error) { console.error("Something went wrong when fetching the message:", error); return; } } if (!reaction.message.guild) return; const entry = entries.find((entry) => entry.server === reaction.message.guildId); if (entry === undefined) return; if ((entry.channel_type === Type.EXCLUDE) === entry.channels.includes(reaction.message.channelId)) return; if ((entry.emoji_type === Type.EXCLUDE) === entry.emojis.includes(`${reaction.emoji.name}`)) return; console.log(`Reaction added: ${reaction.emoji.name} in ${reaction.message.guild.channels.cache.get(reaction.message.channelId)?.name}`); if (reaction.count === null || reaction.count < entry.count) return; if (reaction.count === entry.count) { const attachments = reaction.message.attachments.filter((attachment) => !(!attachment.height && !attachment.width)) const channel = reaction.message.guild.channels.cache.get(entry.output_channel) as TextChannel; if (!channel) return; channel.send({ embeds: [awardEmbed(reaction)] }); } else if (reaction.count > entry.count) { } }); client.login(TOKEN);