new commands
This commit is contained in:
279
Guides/5.CommandArguments.md
Normal file
279
Guides/5.CommandArguments.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# 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.
|
||||
|
||||
```c#
|
||||
// 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`.
|
||||
|
||||
```c#
|
||||
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).
|
||||
|
||||
```c#
|
||||
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`:
|
||||
|
||||
```c#
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br><br>
|
||||
### Full code below
|
||||
|
||||
```c#
|
||||
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](6.MemberInfo.md)
|
||||
Reference in New Issue
Block a user