From 30547e9d6a14ae14dd4ff8b9ba8529de019daff3 Mon Sep 17 00:00:00 2001 From: Ean Milligan Date: Fri, 25 Apr 2025 22:08:07 -0400 Subject: [PATCH] deno fmt + l!p now sends available presets --- README.md | 2 +- config.example.ts | 50 +++--- mod.ts | 413 +++++++++++++++++++++++++--------------------- 3 files changed, 252 insertions(+), 213 deletions(-) diff --git a/README.md b/README.md index 7fa0a9d..e1e3271 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Logogram Discord Bot - A FFXIV Eureka Utility Bot | V1.1.6 - 2025/09/21 +# Logogram Discord Bot - A FFXIV Eureka Utility Bot | V1.2.0 - 2025/09/21 A Discord bot for Eureka Logos Actions and their recipes. ## Commands diff --git a/config.example.ts b/config.example.ts index fb04c33..f16ea47 100755 --- a/config.example.ts +++ b/config.example.ts @@ -1,29 +1,31 @@ export const config = { - 'name': 'Logogram Bot', // Name of the bot - 'version': '1.1.6', // Version of the bot - 'token': 'the_bot_token', // Discord API Token for this bot - 'localToken': 'local_testing_token', // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token" - 'prefix': 'l!', // Prefix for all commands - 'logChannel': 0n, // Discord channel ID where the bot should put startup messages and other error messages needed - 'reportChannel': 0n, // Discord channel ID where reports will be sent when using the built-in report command - 'devServer': 0n, // Discord guild ID where testing of indev features/commands will be handled, used in conjunction with the DEVMODE bool in mod.ts - 'owner': 0n, // Discord user ID of the bot admin - 'imageUrl': '', // Base URL for logos action images - 'resultsPerPage': 5, // Results to show on each page - 'mneme': { // Emojis for the mnemes - 'blue': '', - 'cyan': '', - 'green': '', - 'purple': '', - 'red': '', - 'yellow': '', + name: 'Logogram Bot', // Name of the bot + version: '1.2.0', // Version of the bot + token: 'the_bot_token', // Discord API Token for this bot + localToken: 'local_testing_token', // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token" + prefix: 'l!', // Prefix for all commands + logChannel: 0n, // Discord channel ID where the bot should put startup messages and other error messages needed + reportChannel: 0n, // Discord channel ID where reports will be sent when using the built-in report command + devServer: 0n, // Discord guild ID where testing of indev features/commands will be handled, used in conjunction with the DEVMODE bool in mod.ts + owner: 0n, // Discord user ID of the bot admin + imageUrl: '', // Base URL for logos action images + resultsPerPage: 5, // Results to show on each page + mneme: { + // Emojis for the mnemes + blue: '', + cyan: '', + green: '', + purple: '', + red: '', + yellow: '', }, - 'jobType': { // Emojis for job type icons - 'tank': '', - 'healer': '', - 'melee': '', - 'ranged': '', - 'magic': '', + jobType: { + // Emojis for job type icons + tank: '', + healer: '', + melee: '', + ranged: '', + magic: '', }, }; diff --git a/mod.ts b/mod.ts index dc7909b..c9cf8be 100755 --- a/mod.ts +++ b/mod.ts @@ -1,17 +1,17 @@ import { - DiscordActivityTypes, - DiscordenoGuild, - DiscordenoMessage, - editBotNickname, - editBotStatus, - // Log4Deno deps - initLog, - Intents, - log, - LT, - sendMessage, - // Discordeno deps - startBot, + DiscordActivityTypes, + DiscordenoGuild, + DiscordenoMessage, + editBotNickname, + editBotStatus, + // Log4Deno deps + initLog, + Intents, + log, + LT, + sendMessage, + // Discordeno deps + startBot, } from './deps.ts'; import { constantCmds } from './src/constantCmds.ts'; @@ -26,189 +26,226 @@ import { classToType } from './src/utils.ts'; initLog('logs', DEBUG); startBot({ - token: LOCALMODE ? config.localToken : config.token, - intents: [Intents.GuildMessages, Intents.DirectMessages, Intents.Guilds], - eventHandlers: { - ready: () => { - editBotStatus({ - activities: [{ - name: 'Booting up . . .', - type: DiscordActivityTypes.Game, - createdAt: new Date().getTime(), - }], - status: 'online', - }); + token: LOCALMODE ? config.localToken : config.token, + intents: [Intents.GuildMessages, Intents.DirectMessages, Intents.Guilds], + eventHandlers: { + ready: () => { + editBotStatus({ + activities: [ + { + name: 'Booting up . . .', + type: DiscordActivityTypes.Game, + createdAt: new Date().getTime(), + }, + ], + status: 'online', + }); - // setTimeout added to make sure the startup message does not error out - setTimeout(() => { - LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`); - editBotStatus({ - activities: [{ - name: 'Booting Complete', - type: DiscordActivityTypes.Game, - createdAt: new Date().getTime(), - }], - status: 'online', - }); - sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); - }); - }, 1000); - }, - guildCreate: (guild: DiscordenoGuild) => { - sendMessage(config.logChannel, `New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); - }); - }, - guildDelete: (guild: DiscordenoGuild) => { - sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); - }); - }, - messageCreate: (message: DiscordenoMessage) => { - // Ignore all other bots - if (message.isBot) return; + // setTimeout added to make sure the startup message does not error out + setTimeout(() => { + LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`); + editBotStatus({ + activities: [ + { + name: 'Booting Complete', + type: DiscordActivityTypes.Game, + createdAt: new Date().getTime(), + }, + ], + status: 'online', + }); + sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); + }); + }, 1000); + }, + guildCreate: (guild: DiscordenoGuild) => { + sendMessage(config.logChannel, `New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); + }); + }, + guildDelete: (guild: DiscordenoGuild) => { + sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); + }); + }, + messageCreate: (message: DiscordenoMessage) => { + // Ignore all other bots + if (message.isBot) return; - // Ignore all messages that are not commands - if (message.content.indexOf(config.prefix) !== 0) return; + // Ignore all messages that are not commands + if (message.content.indexOf(config.prefix) !== 0) return; - // Split into standard command + args format - const args = message.content.slice(config.prefix.length).trim().split(/[ \n]+/g); - const command = args.shift()?.toLowerCase(); + // Split into standard command + args format + const args = message.content + .slice(config.prefix.length) + .trim() + .split(/[ \n]+/g); + const command = args.shift()?.toLowerCase(); - if (command === 'help' || command === 'h' || command === '?') { - // l!help or l!h or l!? - // Help command, prints from help file - message.send(constantCmds.help).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else if (command === 'info' || command === 'i') { - // l!info or l!i - // Info command, prints short desc on bot and some links - message.send(constantCmds.info).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else if (command === 'version' || command === 'v') { - // l!version or l!v - // Returns version of the bot - message.send(constantCmds.version).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else if (command === 'flowchart' || command === 'flow' || command === 'f') { - // l!flowchart or l!flow or l!logos or l!f - // Returns logos actions stuff - message.send(constantCmds.flowchart).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else if (command === 'logograms' || command === 'logogram' || command === 'logos' || command === 'logo' || command === 'l') { - // l!logograms or l!logograms or l!logos or l!logo or l!l - // Returns logos actions stuff - if (!args.length) { - message.send(constantCmds.logogramsNoQuery).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else { - const params = { - class: '', - rawClass: '', - isNin: false, - page: 1, - debug: false, - }; + if (command === 'help' || command === 'h' || command === '?') { + // l!help or l!h or l!? + // Help command, prints from help file + message.send(constantCmds.help).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (command === 'info' || command === 'i') { + // l!info or l!i + // Info command, prints short desc on bot and some links + message.send(constantCmds.info).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (command === 'version' || command === 'v') { + // l!version or l!v + // Returns version of the bot + message.send(constantCmds.version).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (command === 'flowchart' || command === 'flow' || command === 'f') { + // l!flowchart or l!flow or l!logos or l!f + // Returns logos actions stuff + message.send(constantCmds.flowchart).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (command === 'logograms' || command === 'logogram' || command === 'logos' || command === 'logo' || command === 'l') { + // l!logograms or l!logograms or l!logos or l!logo or l!l + // Returns logos actions stuff + if (!args.length) { + message.send(constantCmds.logogramsNoQuery).catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else { + const params = { + class: '', + rawClass: '', + isNin: false, + page: 1, + debug: false, + }; - const classPrefixes = ['-class=', 'class=', '-c=', 'c=']; - const pagePrefixes = ['-page=', 'page=', '-p=', 'p=']; - const debugPrefixes = ['-debug=', 'debug=', '-d=', 'd=']; - const allPrefixes = classPrefixes.concat(pagePrefixes).concat(debugPrefixes); + const classPrefixes = ['-class=', 'class=', '-c=', 'c=']; + const pagePrefixes = ['-page=', 'page=', '-p=', 'p=']; + const debugPrefixes = ['-debug=', 'debug=', '-d=', 'd=']; + const allPrefixes = classPrefixes.concat(pagePrefixes).concat(debugPrefixes); - args.forEach((arg) => { - if (classPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { // - params.rawClass = arg.split('=')[1]; - params.class = classToType(params.rawClass); - params.isNin = params.rawClass.toLowerCase() === 'nin'; - } else if (pagePrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { - params.page = parseInt(arg.split('=')[1]); - } else if (debugPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { - params.debug = true; - } - }); + args.forEach((arg) => { + if (classPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { + // + params.rawClass = arg.split('=')[1]; + params.class = classToType(params.rawClass); + params.isNin = params.rawClass.toLowerCase() === 'nin'; + } else if (pagePrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { + params.page = parseInt(arg.split('=')[1]); + } else if (debugPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { + params.debug = true; + } + }); - const cleanArgs = args.filter((arg) => !(allPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx)))); - const rawQuery = cleanArgs.join(' '); - const query = rawQuery.toLowerCase(); + const cleanArgs = args.filter((arg) => !allPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))); + const rawQuery = cleanArgs.join(' '); + const query = rawQuery.toLowerCase(); - if (data.ActionNames.includes(query)) { - log(LT.LOG, `in name matched '${query}'`); - const singleAction: Array = [data.ActionNames.indexOf(query)]; - message.send({ - content: 'Showing single action:', - embeds: generateEmbeds(singleAction, params.debug), - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else if (query && data.ActionShortNames.includes(query)) { - log(LT.LOG, `in shorthand matched '${query}'`); - const searchResults: Array = data.Actions.filter((action) => action.shorthand === query).map((action) => data.ActionNames.indexOf(action.name.toLowerCase())); - message.send({ - content: searchResults.length > 1 ? `Showing ${searchResults.length} actions:` : 'Showing single action:', - embeds: generateEmbeds(searchResults, params.debug), - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else { - log(LT.LOG, `in general search '${query}'`); - const initialSearchResults: Array = data.ActionNames.filter((action) => action.includes(query)).map((action) => data.ActionNames.indexOf(action)); - const searchResults: Array = initialSearchResults.filter((actionIdx) => - params.class ? (data.Actions[actionIdx].jobs.includes('all-nin') && !params.isNin) || data.Actions[actionIdx].jobs.includes('all') || data.Actions[actionIdx].jobs.includes(params.class) : true - ); + if (data.ActionNames.includes(query)) { + log(LT.LOG, `in name matched '${query}'`); + const singleAction: Array = [data.ActionNames.indexOf(query)]; + message + .send({ + content: 'Showing single action:', + embeds: generateEmbeds(singleAction, params.debug), + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (query && data.ActionShortNames.includes(query)) { + log(LT.LOG, `in shorthand matched '${query}'`); + const searchResults: Array = data.Actions.filter((action) => action.shorthand === query).map((action) => data.ActionNames.indexOf(action.name.toLowerCase())); + message + .send({ + content: searchResults.length > 1 ? `Showing ${searchResults.length} actions:` : 'Showing single action:', + embeds: generateEmbeds(searchResults, params.debug), + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else { + log(LT.LOG, `in general search '${query}'`); + const initialSearchResults: Array = data.ActionNames.filter((action) => action.includes(query)).map((action) => data.ActionNames.indexOf(action)); + const searchResults: Array = initialSearchResults.filter((actionIdx) => + params.class + ? (data.Actions[actionIdx].jobs.includes('all-nin') && !params.isNin) || + data.Actions[actionIdx].jobs.includes('all') || + data.Actions[actionIdx].jobs.includes(params.class) + : true + ); - if (searchResults.length) { - const totalPages = Math.ceil(searchResults.length / config.resultsPerPage); - if (params.page > totalPages) { - params.page = totalPages; - } - const classMessage = params.class ? ` -class=${params.rawClass}` : ''; - const userQuery = `${rawQuery}${classMessage}`.trim(); - const paginationMessage = searchResults.length > config.resultsPerPage - ? `\nShowing page ${params.page} of ${totalPages}\n\nTo see more results, please run \`${config.prefix}logos ${userQuery} -page=#\`, where # is the page number you wish to see.` - : ''; - message.send({ - content: `${searchResults.length} result${searchResults.length > 1 ? 's' : ''} matching query: \`${userQuery}\`${paginationMessage}`, - embeds: generateEmbeds(searchResults.slice((params.page - 1) * config.resultsPerPage, config.resultsPerPage * params.page), params.debug), - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else { - message.send({ - content: `No results found matching query: \`${rawQuery}\``, - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } - } - } - } else if (command === 'preset' || command === 'p') { - // l!preset or l!p - // Returns logos actions stuff - const rawQuery = args.join(' '); - const query = rawQuery.toLowerCase(); + if (searchResults.length) { + const totalPages = Math.ceil(searchResults.length / config.resultsPerPage); + if (params.page > totalPages) { + params.page = totalPages; + } + const classMessage = params.class ? ` -class=${params.rawClass}` : ''; + const userQuery = `${rawQuery}${classMessage}`.trim(); + const paginationMessage = searchResults.length > config.resultsPerPage + ? `\nShowing page ${params.page} of ${totalPages}\n\nTo see more results, please run \`${config.prefix}logos ${userQuery} -page=#\`, where # is the page number you wish to see.` + : ''; + message + .send({ + content: `${searchResults.length} result${searchResults.length > 1 ? 's' : ''} matching query: \`${userQuery}\`${paginationMessage}`, + embeds: generateEmbeds(searchResults.slice((params.page - 1) * config.resultsPerPage, config.resultsPerPage * params.page), params.debug), + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else { + message + .send({ + content: `No results found matching query: \`${rawQuery}\``, + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } + } + } + } else if (command === 'preset' || command === 'p') { + // l!preset or l!p + // Returns logos actions stuff + const rawQuery = args.join(' '); + const query = rawQuery.toLowerCase(); - if (data.Presets.has(query)) { - const preset: Array = data.Presets.get(query) ?? []; - message.send({ - content: `Showing ${rawQuery} Preset:`, - embeds: generateEmbeds(preset, false), - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } else { - message.send({ - content: `No preset found matching query: \`${rawQuery}\``, - }).catch((e) => { - log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); - }); - } - } - }, - }, + if (data.Presets.has(query)) { + const preset: Array = data.Presets.get(query) ?? []; + message + .send({ + content: `Showing ${rawQuery} Preset:`, + embeds: generateEmbeds(preset, false), + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else if (!query) { + message + .send({ + content: `Available presets: ${ + data.Presets.keys() + .toArray() + .map((p) => `\`${p}\``) + .join(', ') + }`, + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } else { + message + .send({ + content: `No preset found matching query: \`${rawQuery}\``, + }) + .catch((e) => { + log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); + }); + } + } + }, + }, });