Change artigen to take rollRequest to use originalCommand as the raw text, then use remaining args after getModifiers eats mods

This commit is contained in:
Ean Milligan 2025-05-05 18:19:39 -04:00
parent 2fe2c5f296
commit b169ee8632
5 changed files with 65 additions and 53 deletions

View File

@ -3,7 +3,7 @@ import { log, LogTypes as LT } from '@Log4Deno';
import { SolvedRoll } from 'artigen/artigen.d.ts'; import { SolvedRoll } from 'artigen/artigen.d.ts';
import { tokenizeCmd } from 'artigen/cmdTokenizer.ts'; import { tokenizeCmd } from 'artigen/cmdTokenizer.ts';
import { RollModifiers } from 'artigen/dice/dice.d.ts'; import { QueuedRoll } from 'artigen/managers/manager.d.ts';
import { cmdSplitRegex, escapeCharacters } from 'artigen/utils/escape.ts'; import { cmdSplitRegex, escapeCharacters } from 'artigen/utils/escape.ts';
import { loggingEnabled } from 'artigen/utils/logFlag.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts';
@ -11,9 +11,9 @@ import { assertPrePostBalance } from 'artigen/utils/parenBalance.ts';
import { compareTotalRolls, compareTotalRollsReverse } from 'artigen/utils/sortFuncs.ts'; import { compareTotalRolls, compareTotalRollsReverse } from 'artigen/utils/sortFuncs.ts';
import { translateError } from 'artigen/utils/translateError.ts'; import { translateError } from 'artigen/utils/translateError.ts';
// runCmd(fullCmd, modifiers) // runCmd(rollRequest)
// runCmd handles converting fullCmd into a computer readable format for processing, and finally executes the solving // runCmd handles converting rollRequest into a computer readable format for processing, and finally executes the solving
export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => { export const runCmd = (rollRequest: QueuedRoll): SolvedRoll => {
const returnMsg: SolvedRoll = { const returnMsg: SolvedRoll = {
error: false, error: false,
errorCode: '', errorCode: '',
@ -34,22 +34,19 @@ export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll =>
// Whole processor lives in a try-catch to catch artigen's intentional error conditions // Whole processor lives in a try-catch to catch artigen's intentional error conditions
try { try {
// filter removes all null/empty strings since we don't care about them // filter removes all null/empty strings since we don't care about them
const sepCmds = fullCmd.split(cmdSplitRegex).filter((x) => x); const sepCmds = rollRequest.rollCmd.split(cmdSplitRegex).filter((x) => x);
loggingEnabled && log(LT.LOG, `Split cmd into parts ${JSON.stringify(sepCmds)}`); loggingEnabled && log(LT.LOG, `Split cmd into parts ${JSON.stringify(sepCmds)}`);
// Verify prefix/postfix balance // Verify prefix/postfix balance
assertPrePostBalance(sepCmds); assertPrePostBalance(sepCmds);
// Send the split roll into the command tokenizer to get raw response data // Send the split roll into the command tokenizer to get raw response data
const [tempReturnData, tempCountDetails] = tokenizeCmd(sepCmds, modifiers, true); const [tempReturnData, tempCountDetails] = tokenizeCmd(sepCmds, rollRequest.modifiers, true);
loggingEnabled && log(LT.LOG, `Return data is back ${JSON.stringify(tempReturnData)}`); loggingEnabled && log(LT.LOG, `Return data is back ${JSON.stringify(tempReturnData)}`);
// Remove any floating spaces from fullCmd // Remove any floating spaces from originalCommand
fullCmd = fullCmd.trim(); // Escape any | and ` chars in originalCommand to prevent spoilers and code blocks from acting up
const rawCmd = escapeCharacters(rollRequest.originalCommand.trim(), '|').replace(/`/g, '');
// Escape any | and ` chars in fullCmd to prevent spoilers and code blocks from acting up
fullCmd = escapeCharacters(fullCmd, '|');
fullCmd = fullCmd.replace(/`/g, '');
let line1 = ''; let line1 = '';
let line2 = ''; let line2 = '';
@ -60,26 +57,26 @@ export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll =>
line2 = resultStr; line2 = resultStr;
// If a theoretical roll is requested, mark the output as such, else use default formatting // If a theoretical roll is requested, mark the output as such, else use default formatting
if (modifiers.maxRoll || modifiers.minRoll || modifiers.nominalRoll) { if (rollRequest.modifiers.maxRoll || rollRequest.modifiers.minRoll || rollRequest.modifiers.nominalRoll) {
const theoreticalTexts = ['Maximum', 'Minimum', 'Nominal']; const theoreticalTexts = ['Maximum', 'Minimum', 'Nominal'];
const theoreticalBools = [modifiers.maxRoll, modifiers.minRoll, modifiers.nominalRoll]; const theoreticalBools = [rollRequest.modifiers.maxRoll, rollRequest.modifiers.minRoll, rollRequest.modifiers.nominalRoll];
const theoreticalText = theoreticalTexts[theoreticalBools.indexOf(true)]; const theoreticalText = theoreticalTexts[theoreticalBools.indexOf(true)];
line1 = ` requested the Theoretical ${theoreticalText} of:\n\`${fullCmd}\``; line1 = ` requested the Theoretical ${theoreticalText} of:\n\`${rawCmd}\``;
line2 = `Theoretical ${theoreticalText} ${resultStr}`; line2 = `Theoretical ${theoreticalText} ${resultStr}`;
} else if (modifiers.order === 'a') { } else if (rollRequest.modifiers.order === 'a') {
line1 = ` requested the following rolls to be ordered from least to greatest:\n\`${fullCmd}\``; line1 = ` requested the following rolls to be ordered from least to greatest:\n\`${rawCmd}\``;
tempReturnData.sort(compareTotalRolls); tempReturnData.sort(compareTotalRolls);
} else if (modifiers.order === 'd') { } else if (rollRequest.modifiers.order === 'd') {
line1 = ` requested the following rolls to be ordered from greatest to least:\n\`${fullCmd}\``; line1 = ` requested the following rolls to be ordered from greatest to least:\n\`${rawCmd}\``;
tempReturnData.sort(compareTotalRollsReverse); tempReturnData.sort(compareTotalRollsReverse);
} else { } else {
line1 = ` rolled:\n\`${fullCmd}\``; line1 = ` rolled:\n\`${rawCmd}\``;
} }
// Fill out all of the details and results now // Fill out all of the details and results now
tempReturnData.forEach((e) => { tempReturnData.forEach((e) => {
loggingEnabled && log(LT.LOG, `Parsing roll ${fullCmd} | Making return text ${JSON.stringify(e)}`); loggingEnabled && log(LT.LOG, `Parsing roll ${rollRequest.rollCmd} | Making return text ${JSON.stringify(e)}`);
let preFormat = ''; let preFormat = '';
let postFormat = ''; let postFormat = '';
@ -94,21 +91,21 @@ export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll =>
} }
// Populate line2 (the results) and line3 (the details) with their data // Populate line2 (the results) and line3 (the details) with their data
if (modifiers.order === '') { if (rollRequest.modifiers.order === '') {
line2 += `${e.rollPreFormat ? escapeCharacters(e.rollPreFormat, '|*_~`') : ' '}${preFormat}${modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}${ line2 += `${e.rollPreFormat ? escapeCharacters(e.rollPreFormat, '|*_~`') : ' '}${preFormat}${rollRequest.modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}${
e.rollPostFormat ? escapeCharacters(e.rollPostFormat, '|*_~`') : '' e.rollPostFormat ? escapeCharacters(e.rollPostFormat, '|*_~`') : ''
}`; }`;
} else { } else {
// If order is on, turn rolls into csv without formatting // If order is on, turn rolls into csv without formatting
line2 += `${preFormat}${modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}, `; line2 += `${preFormat}${rollRequest.modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}, `;
} }
const rollDetails = modifiers.noDetails ? ' = ' : ` = ${e.rollDetails} = `; const rollDetails = rollRequest.modifiers.noDetails ? ' = ' : ` = ${e.rollDetails} = `;
line3 += `\`${e.initConfig}\`${rollDetails}${preFormat}${modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}\n`; line3 += `\`${e.initConfig}\`${rollDetails}${preFormat}${rollRequest.modifiers.commaTotals ? e.rollTotal.toLocaleString() : e.rollTotal}${postFormat}\n`;
}); });
// If order is on, remove trailing ", " // If order is on, remove trailing ", "
if (modifiers.order !== '') { if (rollRequest.modifiers.order !== '') {
line2 = line2.substring(0, line2.length - 2); line2 = line2.substring(0, line2.length - 2);
} }
@ -139,7 +136,7 @@ export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll =>
} catch (e) { } catch (e) {
// Fill in the return block // Fill in the return block
const solverError = e as Error; const solverError = e as Error;
loggingEnabled && log(LT.ERROR, `Error hit: ${solverError.message} | ${fullCmd}`); loggingEnabled && log(LT.ERROR, `Error hit: ${solverError.message} | ${rollRequest.rollCmd}`);
returnMsg.error = true; returnMsg.error = true;
[returnMsg.errorCode, returnMsg.errorMsg] = translateError(solverError); [returnMsg.errorCode, returnMsg.errorMsg] = translateError(solverError);
} }

View File

@ -2,7 +2,22 @@ import { log, LogTypes as LT } from '@Log4Deno';
import { RollModifiers } from 'artigen/dice/dice.d.ts'; import { RollModifiers } from 'artigen/dice/dice.d.ts';
export const getModifiers = (args: string[]): RollModifiers => { export const Modifiers = Object.freeze({
Count: '-c',
NoDetails: '-nd',
SuperNoDetails: '-snd',
HideRaw: '-hr',
Spoiler: '-s',
Max: '-max',
MaxShorthand: '-m',
Min: '-min',
Nominal: '-n',
GM: '-gm',
Order: '-o',
CommaTotals: '-ct',
});
export const getModifiers = (args: string[]): [RollModifiers, string[]] => {
const modifiers: RollModifiers = { const modifiers: RollModifiers = {
noDetails: false, noDetails: false,
superNoDetails: false, superNoDetails: false,
@ -26,32 +41,32 @@ export const getModifiers = (args: string[]): RollModifiers => {
log(LT.LOG, `Checking ${args.join(' ')} for command modifiers ${i}`); log(LT.LOG, `Checking ${args.join(' ')} for command modifiers ${i}`);
let defaultCase = false; let defaultCase = false;
switch (args[i].toLowerCase()) { switch (args[i].toLowerCase()) {
case '-c': case Modifiers.Count:
modifiers.count = true; modifiers.count = true;
break; break;
case '-nd': case Modifiers.NoDetails:
modifiers.noDetails = true; modifiers.noDetails = true;
break; break;
case '-snd': case Modifiers.SuperNoDetails:
modifiers.superNoDetails = true; modifiers.superNoDetails = true;
break; break;
case '-hr': case Modifiers.HideRaw:
modifiers.hideRaw = true; modifiers.hideRaw = true;
break; break;
case '-s': case Modifiers.Spoiler:
modifiers.spoiler = '||'; modifiers.spoiler = '||';
break; break;
case '-max': case Modifiers.Max:
case '-m': case Modifiers.MaxShorthand:
modifiers.maxRoll = true; modifiers.maxRoll = true;
break; break;
case '-min': case Modifiers.Min:
modifiers.minRoll = true; modifiers.minRoll = true;
break; break;
case '-n': case Modifiers.Nominal:
modifiers.nominalRoll = true; modifiers.nominalRoll = true;
break; break;
case '-gm': case Modifiers.GM:
modifiers.gmRoll = true; modifiers.gmRoll = true;
// -gm is a little more complex, as we must get all of the GMs that need to be DMd // -gm is a little more complex, as we must get all of the GMs that need to be DMd
@ -65,10 +80,10 @@ export const getModifiers = (args: string[]): RollModifiers => {
// If -gm is on and none were found, throw an error // If -gm is on and none were found, throw an error
modifiers.error.name = 'NoGMsFound'; modifiers.error.name = 'NoGMsFound';
modifiers.error.message = 'Must specify at least one GM by @mentioning them'; modifiers.error.message = 'Must specify at least one GM by @mentioning them';
return modifiers; return [modifiers, args];
} }
break; break;
case '-o': case Modifiers.Order:
// Shift the -o out of the array so the next item is the direction // Shift the -o out of the array so the next item is the direction
args.splice(i, 1); args.splice(i, 1);
@ -76,12 +91,12 @@ export const getModifiers = (args: string[]): RollModifiers => {
// If -o is on and asc or desc was not specified, error out // If -o is on and asc or desc was not specified, error out
modifiers.error.name = 'NoOrderFound'; modifiers.error.name = 'NoOrderFound';
modifiers.error.message = 'Must specify `a` or `d` to order the rolls ascending or descending'; modifiers.error.message = 'Must specify `a` or `d` to order the rolls ascending or descending';
return modifiers; return [modifiers, args];
} }
modifiers.order = args[i].toLowerCase()[0]; modifiers.order = args[i].toLowerCase()[0];
break; break;
case '-ct': case Modifiers.CommaTotals:
modifiers.commaTotals = true; modifiers.commaTotals = true;
break; break;
default: default:
@ -100,9 +115,9 @@ export const getModifiers = (args: string[]): RollModifiers => {
if ([modifiers.maxRoll, modifiers.minRoll, modifiers.nominalRoll].filter((b) => b).length > 1) { if ([modifiers.maxRoll, modifiers.minRoll, modifiers.nominalRoll].filter((b) => b).length > 1) {
modifiers.error.name = 'MaxAndNominal'; modifiers.error.name = 'MaxAndNominal';
modifiers.error.message = 'Can only use one of the following at a time:\n`maximize`, `minimize`, `nominal`'; modifiers.error.message = 'Can only use one of the following at a time:\n`maximize`, `minimize`, `nominal`';
return modifiers; return [modifiers, args];
} }
modifiers.valid = true; modifiers.valid = true;
return modifiers; return [modifiers, args];
}; };

View File

@ -1,6 +1,9 @@
import { closeLog, initLog } from '@Log4Deno'; import { closeLog, initLog } from '@Log4Deno';
import { runCmd } from 'artigen/artigen.ts'; import { runCmd } from 'artigen/artigen.ts';
import { QueuedRoll } from 'artigen/managers/manager.d.ts';
import { loggingEnabled } from 'artigen/utils/logFlag.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts';
loggingEnabled && initLog('logs/worker', loggingEnabled); loggingEnabled && initLog('logs/worker', loggingEnabled);
@ -9,9 +12,9 @@ loggingEnabled && initLog('logs/worker', loggingEnabled);
self.postMessage('ready'); self.postMessage('ready');
// Handle the roll // Handle the roll
self.onmessage = async (e) => { self.onmessage = async (e: MessageEvent<QueuedRoll>) => {
const payload = e.data; const payload = e.data;
const returnMsg = runCmd(payload.rollCmd, payload.modifiers) || { const returnMsg = runCmd(payload) || {
error: true, error: true,
errorCode: 'EmptyMessage', errorCode: 'EmptyMessage',
errorMsg: 'Error: Empty message', errorMsg: 'Error: Empty message',

View File

@ -6,8 +6,5 @@ import { loggingEnabled } from 'artigen/utils/logFlag.ts';
export const onWorkerReady = (rollWorker: Worker, rollRequest: QueuedRoll) => { export const onWorkerReady = (rollWorker: Worker, rollRequest: QueuedRoll) => {
loggingEnabled && log(LT.LOG, `Sending roll to worker: ${rollRequest.rollCmd}, ${JSON.stringify(rollRequest.modifiers)}`); loggingEnabled && log(LT.LOG, `Sending roll to worker: ${rollRequest.rollCmd}, ${JSON.stringify(rollRequest.modifiers)}`);
rollWorker.postMessage({ rollWorker.postMessage(rollRequest);
rollCmd: rollRequest.rollCmd,
modifiers: rollRequest.modifiers,
});
}; };

View File

@ -45,7 +45,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
const m = await message.reply(rollingEmbed); const m = await message.reply(rollingEmbed);
// Get modifiers from command // Get modifiers from command
const modifiers = getModifiers(args); const [modifiers, remainingArgs] = getModifiers(args);
// Return early if the modifiers were invalid // Return early if the modifiers were invalid
if (!modifiers.valid) { if (!modifiers.valid) {
@ -60,7 +60,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
return; return;
} }
let rollCmd = message.content.startsWith(`${config.prefix}r`) ? args.join(' ') : message.content; let rollCmd = message.content.startsWith(`${config.prefix}r`) ? remainingArgs.join(' ') : `${config.prefix}${command} ${remainingArgs.join(' ')}`;
// Try to ensure the roll is wrapped // Try to ensure the roll is wrapped
if (!rollCmd.includes(config.prefix)) { if (!rollCmd.includes(config.prefix)) {