feat: add array-wrap and array-unwrap commands (#5277) * feat: add array-wrap and array-unwrap commands * Add LIST as available argument type Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Throw when trying to wrap a closure Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Throw on closure in array-unwrap * Add the rest of argument types for array-unwrap Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Add Python-friendly aliases * Don't filter out just strings Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Proper primitive value unwrapping * Throw on multiple unnamed arguments * Enhance parsed object wrapping * Update comment to clarify boolean support in value wrapping --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

db07c4a120c9b4e3da9616a111caaeac589fb4dd

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +103 -0Ignore whitespace
public/scripts/slash-commands.js+103 -0
@@ -3214,6 +3214,109 @@ export function initDefaultSlashCommands() {
32143214 helpString: t`Plays the message received sound effect.`,
32153215 }));
32163216
3217+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
3218+ name: 'array-wrap',
3219+ aliases: ['list-wrap'],
3220+ returns: t`unnamed argument value wrapped into an array`,
3221+ helpString: t`Wraps a single unnamed argument into an array if it's not already an array. If the value is an empty string, returns an empty array.`,
3222+ unnamedArgumentList: [
3223+ SlashCommandArgument.fromProps({
3224+ description: t`value`,
3225+ acceptsMultiple: false,
3226+ isRequired: true,
3227+ typeList: [ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.DICTIONARY, ARGUMENT_TYPE.BOOLEAN, ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.LIST],
3228+ }),
3229+ ],
3230+ callback: (_args, value) => {
3231+ // Closures are not supported
3232+ if (value instanceof SlashCommandClosure) {
3233+ throw new SlashCommandExecutionError(t`Closures are not supported as unnamed arguments for /array-wrap. Did you forget to call the closure with parentheses?`);
3234+ }
3235+
3236+ // Multiple unnamed arguments are not supported since acceptsMultiple is false, but check just in case
3237+ if (Array.isArray(value)) {
3238+ throw new SlashCommandExecutionError(t`/array-wrap does not support multiple unnamed arguments.`);
3239+ }
3240+
3241+ // Empty string - empty arrays
3242+ if (value === '') {
3243+ return JSON.stringify([]);
3244+ }
3245+
3246+ try {
3247+ // If the value is a valid JSON string, parse it
3248+ const parsedValue = JSON.parse(value);
3249+
3250+ // Already an array - return as-is
3251+ if (Array.isArray(parsedValue)) {
3252+ return value;
3253+ }
3254+
3255+ // If it's an object, wrap it into an array and stringify
3256+ if (typeof parsedValue === 'object' && parsedValue !== null) {
3257+ return JSON.stringify([parsedValue]);
3258+ }
3259+
3260+ // Wrap the original value (string, number, boolean) into an array, preserving quotes for strings
3261+ return JSON.stringify([value]);
3262+ } catch {
3263+ // Not a valid JSON string - wrap the original value
3264+ return JSON.stringify([value]);
3265+ }
3266+ },
3267+ }));
3268+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
3269+ name: 'array-unwrap',
3270+ aliases: ['list-unwrap'],
3271+ returns: t`unnamed argument value unwrapped from an array`,
3272+ helpString: t`Unwraps the first element of an array provided as an unnamed argument. If the value is not an array, returns the value as-is. If the array is empty, returns an empty string.`,
3273+ unnamedArgumentList: [
3274+ SlashCommandArgument.fromProps({
3275+ description: t`value`,
3276+ acceptsMultiple: false,
3277+ isRequired: true,
3278+ typeList: [ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.DICTIONARY, ARGUMENT_TYPE.BOOLEAN, ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.LIST],
3279+ }),
3280+ ],
3281+ callback: (_args, value) => {
3282+ // Closures are not supported
3283+ if (value instanceof SlashCommandClosure) {
3284+ throw new SlashCommandExecutionError(t`Closures are not supported as unnamed arguments for /array-unwrap. Did you forget to call the closure with parentheses?`);
3285+ }
3286+
3287+ // Multiple unnamed arguments are not supported since acceptsMultiple is false, but check just in case
3288+ if (Array.isArray(value)) {
3289+ throw new SlashCommandExecutionError(t`/array-unwrap does not support multiple unnamed arguments.`);
3290+ }
3291+
3292+ try {
3293+ // If the value is a JSON array, get the first element
3294+ const parsed = JSON.parse(value);
3295+
3296+ if (Array.isArray(parsed)) {
3297+ const unwrappedValue = parsed?.[0] ?? '';
3298+
3299+ // If the first element is null or undefined, return an empty string
3300+ if (unwrappedValue === null || unwrappedValue === undefined) {
3301+ return '';
3302+ }
3303+
3304+ // If the first element is an object, stringify it.
3305+ if (typeof unwrappedValue === 'object') {
3306+ return JSON.stringify(unwrappedValue);
3307+ }
3308+
3309+ // Otherwise, return it as a string.
3310+ return String(unwrappedValue);
3311+ }
3312+ return value;
3313+ } catch {
3314+ // Not a valid JSON - return as-is
3315+ return value;
3316+ }
3317+ },
3318+ }));
3319+
32173320 registerVariableCommands();
32183321}
32193322