diff --git a/.sonarcloud.properties b/.sonarcloud.properties index e264b04..7012155 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -12,6 +12,6 @@ sonar.exclusions=emojis sonar.sourceEncoding=UTF-8 # Exclusions for copy-paste detection -# src/constantCmds.ts is excluded to get rid of the duplicate code compliant. Sonar does not like you initializing JSON in ts files. +# src/commandUtils.ts is excluded to get rid of the duplicate code compliant. Sonar does not like you initializing JSON in ts files. # db/initialize.ts, db/populateDefaults.ts are excluded to get rid of some duplicate code compliants. Sonar does not like the repeated DB calls even when they are unique calls. -sonar.cpd.exclusions=src/constantCmds.ts,db/initialize.ts,db/populateDefaults.ts \ No newline at end of file +sonar.cpd.exclusions=src/commandUtils.ts,db/initialize.ts,db/populateDefaults.ts \ No newline at end of file diff --git a/src/api.ts b/src/api.ts index fdd8d76..0f54cd3 100644 --- a/src/api.ts +++ b/src/api.ts @@ -23,7 +23,7 @@ import { import { RollModifiers } from './mod.d.ts'; import { dbClient, queries } from './db.ts'; import solver from './solver/_index.ts'; -import { generateApiDeleteEmail, generateApiKeyEmail, generateDMFailed } from './constantCmds.ts'; +import { generateApiDeleteEmail, generateApiKeyEmail, generateDMFailed } from './commandUtils.ts'; import config from '../config.ts'; diff --git a/src/commandUtils.ts b/src/commandUtils.ts new file mode 100644 index 0000000..a401882 --- /dev/null +++ b/src/commandUtils.ts @@ -0,0 +1,303 @@ +import config from '../config.ts'; +import { CountDetails, SolvedRoll } from './solver/solver.d.ts'; +import { RollModifiers } from './mod.d.ts'; + +export const failColor = 0xe71212; +export const warnColor = 0xe38f28; +export const successColor = 0x0f8108; +export const infoColor1 = 0x313bf9; +export const infoColor2 = 0x6805e9; + +export const generatePing = (time: number) => ({ + embeds: [{ + color: infoColor1, + title: time === -1 ? 'Ping?' : `Pong! Latency is ${time}ms.`, + }], +}); + +export const generateReport = (msg: string) => ({ + embeds: [{ + color: infoColor2, + title: 'USER REPORT:', + description: msg || 'No message', + }], +}); + +export const generateStats = (guildCount: number, channelCount: number, memberCount: number, rollCount: bigint, utilityCount: bigint) => ({ + embeds: [{ + color: infoColor2, + title: 'The Artificer\'s Statistics:', + fields: [ + { + name: 'Guilds:', + value: `${guildCount}`, + inline: true, + }, + { + name: 'Channels:', + value: `${channelCount}`, + inline: true, + }, + { + name: 'Active Members:', + value: `${memberCount}`, + inline: true, + }, + { + name: 'Roll Commands:', + value: `${rollCount}`, + inline: true, + }, + { + name: 'Utility Commands:', + value: `${utilityCount}`, + inline: true, + }, + ], + }], +}); + +export const generateApiFailed = (args: string) => ({ + embeds: [{ + color: failColor, + title: `Failed to ${args} API rolls for this guild.`, + description: 'If this issue persists, please report this to the developers.', + }], +}); + +export const generateApiStatus = (banned: boolean, active: boolean) => { + const apiStatus = active ? 'allowed' : 'blocked from being used'; + return { + embeds: [{ + color: infoColor1, + title: `The Artificer's API is ${config.api.enable ? 'currently enabled' : 'currently disabled'}.`, + description: banned ? 'API rolls are banned from being used in this guild.\n\nThis will not be reversed.' : `API rolls are ${apiStatus} in this guild.`, + }], + }; +}; + +export const generateApiSuccess = (args: string) => ({ + embeds: [{ + color: successColor, + title: `API rolls have successfully been ${args} for this guild.`, + }], +}); + +export const generateDMFailed = (user: string) => ({ + embeds: [{ + color: failColor, + title: `WARNING: ${user} could not be messaged.`, + description: 'If this issue persists, make sure direct messages are allowed from this server.', + }], +}); + +export const generateApiKeyEmail = (email: string, key: string) => ({ + content: `<@${config.api.admin}> A USER HAS REQUESTED AN API KEY`, + embeds: [{ + color: infoColor1, + fields: [ + { + name: 'Send to:', + value: email, + }, + { + name: 'Subject:', + value: 'Artificer API Key', + }, + { + name: 'Body:', + value: `Hello Artificer API User, + +Welcome aboard The Artificer's API. You can find full details about the API on the GitHub: https://github.com/Burn-E99/TheArtificer + +Your API Key is: ${key} + +Guard this well, as there is zero tolerance for API abuse. + +Welcome aboard, +The Artificer Developer - Ean Milligan`, + }, + ], + }], +}); + +export const generateApiDeleteEmail = (email: string, deleteCode: string) => ({ + content: `<@${config.api.admin}> A USER HAS REQUESTED A DELETE CODE`, + embeds: [{ + color: infoColor1, + fields: [ + { + name: 'Send to:', + value: email, + }, + { + name: 'Subject:', + value: 'Artificer API Delete Code', + }, + { + name: 'Body:', + value: `Hello Artificer API User, + +I am sorry to see you go. If you would like, please respond to this email detailing what I could have done better. + +As requested, here is your delete code: ${deleteCode} + +Sorry to see you go, +The Artificer Developer - Ean Milligan`, + }, + ], + }], +}); + +export const generateRollError = (errorType: string, errorMsg: string) => ({ + embeds: [{ + color: failColor, + title: 'Roll command encountered the following error:', + fields: [{ + name: errorType, + value: `${errorMsg}\n\nPlease try again. If the error is repeated, please report the issue using the \`${config.prefix}report\` command.`, + }], + }], +}); + +export const generateCountDetailsEmbed = (counts: CountDetails) => ({ + color: infoColor1, + title: 'Roll Count Details:', + fields: [ + { + name: 'Total Rolls:', + value: `${counts.total}`, + inline: true, + }, + { + name: 'Successful Rolls:', + value: `${counts.successful}`, + inline: true, + }, + { + name: 'Failed Rolls:', + value: `${counts.failed}`, + inline: true, + }, + { + name: 'Rerolled Dice:', + value: `${counts.rerolled}`, + inline: true, + }, + { + name: 'Dropped Dice:', + value: `${counts.dropped}`, + inline: true, + }, + { + name: 'Exploded Dice:', + value: `${counts.exploded}`, + inline: true, + }, + ], +}); + +export const generateRollEmbed = async (authorId: bigint, returnDetails: SolvedRoll, modifiers: RollModifiers) => { + if (returnDetails.error) { + // Roll had an error, send error embed + return { + embed: { + color: failColor, + title: 'Roll failed:', + description: `${returnDetails.errorMsg}`, + }, + hasAttachment: false, + attachment: { + 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), + 'name': 'rollDetails.txt', + }, + }; + } else { + if (modifiers.gmRoll) { + // Roll is a GM Roll, send this in the pub channel (this funciton will be ran again to get details for the GMs) + return { + embed: { + color: infoColor2, + description: `<@${authorId}>${returnDetails.line1} + +Results have been messaged to the following GMs: ${modifiers.gms.join(' ')}`, + }, + hasAttachment: false, + attachment: { + 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), + 'name': 'rollDetails.txt', + }, + }; + } else { + // Roll is normal, make normal embed + const line2Details = returnDetails.line2.split(': '); + let details = ''; + + if (!modifiers.superNoDetails) { + if (modifiers.noDetails) { + details = `**Details:** +Suppressed by -nd flag`; + } else { + details = `**Details:** +${modifiers.spoiler}${returnDetails.line3}${modifiers.spoiler}`; + } + } + + const baseDesc = `<@${authorId}>${returnDetails.line1} +**${line2Details.shift()}:** +${line2Details.join(': ')}`; + + if (baseDesc.length + details.length < 4090) { + return { + embed: { + color: infoColor2, + description: `${baseDesc} + +${details}`, + }, + hasAttachment: false, + attachment: { + 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), + 'name': 'rollDetails.txt', + }, + }; + } else { + // If its too big, collapse it into a .txt file and send that instead. + const b = await new Blob([`${baseDesc}\n\n${details}` as BlobPart], { 'type': 'text' }); + details = 'Details have been ommitted from this message for being over 2000 characters.'; + if (b.size > 8388290) { + details += + 'Full details could not be attached to this messaged as a \`.txt\` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one.'; + return { + embed: { + color: infoColor2, + description: `${baseDesc} + + ${details}`, + }, + hasAttachment: false, + attachment: { + 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), + 'name': 'rollDetails.txt', + }, + }; + } else { + details += 'Full details have been attached to this messaged as a \`.txt\` file for verification purposes.'; + return { + embed: { + color: infoColor2, + description: `${baseDesc} + +${details}`, + }, + hasAttachment: true, + attachment: { + 'blob': b, + 'name': 'rollDetails.txt', + }, + }; + } + } + } + } +}; diff --git a/src/commands/apiCmd.ts b/src/commands/apiCmd.ts index 78d4cdb..afe3285 100644 --- a/src/commands/apiCmd.ts +++ b/src/commands/apiCmd.ts @@ -8,7 +8,7 @@ import { LT, } from '../../deps.ts'; import apiCommands from './apiCmd/_index.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { failColor } from '../commandUtils.ts'; export const api = async (message: DiscordenoMessage, args: string[]) => { // Light telemetry to see how many times a command is being run @@ -21,7 +21,12 @@ export const api = async (message: DiscordenoMessage, args: string[]) => { // Alert users who DM the bot that this command is for guilds only if (message.guildId === 0n) { - message.send(constantCmds.apiGuildOnly).catch((e) => { + message.send({ + embeds: [{ + color: failColor, + title: 'API commands are only available in guilds.', + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); return; @@ -51,7 +56,13 @@ export const api = async (message: DiscordenoMessage, args: string[]) => { apiCommands.showHideWarn(message, apiArg); } } else { - message.send(constantCmds.apiPermError).catch((e) => { + message.send({ + embeds: [{ + color: failColor, + title: 'API commands are powerful and can only be used by guild Owners and Admins.', + description: 'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).', + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); } diff --git a/src/commands/apiCmd/allowBlock.ts b/src/commands/apiCmd/allowBlock.ts index 20d47e8..120fc6f 100644 --- a/src/commands/apiCmd/allowBlock.ts +++ b/src/commands/apiCmd/allowBlock.ts @@ -6,7 +6,7 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { generateApiFailed, generateApiSuccess } from '../../constantCmds.ts'; +import { generateApiFailed, generateApiSuccess } from '../../commandUtils.ts'; export const allowBlock = async (message: DiscordenoMessage, apiArg: string) => { let errorOutInitial = false; diff --git a/src/commands/apiCmd/apiHelp.ts b/src/commands/apiCmd/apiHelp.ts index 3cc2e7e..16060eb 100644 --- a/src/commands/apiCmd/apiHelp.ts +++ b/src/commands/apiCmd/apiHelp.ts @@ -1,3 +1,4 @@ +import config from '../../../config.ts'; import { // Discordeno deps DiscordenoMessage, @@ -5,10 +6,64 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { constantCmds } from '../../constantCmds.ts'; +import { infoColor1, infoColor2 } from '../../commandUtils.ts'; export const help = (message: DiscordenoMessage) => { - message.send(constantCmds.apiHelp).catch((e) => { + message.send({ + embeds: [ + { + color: infoColor2, + title: 'The Artificer\'s API Details:', + description: + `The Artificer has a built in API that allows user to roll dice into Discord using third party programs. By default, API rolls are blocked from being sent in your guild. The API warning is also enabled by default. These commands may only be used by the Owner or Admins of your guild. + +For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer). + +You may enable and disable the API rolls for your guild as needed.`, + }, + { + color: infoColor1, + title: 'Available API Commands:', + fields: [ + { + name: `\`${config.prefix}api help\``, + value: 'This command', + inline: true, + }, + { + name: `\`${config.prefix}api status\``, + value: 'Shows the current status of the API for the channel this was run in', + inline: true, + }, + { + name: `\`${config.prefix}api allow/enable\``, + value: 'Allows API Rolls to be sent to the channel this was run in', + inline: true, + }, + { + name: `\`${config.prefix}api block/disable\``, + value: 'Blocks API Rolls from being sent to the channel this was run in', + inline: true, + }, + { + name: `\`${config.prefix}api delete\``, + value: 'Deletes this channel\'s settings from The Artificer\'s database', + inline: true, + }, + { + name: `\`${config.prefix}api show-warn\``, + value: 'Shows the API warning on all rolls sent to the channel this was run in', + inline: true, + }, + { + name: `\`${config.prefix}api hide-warn\``, + value: 'Hides the API warning on all rolls sent to the channel this was run in', + inline: true, + }, + ], + }, + ], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/apiCmd/deleteGuild.ts b/src/commands/apiCmd/deleteGuild.ts index bb0e5af..46056c9 100644 --- a/src/commands/apiCmd/deleteGuild.ts +++ b/src/commands/apiCmd/deleteGuild.ts @@ -6,13 +6,19 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { constantCmds } from '../../constantCmds.ts'; +import { failColor, successColor } from '../../commandUtils.ts'; export const deleteGuild = async (message: DiscordenoMessage) => { let errorOut = false; await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`); - message.send(constantCmds.apiDeleteFail).catch((e1) => { + message.send({ + embeds: [{ + color: failColor, + title: 'Failed to delete this guild from the database.', + description: 'If this issue persists, please report this to the developers.', + }], + }).catch((e1) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); }); errorOut = true; @@ -20,7 +26,12 @@ export const deleteGuild = async (message: DiscordenoMessage) => { if (errorOut) return; // We won't get here if there's any errors, so we know it has bee successful, so report as such - message.send(constantCmds.apiRemoveGuild).catch((e) => { + message.send({ + embeds: [{ + color: successColor, + title: 'This guild\'s API setting has been removed from The Artifier\'s Database.', + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/apiCmd/showHideWarn.ts b/src/commands/apiCmd/showHideWarn.ts index c0c087f..c7ff01e 100644 --- a/src/commands/apiCmd/showHideWarn.ts +++ b/src/commands/apiCmd/showHideWarn.ts @@ -6,7 +6,7 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { generateApiFailed, generateApiSuccess } from '../../constantCmds.ts'; +import { generateApiFailed, generateApiSuccess } from '../../commandUtils.ts'; export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) => { let errorOutInitial = false; diff --git a/src/commands/apiCmd/status.ts b/src/commands/apiCmd/status.ts index f999795..940ffb2 100644 --- a/src/commands/apiCmd/status.ts +++ b/src/commands/apiCmd/status.ts @@ -6,14 +6,20 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { constantCmds, generateApiStatus } from '../../constantCmds.ts'; +import { failColor, generateApiStatus } from '../../commandUtils.ts'; export const status = async (message: DiscordenoMessage) => { // Get status of guild from the db let errorOut = false; const guildQuery = await dbClient.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`); - message.send(constantCmds.apiStatusFail).catch((e1) => { + message.send({ + embeds: [{ + color: failColor, + title: 'Failed to check API rolls status for this guild.', + description: 'If this issue persists, please report this to the developers.', + }], + }).catch((e1) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); }); errorOut = true; diff --git a/src/commands/handleMentions.ts b/src/commands/handleMentions.ts index dab70e7..ab2deb2 100644 --- a/src/commands/handleMentions.ts +++ b/src/commands/handleMentions.ts @@ -1,3 +1,4 @@ +import config from '../../config.ts'; import { dbClient } from '../db.ts'; import { // Discordeno deps @@ -6,7 +7,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor1 } from '../commandUtils.ts'; export const handleMentions = (message: DiscordenoMessage) => { log(LT.LOG, `Handling @mention message: ${JSON.stringify(message)}`); @@ -16,7 +17,16 @@ export const handleMentions = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.mention).catch((e) => { + message.send({ + embeds: [{ + color: infoColor1, + title: `Hello! I am ${config.name}!`, + fields: [{ + name: 'I am a bot that specializes in rolling dice and doing basic algebra', + value: `To learn about my available commands, please run \`${config.prefix}help\``, + }], + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/help.ts b/src/commands/help.ts index 42ee338..68e0141 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,3 +1,4 @@ +import config from '../../config.ts'; import { dbClient } from '../db.ts'; import { // Discordeno deps @@ -6,7 +7,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor2 } from '../commandUtils.ts'; export const help = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +15,70 @@ export const help = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.help).catch((e) => { + message.send({ + embeds: [{ + color: infoColor2, + title: 'The Artificer\'s Available Commands:', + fields: [ + { + name: `\`${config.prefix}?\``, + value: 'This command', + inline: true, + }, + { + name: `\`${config.prefix}rollhelp\` or \`${config.prefix}??\``, + value: `Details on how to use the roll command, listed as \`${config.prefix}xdy...${config.postfix}\` below`, + inline: true, + }, + { + name: `\`${config.prefix}api [subcommand]\``, + value: `Administrative tools for the bots's API, run \`${config.prefix}api help\` for more details`, + inline: true, + }, + { + name: `\`${config.prefix}ping\``, + value: 'Pings the bot to check connectivity', + inline: true, + }, + { + name: `\`${config.prefix}info\``, + value: 'Prints some information and links relating to the bot', + inline: true, + }, + { + name: `\`${config.prefix}privacy\``, + value: 'Prints some information about the Privacy Policy', + inline: true, + }, + { + name: `\`${config.prefix}version\``, + value: 'Prints the bots version', + inline: true, + }, + { + name: `\`${config.prefix}popcat\``, + value: 'Popcat', + inline: true, + }, + { + name: `\`${config.prefix}report [text]\``, + value: 'Report a command that failed to run', + inline: true, + }, + { + name: `\`${config.prefix}stats\``, + value: 'Statistics on the bot', + inline: true, + }, + { + name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, + value: + `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`, + inline: true, + }, + ], + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/info.ts b/src/commands/info.ts index d03f119..69c54ea 100644 --- a/src/commands/info.ts +++ b/src/commands/info.ts @@ -6,7 +6,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor2 } from '../commandUtils.ts'; export const info = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +14,16 @@ export const info = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.info).catch((e) => { + message.send({ + embeds: [{ + color: infoColor2, + title: 'The Artificer, a Discord bot that specializing in rolling dice and calculating math', + description: `The Artificer is developed by Ean AKA Burn_E99. +Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/). +Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer). +Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`, + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/ping.ts b/src/commands/ping.ts index 9292cf6..0330ad4 100644 --- a/src/commands/ping.ts +++ b/src/commands/ping.ts @@ -6,7 +6,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { generatePing } from '../constantCmds.ts'; +import { generatePing } from '../commandUtils.ts'; export const ping = async (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts index 3f640db..60a5ff1 100644 --- a/src/commands/privacy.ts +++ b/src/commands/privacy.ts @@ -1,3 +1,4 @@ +import config from '../../config.ts'; import { dbClient } from '../db.ts'; import { // Discordeno deps @@ -6,7 +7,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor1 } from '../commandUtils.ts'; export const privacy = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +15,21 @@ export const privacy = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.privacy).catch((e) => { + message.send({ + embeds: [{ + color: infoColor1, + title: 'Privacy Policy', + fields: [{ + name: 'The Artificer does not track or collect user information via Discord.', + value: + `The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see. + +For more details, please check out the Privacy Policy on the GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/PRIVACY.md). + +Terms of Service can also be found on GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/TERMS.md).`, + }], + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/report.ts b/src/commands/report.ts index c924a00..9c93203 100644 --- a/src/commands/report.ts +++ b/src/commands/report.ts @@ -8,7 +8,7 @@ import { LT, sendMessage, } from '../../deps.ts'; -import { constantCmds, generateReport } from '../constantCmds.ts'; +import { successColor, failColor, generateReport } from '../commandUtils.ts'; export const report = (message: DiscordenoMessage, args: string[]) => { // Light telemetry to see how many times a command is being run @@ -20,11 +20,23 @@ export const report = (message: DiscordenoMessage, args: string[]) => { sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); - message.send(constantCmds.report).catch((e) => { + message.send({ + embeds: [{ + color: successColor, + title: 'Failed command has been reported to my developer.', + description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`, + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); } else { - message.send(constantCmds.reportFail).catch((e) => { + message.send({ + embeds: [{ + color: failColor, + title: 'Please provide a short description of what failed', + description: 'Providing a short description helps my developer quickly diagnose what went wrong.', + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); } diff --git a/src/commands/rip.ts b/src/commands/rip.ts index 189c0a8..2ce6fdb 100644 --- a/src/commands/rip.ts +++ b/src/commands/rip.ts @@ -6,7 +6,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor2 } from '../commandUtils.ts'; export const rip = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +14,15 @@ export const rip = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.rip).catch((e) => { + message.send({ + embeds: [{ + color: infoColor2, + title: 'The Artificer was built in memory of my Grandmother, Babka', + description: `With much love, Ean + + December 21, 2020`, + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/roll.ts b/src/commands/roll.ts index c35f223..db309db 100644 --- a/src/commands/roll.ts +++ b/src/commands/roll.ts @@ -11,7 +11,7 @@ import { } from '../../deps.ts'; import solver from '../solver/_index.ts'; import { SolvedRoll } from '../solver/solver.d.ts'; -import { constantCmds, generateCountDetailsEmbed, generateDMFailed, generateRollEmbed } from '../constantCmds.ts'; +import { warnColor, infoColor1, generateCountDetailsEmbed, generateDMFailed, generateRollEmbed } from '../commandUtils.ts'; import rollFuncs from './roll/_index.ts'; export const roll = async (message: DiscordenoMessage, args: string[], command: string) => { @@ -22,7 +22,12 @@ export const roll = async (message: DiscordenoMessage, args: string[], command: // If DEVMODE is on, only allow this command to be used in the devServer if (DEVMODE && message.guildId !== config.devServer) { - message.send(constantCmds.indev).catch((e) => { + message.send({ + embeds: [{ + color: warnColor, + title: 'Command is in development, please try again later.', + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); return; @@ -32,7 +37,12 @@ export const roll = async (message: DiscordenoMessage, args: string[], command: try { const originalCommand = `${config.prefix}${command} ${args.join(' ')}`; - const m = await message.reply(constantCmds.rolling); + const m = await message.reply({ + embeds: [{ + color: infoColor1, + title: 'Rolling . . .', + }], + }); // Get modifiers from command const modifiers = rollFuncs.getModifiers(m, args, command, originalCommand); diff --git a/src/commands/roll/getModifiers.ts b/src/commands/roll/getModifiers.ts index 56af1fd..3eb27f9 100644 --- a/src/commands/roll/getModifiers.ts +++ b/src/commands/roll/getModifiers.ts @@ -8,7 +8,7 @@ import { // Log4Deno deps LT, } from '../../../deps.ts'; -import { generateRollError } from '../../constantCmds.ts'; +import { generateRollError } from '../../commandUtils.ts'; import { RollModifiers } from '../../mod.d.ts'; export const getModifiers = (m: DiscordenoMessage, args: string[], command: string, originalCommand: string): RollModifiers => { diff --git a/src/commands/rollHelp.ts b/src/commands/rollHelp.ts index 21b9ee6..27af935 100644 --- a/src/commands/rollHelp.ts +++ b/src/commands/rollHelp.ts @@ -1,3 +1,4 @@ +import config from '../../config.ts'; import { dbClient } from '../db.ts'; import { // Discordeno deps @@ -6,7 +7,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor1, infoColor2, successColor } from '../commandUtils.ts'; export const rollHelp = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +15,235 @@ export const rollHelp = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.rollHelp).catch((e) => { + message.send({ + embeds: [ + { + color: infoColor2, + title: 'The Artificer\'s Roll Command Details:', + description: `You can chain as many of these options as you want, as long as the option does not disallow it. + + This command also can fully solve math equations with parenthesis. + + The Artificer supports most of the [Roll20 formatting](https://artificer.eanm.dev/roll20). More details and examples can be found [here](https://artificer.eanm.dev/roll20).`, + fields: [ + { + name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, + value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`)`, + }, + { + name: '`x` [Optional]', + value: 'Number of dice to roll, if omitted, 1 is used', + inline: true, + }, + { + name: '`dy` [Required]', + value: 'Size of dice to roll, `d20` = 20 sided die', + inline: true, + }, + { + name: '`dz` or `dlz` [Optional]', + value: 'Drops the lowest `z` dice, cannot be used with `kz`', + inline: true, + }, + { + name: '`kz` or `khz` [Optional]', + value: 'Keeps the highest `z` dice, cannot be used with `dz`', + inline: true, + }, + { + name: '`dhz` [Optional]', + value: 'Drops the highest `z` dice, cannot be used with `kz`', + inline: true, + }, + { + name: '`klz` [Optional]', + value: 'Keeps the lowest `z` dice, cannot be used with `dz`', + inline: true, + }, + { + name: '`ra` or `r=q` [Optional]', + value: 'Rerolls any rolls that match `a`, `r3` will reroll every die that land on 3, throwing out old rolls, cannot be used with `ro`', + inline: true, + }, + { + name: '`rq` [Optional]', + value: 'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`', + inline: true, + }, + { + name: '`roa` or `ro=q` [Optional]', + value: 'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', + inline: true, + }, + { + name: '`roq` [Optional]', + value: 'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', + inline: true, + }, + { + name: '`csq` or `cs=q` [Optional]', + value: 'Changes crit score to `q`', + inline: true, + }, + { + name: '`csq` [Optional]', + value: 'Changes crit score to be greater than or equal to `q`', + inline: true, + }, + { + name: '`cfq` or `cf=q` [Optional]', + value: 'Changes crit fail to `q`', + inline: true, + }, + { + name: '`cfq` [Optional]', + value: 'Changes crit fail to be greater than or equal to `q`', + inline: true, + }, + { + name: '`!` [Optional]', + value: 'Exploding, rolls another `dy` for every crit success', + inline: true, + }, + { + name: '`!o` [Optional]', + value: 'Exploding Once, rolls one `dy` for each original crit success', + inline: true, + }, + { + name: '`!=u` [Optional]', + value: 'Explode on `u`, rolls another `dy` for every die that lands on `u`', + inline: true, + }, + { + name: '`!>u` [Optional]', + value: 'Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater', + inline: true, + }, + { + name: '`!u` [Optional]', + value: 'Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater', + inline: true, + }, + { + name: '`!o { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/commands/stats.ts b/src/commands/stats.ts index dfc58ce..81d0e74 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -8,7 +8,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds, generateStats } from '../constantCmds.ts'; +import { warnColor, generateStats } from '../commandUtils.ts'; export const stats = async (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -17,7 +17,12 @@ export const stats = async (message: DiscordenoMessage) => { }); try { - const m = await message.send(constantCmds.loadingStats); + const m = await message.send({ + embeds: [{ + color: warnColor, + title: 'Compiling latest statistics . . .', + }], + }); // Calculate how many times commands have been run const rollQuery = await dbClient.query(`SELECT count FROM command_cnt WHERE command = "roll";`).catch((e) => { diff --git a/src/commands/version.ts b/src/commands/version.ts index 9e4c317..af4d301 100644 --- a/src/commands/version.ts +++ b/src/commands/version.ts @@ -1,3 +1,4 @@ +import config from '../../config.ts'; import { dbClient } from '../db.ts'; import { // Discordeno deps @@ -6,7 +7,7 @@ import { // Log4Deno deps LT, } from '../../deps.ts'; -import { constantCmds } from '../constantCmds.ts'; +import { infoColor1 } from '../commandUtils.ts'; export const version = (message: DiscordenoMessage) => { // Light telemetry to see how many times a command is being run @@ -14,7 +15,12 @@ export const version = (message: DiscordenoMessage) => { log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); }); - message.send(constantCmds.version).catch((e) => { + message.send({ + embeds: [{ + color: infoColor1, + title: `My current version is ${config.version}`, + }], + }).catch((e) => { log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); }); }; diff --git a/src/constantCmds.ts b/src/constantCmds.ts deleted file mode 100644 index 7737aed..0000000 --- a/src/constantCmds.ts +++ /dev/null @@ -1,769 +0,0 @@ -import config from '../config.ts'; -import { CountDetails, SolvedRoll } from './solver/solver.d.ts'; -import { RollModifiers } from './mod.d.ts'; - -const failColor = 0xe71212; -const warnColor = 0xe38f28; -const successColor = 0x0f8108; -const infoColor1 = 0x313bf9; -const infoColor2 = 0x6805e9; - -export const constantCmds = { - apiDeleteFail: { - embeds: [{ - color: failColor, - title: 'Failed to delete this guild from the database.', - description: 'If this issue persists, please report this to the developers.', - }], - }, - apiGuildOnly: { - embeds: [{ - color: failColor, - title: 'API commands are only available in guilds.', - }], - }, - apiHelp: { - embeds: [ - { - color: infoColor2, - title: 'The Artificer\'s API Details:', - description: - `The Artificer has a built in API that allows user to roll dice into Discord using third party programs. By default, API rolls are blocked from being sent in your guild. The API warning is also enabled by default. These commands may only be used by the Owner or Admins of your guild. - -For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer). - -You may enable and disable the API rolls for your guild as needed.`, - }, - { - color: infoColor1, - title: 'Available API Commands:', - fields: [ - { - name: `\`${config.prefix}api help\``, - value: 'This command', - inline: true, - }, - { - name: `\`${config.prefix}api status\``, - value: 'Shows the current status of the API for the channel this was run in', - inline: true, - }, - { - name: `\`${config.prefix}api allow/enable\``, - value: 'Allows API Rolls to be sent to the channel this was run in', - inline: true, - }, - { - name: `\`${config.prefix}api block/disable\``, - value: 'Blocks API Rolls from being sent to the channel this was run in', - inline: true, - }, - { - name: `\`${config.prefix}api delete\``, - value: 'Deletes this channel\'s settings from The Artificer\'s database', - inline: true, - }, - { - name: `\`${config.prefix}api show-warn\``, - value: 'Shows the API warning on all rolls sent to the channel this was run in', - inline: true, - }, - { - name: `\`${config.prefix}api hide-warn\``, - value: 'Hides the API warning on all rolls sent to the channel this was run in', - inline: true, - }, - ], - }, - ], - }, - apiPermError: { - embeds: [{ - color: failColor, - title: 'API commands are powerful and can only be used by guild Owners and Admins.', - description: 'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).', - }], - }, - apiRemoveGuild: { - embeds: [{ - color: successColor, - title: 'This guild\'s API setting has been removed from The Artifier\'s Database.', - }], - }, - apiStatusFail: { - embeds: [{ - color: failColor, - title: 'Failed to check API rolls status for this guild.', - description: 'If this issue persists, please report this to the developers.', - }], - }, - help: { - embeds: [{ - color: infoColor2, - title: 'The Artificer\'s Available Commands:', - fields: [ - { - name: `\`${config.prefix}?\``, - value: 'This command', - inline: true, - }, - { - name: `\`${config.prefix}rollhelp\` or \`${config.prefix}??\``, - value: `Details on how to use the roll command, listed as \`${config.prefix}xdy...${config.postfix}\` below`, - inline: true, - }, - { - name: `\`${config.prefix}api [subcommand]\``, - value: `Administrative tools for the bots's API, run \`${config.prefix}api help\` for more details`, - inline: true, - }, - { - name: `\`${config.prefix}ping\``, - value: 'Pings the bot to check connectivity', - inline: true, - }, - { - name: `\`${config.prefix}info\``, - value: 'Prints some information and links relating to the bot', - inline: true, - }, - { - name: `\`${config.prefix}privacy\``, - value: 'Prints some information about the Privacy Policy', - inline: true, - }, - { - name: `\`${config.prefix}version\``, - value: 'Prints the bots version', - inline: true, - }, - { - name: `\`${config.prefix}popcat\``, - value: 'Popcat', - inline: true, - }, - { - name: `\`${config.prefix}report [text]\``, - value: 'Report a command that failed to run', - inline: true, - }, - { - name: `\`${config.prefix}stats\``, - value: 'Statistics on the bot', - inline: true, - }, - { - name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, - value: - `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`, - inline: true, - }, - ], - }], - }, - indev: { - embeds: [{ - color: warnColor, - title: 'Command is in development, please try again later.', - }], - }, - info: { - embeds: [{ - color: infoColor2, - title: 'The Artificer, a Discord bot that specializing in rolling dice and calculating math', - description: `The Artificer is developed by Ean AKA Burn_E99. -Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/). -Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer). -Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`, - }], - }, - loadingStats: { - embeds: [{ - color: warnColor, - title: 'Compiling latest statistics . . .', - }], - }, - mention: { - embeds: [{ - color: infoColor1, - title: `Hello! I am ${config.name}!`, - fields: [{ - name: 'I am a bot that specializes in rolling dice and doing basic algebra', - value: `To learn about my available commands, please run \`${config.prefix}help\``, - }], - }], - }, - privacy: { - embeds: [{ - color: infoColor1, - title: 'Privacy Policy', - fields: [{ - name: 'The Artificer does not track or collect user information via Discord.', - value: - `The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see. - -For more details, please check out the Privacy Policy on the GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/PRIVACY.md). - -Terms of Service can also be found on GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/TERMS.md).`, - }], - }], - }, - report: { - embeds: [{ - color: successColor, - title: 'Failed command has been reported to my developer.', - description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`, - }], - }, - reportFail: { - embeds: [{ - color: failColor, - title: 'Please provide a short description of what failed', - description: 'Providing a short description helps my developer quickly diagnose what went wrong.', - }], - }, - rip: { - embeds: [{ - color: infoColor2, - title: 'The Artificer was built in memory of my Grandmother, Babka', - description: `With much love, Ean - - December 21, 2020`, - }], - }, - rollHelp: { - embeds: [ - { - color: infoColor2, - title: 'The Artificer\'s Roll Command Details:', - description: `You can chain as many of these options as you want, as long as the option does not disallow it. - - This command also can fully solve math equations with parenthesis. - - The Artificer supports most of the [Roll20 formatting](https://artificer.eanm.dev/roll20). More details and examples can be found [here](https://artificer.eanm.dev/roll20).`, - fields: [ - { - name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, - value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`)`, - }, - { - name: '`x` [Optional]', - value: 'Number of dice to roll, if omitted, 1 is used', - inline: true, - }, - { - name: '`dy` [Required]', - value: 'Size of dice to roll, `d20` = 20 sided die', - inline: true, - }, - { - name: '`dz` or `dlz` [Optional]', - value: 'Drops the lowest `z` dice, cannot be used with `kz`', - inline: true, - }, - { - name: '`kz` or `khz` [Optional]', - value: 'Keeps the highest `z` dice, cannot be used with `dz`', - inline: true, - }, - { - name: '`dhz` [Optional]', - value: 'Drops the highest `z` dice, cannot be used with `kz`', - inline: true, - }, - { - name: '`klz` [Optional]', - value: 'Keeps the lowest `z` dice, cannot be used with `dz`', - inline: true, - }, - { - name: '`ra` or `r=q` [Optional]', - value: 'Rerolls any rolls that match `a`, `r3` will reroll every die that land on 3, throwing out old rolls, cannot be used with `ro`', - inline: true, - }, - { - name: '`rq` [Optional]', - value: 'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`', - inline: true, - }, - { - name: '`roa` or `ro=q` [Optional]', - value: 'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', - inline: true, - }, - { - name: '`roq` [Optional]', - value: 'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', - inline: true, - }, - { - name: '`csq` or `cs=q` [Optional]', - value: 'Changes crit score to `q`', - inline: true, - }, - { - name: '`csq` [Optional]', - value: 'Changes crit score to be greater than or equal to `q`', - inline: true, - }, - { - name: '`cfq` or `cf=q` [Optional]', - value: 'Changes crit fail to `q`', - inline: true, - }, - { - name: '`cfq` [Optional]', - value: 'Changes crit fail to be greater than or equal to `q`', - inline: true, - }, - { - name: '`!` [Optional]', - value: 'Exploding, rolls another `dy` for every crit success', - inline: true, - }, - { - name: '`!o` [Optional]', - value: 'Exploding Once, rolls one `dy` for each original crit success', - inline: true, - }, - { - name: '`!=u` [Optional]', - value: 'Explode on `u`, rolls another `dy` for every die that lands on `u`', - inline: true, - }, - { - name: '`!>u` [Optional]', - value: 'Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater', - inline: true, - }, - { - name: '`!u` [Optional]', - value: 'Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater', - inline: true, - }, - { - name: '`!o ({ - embeds: [{ - color: infoColor1, - title: time === -1 ? 'Ping?' : `Pong! Latency is ${time}ms.`, - }], -}); - -export const generateReport = (msg: string) => ({ - embeds: [{ - color: infoColor2, - title: 'USER REPORT:', - description: msg || 'No message', - }], -}); - -export const generateStats = (guildCount: number, channelCount: number, memberCount: number, rollCount: bigint, utilityCount: bigint) => ({ - embeds: [{ - color: infoColor2, - title: 'The Artificer\'s Statistics:', - fields: [ - { - name: 'Guilds:', - value: `${guildCount}`, - inline: true, - }, - { - name: 'Channels:', - value: `${channelCount}`, - inline: true, - }, - { - name: 'Active Members:', - value: `${memberCount}`, - inline: true, - }, - { - name: 'Roll Commands:', - value: `${rollCount}`, - inline: true, - }, - { - name: 'Utility Commands:', - value: `${utilityCount}`, - inline: true, - }, - ], - }], -}); - -export const generateApiFailed = (args: string) => ({ - embeds: [{ - color: failColor, - title: `Failed to ${args} API rolls for this guild.`, - description: 'If this issue persists, please report this to the developers.', - }], -}); - -export const generateApiStatus = (banned: boolean, active: boolean) => { - const apiStatus = active ? 'allowed' : 'blocked from being used'; - return { - embeds: [{ - color: infoColor1, - title: `The Artificer's API is ${config.api.enable ? 'currently enabled' : 'currently disabled'}.`, - description: banned ? 'API rolls are banned from being used in this guild.\n\nThis will not be reversed.' : `API rolls are ${apiStatus} in this guild.`, - }], - }; -}; - -export const generateApiSuccess = (args: string) => ({ - embeds: [{ - color: successColor, - title: `API rolls have successfully been ${args} for this guild.`, - }], -}); - -export const generateDMFailed = (user: string) => ({ - embeds: [{ - color: failColor, - title: `WARNING: ${user} could not be messaged.`, - description: 'If this issue persists, make sure direct messages are allowed from this server.', - }], -}); - -export const generateApiKeyEmail = (email: string, key: string) => ({ - content: `<@${config.api.admin}> A USER HAS REQUESTED AN API KEY`, - embeds: [{ - color: infoColor1, - fields: [ - { - name: 'Send to:', - value: email, - }, - { - name: 'Subject:', - value: 'Artificer API Key', - }, - { - name: 'Body:', - value: `Hello Artificer API User, - -Welcome aboard The Artificer's API. You can find full details about the API on the GitHub: https://github.com/Burn-E99/TheArtificer - -Your API Key is: ${key} - -Guard this well, as there is zero tolerance for API abuse. - -Welcome aboard, -The Artificer Developer - Ean Milligan`, - }, - ], - }], -}); - -export const generateApiDeleteEmail = (email: string, deleteCode: string) => ({ - content: `<@${config.api.admin}> A USER HAS REQUESTED A DELETE CODE`, - embeds: [{ - color: infoColor1, - fields: [ - { - name: 'Send to:', - value: email, - }, - { - name: 'Subject:', - value: 'Artificer API Delete Code', - }, - { - name: 'Body:', - value: `Hello Artificer API User, - -I am sorry to see you go. If you would like, please respond to this email detailing what I could have done better. - -As requested, here is your delete code: ${deleteCode} - -Sorry to see you go, -The Artificer Developer - Ean Milligan`, - }, - ], - }], -}); - -export const generateRollError = (errorType: string, errorMsg: string) => ({ - embeds: [{ - color: failColor, - title: 'Roll command encountered the following error:', - fields: [{ - name: errorType, - value: `${errorMsg}\n\nPlease try again. If the error is repeated, please report the issue using the \`${config.prefix}report\` command.`, - }], - }], -}); - -export const generateCountDetailsEmbed = (counts: CountDetails) => ({ - color: infoColor1, - title: 'Roll Count Details:', - fields: [ - { - name: 'Total Rolls:', - value: `${counts.total}`, - inline: true, - }, - { - name: 'Successful Rolls:', - value: `${counts.successful}`, - inline: true, - }, - { - name: 'Failed Rolls:', - value: `${counts.failed}`, - inline: true, - }, - { - name: 'Rerolled Dice:', - value: `${counts.rerolled}`, - inline: true, - }, - { - name: 'Dropped Dice:', - value: `${counts.dropped}`, - inline: true, - }, - { - name: 'Exploded Dice:', - value: `${counts.exploded}`, - inline: true, - }, - ], -}); - -export const generateRollEmbed = async (authorId: bigint, returnDetails: SolvedRoll, modifiers: RollModifiers) => { - if (returnDetails.error) { - // Roll had an error, send error embed - return { - embed: { - color: failColor, - title: 'Roll failed:', - description: `${returnDetails.errorMsg}`, - }, - hasAttachment: false, - attachment: { - 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), - 'name': 'rollDetails.txt', - }, - }; - } else { - if (modifiers.gmRoll) { - // Roll is a GM Roll, send this in the pub channel (this funciton will be ran again to get details for the GMs) - return { - embed: { - color: infoColor2, - description: `<@${authorId}>${returnDetails.line1} - -Results have been messaged to the following GMs: ${modifiers.gms.join(' ')}`, - }, - hasAttachment: false, - attachment: { - 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), - 'name': 'rollDetails.txt', - }, - }; - } else { - // Roll is normal, make normal embed - const line2Details = returnDetails.line2.split(': '); - let details = ''; - - if (!modifiers.superNoDetails) { - if (modifiers.noDetails) { - details = `**Details:** -Suppressed by -nd flag`; - } else { - details = `**Details:** -${modifiers.spoiler}${returnDetails.line3}${modifiers.spoiler}`; - } - } - - const baseDesc = `<@${authorId}>${returnDetails.line1} -**${line2Details.shift()}:** -${line2Details.join(': ')}`; - - if (baseDesc.length + details.length < 4090) { - return { - embed: { - color: infoColor2, - description: `${baseDesc} - -${details}`, - }, - hasAttachment: false, - attachment: { - 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), - 'name': 'rollDetails.txt', - }, - }; - } else { - // If its too big, collapse it into a .txt file and send that instead. - const b = await new Blob([`${baseDesc}\n\n${details}` as BlobPart], { 'type': 'text' }); - details = 'Details have been ommitted from this message for being over 2000 characters.'; - if (b.size > 8388290) { - details += - 'Full details could not be attached to this messaged as a \`.txt\` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one.'; - return { - embed: { - color: infoColor2, - description: `${baseDesc} - - ${details}`, - }, - hasAttachment: false, - attachment: { - 'blob': await new Blob(['' as BlobPart], { 'type': 'text'}), - 'name': 'rollDetails.txt', - }, - }; - } else { - details += 'Full details have been attached to this messaged as a \`.txt\` file for verification purposes.'; - return { - embed: { - color: infoColor2, - description: `${baseDesc} - -${details}`, - }, - hasAttachment: true, - attachment: { - 'blob': b, - 'name': 'rollDetails.txt', - }, - }; - } - } - } - } -};