diff --git a/README.md b/README.md index 433dabf..6919fb6 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ The Artificer comes with a few supplemental commands to the main rolling command * `[[d20/40]]` will roll a d20 die and divide it by 40. * `[[((d20+20) - 10) / 5]]` will roll a d20, add 20 to that roll, subtract off 10, and finally divide by 5. * This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message: + * `-c` - Count - Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions * `-nd` - No Details - Suppresses all details of the requested roll * `-snd` - Super No Details - Suppresses all details of the requested roll and hides no details message * `-s` - Spoiler - Spoilers all details of the requested roll @@ -134,8 +135,9 @@ Available Endpoints and Methods Required: * `channel` - The Discord Channel ID that the bot is to send the results into. * `rollstr` - A roll string formatted identically to the roll command detailed in the "Available Commands" section. * Optional query parameters (these parameters do not require values unless specified): - * `snd` - Super No Details - Suppresses all details of the requested roll and hides no details message. + * `c` - Count - Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions * `nd` - No Details - Suppresses all details of the requested roll. + * `snd` - Super No Details - Suppresses all details of the requested roll and hides no details message. * `s` - Spoiler - Spoilers all details of the requested roll. * `m` - Maximize Roll - Rolls the theoretical maximum roll, cannot be used with Nominal roll. * `n` - Nominal Roll - Rolls the theoretical nominal roll, cannot be used with Maximise roll. @@ -200,11 +202,6 @@ If you choose to run version `1.1.0` or newer, ensure you disable the API in `co --- -## Development Plans -Current and future plans are listed on [the Milestones page](https://github.com/Burn-E99/TheArtificer/milestones). - ---- - ## Privacy Policy and Terms of Service The Artificer has a Privacy Policy and Terms of Service to detail expectations of what user data is stored and how users should use The Artificer. The following Privacy Policy and Terms of Service only apply to the officially hosted version of The Artificer (`The Artificer#8166`, Discord ID: `789045930011656223`). diff --git a/src/api.ts b/src/api.ts index d68aaa0..f81f0c1 100644 --- a/src/api.ts +++ b/src/api.ts @@ -19,6 +19,7 @@ import { LT, log } from "../deps.ts"; +import { RollModifiers } from "./mod.d.ts"; import { dbClient, queries } from "./db.ts"; import solver from "./solver/_index.ts"; import { @@ -238,8 +239,21 @@ const start = async (): Promise => { // Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord rollCmd = rollCmd.substring(rollCmd.indexOf(config.prefix) + 2).replace(/%20/g, " "); + const modifiers: RollModifiers = { + noDetails: false, + superNoDetails: false, + spoiler: "", + maxRoll: query.has("m"), + nominalRoll: query.has("n"), + gmRoll: false, + gms: [], + order: query.has("o") ? (query.get("o")?.toLowerCase() || "") : "", + valid: true, + count: query.has("c") + }; + // Parse the roll and get the return text - const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, query.has("m"), query.has("n"), query.has("o") ? (query.get("o")?.toLowerCase() || "") : ""); + const returnmsg = solver.parseRoll(rollCmd, modifiers); // Alert users why this message just appeared and how they can report abues pf this feature const apiPrefix = hideWarn ? '' : `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>\n\n`; diff --git a/src/commands/roll.ts b/src/commands/roll.ts index 161f550..28ef81e 100644 --- a/src/commands/roll.ts +++ b/src/commands/roll.ts @@ -42,7 +42,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command: // Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in const rollCmd = `${command} ${args.join(" ")}`; - const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, modifiers.maxRoll, modifiers.nominalRoll, modifiers.order) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" }; + const returnmsg = solver.parseRoll(rollCmd, modifiers) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" }; let returnText = ""; diff --git a/src/commands/roll/getModifiers.ts b/src/commands/roll/getModifiers.ts index a97bed0..c4edbc3 100644 --- a/src/commands/roll/getModifiers.ts +++ b/src/commands/roll/getModifiers.ts @@ -22,7 +22,8 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri gmRoll: false, gms: [], order: "", - valid: false + valid: false, + count: false }; // Check if any of the args are command flags and pull those out into the modifiers object @@ -30,6 +31,9 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri log(LT.LOG, `Checking ${command}${args.join(" ")} for command modifiers ${i}`); let defaultCase = false; switch (args[i].toLowerCase()) { + case "-c": + modifiers.count = true; + break; case "-nd": modifiers.noDetails = true; break; @@ -69,6 +73,7 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri } break; case "-o": + // Shift the -o out of the array so the next item is the direction args.splice(i, 1); if (!args[i] || args[i].toLowerCase()[0] !== "d" && args[i].toLowerCase()[0] !== "a") { diff --git a/src/constantCmds.ts b/src/constantCmds.ts index d6c90e9..9e4857b 100644 --- a/src/constantCmds.ts +++ b/src/constantCmds.ts @@ -365,6 +365,10 @@ export const constantCmds = { 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 + }, { + name: "`-c` - Count Rolls", + value: "Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions", + inline: true }, { name: "`-o [direction]` - Order Roll", value: `Rolls the requested roll and orders the results in the requested direction diff --git a/src/mod.d.ts b/src/mod.d.ts index 6f5d556..dcb8cdf 100644 --- a/src/mod.d.ts +++ b/src/mod.d.ts @@ -9,6 +9,7 @@ export type EmojiConf = { deleteSender: boolean }; +// RollModifiers is the structure to keep track of the decorators applied to a roll command export type RollModifiers = { noDetails: boolean, superNoDetails: boolean, @@ -18,5 +19,6 @@ export type RollModifiers = { gmRoll: boolean, gms: string[], order: string, - valid: boolean + valid: boolean, + count: boolean } diff --git a/src/solver/parser.ts b/src/solver/parser.ts index 921a0dd..c204553 100644 --- a/src/solver/parser.ts +++ b/src/solver/parser.ts @@ -5,14 +5,15 @@ import { import config from "../../config.ts"; +import { RollModifiers } from "../mod.d.ts"; import { SolvedStep, SolvedRoll, ReturnData } from "./solver.d.ts"; import { compareTotalRolls, escapeCharacters } from "./rollUtils.ts"; import { formatRoll } from "./rollFormatter.ts"; import { fullSolver } from "./solver.ts"; -// parseRoll(fullCmd, localPrefix, localPostfix, maximiseRoll, nominalRoll) +// parseRoll(fullCmd, modifiers) // parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving -export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, maximiseRoll: boolean, nominalRoll: boolean, order: string): SolvedRoll => { +export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => { const returnmsg = { error: false, errorMsg: "", @@ -25,7 +26,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st // Whole function lives in a try-catch to allow safe throwing of errors on purpose try { // Split the fullCmd by the command prefix to allow every roll/math op to be handled individually - const sepRolls = fullCmd.split(localPrefix); + const sepRolls = fullCmd.split(config.prefix); const tempReturnData: ReturnData[] = []; @@ -33,7 +34,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st for (let i = 0; i < sepRolls.length; i++) { log(LT.LOG, `Parsing roll ${fullCmd} | Working ${sepRolls[i]}`); // Split the current iteration on the command postfix to separate the operation to be parsed and the text formatting after the opertaion - const [tempConf, tempFormat] = sepRolls[i].split(localPostfix); + const [tempConf, tempFormat] = sepRolls[i].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); @@ -66,7 +67,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st mathConf[i] = parseFloat(mathConf[i].toString()); } else if (/([0123456789])/g.test(mathConf[i].toString())) { // If there is a number somewhere in mathconf[i] but there are also other characters preventing it from parsing correctly as a number, it should be a dice roll, parse it as such (if it for some reason is not a dice roll, formatRoll/roll will handle it) - mathConf[i] = formatRoll(mathConf[i].toString(), maximiseRoll, nominalRoll); + mathConf[i] = formatRoll(mathConf[i].toString(), modifiers.maxRoll, modifiers.nominalRoll); } else if (mathConf[i].toString().toLowerCase() === "e") { // If the operand is the constant e, create a SolvedStep for it mathConf[i] = { @@ -130,23 +131,23 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st let line3 = ""; // If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting - if (maximiseRoll) { - line1 = ` requested the theoretical maximum of: \`${localPrefix}${fullCmd}\``; + if (modifiers.maxRoll) { + line1 = ` requested the theoretical maximum of: \`${config.prefix}${fullCmd}\``; line2 = "Theoretical Maximum Results: "; - } else if (nominalRoll) { - line1 = ` requested the theoretical nominal of: \`${localPrefix}${fullCmd}\``; + } else if (modifiers.nominalRoll) { + line1 = ` requested the theoretical nominal of: \`${config.prefix}${fullCmd}\``; line2 = "Theoretical Nominal Results: "; - } else if (order === "a") { - line1 = ` requested the following rolls to be ordered from least to greatest: \`${localPrefix}${fullCmd}\``; + } else if (modifiers.order === "a") { + line1 = ` requested the following rolls to be ordered from least to greatest: \`${config.prefix}${fullCmd}\``; line2 = "Results: "; tempReturnData.sort(compareTotalRolls); - } else if (order === "d") { - line1 = ` requested the following rolls to be ordered from greatest to least: \`${localPrefix}${fullCmd}\``; + } else if (modifiers.order === "d") { + line1 = ` requested the following rolls to be ordered from greatest to least: \`${config.prefix}${fullCmd}\``; line2 = "Results: "; tempReturnData.sort(compareTotalRolls); tempReturnData.reverse(); } else { - line1 = ` rolled: \`${localPrefix}${fullCmd}\``; + line1 = ` rolled: \`${config.prefix}${fullCmd}\``; line2 = "Results: "; } @@ -167,7 +168,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st } // Populate line2 (the results) and line3 (the details) with their data - if (order === "") { + if (modifiers.order === "") { line2 += `${preFormat}${e.rollTotal}${postFormat}${escapeCharacters(e.rollPostFormat, "|*_~`")}`; } else { // If order is on, turn rolls into csv without formatting @@ -180,7 +181,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st }); // If order is on, remove trailing ", " - if (order !== "") { + if (modifiers.order !== "") { line2 = line2.substring(0, (line2.length - 2)); } @@ -213,7 +214,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st if (errorDetails === "-") { errorMsg += "\nNote: Negative numbers are not supported"; } else if (errorDetails === " ") { - errorMsg += `\nNote: Every roll must be closed by ${localPostfix}`; + errorMsg += `\nNote: Every roll must be closed by ${config.postfix}`; } break; case "NoZerosAllowed":