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 -0Showing whitespace changes
public/scripts/slash-commands.js+103 -0
@@ -3214,6 +3214,109 @@ export function initDefaultSlashCommands() {
3214 helpString: t`Plays the message received sound effect.`,3214 helpString: t`Plays the message received sound effect.`,
3215 }));3215 }));
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
3217 registerVariableCommands();3320 registerVariableCommands();
3218}3321}
32193322