diff --git a/commands/utility/api.js b/commands/utility/api.js new file mode 100644 index 0000000..527a589 --- /dev/null +++ b/commands/utility/api.js @@ -0,0 +1,17 @@ +const { SlashCommandBuilder } = require('discord.js'); +const torn = require('../../torn.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('api') + .setDescription('Directly request the Torn API') + .addStringOption(option => + option.setName('url') + .setDescription('Full URL excluding API key')), + async execute(interaction) { + const url = interaction.options.getString('url'); + const res = await torn.api(url) + console.log(JSON.stringify(res)) + await interaction.reply("```json\n" + JSON.stringify(res) + "\n```"); + }, +}; \ No newline at end of file diff --git a/commands/utility/task.js b/commands/utility/task.js new file mode 100644 index 0000000..fd3433b --- /dev/null +++ b/commands/utility/task.js @@ -0,0 +1,10 @@ +const { SlashCommandBuilder } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('task') + .setDescription('Execute a task.'), + async execute(interaction) { + await interaction.reply('todo'); + }, +}; \ No newline at end of file diff --git a/commands/utility/tasks.js b/commands/utility/tasks.js new file mode 100644 index 0000000..5b03c7b --- /dev/null +++ b/commands/utility/tasks.js @@ -0,0 +1,11 @@ +const { SlashCommandBuilder } = require('discord.js'); +const torn = require('../../torn.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('tasks') + .setDescription('List tasks'), + async execute(interaction) { + await interaction.reply('todo'); + }, +}; \ No newline at end of file diff --git a/commands/utility/test.js b/commands/utility/test.js new file mode 100644 index 0000000..df52d6a --- /dev/null +++ b/commands/utility/test.js @@ -0,0 +1,11 @@ +const { SlashCommandBuilder } = require('discord.js'); +const torn = require('../../torn.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('test') + .setDescription('Test the Torn API'), + async execute(interaction) { + await interaction.reply(await torn.test()); + }, +}; \ No newline at end of file diff --git a/deploy-commands.js b/deploy-commands.js new file mode 100644 index 0000000..6991249 --- /dev/null +++ b/deploy-commands.js @@ -0,0 +1,48 @@ +// yoinked right from the guide + +const { REST, Routes } = require('discord.js'); +const { client, guildId, token } = require('./config.json'); +const fs = require('node:fs'); +const path = require('node:path'); + +const commands = []; +// Grab all the command folders from the commands directory you created earlier +const foldersPath = path.join(__dirname, 'commands'); +const commandFolders = fs.readdirSync(foldersPath); + +for (const folder of commandFolders) { + // Grab all the command files from the commands directory you created earlier + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + commands.push(command.data.toJSON()); + } else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } +} + +// Construct and prepare an instance of the REST module +const rest = new REST().setToken(token); + +// and deploy your commands! +(async () => { + try { + console.log(`Started refreshing ${commands.length} application (/) commands.`); + + // The put method is used to fully refresh all commands in the guild with the current set + const data = await rest.put( + Routes.applicationCommands(client), + { body: commands }, + ); + + console.log(`Successfully reloaded ${data.length} application (/) commands.`); + } catch (error) { + // And of course, make sure you catch and log any errors! + console.error(error); + } +})(); \ No newline at end of file diff --git a/index.js b/index.js index cb76477..b94eed5 100644 --- a/index.js +++ b/index.js @@ -1,33 +1,69 @@ -// Require the necessary discord.js classes -const { Client, Events, GatewayIntentBits } = require('discord.js'); const cron = require('node-cron'); const fs = require('fs'); +const path = require('node:path'); const torn = require('./torn.js'); const config = require('./config.json'); const state = require('./state.json'); -// Create a new client instance +// the basic discord setup stuff yoinked from their guide +const { Client, Collection, Events, GatewayIntentBits, SlashCommandBuilder } = require('discord.js'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); - -// When the client is ready, run this code (only once). -// The distinction between `client: Client` and `readyClient: Client` is important for TypeScript developers. -// It makes some properties non-nullable. client.once(Events.ClientReady, readyClient => { console.log(`Connected to Discord as ${readyClient.user.tag}`); }); +client.login(config.token); +client.commands = new Collection(); torn.readyCheck(config.torn); -// Log in to Discord with your client's token -client.login(config.token); -let task +let task = {}; fs.readdir('./tasks/', (err, files) => { if (err) return console.log(err); files.forEach(file => { - const task = require(`./tasks/${file}`); - const taskName = file.split('.')[0]; - console.log(`Scheduling task "${taskName}" for ${task.schedule}`); - cron.schedule(task.schedule, () => { task(client, torn, config, state); }); + const taskFile = require(`./tasks/${file}`); + const taskName = file.split('.')[0]; + task[taskName] = taskFile; + if (taskFile.schedule) { + console.log(`Scheduling task "${taskName}" for ${taskFile.schedule}`); + cron.schedule(taskFile.schedule, () => { taskFile(client, torn, config, state); }); + } else { + console.log(`Registered task "${taskName}"`); + } }); - }); +}); + +// discord command stuff also yoinked +const foldersPath = path.join(__dirname, 'commands'); +const commandFolders = fs.readdirSync(foldersPath); + for (const folder of commandFolders) { + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + client.commands.set(command.data.name, command); + } else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } +} + +client.on(Events.InteractionCreate, async interaction => { + if (!interaction.isChatInputCommand()) return; + const command = interaction.client.commands.get(interaction.commandName); + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } try { + await command.execute(interaction); + } catch (error) { + console.error(error); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } else { + await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral }); + } + } +}); diff --git a/tasks/example2.js b/tasks/example2.js new file mode 100644 index 0000000..402a43a --- /dev/null +++ b/tasks/example2.js @@ -0,0 +1,3 @@ +module.exports = (client, config, state) => { + //console.log(`example log ${client.user.tag}`); +}; \ No newline at end of file diff --git a/torn.js b/torn.js index 594a4e7..3338686 100644 --- a/torn.js +++ b/torn.js @@ -1,3 +1,4 @@ +const config = require('./config') module.exports = (client, torn, config, state) => { //console.log(`example log ${client.user.tag}`); }; @@ -6,4 +7,15 @@ module.exports.readyCheck = async (key) => { const response = await fetch(url); const data = await response.json(); console.log(`Connected to Torn as ${data.name} [${data.player_id}]`); - }; \ No newline at end of file +}; +module.exports.test = async () => { + const url = `https://api.torn.com/user/?selections=basic&key=${config.torn}` + const response = await fetch(url); + const data = await response.json(); + return(`Connected to Torn as ${data.name} [${data.player_id}]`); +}; +module.exports.api = async (url) => { + const response = await fetch(`${url}&key=${config.torn}`); + const data = await response.json(); + return(data); +}; \ No newline at end of file