Update return types as optional via named arg - Update the modified slash commands for chat sending to use the named arg - Add `slashCommandReturnHelper` for shared funcitonality on return type usage

d8379edee7d8fb0a99e742aa929dc02602490860

Wolfsblvt <wolfsblvt@gmail.com>

3 files changed, +106 -6Showing whitespace changes
public/scripts/slash-commands.js+31 -6
@@ -71,6 +71,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom
7171import { SlashCommandDebugController } from './slash-commands/SlashCommandDebugController.js';
7272import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js';
7373import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js';
74+import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';
7475export {
7576 executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand,
7677};
@@ -176,7 +177,7 @@ export function initDefaultSlashCommands() {
176177 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
177178 name: 'sendas',
178179 callback: sendMessageAs,
179180 returns: 'TheOptionally the text of the sent message, if specified in the "return" argument',
180181 namedArgumentList: [
181182 SlashCommandNamedArgument.fromProps({
182183 name: 'name',
@@ -195,6 +196,14 @@ export function initDefaultSlashCommands() {
195196 typeList: [ARGUMENT_TYPE.NUMBER],
196197 enumProvider: commonEnumProviders.messages({ allowIdAfter: true }),
197198 }),
199+ SlashCommandNamedArgument.fromProps({
200+ name: 'return',
201+ description: 'The way how you want the return value to be provided',
202+ typeList: [ARGUMENT_TYPE.STRING],
203+ defaultValue: 'none',
204+ enumList: slashCommandReturnHelper.enumList({ allowObject: true }),
205+ forceEnum: true,
206+ }),
198207 ],
199208 unnamedArgumentList: [
200209 new SlashCommandArgument(
@@ -223,7 +232,7 @@ export function initDefaultSlashCommands() {
223232 name: 'sys',
224233 callback: sendNarratorMessage,
225234 aliases: ['nar'],
226235 returns: 'TheOptionally the text of the sent message, if specified in the "return" argument',
227236 namedArgumentList: [
228237 new SlashCommandNamedArgument(
229238 'compact',
@@ -239,6 +248,14 @@ export function initDefaultSlashCommands() {
239248 typeList: [ARGUMENT_TYPE.NUMBER],
240249 enumProvider: commonEnumProviders.messages({ allowIdAfter: true }),
241250 }),
251+ SlashCommandNamedArgument.fromProps({
252+ name: 'return',
253+ description: 'The way how you want the return value to be provided',
254+ typeList: [ARGUMENT_TYPE.STRING],
255+ defaultValue: 'none',
256+ enumList: slashCommandReturnHelper.enumList({ allowObject: true }),
257+ forceEnum: true,
258+ }),
242259 ],
243260 unnamedArgumentList: [
244261 new SlashCommandArgument(
@@ -278,7 +295,7 @@ export function initDefaultSlashCommands() {
278295 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
279296 name: 'comment',
280297 callback: sendCommentMessage,
281298 returns: 'TheOptionally the text of the sent message, if specified in the "return" argument',
282299 namedArgumentList: [
283300 new SlashCommandNamedArgument(
284301 'compact',
@@ -294,6 +311,14 @@ export function initDefaultSlashCommands() {
294311 typeList: [ARGUMENT_TYPE.NUMBER],
295312 enumProvider: commonEnumProviders.messages({ allowIdAfter: true }),
296313 }),
314+ SlashCommandNamedArgument.fromProps({
315+ name: 'return',
316+ description: 'The way how you want the return value to be provided',
317+ typeList: [ARGUMENT_TYPE.STRING],
318+ defaultValue: 'none',
319+ enumList: slashCommandReturnHelper.enumList({ allowObject: true }),
320+ forceEnum: true,
321+ }),
297322 ],
298323 unnamedArgumentList: [
299324 new SlashCommandArgument(
@@ -3210,7 +3235,7 @@ export async function sendMessageAs(args, text) {
32103235 await saveChatConditional();
32113236 }
32123237
3213- return message.mes;
3238+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
32143239}
32153240
32163241export async function sendNarratorMessage(args, text) {
@@ -3264,7 +3289,7 @@ export async function sendNarratorMessage(args, text) {
32643289 await saveChatConditional();
32653290 }
32663291
3267- return message.mes;
3292+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
32683293}
32693294
32703295export async function promptQuietForLoudResponse(who, text) {
@@ -3353,7 +3378,7 @@ async function sendCommentMessage(args, text) {
33533378 await saveChatConditional();
33543379 }
33553380
3356- return message.mes;
3381+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
33573382}
33583383
33593384/**
public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js+1 -0
@@ -36,6 +36,7 @@ export const enumIcons = {
3636 message: '💬',
3737 voice: '🎤',
3838 server: '🖥️',
39+ popup: '🗔',
3940
4041 true: '✔️',
4142 false: '❌',
public/scripts/slash-commands/SlashCommandReturnHelper.js+74 -0
@@ -0,0 +1,74 @@
1+import { sendSystemMessage, system_message_types } from '../../script.js';
2+import { callGenericPopup, POPUP_TYPE } from '../popup.js';
3+import { escapeHtml } from '../utils.js';
4+import { enumIcons } from './SlashCommandCommonEnumsProvider.js';
5+import { enumTypes, SlashCommandEnumValue } from './SlashCommandEnumValue.js';
6+
7+/** @typedef {'pipe'|'object'|'chat-html'|'chat-text'|'popup-html'|'popup-text'|'toast-html'|'toast-text'|'console'|'none'} SlashCommandReturnType */
8+
9+export const slashCommandReturnHelper = {
10+ /**
11+ * Gets/creates the enum list of types of return relevant for a slash command
12+ *
13+ * @param {object} [options={}] Options
14+ * @param {boolean} [options.allowPipe=true] Allow option to pipe the return value
15+ * @param {boolean} [options.allowObject=false] Allow option to return the value as an object
16+ * @param {boolean} [options.allowChat=false] Allow option to return the value as a chat message
17+ * @param {boolean} [options.allowPopup=false] Allow option to return the value as a popup
18+ * @returns {SlashCommandEnumValue[]} The enum list
19+ */
20+ enumList: ({ allowPipe = true, allowObject = false, allowChat = false, allowPopup = false } = {}) => [
21+ allowPipe && new SlashCommandEnumValue('pipe', 'Return to the pipe for the next command', enumTypes.name, '|'),
22+ allowObject && new SlashCommandEnumValue('object', 'Return as an object to the pipe for the next command', enumTypes.variable, enumIcons.dictionary),
23+ allowChat && new SlashCommandEnumValue('chat-html', 'Sending a chat message with the return value - Can display HTML', enumTypes.command, enumIcons.message),
24+ allowChat && new SlashCommandEnumValue('chat-text', 'Sending a chat message with the return value - Will only display as text', enumTypes.qr, enumIcons.message),
25+ new SlashCommandEnumValue('popup-html', 'Showing as a popup with the return value - Can display HTML', enumTypes.command, enumIcons.popup),
26+ new SlashCommandEnumValue('popup-text', 'Showing as a popup with the return value - Will only display as text', enumTypes.qr, enumIcons.popup),
27+ new SlashCommandEnumValue('toast-html', 'Show the return value as a toast notification - Can display HTML', enumTypes.command, 'ℹ️'),
28+ new SlashCommandEnumValue('toast-text', 'Show the return value as a toast notification - Will only display as text', enumTypes.qr, 'ℹ️'),
29+ new SlashCommandEnumValue('console', 'Log the return value to the console', enumTypes.enum, '>'),
30+ new SlashCommandEnumValue('none', 'No return value'),
31+ ].filter(x => !!x),
32+
33+ /**
34+ * Handles the return value based on the specified type
35+ *
36+ * @param {SlashCommandReturnType} type The type of return
37+ * @param {object|number|string} value The value to return
38+ * @param {object} [options={}] Options
39+ * @param {(o: object) => string} [options.objectToStringFunc=null] Function to convert the object to a string, if object was provided and 'object' was not the chosen return type
40+ * @returns {Promise<*>} The processed return value
41+ */
42+ async doReturn(type, value, { objectToStringFunc = o => o?.toString() } = {}) {
43+ const stringValue = typeof value !== 'string' ? objectToStringFunc(value) : value;
44+
45+ switch (type) {
46+ case 'popup-html':
47+ case 'popup-text':
48+ case 'chat-text':
49+ case 'chat-html':
50+ case 'toast-text':
51+ case 'toast-html': {
52+ const shouldHtml = type.endsWith('html');
53+ const makeHtml = (str) => (new showdown.Converter()).makeHtml(str);
54+
55+ if (type.startsWith('popup')) await callGenericPopup(shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue), POPUP_TYPE.TEXT);
56+ if (type.startsWith('chat')) sendSystemMessage(system_message_types.GENERIC, shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue));
57+ if (type.startsWith('toast')) toastr.info(stringValue, null, { escapeHtml: !shouldHtml }); // Toastr handles HTML conversion internally already
58+
59+ return '';
60+ }
61+ case 'pipe':
62+ return stringValue ?? '';
63+ case 'object':
64+ return JSON.stringify(value);
65+ case 'console':
66+ console.info(value);
67+ return '';
68+ case 'none':
69+ return '';
70+ default:
71+ throw new Error(`Unknown return type: ${type}`);
72+ }
73+ },
74+};