Compare commits

..

No commits in common. "30547e9d6a14ae14dd4ff8b9ba8529de019daff3" and "0bf818288a3028fd36c267a93cf7bc75c28a0ed5" have entirely different histories.

6 changed files with 303 additions and 328 deletions

View File

@ -1,4 +1,4 @@
# Logogram Discord Bot - A FFXIV Eureka Utility Bot | V1.2.0 - 2025/09/21 # Logogram Discord Bot - A FFXIV Eureka Utility Bot | V1.1.6 - 2025/09/21
A Discord bot for Eureka Logos Actions and their recipes. A Discord bot for Eureka Logos Actions and their recipes.
## Commands ## Commands

View File

@ -1,31 +1,29 @@
export const config = { export const config = {
name: 'Logogram Bot', // Name of the bot 'name': 'Logogram Bot', // Name of the bot
version: '1.2.0', // Version of the bot 'version': '1.1.6', // Version of the bot
token: 'the_bot_token', // Discord API Token for this 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" '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 'prefix': 'l!', // Prefix for all commands
logChannel: 0n, // Discord channel ID where the bot should put startup messages and other error messages needed '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 '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 '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 'owner': 0n, // Discord user ID of the bot admin
imageUrl: '', // Base URL for logos action images 'imageUrl': '', // Base URL for logos action images
resultsPerPage: 5, // Results to show on each page 'resultsPerPage': 5, // Results to show on each page
mneme: { 'mneme': { // Emojis for the mnemes
// Emojis for the mnemes 'blue': '',
blue: '', 'cyan': '',
cyan: '', 'green': '',
green: '', 'purple': '',
purple: '', 'red': '',
red: '', 'yellow': '',
yellow: '',
}, },
jobType: { 'jobType': { // Emojis for job type icons
// Emojis for job type icons 'tank': '',
tank: '', 'healer': '',
healer: '', 'melee': '',
melee: '', 'ranged': '',
ranged: '', 'magic': '',
magic: '',
}, },
}; };

View File

@ -1,11 +1,14 @@
{ {
"compilerOptions": { "compilerOptions": {
"allowJs": true,
"lib": ["deno.worker"], "lib": ["deno.worker"],
"strict": true "strict": true
}, },
"lint": { "lint": {
"files": {
"include": ["src/", "db/", "mod.ts", "deps.ts", "config.ts", "config.example.ts"], "include": ["src/", "db/", "mod.ts", "deps.ts", "config.ts", "config.example.ts"],
"exclude": [], "exclude": []
},
"rules": { "rules": {
"tags": ["recommended"], "tags": ["recommended"],
"include": ["ban-untagged-todo"], "include": ["ban-untagged-todo"],
@ -13,12 +16,16 @@
} }
}, },
"fmt": { "fmt": {
"files": {
"include": ["src/", "db/", "mod.ts", "deps.ts", "config.ts", "config.example.ts"], "include": ["src/", "db/", "mod.ts", "deps.ts", "config.ts", "config.example.ts"],
"exclude": [], "exclude": []
"useTabs": false, },
"options": {
"useTabs": true,
"lineWidth": 250, "lineWidth": 250,
"indentWidth": 2, "indentWidth": 2,
"singleQuote": true, "singleQuote": true,
"proseWrap": "preserve" "proseWrap": "preserve"
} }
}
} }

11
deps.ts
View File

@ -1,5 +1,12 @@
export { cache, cacheHandlers, DiscordActivityTypes, editBotNickname, editBotStatus, Intents, sendMessage, startBot } from 'https://deno.land/x/discordeno@12.0.1/mod.ts'; export {
startBot, editBotStatus, editBotNickname,
sendMessage,
Intents, DiscordActivityTypes,
cache, cacheHandlers
} from "https://deno.land/x/discordeno@12.0.1/mod.ts";
export type { DiscordenoGuild, DiscordenoMessage, Embed } from 'https://deno.land/x/discordeno@12.0.1/mod.ts'; export type {
DiscordenoMessage, DiscordenoGuild, Embed
} from "https://deno.land/x/discordeno@12.0.1/mod.ts";
export { initLog, log, LogTypes as LT } from 'https://raw.githubusercontent.com/Burn-E99/Log4Deno/V1.1.1/mod.ts'; export { initLog, log, LogTypes as LT } from 'https://raw.githubusercontent.com/Burn-E99/Log4Deno/V1.1.1/mod.ts';

77
mod.ts
View File

@ -31,13 +31,11 @@ startBot({
eventHandlers: { eventHandlers: {
ready: () => { ready: () => {
editBotStatus({ editBotStatus({
activities: [ activities: [{
{
name: 'Booting up . . .', name: 'Booting up . . .',
type: DiscordActivityTypes.Game, type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(), createdAt: new Date().getTime(),
}, }],
],
status: 'online', status: 'online',
}); });
@ -45,13 +43,11 @@ startBot({
setTimeout(() => { setTimeout(() => {
LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`); LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`);
editBotStatus({ editBotStatus({
activities: [ activities: [{
{
name: 'Booting Complete', name: 'Booting Complete',
type: DiscordActivityTypes.Game, type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(), createdAt: new Date().getTime(),
}, }],
],
status: 'online', status: 'online',
}); });
sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch((e) => { sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch((e) => {
@ -77,10 +73,7 @@ startBot({
if (message.content.indexOf(config.prefix) !== 0) return; if (message.content.indexOf(config.prefix) !== 0) return;
// Split into standard command + args format // Split into standard command + args format
const args = message.content const args = message.content.slice(config.prefix.length).trim().split(/[ \n]+/g);
.slice(config.prefix.length)
.trim()
.split(/[ \n]+/g);
const command = args.shift()?.toLowerCase(); const command = args.shift()?.toLowerCase();
if (command === 'help' || command === 'h' || command === '?') { if (command === 'help' || command === 'h' || command === '?') {
@ -129,8 +122,7 @@ startBot({
const allPrefixes = classPrefixes.concat(pagePrefixes).concat(debugPrefixes); const allPrefixes = classPrefixes.concat(pagePrefixes).concat(debugPrefixes);
args.forEach((arg) => { args.forEach((arg) => {
if (classPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { if (classPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))) { //
//
params.rawClass = arg.split('=')[1]; params.rawClass = arg.split('=')[1];
params.class = classToType(params.rawClass); params.class = classToType(params.rawClass);
params.isNin = params.rawClass.toLowerCase() === 'nin'; params.isNin = params.rawClass.toLowerCase() === 'nin';
@ -141,41 +133,33 @@ startBot({
} }
}); });
const cleanArgs = args.filter((arg) => !allPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))); const cleanArgs = args.filter((arg) => !(allPrefixes.some((pfx) => arg.toLowerCase().startsWith(pfx))));
const rawQuery = cleanArgs.join(' '); const rawQuery = cleanArgs.join(' ');
const query = rawQuery.toLowerCase(); const query = rawQuery.toLowerCase();
if (data.ActionNames.includes(query)) { if (data.ActionNames.includes(query)) {
log(LT.LOG, `in name matched '${query}'`); log(LT.LOG, `in name matched '${query}'`);
const singleAction: Array<number> = [data.ActionNames.indexOf(query)]; const singleAction: Array<number> = [data.ActionNames.indexOf(query)];
message message.send({
.send({
content: 'Showing single action:', content: 'Showing single action:',
embeds: generateEmbeds(singleAction, params.debug), embeds: generateEmbeds(singleAction, params.debug),
}) }).catch((e) => {
.catch((e) => {
log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} else if (query && data.ActionShortNames.includes(query)) { } else if (query && data.ActionShortNames.includes(query)) {
log(LT.LOG, `in shorthand matched '${query}'`); log(LT.LOG, `in shorthand matched '${query}'`);
const searchResults: Array<number> = data.Actions.filter((action) => action.shorthand === query).map((action) => data.ActionNames.indexOf(action.name.toLowerCase())); const searchResults: Array<number> = data.Actions.filter((action) => action.shorthand === query).map((action) => data.ActionNames.indexOf(action.name.toLowerCase()));
message message.send({
.send({
content: searchResults.length > 1 ? `Showing ${searchResults.length} actions:` : 'Showing single action:', content: searchResults.length > 1 ? `Showing ${searchResults.length} actions:` : 'Showing single action:',
embeds: generateEmbeds(searchResults, params.debug), embeds: generateEmbeds(searchResults, params.debug),
}) }).catch((e) => {
.catch((e) => {
log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} else { } else {
log(LT.LOG, `in general search '${query}'`); log(LT.LOG, `in general search '${query}'`);
const initialSearchResults: Array<number> = data.ActionNames.filter((action) => action.includes(query)).map((action) => data.ActionNames.indexOf(action)); const initialSearchResults: Array<number> = data.ActionNames.filter((action) => action.includes(query)).map((action) => data.ActionNames.indexOf(action));
const searchResults: Array<number> = initialSearchResults.filter((actionIdx) => const searchResults: Array<number> = initialSearchResults.filter((actionIdx) =>
params.class 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
? (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) { if (searchResults.length) {
@ -188,20 +172,16 @@ startBot({
const paginationMessage = searchResults.length > config.resultsPerPage 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.` ? `\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 message.send({
.send({
content: `${searchResults.length} result${searchResults.length > 1 ? 's' : ''} matching query: \`${userQuery}\`${paginationMessage}`, 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), embeds: generateEmbeds(searchResults.slice((params.page - 1) * config.resultsPerPage, config.resultsPerPage * params.page), params.debug),
}) }).catch((e) => {
.catch((e) => {
log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} else { } else {
message message.send({
.send({
content: `No results found matching query: \`${rawQuery}\``, content: `No results found matching query: \`${rawQuery}\``,
}) }).catch((e) => {
.catch((e) => {
log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -215,33 +195,16 @@ startBot({
if (data.Presets.has(query)) { if (data.Presets.has(query)) {
const preset: Array<number> = data.Presets.get(query) ?? []; const preset: Array<number> = data.Presets.get(query) ?? [];
message message.send({
.send({
content: `Showing ${rawQuery} Preset:`, content: `Showing ${rawQuery} Preset:`,
embeds: generateEmbeds(preset, false), embeds: generateEmbeds(preset, false),
}) }).catch((e) => {
.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)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} else { } else {
message message.send({
.send({
content: `No preset found matching query: \`${rawQuery}\``, content: `No preset found matching query: \`${rawQuery}\``,
}) }).catch((e) => {
.catch((e) => {
log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }