Mass spelling fix

This commit is contained in:
Ean Milligan 2025-04-26 23:08:57 -04:00
parent 74c733308f
commit 864f281c60
38 changed files with 322 additions and 237 deletions

43
.vscode/settings.json vendored
View File

@ -8,5 +8,46 @@
"spellright.language": [
"en"
],
"spellright.documentTypes": []
"spellright.documentTypes": [],
"cSpell.words": [
"channelid",
"CWOD",
"DEVMODE",
"Discordeno",
"dkdk",
"EMDAS",
"funciton",
"guildid",
"hidewarn",
"imagescript",
"indev",
"Inno",
"LOCALMODE",
"localtoken",
"longtext",
"Mult",
"nojs",
"nominize",
"noodp",
"noydir",
"oldcnt",
"oper",
"ovad",
"PEMDAS",
"Rehost",
"Rehosts",
"resultid",
"rolldecorators",
"rollhelp",
"rollstr",
"sproc",
"Tarantallegra",
"tinyint",
"unauthorised",
"unban",
"xcwody",
"xdydz",
"xdydzracsq",
"xovady"
]
}

View File

@ -66,11 +66,11 @@ The Artificer comes with a few supplemental commands to the main rolling command
* `[[xdydzracsq!]]`
* This is the command the bot was built specifically for.
* It looks a little complicated at first, but if you are familiar with the [Roll20 formatting](https://artificer.eanm.dev/roll20), this will no different.
* Any math (limited to exponentials, multiplication, division, modulus, addition, and subtraction) will be correctly handled in PEMDAS order, so use parenthesis as needed.
* Any math (limited to exponential, multiplication, division, modulus, addition, and subtraction) will be correctly handled in PEMDAS order, so use parenthesis as needed.
* PI and e are available for use.
* Parameters for rolling:
| Paramater | Required? | Repeatable? | Description |
| Parameter | Required? | Repeatable? | Description |
|---------------|-------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| x | Optional | No | number of dice to roll, if omitted, 1 is used, additionally, replace x with `F` to roll the dice as Fate dice |
| dy | Required | No | size of dice to roll, d20 = 20 sided die |
@ -128,7 +128,7 @@ The Artificer comes with a few supplemental commands to the main rolling command
* `-s` - Spoiler - Spoilers all details of the requested roll
* `-m` - Maximize Roll - Rolls the theoretical maximum roll, cannot be used with -n
* `-n` - Nominal Roll - Rolls the theoretical nominal roll, cannot be used with -m
* `-gm @user1 @user2 ... @usern` - GM Roll - Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs
* `-gm @user1 @user2 ... @userN` - GM Roll - Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs
* `-o a` or `-o d` - Order Roll - Rolls the requested roll and orders the results in the requested direction
* The results have some formatting applied on them to provide details on what happened during this roll.
* Critical successes will be **bolded**
@ -153,7 +153,7 @@ Official API URL: `https://artificer.eanm.dev/api/`
API Documentation can be found in the `.bruno` folder, which can be viewed in [Bruno](https://www.usebruno.com/).
API Key management via a basic GUI is availble on the [API Tools](https://artificer.eanm.dev/) website.
API Key management via a basic GUI is available on the [API Tools](https://artificer.eanm.dev/) website.
## Problems? Feature requests?
If you run into any errors or problems with the bot, or think you have a good idea to add to the bot, please submit a new GitHub issue detailing it. If you don't have a GitHub account, a report command (detailed above) is provided for use in Discord.

View File

@ -28,14 +28,14 @@ export const config = {
host: '', // IP address for the db, usually localhost
localhost: '', // IP address for a secondary OPTIONAL local testing DB, usually also is localhost, but depends on your dev environment
port: 3306, // Port for the db
username: '', // Username for the account that will access your DB, this account will need "DB Manager" admin rights and "REFERENCES" Global Privalages
username: '', // Username for the account that will access your DB, this account will need "DB Manager" admin rights and "REFERENCES" Global Privileges
password: '', // Password for the account, user account may need to be authenticated with the "Standard" Authentication Type if this does not work out of the box
name: '', // Name of the database Schema to use for the bot
},
logRolls: false, // Enables logging of roll commands, this should be left disabled for privacy, but exists to allow verification of rolls before deployment, all API rolls will always be logged no matter what this is set to
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 conjuction 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
emojis: [
// Array of objects containing all emojis that the bot can send on your behalf, empty this array if you don't want any of them
{

View File

@ -7,7 +7,7 @@ console.log('Attempting to populate DB Admin API key');
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [config.api.admin, config.api.adminKey]).catch((e) => {
console.log('Failed to insert into database', e);
});
console.log('Inesrtion done');
console.log('Insertion done');
console.log('Attempting to insert default commands into command_cnt');
const commands = [

View File

@ -1,4 +1,4 @@
// All external dependancies are to be loaded here to make updating dependancy versions much easier
// All external dependencies are to be loaded here to make updating dependency versions much easier
export {
botId,
cache,

32
mod.ts
View File

@ -6,7 +6,21 @@
import config from './config.ts';
import { DEBUG, DEVMODE, LOCALMODE } from './flags.ts';
import { botId, cache, DiscordActivityTypes, DiscordenoGuild, DiscordenoMessage, editBotNickname, editBotStatus, initLog, Intents, log, LT, sendMessage, startBot } from './deps.ts';
import {
botId,
cache,
DiscordActivityTypes,
DiscordenoGuild,
DiscordenoMessage,
editBotNickname,
editBotStatus,
initLog,
Intents,
log,
LT,
sendMessage,
startBot,
} from './deps.ts';
import api from './src/api.ts';
import dbClient from './src/db/client.ts';
import { ignoreList } from './src/db/common.ts';
@ -66,10 +80,12 @@ startBot({
}, 30000);
// Interval to update bot list stats every 24 hours
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : setInterval(() => {
log(LT.LOG, 'Updating all bot lists statistics');
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
}, 86400000);
LOCALMODE
? log(LT.INFO, 'updateListStatistics not running')
: setInterval(() => {
log(LT.LOG, 'Updating all bot lists statistics');
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
}, 86400000);
// Interval to update hourlyRates every hour
setInterval(() => {
@ -175,8 +191,8 @@ startBot({
.execute('DELETE FROM allowed_guilds WHERE guildid = ? AND banned = 0', [guild.id])
.catch((e) => utils.commonLoggers.dbError('mod.ts:100', 'delete from', e));
},
debug: DEVMODE ? (dmsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`) : undefined,
raw: DEVMODE ? (dmsg) => log(LT.LOG, `Raw Debug Message | ${JSON.stringify(dmsg)}`) : undefined,
debug: DEVMODE ? (dMsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dMsg)}`) : undefined,
raw: DEVMODE ? (dMsg) => log(LT.LOG, `Raw Debug Message | ${JSON.stringify(dMsg)}`) : undefined,
messageCreate: (message: DiscordenoMessage) => {
// Ignore all other bots
if (message.isBot) return;
@ -308,7 +324,7 @@ startBot({
// Dice rolling commence!
commands.roll(message, args, command);
} else if (command) {
// [[emoji or [[emojialias
// [[emoji or [[emoji-alias
// Check if the unhandled command is an emoji request
commands.emoji(message, command);
}

View File

@ -165,7 +165,7 @@ const start = () => {
return stdResp.MethodNotAllowed('Auth');
}
} else {
// Handle the unathenticated request
// Handle the unauthenticated request
switch (request.method) {
case 'GET':
switch (path.toLowerCase()) {

View File

@ -45,7 +45,7 @@ export const generateStats = (
rollCount: bigint,
utilityCount: bigint,
rollRate: number,
utilityRate: number,
utilityRate: number
) => ({
embeds: [
{

View File

@ -74,7 +74,8 @@ export const api = async (message: DiscordenoMessage, args: string[]) => {
{
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).',
description:
'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).',
},
],
})

View File

@ -31,7 +31,7 @@ export const deleteGuild = async (message: DiscordenoMessage) => {
embeds: [
{
color: successColor,
title: "This guild's API setting has been removed from The Artifier's Database.",
title: "This guild's API setting has been removed from The Artificer's Database.",
},
],
})

View File

@ -23,7 +23,7 @@ export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) =
await dbClient
.execute(`INSERT INTO allowed_guilds(guildid,channelid,hidewarn) values(?,?,?)`, [message.guildId, message.channelId, apiArg === 'hide-warn' ? 1 : 0])
.catch((e0) => {
utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert inot', e0);
utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert into', e0);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e));
errorOut = true;
});

View File

@ -32,7 +32,7 @@ export const audit = (message: DiscordenoMessage, args: string[]) => {
break;
case 'guilds':
// [[audit guilds
// Shows breakdown of guilds and detials on them
// Shows breakdown of guilds and details on them
auditCommands.auditGuilds(message);
break;
default:

View File

@ -37,58 +37,62 @@ Tot mem: ${guild.memberCount} | Real: ${localRealCount} | Bot: ${localBotCount}
`;
});
const b = await new Blob([auditText as BlobPart], { 'type': 'text' });
const tooBig = await new Blob(['tooBig' as BlobPart], { 'type': 'text' });
const b = await new Blob([auditText as BlobPart], { type: 'text' });
const tooBig = await new Blob(['tooBig' as BlobPart], { type: 'text' });
message.send({
embeds: [{
color: infoColor2,
title: 'Guilds Audit',
description: `Shows details of the guilds that ${config.name} serves.
message
.send({
embeds: [
{
color: infoColor2,
title: 'Guilds Audit',
description: `Shows details of the guilds that ${config.name} serves.
Please see attached file for audit details on cached guilds and members.`,
timestamp: new Date().toISOString(),
fields: [
{
name: 'Total Guilds:',
value: `${cache.guilds.size}`,
inline: true,
},
{
name: 'Cached Guilds:',
value: `${cachedGuilds}`,
inline: true,
},
{
name: 'Uncached Guilds:',
value: `${cache.dispatchedGuildIds.size}`,
inline: true,
},
{
name: 'Total Members\n(may be artificially higher if 1 user is in multiple guilds the bot is in):',
value: `${totalCount}`,
inline: true,
},
{
name: 'Cached Real People:',
value: `${realCount}`,
inline: true,
},
{
name: 'Cached Bots:',
value: `${botsCount}`,
inline: true,
},
{
name: 'Average members per guild:',
value: `${(totalCount / cache.guilds.size).toFixed(2)}`,
inline: true,
timestamp: new Date().toISOString(),
fields: [
{
name: 'Total Guilds:',
value: `${cache.guilds.size}`,
inline: true,
},
{
name: 'Cached Guilds:',
value: `${cachedGuilds}`,
inline: true,
},
{
name: 'Uncached Guilds:',
value: `${cache.dispatchedGuildIds.size}`,
inline: true,
},
{
name: 'Total Members\n(may be artificially higher if 1 user is in multiple guilds the bot is in):',
value: `${totalCount}`,
inline: true,
},
{
name: 'Cached Real People:',
value: `${realCount}`,
inline: true,
},
{
name: 'Cached Bots:',
value: `${botsCount}`,
inline: true,
},
{
name: 'Average members per guild:',
value: `${(totalCount / cache.guilds.size).toFixed(2)}`,
inline: true,
},
],
},
],
}],
file: {
'blob': b.size > 8388290 ? tooBig : b,
'name': 'auditDetails.txt',
},
}).catch((e: Error) => utils.commonLoggers.messageSendError('auditGuild.ts:19', message, e));
file: {
blob: b.size > 8388290 ? tooBig : b,
name: 'auditDetails.txt',
},
})
.catch((e: Error) => utils.commonLoggers.messageSendError('auditGuild.ts:19', message, e));
};

View File

@ -7,27 +7,31 @@ import { infoColor1 } from '../../commandUtils.ts';
import utils from '../../utils.ts';
export const auditHelp = (message: DiscordenoMessage) => {
message.send({
embeds: [{
color: infoColor1,
title: 'Audit Help',
fields: [
message
.send({
embeds: [
{
name: `\`${config.prefix}audit help\``,
value: 'This command',
inline: true,
},
{
name: `\`${config.prefix}audit db\``,
value: 'Shows current DB table sizes',
inline: true,
},
{
name: `\`${config.prefix}audit guilds\``,
value: 'Shows breakdown of guilds and detials on them',
inline: true,
color: infoColor1,
title: 'Audit Help',
fields: [
{
name: `\`${config.prefix}audit help\``,
value: 'This command',
inline: true,
},
{
name: `\`${config.prefix}audit db\``,
value: 'Shows current DB table sizes',
inline: true,
},
{
name: `\`${config.prefix}audit guilds\``,
value: 'Shows breakdown of guilds and details on them',
inline: true,
},
],
},
],
}],
}).catch((e: Error) => utils.commonLoggers.messageSendError('auditHelp.ts:35', message, e));
})
.catch((e: Error) => utils.commonLoggers.messageSendError('auditHelp.ts:35', message, e));
};

View File

@ -13,26 +13,26 @@ import utils from '../utils.ts';
const allEmojiAliases: string[] = [];
config.emojis.forEach((emji: EmojiConf) => {
allEmojiAliases.push(...emji.aliases);
config.emojis.forEach((curEmoji: EmojiConf) => {
allEmojiAliases.push(...curEmoji.aliases);
});
export const emoji = (message: DiscordenoMessage, command: string) => {
if (allEmojiAliases.includes(command)) {
// Start looping thru the possible emojis
config.emojis.some((emji: EmojiConf) => {
log(LT.LOG, `Checking if command was emoji ${JSON.stringify(emji)}`);
config.emojis.some((curEmoji: EmojiConf) => {
log(LT.LOG, `Checking if command was emoji ${JSON.stringify(curEmoji)}`);
// If a match gets found
if (emji.aliases.indexOf(command || '') > -1) {
if (curEmoji.aliases.indexOf(command || '') > -1) {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('emojis')).catch((e) => utils.commonLoggers.dbError('emojis.ts:28', 'call sproc INC_CNT on', e));
// Send the needed emoji
message
.send(`<${emji.animated ? 'a' : ''}:${emji.name}:${emji.id}>`)
.send(`<${curEmoji.animated ? 'a' : ''}:${curEmoji.name}:${curEmoji.id}>`)
.catch((e: Error) => utils.commonLoggers.messageSendError('emoji.ts:33', message, e));
// And attempt to delete if needed
if (emji.deleteSender) {
if (curEmoji.deleteSender) {
message.delete().catch((e: Error) => utils.commonLoggers.messageDeleteError('emoji.ts:36', message, e));
}
return true;

View File

@ -10,7 +10,7 @@ import utils from '../utils.ts';
export const help = (message: DiscordenoMessage) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('htlp.ts:15', 'call sproc INC_CNT on', e));
dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('help.ts:15', 'call sproc INC_CNT on', e));
message
.send({
@ -91,8 +91,7 @@ export const help = (message: DiscordenoMessage) => {
},
{
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`,
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,
},
],

View File

@ -21,8 +21,7 @@ export const privacy = (message: DiscordenoMessage) => {
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.
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).

View File

@ -49,7 +49,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
return;
}
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituted in
const rollCmd = message.content.substring(2);
queueRoll({
@ -60,6 +60,6 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
originalCommand,
});
} catch (e) {
log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`);
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(e)}`);
}
};

View File

@ -64,7 +64,9 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
}
if (modifiers.gms.length < 1) {
// If -gm is on and none were found, throw an error
m.edit(generateRollError(errorType, 'Must specifiy at least one GM by @mentioning them')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e));
m.edit(generateRollError(errorType, 'Must specify at least one GM by @mentioning them')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e)
);
if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math
@ -81,7 +83,9 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
if (!args[i] || (args[i].toLowerCase()[0] !== 'd' && args[i].toLowerCase()[0] !== 'a')) {
// If -o is on and asc or desc was not specified, error out
m.edit(generateRollError(errorType, 'Must specifiy `a` or `d` to order the rolls ascending or descending')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e));
m.edit(generateRollError(errorType, 'Must specify `a` or `d` to order the rolls ascending or descending')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e)
);
if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math
@ -108,7 +112,9 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
// maxRoll and nominalRoll cannot both be on, throw an error
if (modifiers.maxRoll && modifiers.nominalRoll) {
m.edit(generateRollError(errorType, 'Cannot maximise and nominise the roll at the same time')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e));
m.edit(generateRollError(errorType, 'Cannot maximize and nominize the roll at the same time')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e)
);
if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math

View File

@ -48,8 +48,9 @@ Examples: \`${config.prefix}d20${config.postfix} -nd\`, \`${config.prefix}d20${c
inline: true,
},
{
name: '`-gm @user1 @user2 @usern` - GM Roll',
value: 'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs',
name: '`-gm @user1 @user2 @userN` - GM Roll',
value:
'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs',
inline: true,
},
{

View File

@ -72,27 +72,32 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
},
{
name: '`r<q` [Optional]',
value: 'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`',
value:
'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`',
inline: true,
},
{
name: '`r>q` [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`',
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`',
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: '`ro<q` [Optional]',
value: 'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
value:
'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
inline: true,
},
{
name: '`ro>q` [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`',
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,
},
{
@ -187,27 +192,32 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
},
{
name: '`!p>u` [Optional]',
value: 'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion',
value:
'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion',
inline: true,
},
{
name: '`!p<u` [Optional]',
value: 'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion',
value:
'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion',
inline: true,
},
{
name: '`!!=u` [Optional]',
value: 'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion',
value:
'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion',
inline: true,
},
{
name: '`!!>u` [Optional]',
value: 'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion',
value:
'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion',
inline: true,
},
{
name: '`!!<u` [Optional]',
value: 'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion',
value:
'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion',
inline: true,
},
],

View File

@ -40,8 +40,8 @@ export const stats = async (message: DiscordenoMessage) => {
rolls,
total - rolls,
rollRate,
totalRate - rollRate,
),
totalRate - rollRate
)
).catch((e: Error) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
} catch (e) {
utils.commonLoggers.messageSendError('stats.ts:41', message, e as Error);

View File

@ -1,8 +1,10 @@
import { warnColor } from './commandUtils.ts';
export const compilingStats = {
embeds: [{
color: warnColor,
title: 'Compiling latest statistics . . .',
}],
embeds: [
{
color: warnColor,
title: 'Compiling latest statistics . . .',
},
],
};

View File

@ -16,7 +16,7 @@ export const apiKeyDelete = async (query: Map<string, string>, apiUserid: bigint
if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) {
if (verifyQueryHasParams(query, ['code'])) {
if ((query.get('code') || '') === apiUserDelCode) {
// User has recieved their delete code and we need to delete the account now
// User has received their delete code and we need to delete the account now
let erroredOut = false;
await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {

View File

@ -18,7 +18,7 @@ export const apiChannel = async (query: Map<string, string>, apiUserid: bigint):
if (erroredOut) {
return stdResp.InternalServerError('Failed to get channels.');
} else {
// Customized strinification to handle BigInts correctly
// Customized stringification to handle BigInts correctly
const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
// Send channel list as response
return stdResp.OK(returnChannels);

View File

@ -113,7 +113,7 @@ export const apiRoll = async (query: Map<string, string>, apiUserid: bigint): Pr
} else {
// Alert API user that they messed up
return stdResp.Forbidden(
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`,
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`
);
}
} else {

View File

@ -5,7 +5,8 @@ import {
StatusCode,
} from '../../deps.ts';
const genericResponse = (customText: string, status: StatusCode) => new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
const genericResponse = (customText: string, status: StatusCode) =>
new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
export default {
BadRequest: (customText: string) => genericResponse(customText, STATUS_CODE.BadRequest),

View File

@ -44,7 +44,7 @@ const getRandomStatus = async (): Promise<string> => {
return status;
};
// updateListStatistics(bot ID, current guild count) returns nothing, posts to botlists
// updateListStatistics(bot ID, current guild count) returns nothing, posts to bot lists
// Sends the current server count to all bot list sites we are listed on
const updateListStatistics = (botID: bigint, serverCount: number): void => {
config.botLists.forEach(async (e) => {
@ -58,7 +58,7 @@ const updateListStatistics = (botID: bigint, serverCount: number): void => {
const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.toString()), {
method: 'POST',
headers: tempHeaders,
body: JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()), // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number
body: JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()), // ?{server_count} needs the "" removed from around it as well to make sure its sent as a number
});
log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`);
}
@ -198,7 +198,7 @@ const updateHeatmapPng = async () => {
hourPixels[hour][0] + 1,
dayPixels[day][1] - dayPixels[day][0] + 1,
hourPixels[hour][1] - hourPixels[hour][0] + 1,
is.Image.rgbToColor(255 * (1 - percent), 255 * percent, 0),
is.Image.rgbToColor(255 * (1 - percent), 255 * percent, 0)
);
}
}

View File

@ -16,7 +16,7 @@ import { fullSolver } from './solver.ts';
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
const operators = ['^', '*', '/', '%', '+', '-', '(', ')'];
const returnmsg = <SolvedRoll> {
const returnMsg = <SolvedRoll>{
error: false,
errorCode: '',
errorMsg: '',
@ -57,7 +57,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
const [tempConf, tempFormat] = sepRoll.split(config.postfix);
// Remove all spaces from the operation config and split it by any operator (keeping the operator in mathConf for fullSolver to do math on)
const mathConf: (string | number | SolvedStep)[] = <(string | number | SolvedStep)[]> tempConf.replace(/ /g, '').split(/([-+()*/%^])/g);
const mathConf: (string | number | SolvedStep)[] = <(string | number | SolvedStep)[]>tempConf.replace(/ /g, '').split(/([-+()*/%^])/g);
// Verify there are equal numbers of opening and closing parenthesis by adding 1 for opening parens and subtracting 1 for closing parens
let parenCnt = 0;
@ -77,7 +77,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
// Evaluate all rolls into stepSolve format and all numbers into floats
for (let i = 0; i < mathConf.length; i++) {
loggingEnabled && log(LT.LOG, `Parsing roll ${fullCmd} | Evaluating rolls into mathable items ${JSON.stringify(mathConf[i])}`);
loggingEnabled && log(LT.LOG, `Parsing roll ${fullCmd} | Evaluating rolls into math-able items ${JSON.stringify(mathConf[i])}`);
if (mathConf[i].toString().length === 0) {
// If its an empty string, get it out of here
mathConf.splice(i, 1);
@ -139,7 +139,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
containsCrit: false,
containsFail: false,
},
],
]
);
} else if (!operators.includes(mathConf[i].toString())) {
// If nothing else has handled it by now, try it as a roll
@ -150,10 +150,10 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
if (mathConf[i - 1] === '-' && ((!mathConf[i - 2] && mathConf[i - 2] !== 0) || mathConf[i - 2] === '(')) {
if (typeof mathConf[i] === 'number') {
mathConf[i] = <number> mathConf[i] * -1;
mathConf[i] = <number>mathConf[i] * -1;
} else {
(<SolvedStep> mathConf[i]).total = (<SolvedStep> mathConf[i]).total * -1;
(<SolvedStep> mathConf[i]).details = `-${(<SolvedStep> mathConf[i]).details}`;
(<SolvedStep>mathConf[i]).total = (<SolvedStep>mathConf[i]).total * -1;
(<SolvedStep>mathConf[i]).details = `-${(<SolvedStep>mathConf[i]).details}`;
}
mathConf.splice(i - 1, 1);
i--;
@ -189,7 +189,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
let line2 = '';
let line3 = '';
// If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting
// If maximizeRoll or nominalRoll are on, mark the output as such, else use default formatting
if (modifiers.maxRoll) {
line1 = ` requested the theoretical maximum of:\n\`${config.prefix}${fullCmd}\``;
line2 = 'Theoretical Maximum Results: ';
@ -216,7 +216,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
let preFormat = '';
let postFormat = '';
// If the roll containted a crit success or fail, set the formatting around it
// If the roll contained a crit success or fail, set the formatting around it
if (e.containsCrit) {
preFormat = `**${preFormat}`;
postFormat = `${postFormat}**`;
@ -248,12 +248,12 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
}
// Fill in the return block
returnmsg.line1 = line1;
returnmsg.line2 = line2;
returnmsg.line3 = line3;
returnMsg.line1 = line1;
returnMsg.line2 = line2;
returnMsg.line3 = line3;
// Reduce counts to a single object
returnmsg.counts = tempCountDetails.reduce((acc, cnt) => ({
returnMsg.counts = tempCountDetails.reduce((acc, cnt) => ({
total: acc.total + cnt.total,
successful: acc.successful + cnt.successful,
failed: acc.failed + cnt.failed,
@ -344,16 +344,16 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
errorMsg = 'Error: Roll became undefined, one or more operands are not a roll or a number, check input';
break;
default:
log(LT.ERROR, `Undangled Error: ${errorName}, ${errorDetails}`);
log(LT.ERROR, `Unhandled Parser Error: ${errorName}, ${errorDetails}`);
errorMsg = `Unhandled Error: ${solverError.message}\nCheck input and try again, if issue persists, please use \`${config.prefix}report\` to alert the devs of the issue`;
break;
}
// Fill in the return block
returnmsg.error = true;
returnmsg.errorCode = solverError.message;
returnmsg.errorMsg = errorMsg;
returnMsg.error = true;
returnMsg.errorCode = solverError.message;
returnMsg.errorMsg = errorMsg;
}
return returnmsg;
return returnMsg;
};

View File

@ -9,16 +9,16 @@ import { rollCounter } from './counter.ts';
import { RollFormat } from './solver.d.ts';
import { loggingEnabled } from './rollUtils.ts';
// formatRoll(rollConf, maximiseRoll, nominalRoll) returns one SolvedStep
// formatRoll(rollConf, maximizeRoll, nominalRoll) returns one SolvedStep
// formatRoll handles creating and formatting the completed rolls into the SolvedStep format
export const formatRoll = (rollConf: string, maximiseRoll: boolean, nominalRoll: boolean): RollFormat => {
export const formatRoll = (rollConf: string, maximizeRoll: boolean, nominalRoll: boolean): RollFormat => {
let tempTotal = 0;
let tempDetails = '[';
let tempCrit = false;
let tempFail = false;
// Generate the roll, passing flags thru
const tempRollSet = roll(rollConf, maximiseRoll, nominalRoll);
const tempRollSet = roll(rollConf, maximizeRoll, nominalRoll);
// Loop thru all parts of the roll to document everything that was done to create the total roll
tempRollSet.forEach((e) => {

View File

@ -44,12 +44,12 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
(
await generateRollEmbed(
rq.dd.message.authorId,
<SolvedRoll> {
<SolvedRoll>{
error: true,
errorCode: 'TooComplex',
errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts',
},
<RollModifiers> {},
<RollModifiers>{}
)
).embed,
],
@ -71,18 +71,18 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
try {
currentWorkers--;
clearTimeout(workerTimeout);
const returnmsg = workerMessage.data;
loggingEnabled && log(LT.LOG, `Roll came back from worker: ${returnmsg.line1.length} |&| ${returnmsg.line2.length} |&| ${returnmsg.line3.length} `);
loggingEnabled && log(LT.LOG, `Roll came back from worker: ${returnmsg.line1} |&| ${returnmsg.line2} |&| ${returnmsg.line3} `);
const pubEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, rq.modifiers);
const gmEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, gmModifiers);
const countEmbed = generateCountDetailsEmbed(returnmsg.counts);
const returnMsg = workerMessage.data;
loggingEnabled && log(LT.LOG, `Roll came back from worker: ${returnMsg.line1.length} |&| ${returnMsg.line2.length} |&| ${returnMsg.line3.length} `);
loggingEnabled && log(LT.LOG, `Roll came back from worker: ${returnMsg.line1} |&| ${returnMsg.line2} |&| ${returnMsg.line3} `);
const pubEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnMsg, rq.modifiers);
const gmEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnMsg, gmModifiers);
const countEmbed = generateCountDetailsEmbed(returnMsg.counts);
loggingEnabled && log(LT.LOG, `Embeds are generated: ${JSON.stringify(pubEmbedDetails)} |&| ${JSON.stringify(gmEmbedDetails)}`);
// If there was an error, report it to the user in hopes that they can determine what they did wrong
if (returnmsg.error) {
if (returnMsg.error) {
if (rq.apiRoll) {
rq.api.resolve(stdResp.InternalServerError(returnmsg.errorMsg));
rq.api.resolve(stdResp.InternalServerError(returnMsg.errorMsg));
} else {
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
}
@ -90,7 +90,7 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
if (rq.apiRoll || (DEVMODE && config.logRolls)) {
// If enabled, log rolls so we can see what went wrong
dbClient
.execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnmsg.errorCode, rq.apiRoll ? null : rq.dd.m.id])
.execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnMsg.errorCode, rq.apiRoll ? null : rq.dd.m.id])
.catch((e) => utils.commonLoggers.dbError('rollQueue.ts:82', 'insert into', e));
}
} else {
@ -167,7 +167,7 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
if (rq.apiRoll && !apiErroredOut) {
dbClient
.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnmsg.errorCode, n ? n.id : null])
.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnMsg.errorCode, n ? n.id : null])
.catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e));
rq.api.resolve(
@ -175,19 +175,19 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
JSON.stringify(
rq.modifiers.count
? {
counts: countEmbed,
details: pubEmbedDetails,
}
counts: countEmbed,
details: pubEmbedDetails,
}
: {
details: pubEmbedDetails,
},
),
),
details: pubEmbedDetails,
}
)
)
);
}
}
} catch (e) {
log(LT.ERROR, `Unddandled Error: ${JSON.stringify(e)}`);
log(LT.ERROR, `Unhandled RQ Error: ${JSON.stringify(e)}`);
if (rq.apiRoll && !apiErroredOut) {
rq.api.resolve(stdResp.InternalServerError(JSON.stringify(e)));
}
@ -223,7 +223,7 @@ The results for this roll will replace this message when it is done.`,
setInterval(() => {
log(
LT.LOG,
`Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`,
`Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`
);
if (rollQueue.length && currentWorkers < config.limits.maxWorkers) {
const temp = rollQueue.shift();

View File

@ -10,8 +10,8 @@ export const loggingEnabled = true;
// genRoll(size) returns number
// genRoll rolls a die of size size and returns the result
export const genRoll = (size: number, maximiseRoll: boolean, nominalRoll: boolean): number => {
if (maximiseRoll) {
export const genRoll = (size: number, maximizeRoll: boolean, nominalRoll: boolean): number => {
if (maximizeRoll) {
return size;
} else {
// Math.random * size will return a decimal number between 0 and size (excluding size), so add 1 and floor the result to not get 0 as a result
@ -21,12 +21,12 @@ export const genRoll = (size: number, maximiseRoll: boolean, nominalRoll: boolea
// genFateRoll returns -1|0|1
// genFateRoll turns a d6 into a fate die, with sides: -1, -1, 0, 0, 1, 1
export const genFateRoll = (maximiseRoll: boolean, nominalRoll: boolean): number => {
export const genFateRoll = (maximizeRoll: boolean, nominalRoll: boolean): number => {
if (nominalRoll) {
return 0;
} else {
const sides = [-1, -1, 0, 0, 1, 1];
return sides[genRoll(6, maximiseRoll, nominalRoll) - 1];
return sides[genRoll(6, maximizeRoll, nominalRoll) - 1];
}
};
@ -55,12 +55,12 @@ export const compareTotalRolls = (a: ReturnData, b: ReturnData): number => {
};
// compareRolls(a, b) returns -1|0|1
// compareRolls is used to order an array of RollSets by RollSet.origidx
export const compareOrigidx = (a: RollSet, b: RollSet): number => {
if (a.origidx < b.origidx) {
// compareRolls is used to order an array of RollSets by RollSet.origIdx
export const compareOrigIdx = (a: RollSet, b: RollSet): number => {
if (a.origIdx < b.origIdx) {
return -1;
}
if (a.origidx > b.origidx) {
if (a.origIdx > b.origIdx) {
return 1;
}
return 0;
@ -73,8 +73,8 @@ export const escapeCharacters = (str: string, esc: string): string => {
for (const e of esc) {
loggingEnabled && log(LT.LOG, `Escaping character ${e} | ${str}, ${esc}`);
// Create a new regex to look for that char that needs replaced and escape it
const temprgx = new RegExp(`[${e}]`, 'g');
str = str.replace(temprgx, `\\${e}`);
const tempRgx = new RegExp(`[${e}]`, 'g');
str = str.replace(tempRgx, `\\${e}`);
}
return str;
};

View File

@ -11,7 +11,7 @@ self.postMessage('ready');
// Handle the roll
self.onmessage = async (e) => {
const payload = e.data;
const returnmsg = parseRoll(payload.rollCmd, payload.modifiers) || {
const returnMsg = parseRoll(payload.rollCmd, payload.modifiers) || {
error: true,
errorCode: 'EmptyMessage',
errorMsg: 'Error: Empty message',
@ -27,7 +27,7 @@ self.onmessage = async (e) => {
exploded: 0,
},
};
self.postMessage(returnmsg);
self.postMessage(returnMsg);
loggingEnabled && (await closeLog());
self.close();
};

View File

@ -6,11 +6,11 @@ import {
} from '../../deps.ts';
import { RollConf, RollSet, RollType } from './solver.d.ts';
import { compareOrigidx, compareRolls, genFateRoll, genRoll, loggingEnabled } from './rollUtils.ts';
import { compareOrigIdx, compareRolls, genFateRoll, genRoll, loggingEnabled } from './rollUtils.ts';
// roll(rollStr, maximiseRoll, nominalRoll) returns RollSet
// roll(rollStr, maximizeRoll, nominalRoll) returns RollSet
// roll parses and executes the rollStr, if needed it will also make the roll the maximum or average
export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolean): RollSet[] => {
export const roll = (rollStr: string, maximizeRoll: boolean, nominalRoll: boolean): RollSet[] => {
/* Roll Capabilities
* Deciphers and rolls a single dice roll set
*
@ -21,7 +21,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
rollStr = rollStr.toLowerCase();
// Split the roll on the die size (and the drop if its there)
const dpts = rollStr.split('d');
const dPts = rollStr.split('d');
// Initialize the configuration to store the parsed data
let rollType: RollType = '';
@ -47,35 +47,35 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
reroll: {
on: false,
once: false,
nums: <number[]> [],
nums: <number[]>[],
},
critScore: {
on: false,
range: <number[]> [],
range: <number[]>[],
},
critFail: {
on: false,
range: <number[]> [],
range: <number[]>[],
},
exploding: {
on: false,
once: false,
compounding: false,
penetrating: false,
nums: <number[]> [],
nums: <number[]>[],
},
};
// If the dpts is not long enough, throw error
if (dpts.length < 2) {
// If the dPts is not long enough, throw error
if (dPts.length < 2) {
throw new Error('YouNeedAD');
}
// Fill out the die count, first item will either be an int or empty string, short circuit execution will take care of replacing the empty string with a 1
const rawDC = dpts.shift() || '1';
const rawDC = dPts.shift() || '1';
const tempDC = rawDC.replace(/\D/g, '');
// Rejoin all remaining parts
let remains = dpts.join('d');
let remains = dPts.join('d');
// Manual Parsing for custom roll types
let manualParse = false;
@ -119,10 +119,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
rollType = 'roll20';
rollConf.dieCount = parseInt(tempDC);
// Finds the end of the die size/beginnning of the additional options
let afterDieIdx = dpts[0].search(/\D/);
// Finds the end of the die size/beginning of the additional options
let afterDieIdx = dPts[0].search(/\D/);
if (afterDieIdx === -1) {
afterDieIdx = dpts[0].length;
afterDieIdx = dPts[0].length;
}
// Get the die size out of the remains and into the rollConf
@ -377,7 +377,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
const rollSet = [];
/* Roll will contain objects of the following format:
* {
* origidx: 0,
* origIdx: 0,
* roll: 0,
* dropped: false,
* rerolled: false,
@ -388,7 +388,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
*
* Each of these is defined as following:
* {
* origidx: The original index of the roll
* origIdx: The original index of the roll
* roll: The resulting roll on this die in the set
* dropped: This die is to be dropped as it was one of the dy lowest dice
* rerolled: This die has been rerolled as it matched rz, it is replaced by the very next die in the set
@ -398,10 +398,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
* }
*/
// Initialize a templet rollSet to copy multiple times
// Initialize a template rollSet to copy multiple times
const templateRoll: RollSet = {
type: rollType,
origidx: 0,
origIdx: 0,
roll: 0,
dropped: false,
rerolled: false,
@ -424,10 +424,10 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
// Copy the template to fill out for this iteration
const rolling = JSON.parse(JSON.stringify(templateRoll));
// If maximiseRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
rolling.roll = rollType === 'fate' ? genFateRoll(maximiseRoll, nominalRoll) : genRoll(rollConf.dieSize, maximiseRoll, nominalRoll);
// Set origidx of roll
rolling.origidx = i;
// If maximizeRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
rolling.roll = rollType === 'fate' ? genFateRoll(maximizeRoll, nominalRoll) : genRoll(rollConf.dieSize, maximizeRoll, nominalRoll);
// Set origIdx of roll
rolling.origIdx = i;
// If critScore arg is on, check if the roll should be a crit, if its off, check if the roll matches the die size
if (rollConf.critScore.on && rollConf.critScore.range.indexOf(rolling.roll) >= 0) {
@ -467,8 +467,8 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
// Copy the template to fill out for this iteration
const newReroll = JSON.parse(JSON.stringify(templateRoll));
// If maximiseRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
newReroll.roll = genRoll(rollConf.dieSize, maximiseRoll, nominalRoll);
// If maximizeRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
newReroll.roll = genRoll(rollConf.dieSize, maximizeRoll, nominalRoll);
// If critScore arg is on, check if the roll should be a crit, if its off, check if the roll matches the die size
if (rollConf.critScore.on && rollConf.critScore.range.indexOf(newReroll.roll) >= 0) {
@ -496,8 +496,8 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
// Copy the template to fill out for this iteration
const newExplodingRoll = JSON.parse(JSON.stringify(templateRoll));
// If maximiseRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
newExplodingRoll.roll = genRoll(rollConf.dieSize, maximiseRoll, nominalRoll);
// If maximizeRoll is on, set the roll to the dieSize, else if nominalRoll is on, set the roll to the average roll of dieSize, else generate a new random roll
newExplodingRoll.roll = genRoll(rollConf.dieSize, maximizeRoll, nominalRoll);
// Always mark this roll as exploding
newExplodingRoll.exploding = true;
@ -572,7 +572,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
}
loggingEnabled && log(LT.LOG, `${loopCount} Handling ${rollType} ${rollStr} | Setting originalIdx on ${JSON.stringify(rollSet[j])}`);
rollSet[j].origidx = j;
rollSet[j].origIdx = j;
if (rollSet[j].rerolled) {
rerollCount++;
@ -634,7 +634,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
}
// Finally, return the rollSet to its original order
rollSet.sort(compareOrigidx);
rollSet.sort(compareOrigIdx);
}
// Handle OVA dropping/keeping

View File

@ -5,7 +5,7 @@ export type RollType = '' | 'roll20' | 'fate' | 'cwod' | 'ova';
// RollSet is used to preserve all information about a calculated roll
export type RollSet = {
type: RollType;
origidx: number;
origIdx: number;
roll: number;
dropped: boolean;
rerolled: boolean;

View File

@ -63,34 +63,34 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
// Call the solver on the items between openParen and closeParen (excluding the parens)
const parenSolve = fullSolver(conf.slice(openParen + 1, closeParen), true);
// Replace the itemes between openParen and closeParen (including the parens) with its solved equilvalent
// Replace the items between openParen and closeParen (including the parens) with its solved equivalent
conf.splice(openParen, closeParen - openParen + 1, parenSolve);
// Determing if we need to add in a multiplication sign to handle implicit multiplication (like "(4)2" = 8)
// Determining if we need to add in a multiplication sign to handle implicit multiplication (like "(4)2" = 8)
// insertedMult flags if there was a multiplication sign inserted before the parens
let insertedMult = false;
// Check if a number was directly before openParen and slip in the "*" if needed
if (((openParen - 1) > -1) && (signs.indexOf(conf[openParen - 1].toString()) === -1)) {
if (openParen - 1 > -1 && signs.indexOf(conf[openParen - 1].toString()) === -1) {
insertedMult = true;
conf.splice(openParen, 0, '*');
}
// Check if a number is directly after closeParen and slip in the "*" if needed
if (!insertedMult && (((openParen + 1) < conf.length) && (signs.indexOf(conf[openParen + 1].toString()) === -1))) {
if (!insertedMult && openParen + 1 < conf.length && signs.indexOf(conf[openParen + 1].toString()) === -1) {
conf.splice(openParen + 1, 0, '*');
} else if (insertedMult && (((openParen + 2) < conf.length) && (signs.indexOf(conf[openParen + 2].toString()) === -1))) {
// insertedMult is utilized here to let us account for an additional item being inserted into the array (the "*" from before openParn)
} else if (insertedMult && openParen + 2 < conf.length && signs.indexOf(conf[openParen + 2].toString()) === -1) {
// insertedMult is utilized here to let us account for an additional item being inserted into the array (the "*" from before openParen)
conf.splice(openParen + 2, 0, '*');
}
}
// Evaluate all EMMDAS by looping thru each teir of operators (exponential is the higehest teir, addition/subtraction the lowest)
// Evaluate all EMDAS by looping thru each tier of operators (exponential is the highest tier, addition/subtraction the lowest)
const allCurOps = [['^'], ['*', '/', '%'], ['+', '-']];
allCurOps.forEach((curOps) => {
loggingEnabled && log(LT.LOG, `Evaluating roll ${JSON.stringify(conf)} | Evaluating ${JSON.stringify(curOps)}`);
// Iterate thru all operators/operands in the conf
for (let i = 0; i < conf.length; i++) {
loggingEnabled && log(LT.LOG, `Evaluating roll ${JSON.stringify(conf)} | Evaluating ${JSON.stringify(curOps)} | Checking ${JSON.stringify(conf[i])}`);
// Check if the current index is in the active teir of operators
// Check if the current index is in the active tier of operators
if (curOps.indexOf(conf[i].toString()) > -1) {
// Grab the operands from before and after the operator
const operand1 = conf[i - 1];
@ -137,7 +137,7 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
}
// Verify a second time that both are numbers before doing math, throwing an error if necessary
if ((typeof oper1 === 'number') && (typeof oper2 === 'number')) {
if (typeof oper1 === 'number' && typeof oper2 === 'number') {
// Finally do the operator on the operands, throw an error if the operator is not found
switch (conf[i]) {
case '^':
@ -177,16 +177,16 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
if (conf.length > 1) {
loggingEnabled && log(LT.LOG, `ConfWHAT? ${JSON.stringify(conf)}`);
throw new Error('ConfWhat');
} else if (singleNum && (typeof (conf[0]) === 'number')) {
} else if (singleNum && typeof conf[0] === 'number') {
// If we are only left with a number, populate the stepSolve with it
stepSolve.total = conf[0];
stepSolve.details = conf[0].toString();
} else {
// Else fully populate the stepSolve with what was computed
stepSolve.total = (<SolvedStep> conf[0]).total;
stepSolve.details = (<SolvedStep> conf[0]).details;
stepSolve.containsCrit = (<SolvedStep> conf[0]).containsCrit;
stepSolve.containsFail = (<SolvedStep> conf[0]).containsFail;
stepSolve.total = (<SolvedStep>conf[0]).total;
stepSolve.details = (<SolvedStep>conf[0]).details;
stepSolve.containsCrit = (<SolvedStep>conf[0]).containsCrit;
stepSolve.containsFail = (<SolvedStep>conf[0]).containsFail;
}
// If this was a nested call, add on parens around the details to show what math we've done

View File

@ -23,7 +23,7 @@ const ask = async (question: string, stdin = Deno.stdin, stdout = Deno.stdout):
await stdout.write(new TextEncoder().encode(question));
// Read console's input into answer
const n = <number> await stdin.read(buf);
const n = <number>await stdin.read(buf);
const answer = new TextDecoder().decode(buf.subarray(0, n));
return answer.trim();
@ -84,8 +84,8 @@ const cmdPrompt = async (logChannel: bigint, botName: string): Promise<void> =>
Available Commands:
exit - closes bot
stop - closes the CLI
m [ChannelID] [messgae] - sends message to specific ChannelID as the bot
ml [message] sends a message to the specified botlog
m [ChannelID] [message] - sends message to specific ChannelID as the bot
ml [message] sends a message to the specified bot log channel
help - this message`);
} // Unhandled commands die here
else {
@ -101,7 +101,8 @@ const messageSendError = (location: string, message: DiscordenoMessage | string,
genericLogger(LT.ERROR, `${location} | Failed to send message: ${JSON.stringify(message)} | Error: ${err.name} - ${err.message}`);
const messageDeleteError = (location: string, message: DiscordenoMessage | string, err: Error) =>
genericLogger(LT.ERROR, `${location} | Failed to delete message: ${JSON.stringify(message)} | Error: ${err.name} - ${err.message}`);
const dbError = (location: string, type: string, err: Error) => genericLogger(LT.ERROR, `${location} | Failed to ${type} database | Error: ${err.name} - ${err.message}`);
const dbError = (location: string, type: string, err: Error) =>
genericLogger(LT.ERROR, `${location} | Failed to ${type} database | Error: ${err.name} - ${err.message}`);
export default {
commonLoggers: {

View File

@ -56,7 +56,7 @@
<h2>Available Commands:</h2>
<div class="slug">
<h3>Rolling Command:</h3>
<p>This command is what the bot is all about. Using the <a href="https://artificer.eanm.dev/roll20" target="_blank" rel="noopener">Roll20 format</a>, any form of dice roll can be performed, with any needed math calculated into the results. This command can even be used as a fairly advanced calculator, supporting parenthesis, exponentials, multiplication, division, modulus, addition, and subtraction.</p>
<p>This command is what the bot is all about. Using the <a href="https://artificer.eanm.dev/roll20" target="_blank" rel="noopener">Roll20 format</a>, any form of dice roll can be performed, with any needed math calculated into the results. This command can even be used as a fairly advanced calculator, supporting parenthesis, exponential, multiplication, division, modulus, addition, and subtraction.</p>
<h4 class="example">Examples:</h4>
<p class="example"><code>[[d20]]</code> - Rolls a simple d20 without anything fancy</p>
<p class="example"><code>[[4d20r1!]]</code> - Rolls 4 d20 dice, rerolling any dice that land on 1, and repeatedly rolling a new d20 for any critical success rolled</p>