Issue with single parameter in Discord.js bot dice command

I’m in the process of creating a Discord bot with the Discord.js-commando library, and I’m facing a challenge with my dice rolling command. The basic functionality is operational, but when I try to execute it with a single number, the validation incorrectly flags it as non-numeric.

Here’s what I’m aiming for:

  • !roll - generates a number between 1 and 6
  • !roll 30 - rolls from 1 to 30
  • !roll 50 100 - generates a number between 50 and 100

The problem arises with the command !roll 30. My validation is not recognizing it as a valid number, while the other command formats work correctly. I suspect there might be a straightforward solution that I’m overlooking.

const commando = require('discord.js-commando');
const _ = require('lodash');

class MyDiceCommand extends commando.Command {

    constructor(bot) {
        super(bot, {
            name: 'roll',
            group: 'random',
            memberName: 'roll',
            description: 'Rolls a dice randomly.'
        });
    }

    async run(message, args) {
        let rollArgs = args.split(' ');
        let validNumber = /^[0-9]+$/;

        if (rollArgs[0] || rollArgs[1]) {
            if (!validNumber.test(rollArgs[0]) || !validNumber.test(rollArgs[1])) {
                console.log('rollArgs[0] -> ' + !validNumber.test(rollArgs[0])); // should show true
                console.log('rollArgs[1] -> ' + !validNumber.test(rollArgs[1])); // should show true

                message.reply('Error: Please enter a valid number.');
                return;
            }
        }
        if (rollArgs.length >= 3) {
            message.reply('Error: You can only provide up to 2 parameters.');
            return;
        }
        if (rollArgs[0] > 1000000 || rollArgs[1] > 1000000) {
            message.reply('Please use smaller numbers, as very large values may cause issues.');
            return;
        }
        if (message.content.match(/^!roll$/)) {
            message.reply('You rolled: ' + _.random(1, 6));
        }
        if (message.content.match(/^!roll [0-9]+/)) {
            message.reply('You rolled: ' + _.random(1, rollArgs[0]));
        }
        if (message.content.match(/^!roll ([0-9]+) ([0-9]+)$/)) {
            message.reply('You rolled: ' + _.random(rollArgs[0], rollArgs[1]));
        }
    }
}

module.exports = MyDiceCommand;

Your validation logic checks both parameters even when you only provide one. When you run !roll 30, rollArgs[1] becomes undefined, and your regex test on undefined returns true (not a valid number), which triggers the error. You need to only check parameters that actually exist. Replace your validation block with this:

if (rollArgs[0] && !validNumber.test(rollArgs[0])) {
    message.reply('Error: Please enter a valid number.');
    return;
}
if (rollArgs[1] && !validNumber.test(rollArgs[1])) {
    message.reply('Error: Please enter a valid number.');
    return;
}

This only validates parameters that are present. I hit the same issue with my bot commands - it’s easy to miss when dealing with optional parameters.

yeah, your validation’s the problem. when you run !roll 30, rollArgs[1] is undefined, and testing undefined against regex fails. but your if statement (rollArgs[0] || rollArgs[1]) still runs because rollArgs[0] exists. just check if (rollArgs.length > 1 && !validNumber.test(rollArgs[1])) for the second parameter instead of testing both every time. been there lol

Your conditional logic is broken. if (rollArgs[0] || rollArgs[1]) always returns true when rollArgs[0] exists, but then you test both parameters anyway. When you pass !roll 30, rollArgs[1] is undefined. Testing undefined against your regex returns false, so !validNumber.test(rollArgs[1]) becomes true and triggers the error. I hit this same issue building my first commando bot. Check rollArgs.length first, then only validate the parameters you actually have. Don’t test both every time. Also, you’re manually splitting args when commando has built-in argument handling that’d make this way cleaner.