discord-reaction-award/src/index.ts
2024-10-20 03:45:32 +09:00

225 lines
7.4 KiB
TypeScript

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);