From ece60db183bb1af599c1cb90aa21ceae17d4db9f Mon Sep 17 00:00:00 2001 From: Dakedres Date: Tue, 18 Mar 2025 16:25:11 -0600 Subject: [PATCH] Change tab size --- src/constants.js | 116 ++++---- src/index.js | 698 +++++++++++++++++++++++------------------------ 2 files changed, 407 insertions(+), 407 deletions(-) diff --git a/src/constants.js b/src/constants.js index 00e5338..860f90a 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,65 +1,65 @@ export default { - rollRegex: /^(\d+)?([dhlfb])(\d+)(\s*([+\-*x\/])\s*(\d+))?/, - optionRollRegex: /^(\d+)?(([dhlfb])(\d+))?(\s*([+\-*x\/])\s*(\d+))?/, - descriptionRegex: /\s*((\d*-\d*)|(\d+))?([^;\n]+)/g, - macroNameRegex: /^[a-z0-9]+$/, + rollRegex: /^(\d+)?([dhlfb])(\d+)(\s*([+\-*x\/])\s*(\d+))?/, + optionRollRegex: /^(\d+)?(([dhlfb])(\d+))?(\s*([+\-*x\/])\s*(\d+))?/, + descriptionRegex: /\s*((\d*-\d*)|(\d+))?([^;\n]+)/g, + macroNameRegex: /^[a-z0-9]+$/, - commands: { - about: { - name: 'about', - description: "Get information about dicedicedice" - }, + commands: { + about: { + name: 'about', + description: "Get information about dicedicedice" + }, - macro: { - name: 'macro', - description: "Manage macros", - 'dm_permission': false, - options: [ - { - name: 'add', - description: "Define a dice macro", - type: 1, // Sub command - options: [ - { - name: "name", - description: "Name of the macro", - type: 3, // String - required: true - }, - { - name: "dice", - description: "The dice expression to save as a macro", - type: 3, // String - required: true - } - ] - }, - { - name: 'remove', - description: "Remove a macro", - type: 1, // Sub command - options: [ - { - name: "name", - description: "Name of the macro", - type: 3, // String - required: true, - autocomplete: true, - getAutocomplete: interaction => { - let macros = globalThis.macroCache.get(interaction.guild.id) - - return macros ? Object.keys(macros) : [] - } - } - ] - } - ] - } - }, + macro: { + name: 'macro', + description: "Manage macros", + 'dm_permission': false, + options: [ + { + name: 'add', + description: "Define a dice macro", + type: 1, // Sub command + options: [ + { + name: "name", + description: "Name of the macro", + type: 3, // String + required: true + }, + { + name: "dice", + description: "The dice expression to save as a macro", + type: 3, // String + required: true + } + ] + }, + { + name: 'remove', + description: "Remove a macro", + type: 1, // Sub command + options: [ + { + name: "name", + description: "Name of the macro", + type: 3, // String + required: true, + autocomplete: true, + getAutocomplete: interaction => { + let macros = globalThis.macroCache.get(interaction.guild.id) + + return macros ? Object.keys(macros) : [] + } + } + ] + } + ] + } + }, - iconUrl: 'https://github.com/Dakedres/dicedicedice/raw/main/assets/eater-transparent.png', + iconUrl: 'https://github.com/Dakedres/dicedicedice/raw/main/assets/eater-transparent.png', - errorMessage: error => `\ + errorMessage: error => `\ Something went wrong trying to execute that command. \`\`\`fix ${error.toString()} @@ -67,7 +67,7 @@ ${error.toString()} If this issue persists please report it here: \ `, - aboutMessage: (guildCount) => `\ + aboutMessage: (guildCount) => `\ A discord bot for metaphorically "rolling dice"/generating random values. Made for use with Weaverdice systems. Present in ~${guildCount} guilds! diff --git a/src/index.js b/src/index.js index 1049843..40b8e96 100644 --- a/src/index.js +++ b/src/index.js @@ -11,508 +11,508 @@ globalThis.macroCache = new Map() const db = new ClassicLevel('./db') const client = new Client({ - intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.MessageContent, - GatewayIntentBits.DirectMessages - ], - partials: [ - Partials.Channel - ] + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.MessageContent, + GatewayIntentBits.DirectMessages + ], + partials: [ + Partials.Channel + ] }) const rest = new REST().setToken(process.env.DISCORD_TOKEN) const ParseRollInt = (value, defaultValue) => - value ? parseInt(value) : defaultValue + value ? parseInt(value) : defaultValue const ParseOptionRoll = expression => { - let match = constants.optionRollRegex.exec(expression.trim()) + let match = constants.optionRollRegex.exec(expression.trim()) - let [ - count, - modeSize, - mode, - size, - operationModifier, - operation, - modifier - ] = match - .slice(1) - - return { - count: ParseRollInt(count), - mode, - size: ParseRollInt(size), - operation, - modifier: ParseRollInt(modifier), - descriptionConditions: PullDescription(expression, match) - } + let [ + count, + modeSize, + mode, + size, + operationModifier, + operation, + modifier + ] = match + .slice(1) + + return { + count: ParseRollInt(count), + mode, + size: ParseRollInt(size), + operation, + modifier: ParseRollInt(modifier), + descriptionConditions: PullDescription(expression, match) + } } const ParseRoll = expression => { - let match = constants.rollRegex.exec(expression.trim()) + let match = constants.rollRegex.exec(expression.trim()) - if(match == null) - return + if(match == null) + return - let [ - count, - mode, - size, - modifierString, - operation, - modifier - ] = match.slice(1) + let [ + count, + mode, + size, + modifierString, + operation, + modifier + ] = match.slice(1) - return { - count: ParseRollInt(count, 1), - mode, - size: ParseRollInt(size), - operation, - modifier: ParseRollInt(modifier), - descriptionConditions: PullDescription(expression, match) - } + return { + count: ParseRollInt(count, 1), + mode, + size: ParseRollInt(size), + operation, + modifier: ParseRollInt(modifier), + descriptionConditions: PullDescription(expression, match) + } } const PullDescription = (expression, match) => { - if(match[0].length == expression.length) - return + if(match[0].length == expression.length) + return - return ParseDescription(expression.slice(match[0].length)) + return ParseDescription(expression.slice(match[0].length)) } const ParseDescription = description => { - let conditions = [] - let match + let conditions = [] + let match - while((match = constants.descriptionRegex.exec(description)) !== null) { - let range - let [ - rangeExp, - valueExp, - content - ] = match.slice(2) + while((match = constants.descriptionRegex.exec(description)) !== null) { + let range + let [ + rangeExp, + valueExp, + content + ] = match.slice(2) - if(rangeExp) { - let split = rangeExp.split('-') + if(rangeExp) { + let split = rangeExp.split('-') - range = { - lower: ParseRollInt(split[0], -Infinity), - upper: ParseRollInt(split[1], Infinity) - } - } else if(valueExp) { - range = { - upper: valueExp, - lower: valueExp - } - } + range = { + lower: ParseRollInt(split[0], -Infinity), + upper: ParseRollInt(split[1], Infinity) + } + } else if(valueExp) { + range = { + upper: valueExp, + lower: valueExp + } + } - conditions.push({ - range, - content: content.trim() - }) - } + conditions.push({ + range, + content: content.trim() + }) + } - return conditions + return conditions } const OnMessage = (message, respond) => { - let dice = ParseRoll(message.content) + let dice = ParseRoll(message.content) - if(dice == undefined) - return // No dice + if(dice == undefined) + return // No dice - RollDice(dice, respond) + RollDice(dice, respond) } const RollDice = (dice, respond) => { - if(dice.size > 255) { - respond('That die is way too big... .-.') - return - } else if(dice.size < 2) { - respond('I cannot even fathom a die with that geometry ;-;') - return - } + if(dice.size > 255) { + respond('That die is way too big... .-.') + return + } else if(dice.size < 2) { + respond('I cannot even fathom a die with that geometry ;-;') + return + } - if(dice.count > 100) { - respond('I don\'t have that many dice O_O') - return - } + if(dice.count > 100) { + respond('I don\'t have that many dice O_O') + return + } - let rolls = [ ...crypto.getRandomValues(new Uint8Array(dice.count) ) ] - .map(n => Math.ceil((n / 256) * dice.size)) - let result = 0 - let operationSymbol = dice.operation - let response = '' + let rolls = [ ...crypto.getRandomValues(new Uint8Array(dice.count) ) ] + .map(n => Math.ceil((n / 256) * dice.size)) + let result = 0 + let operationSymbol = dice.operation + let response = '' - switch(dice.mode.toLowerCase()) { - case 'd': - result = rolls.reduce((a, v) => a + v, 0) - break + switch(dice.mode.toLowerCase()) { + case 'd': + result = rolls.reduce((a, v) => a + v, 0) + break - case 'h': - result = rolls.reduce((a, v) => v > a ? v : a, 0) - break + case 'h': + result = rolls.reduce((a, v) => v > a ? v : a, 0) + break - case 'l': - result = rolls.reduce((a, v) => v < a ? v : a, Infinity) - break + case 'l': + result = rolls.reduce((a, v) => v < a ? v : a, Infinity) + break - case 'f': - let pseudoMedian = Math.floor(dice.size / 2) - let resultDistance = -1 + case 'f': + let pseudoMedian = Math.floor(dice.size / 2) + let resultDistance = -1 - for(let roll of rolls) { - let distance = Math.abs(roll - pseudoMedian) + for(let roll of rolls) { + let distance = Math.abs(roll - pseudoMedian) - if(distance > resultDistance) { - result = roll - resultDistance = distance - } - } - break - } + if(distance > resultDistance) { + result = roll + resultDistance = distance + } + } + break + } - switch(dice.operation) { - case '+': - result += dice.modifier - break + switch(dice.operation) { + case '+': + result += dice.modifier + break - case '-': - result -= dice.modifier - break + case '-': + result -= dice.modifier + break - case 'x': - operationSymbol = '*' - case '*': - result = result * dice.modifier - break + case 'x': + operationSymbol = '*' + case '*': + result = result * dice.modifier + break - case '/': - result = result / dice.modifier - break - } + case '/': + result = result / dice.modifier + break + } - if(dice.descriptionConditions) { - for(let { range, content } of dice.descriptionConditions) { - if(!range || result >= range.lower && result <= range.upper) - response += `'${content}', ` - } - } + if(dice.descriptionConditions) { + for(let { range, content } of dice.descriptionConditions) { + if(!range || result >= range.lower && result <= range.upper) + response += `'${content}', ` + } + } - response += `\` ${result} \` \u27F5 [${rolls.join(', ')}] ${dice.count + dice.mode + dice.size}` + response += `\` ${result} \` \u27F5 [${rolls.join(', ')}] ${dice.count + dice.mode + dice.size}` - if(dice.operation) { - response += ' ' + operationSymbol + ' ' + dice.modifier - } + if(dice.operation) { + response += ' ' + operationSymbol + ' ' + dice.modifier + } - respond(response) + respond(response) } const SaveReply = (message, reply) => { - globalThis.replies.set(message.id, { - id: reply.id, - timestamp: Date.now() - }) + globalThis.replies.set(message.id, { + id: reply.id, + timestamp: Date.now() + }) } const MessageCycle = async message => { - OnMessage(message, async content => { - SaveReply(message, await message.reply(content) ) - }) + OnMessage(message, async content => { + SaveReply(message, await message.reply(content) ) + }) } const RehandleMessage = async (message, reply) => { - OnMessage(message, async content => { - SaveReply(message, await reply.edit(content) ) - }) + OnMessage(message, async content => { + SaveReply(message, await reply.edit(content) ) + }) } const PruneReplies = () => { - for(let [ id, entry ] of globalThis.replies.entries()) { - let age = Date.now() - entry.timestamp + for(let [ id, entry ] of globalThis.replies.entries()) { + let age = Date.now() - entry.timestamp - if(age > 1000 * 60 * 3) { - globalThis.replies.delete(id) - } - } + if(age > 1000 * 60 * 3) { + globalThis.replies.delete(id) + } + } } const InteractionRespond = (interaction, content) => { - let reply = { content, ephemeral: true } + let reply = { content, ephemeral: true } - if(interaction.replied || interaction.deferred) { - return interaction.followUp(reply) - } else { - return interaction.reply(reply) - } + if(interaction.replied || interaction.deferred) { + return interaction.followUp(reply) + } else { + return interaction.reply(reply) + } } const ErrorHandler = (interaction) => (error) => - InteractionRespond(interaction, constants.errorMessage(error) ) - .catch(reportingError => console.error('Could not display error message:\n ', reportingError) ) + InteractionRespond(interaction, constants.errorMessage(error) ) + .catch(reportingError => console.error('Could not display error message:\n ', reportingError) ) const Command = (data, callback) => { - globalThis.commands.set(data.name, { - data, - execute: callback - }) + globalThis.commands.set(data.name, { + data, + execute: callback + }) } const Subcommands = (data, subcommandCallbacks) => - Command(data, interaction => { - return subcommandCallbacks[interaction.options.getSubcommand()](interaction) - }) + Command(data, interaction => { + return subcommandCallbacks[interaction.options.getSubcommand()](interaction) + }) const OpenMacros = guildId => - db.sublevel(guildId).sublevel('macros') + db.sublevel(guildId).sublevel('macros') const ReloadMacros = async guildId => { - let commands = [] - let macros = OpenMacros(guildId) - let cacheEntry = {} + let commands = [] + let macros = OpenMacros(guildId) + let cacheEntry = {} - for await (let [ name, dice ] of macros.iterator() ) { - cacheEntry[name] = dice + for await (let [ name, dice ] of macros.iterator() ) { + cacheEntry[name] = dice - commands.push({ - name, - description: Elipsify("Roll " + dice.replaceAll('\n', ';'), 100), - options: [ - { - name: "options", - description: "Dice, modifiers, or descriptions to apply over the macro", - type: 3 - } - ] - }) - } + commands.push({ + name, + description: Elipsify("Roll " + dice.replaceAll('\n', ';'), 100), + options: [ + { + name: "options", + description: "Dice, modifiers, or descriptions to apply over the macro", + type: 3 + } + ] + }) + } - globalThis.macroCache.set(guildId, cacheEntry) + globalThis.macroCache.set(guildId, cacheEntry) - await rest.put( - Routes.applicationGuildCommands(process.env.DISCORD_ID, guildId), - { body: globalThis.commands } - ) - .catch(err => console.error('Failed to reload macros:', err) ) + await rest.put( + Routes.applicationGuildCommands(process.env.DISCORD_ID, guildId), + { body: globalThis.commands } + ) + .catch(err => console.error('Failed to reload macros:', err) ) } const Elipsify = (string, maxLength) => - string.length > maxLength ? string.slice(0, maxLength - 3) + '...' : string + string.length > maxLength ? string.slice(0, maxLength - 3) + '...' : string const PruneDB = async () => { - let validIds = [] + let validIds = [] - for await(let key of db.keys()) { - let [ guildId ] = key.split('!').slice(1) + for await(let key of db.keys()) { + let [ guildId ] = key.split('!').slice(1) - if(validIds.includes(guildId)) - continue + if(validIds.includes(guildId)) + continue - if(client.guilds.cache.has(guildId)) { - validIds.push(guildId) - } else { - await db.del(key) - } - } + if(client.guilds.cache.has(guildId)) { + validIds.push(guildId) + } else { + await db.del(key) + } + } - return validIds + return validIds } const Responses = (interaction, ephemeral) => async content => - interaction.reply({ content, ephemeral }) + interaction.reply({ content, ephemeral }) const Subscribe = (event, callback) => { - client.on(event, (...args) => { - return callback(...args) - .catch(err => console.error(err)) - }) + client.on(event, (...args) => { + return callback(...args) + .catch(err => console.error(err)) + }) } const HandleCommand = async interaction => { - if(globalThis.commands.has(interaction.commandName) ) { - globalThis.commands.get(interaction.commandName).execute(interaction) - .catch(ErrorHandler(interaction)) - return - } + if(globalThis.commands.has(interaction.commandName) ) { + globalThis.commands.get(interaction.commandName).execute(interaction) + .catch(ErrorHandler(interaction)) + return + } - await interaction.deferReply() - let roll = globalThis.macroCache.get(interaction.guild.id)[interaction.commandName] + await interaction.deferReply() + let roll = globalThis.macroCache.get(interaction.guild.id)[interaction.commandName] - if(roll) { - let dice = ParseRoll(roll) - let options = interaction.options.get('options') - - if(options) { - let optionDice = ParseOptionRoll(options.value) + if(roll) { + let dice = ParseRoll(roll) + let options = interaction.options.get('options') + + if(options) { + let optionDice = ParseOptionRoll(options.value) - for(let [ key, value ] of Object.entries(optionDice)) { - if(value) - dice[key] = Array.isArray(value) ? value.concat(dice[key]) : value - } - } + for(let [ key, value ] of Object.entries(optionDice)) { + if(value) + dice[key] = Array.isArray(value) ? value.concat(dice[key]) : value + } + } - RollDice(dice, content => interaction.followUp(content) ) - } + RollDice(dice, content => interaction.followUp(content) ) + } } const FindOption = (options, name) => - options.find(option => option.name == name) + options.find(option => option.name == name) const HandleAutocomplete = async interaction => { - if(globalThis.commands.has(interaction.commandName) ) { - let { data } = globalThis.commands.get(interaction.commandName) - let subcommand = interaction.options.getSubcommand() - let focusedOption = interaction.options.getFocused(true) + if(globalThis.commands.has(interaction.commandName) ) { + let { data } = globalThis.commands.get(interaction.commandName) + let subcommand = interaction.options.getSubcommand() + let focusedOption = interaction.options.getFocused(true) - if(subcommand !== undefined) { - data = FindOption(data.options, subcommand) - } + if(subcommand !== undefined) { + data = FindOption(data.options, subcommand) + } - let option = FindOption(data.options, focusedOption.name) + let option = FindOption(data.options, focusedOption.name) - if(!option) { - console.error('Could not find option: ' + focusedOption) - return - } + if(!option) { + console.error('Could not find option: ' + focusedOption) + return + } - let filtered = option - .getAutocomplete(interaction) - .filter(choice => choice.startsWith(focusedOption.value) ) - .map(choice => ({ name: choice, value: choice }) ) + let filtered = option + .getAutocomplete(interaction) + .filter(choice => choice.startsWith(focusedOption.value) ) + .map(choice => ({ name: choice, value: choice }) ) - await interaction.respond(filtered) - } + await interaction.respond(filtered) + } } const Interaction = interaction => { - if(interaction.isChatInputCommand()) { - return HandleCommand(interaction) - } else if(interaction.isAutocomplete()) { - return HandleAutocomplete(interaction) - .catch(console.error) - } + if(interaction.isChatInputCommand()) { + return HandleCommand(interaction) + } else if(interaction.isAutocomplete()) { + return HandleAutocomplete(interaction) + .catch(console.error) + } } const MessageUpdate = async (oldMessage, newMessage) => { - if(globalThis.replies.has(newMessage.id) ) { - let { id } = globalThis.replies.get(newMessage.id) + if(globalThis.replies.has(newMessage.id) ) { + let { id } = globalThis.replies.get(newMessage.id) - newMessage.channel.messages.fetch(id) - .then(reply => RehandleMessage(newMessage, reply) ) - .catch(err => MessageCycle(newMessage) ) - } else { - MessageCycle(newMessage) - } + newMessage.channel.messages.fetch(id) + .then(reply => RehandleMessage(newMessage, reply) ) + .catch(err => MessageCycle(newMessage) ) + } else { + MessageCycle(newMessage) + } } const About = async (interaction) => { - let embed = { - title: 'dicedicedice', - thumbnail: { - url: constants.iconUrl - }, - description: constants.aboutMessage(client.guilds.cache.size) - } + let embed = { + title: 'dicedicedice', + thumbnail: { + url: constants.iconUrl + }, + description: constants.aboutMessage(client.guilds.cache.size) + } - await interaction.reply({ - embeds: [ embed ], - ephemeral: true - }) + await interaction.reply({ + embeds: [ embed ], + ephemeral: true + }) } const AddMacro = async (interaction) => { - let respond = Responses(interaction, true) - let name = interaction.options.get('name').value.toLowerCase() + let respond = Responses(interaction, true) + let name = interaction.options.get('name').value.toLowerCase() - if(!constants.macroNameRegex.test(name)) - return respond("Please provide a macro name that consists of only alphanumeric characters.") + if(!constants.macroNameRegex.test(name)) + return respond("Please provide a macro name that consists of only alphanumeric characters.") - if(commands.has(name)) - return respond("Uhh,, I think that macro name is already taken by my own commands, sorry.") + if(commands.has(name)) + return respond("Uhh,, I think that macro name is already taken by my own commands, sorry.") - let macros = globalThis.macroCache.get(interaction.guild.id) + let macros = globalThis.macroCache.get(interaction.guild.id) - if(macros && !macros[name] && Object.keys(macros).length >= 100) - return respond("I can't keep track of that many macros,, ;-;") + if(macros && !macros[name] && Object.keys(macros).length >= 100) + return respond("I can't keep track of that many macros,, ;-;") - let dice = interaction.options.get('dice').value + let dice = interaction.options.get('dice').value - if(!constants.rollRegex.test(dice) ) - return respond("Please provide a valid roll expression.") + if(!constants.rollRegex.test(dice) ) + return respond("Please provide a valid roll expression.") - await interaction.deferReply({ ephemeral: true }) + await interaction.deferReply({ ephemeral: true }) - await Promise.all([ - OpenMacros(interaction.guild.id).put(name, dice), - ReloadMacros(interaction.guild.id) - ]) - interaction.followUp(`Macro added! Try \`/${name}\`! You might need to switch to a different server and back or reopen Discord in order for it to recognize the new command.`) + await Promise.all([ + OpenMacros(interaction.guild.id).put(name, dice), + ReloadMacros(interaction.guild.id) + ]) + interaction.followUp(`Macro added! Try \`/${name}\`! You might need to switch to a different server and back or reopen Discord in order for it to recognize the new command.`) } const RemoveMacro = async (interaction) => { - let name = interaction.options.get('name').value.toLowerCase() - let macros = macroCache.get(interaction.guild.id) - let respond = openResponses(interaction, true) - - if(!macros) - return respond('There aren\'t even any macros in this guild!') + let name = interaction.options.get('name').value.toLowerCase() + let macros = macroCache.get(interaction.guild.id) + let respond = openResponses(interaction, true) + + if(!macros) + return respond('There aren\'t even any macros in this guild!') - let dice = macros && macroCache.get(interaction.guild.id)[name] + let dice = macros && macroCache.get(interaction.guild.id)[name] - if(!dice) - return respond("There isn't a macro with that name .-.") + if(!dice) + return respond("There isn't a macro with that name .-.") - await interaction.deferReply({ ephemeral: true }) - await Promise.all([ - openMacros(interaction.guild.id).del(name), - reloadMacros(interaction.guild.id) - ]) + await interaction.deferReply({ ephemeral: true }) + await Promise.all([ + openMacros(interaction.guild.id).del(name), + reloadMacros(interaction.guild.id) + ]) - await interaction.followUp(`Removed \`${name}\`, its dice expression was: \`\`\`${dice}\`\`\``) + await interaction.followUp(`Removed \`${name}\`, its dice expression was: \`\`\`${dice}\`\`\``) } const Start = async () => { - Command( - constants.commands.about, - About - ) + Command( + constants.commands.about, + About + ) - Subcommands(constants.commands.macro, { - add: AddMacro, - remove: RemoveMacro - }) + Subcommands(constants.commands.macro, { + add: AddMacro, + remove: RemoveMacro + }) - Subscribe('interactionCreate', Interaction) - Subscribe('messageCreate', MessageCycle) - Subscribe('messageUpdate', MessageUpdate) - Subscribe('ready', async () => { - console.log("Logged in!") + Subscribe('interactionCreate', Interaction) + Subscribe('messageCreate', MessageCycle) + Subscribe('messageUpdate', MessageUpdate) + Subscribe('ready', async () => { + console.log("Logged in!") - let guildIds = await PruneDB() + let guildIds = await PruneDB() - for(let guildId of guildIds) - await ReloadMacros(guildId) + for(let guildId of guildIds) + await ReloadMacros(guildId) - console.log("Ready") - }) - - await rest.put( - Routes.applicationCommands(process.env.DISCORD_ID), - { - body: [ ...globalThis.commands.values() ] - .map(command => command.data ) - } - ) - .catch(err => console.error('Command registration failed: ', err) ) + console.log("Ready") + }) + + await rest.put( + Routes.applicationCommands(process.env.DISCORD_ID), + { + body: [ ...globalThis.commands.values() ] + .map(command => command.data ) + } + ) + .catch(err => console.error('Command registration failed: ', err) ) - console.log(process.env) + console.log(process.env) - await client.login(process.env.DISCORD_TOKEN) - .catch(err => console.error('Login failed: ', err) ) + await client.login(process.env.DISCORD_TOKEN) + .catch(err => console.error('Login failed: ', err) ) - setInterval(PruneReplies, 1000 * 60) + setInterval(PruneReplies, 1000 * 60) } Start()