Files
Valour-Bot-Guide/Guides/5.CommandArguments.md
2026-03-29 02:07:51 +01:00

8.4 KiB

Command Arguments

Now that we have basic commands working, lets make them actually useful by adding arguments. Arguments are the extra words a user types after a command, for example:

say Hello World → the bot should reply with Hello World

repeat 3 Hey → the bot should reply with Hey Hey Hey

How arguments work

After we strip the prefix from the message content, we can split the remaining text into an array of words. The first word is the command name, and everything after is the arguments.

// Strip the prefix from the content
string withoutPrefix = content.Substring(prefix.Length);

// Split into parts: parts[0] = command name, parts[1..] = arguments
string[] parts = withoutPrefix.Split(' ', StringSplitOptions.RemoveEmptyEntries);

// The command name is the first part (lowercase so Ping and ping both work)
string command = parts[0].ToLower();

// The arguments are everything after the command name
string[] args = parts.Skip(1).ToArray();

Adding a say command

The say command takes all the arguments and echoes them back as a message. We join the args array back into a single string using string.Join.

if (command == "say")
{
    // Make sure the user actually gave us something to say
    if (args.Length == 0)
    {
        await channel.SendMessageAsync("Usage: bg/say <message>");
        return;
    }

    // Join all the arguments back into one string and send it
    string messageToSay = string.Join(' ', args);
    await channel.SendMessageAsync(messageToSay);
}

Adding a repeat command

The repeat command takes a number and a word, then repeats the word that many times. This shows how to parse an argument as a specific type (int).

else if (command == "repeat")
{
    // Make sure the user gave us a number AND a word
    if (args.Length < 2)
    {
        await channel.SendMessageAsync("Usage: bg/repeat <number> <word>");
        return;
    }

    // Try to parse the first argument as a number
    if (!int.TryParse(args[0], out int times))
    {
        await channel.SendMessageAsync("The first argument must be a number!");
        return;
    }

    // Clamp the number so people can't repeat 10000 times
    times = Math.Clamp(times, 1, 10);

    // Repeat the word and send the result
    string word = args[1];
    string result = string.Join(' ', Enumerable.Repeat(word, times));
    await channel.SendMessageAsync(result);
}

Updating onMessageReceived

Now we replace the old if check with the new argument-aware approach inside onMessageReceived:

// Function for what to do with the received messages
async Task onMessageReceived(Message message)
{
    // Prefix.. duh..
    string prefix = "bg/";
    // What the message says
    string content = message.Content;

    // Get the channel that the message was sent in
    if (!channelCache.TryGetValue(message.ChannelId, out var channel)) return;

    // If the message doesnt start with the prefix then just ignore it
    if (!content.StartsWith(prefix)) return;

    // Strip the prefix and split the rest into parts
    // parts[0] = command name, parts[1..] = arguments
    string withoutPrefix = content.Substring(prefix.Length);
    string[] parts = withoutPrefix.Split(' ', StringSplitOptions.RemoveEmptyEntries);

    // If there's nothing after the prefix, ignore it
    if (parts.Length == 0) return;

    // Grab the command name (lowercase so Ping and ping both work)
    string command = parts[0].ToLower();
    // Grab any arguments that come after the command name
    string[] args = parts.Skip(1).ToArray();

    // Check if the command is ping
    if (command == "ping")
    {
        // Sends the message `Pong!` to the channel
        await channel.SendMessageAsync("Pong!");
    }
    // Check if the command is say
    else if (command == "say")
    {
        // Make sure the user actually gave us something to say
        if (args.Length == 0)
        {
            await channel.SendMessageAsync("Usage: bg/say <message>");
            return;
        }

        // Join all the arguments back into one string and send it
        string messageToSay = string.Join(' ', args);
        await channel.SendMessageAsync(messageToSay);
    }
    // Check if the command is repeat
    else if (command == "repeat")
    {
        // Make sure the user gave us a number AND a word
        if (args.Length < 2)
        {
            await channel.SendMessageAsync("Usage: bg/repeat <number> <word>");
            return;
        }

        // Try to parse the first argument as a number
        if (!int.TryParse(args[0], out int times))
        {
            await channel.SendMessageAsync("The first argument must be a number!");
            return;
        }

        // Clamp the number so people can't repeat 10000 times
        times = Math.Clamp(times, 1, 10);

        // Repeat the word and send the result
        string word = args[1];
        string result = string.Join(' ', Enumerable.Repeat(word, times));
        await channel.SendMessageAsync(result);
    }
}



Full code below

using Valour.Sdk.Client;
using Valour.Shared;
using DotNetEnv;
using Valour.Sdk.Models;
using Valour.Shared.Models;

ValourClient client = new ValourClient("https://api.valour.gg/");
client.SetupHttpClient();

Env.Load();

string token = Environment.GetEnvironmentVariable("TOKEN") ?? string.Empty;

Dictionary<long, Channel> channelCache = new();

if (string.IsNullOrWhiteSpace(token))
{
    Console.WriteLine($"Token invalid. Please make sure you set a valid token in your .env");
    return;
}

TaskResult loginResult = await client.InitializeUser(token);
if (!loginResult.Success)
{
    Console.WriteLine($"Login failed: {loginResult.Message}");
}

Console.WriteLine($"Logged in as {client.Me.Name} (ID: {client.Me.Id})");

foreach (Planet planet in client.PlanetService.JoinedPlanets)
{
    await planet.EnsureReadyAsync();
    await planet.FetchInitialDataAsync();

    foreach (Channel chan in planet.Channels)
    {
        channelCache[chan.Id] = chan;

        if (chan.ChannelType == ChannelTypeEnum.PlanetChat)
        {
            await chan.OpenWithResult("YourBotName");
        }
    }
}

client.MessageService.MessageReceived += onMessageReceived;

async Task onMessageReceived(Message message)
{
    string prefix = "bg/";
    string content = message.Content;

    if (!channelCache.TryGetValue(message.ChannelId, out var channel)) return;
    if (!content.StartsWith(prefix)) return;

    // Strip the prefix and split the rest into parts
    // parts[0] = command name, parts[1..] = arguments
    string withoutPrefix = content.Substring(prefix.Length);
    string[] parts = withoutPrefix.Split(' ', StringSplitOptions.RemoveEmptyEntries);

    // If there's nothing after the prefix, ignore it
    if (parts.Length == 0) return;

    // Grab the command name (lowercase so Ping and ping both work)
    string command = parts[0].ToLower();
    // Grab any arguments that come after the command name
    string[] args = parts.Skip(1).ToArray();

    if (command == "ping")
    {
        await channel.SendMessageAsync("Pong!");
    }
    // Check if the command is say
    else if (command == "say")
    {
        // Make sure the user actually gave us something to say
        if (args.Length == 0)
        {
            await channel.SendMessageAsync($"Usage: {prefix}say <message>");
            return;
        }

        // Join all the arguments back into one string and send it
        string messageToSay = string.Join(' ', args);
        await channel.SendMessageAsync(messageToSay);
    }
    // Check if the command is repeat
    else if (command == "repeat")
    {
        // Make sure the user gave us a number AND a word
        if (args.Length < 2)
        {
            await channel.SendMessageAsync($"Usage: {prefix}repeat <number> <word>");
            return;
        }

        // Try to parse the first argument as a number
        if (!int.TryParse(args[0], out int times))
        {
            await channel.SendMessageAsync("The first argument must be a number!");
            return;
        }

        // Clamp the number so people can't repeat 10000 times
        times = Math.Clamp(times, 1, 10);

        // Repeat the word and send the result
        string word = args[1];
        string result = string.Join(' ', Enumerable.Repeat(word, times));
        await channel.SendMessageAsync(result);
    }
}

await Task.Delay(Timeout.Infinite);

The Next step is getting Member Info