Mass spelling fix
This commit is contained in:
parent
74c733308f
commit
864f281c60
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 = [
|
||||
|
|
2
deps.ts
2
deps.ts
|
@ -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,
|
||||
|
|
26
mod.ts
26
mod.ts
|
@ -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,7 +80,9 @@ startBot({
|
|||
}, 30000);
|
||||
|
||||
// Interval to update bot list stats every 24 hours
|
||||
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : setInterval(() => {
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -45,7 +45,7 @@ export const generateStats = (
|
|||
rollCount: bigint,
|
||||
utilityCount: bigint,
|
||||
rollRate: number,
|
||||
utilityRate: number,
|
||||
utilityRate: number
|
||||
) => ({
|
||||
embeds: [
|
||||
{
|
||||
|
|
|
@ -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).',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
@ -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.",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -37,11 +37,13 @@ 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: [{
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Guilds Audit',
|
||||
description: `Shows details of the guilds that ${config.name} serves.
|
||||
|
@ -85,10 +87,12 @@ Please see attached file for audit details on cached guilds and members.`,
|
|||
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));
|
||||
};
|
||||
|
|
|
@ -7,8 +7,10 @@ import { infoColor1 } from '../../commandUtils.ts';
|
|||
import utils from '../../utils.ts';
|
||||
|
||||
export const auditHelp = (message: DiscordenoMessage) => {
|
||||
message.send({
|
||||
embeds: [{
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: 'Audit Help',
|
||||
fields: [
|
||||
|
@ -24,10 +26,12 @@ export const auditHelp = (message: DiscordenoMessage) => {
|
|||
},
|
||||
{
|
||||
name: `\`${config.prefix}audit guilds\``,
|
||||
value: 'Shows breakdown of guilds and detials on them',
|
||||
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));
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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)}`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { warnColor } from './commandUtils.ts';
|
||||
|
||||
export const compilingStats = {
|
||||
embeds: [{
|
||||
embeds: [
|
||||
{
|
||||
color: warnColor,
|
||||
title: 'Compiling latest statistics . . .',
|
||||
}],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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: '',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -49,7 +49,7 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
|
|||
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(
|
||||
|
@ -180,14 +180,14 @@ const handleRollWorker = (rq: ApiQueuedRoll | DDQueuedRoll) => {
|
|||
}
|
||||
: {
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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 = '';
|
||||
|
@ -66,16 +66,16 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea
|
|||
},
|
||||
};
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,7 +177,7 @@ 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();
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue