new commands

This commit is contained in:
2026-03-29 02:07:51 +01:00
parent f84120883a
commit 5a44d56a24
8 changed files with 846 additions and 92 deletions

219
Guides/6.MemberInfo.md Normal file
View File

@@ -0,0 +1,219 @@
# Member Info
Now that we have commands with arguments, lets make them more personal by fetching info about the user who sent the message.
A `bg/whoami` command will reply with something like:
```
**Username:** SkyJoshua
**Display Name:** SkyJoshua
**User ID:** 15652354820931584
**Member ID:** 42170205766156288
**Roles:** Admin, Moderator, Member
**Joined Valour:** 01/01/2022 00:00:00
**Bot:** False
```
### Fetching the member
Every `Message` has a `FetchAuthorMemberAsync()` method that returns a `PlanetMember` — the sender's membership on that planet. We always check if it's null before using it.
```c#
// Fetch the member object for the message author
PlanetMember member = await message.FetchAuthorMemberAsync();
if (member is null)
{
await channel.SendMessageAsync("Could not find your member info!");
return;
}
```
### Getting the linked User
From the `PlanetMember` you can access the global `User` account directly via `member.User`. This gives you their username, ID, join date, and whether they are a bot.
```c#
// Get the linked user account
User user = member.User;
```
### Reading member properties
Here are the useful properties available on `member` and `user`:
| Property | Description |
|---|---|
| `user.Name` | Their global Valour username |
| `member.Nickname` | Their planet-specific nickname (empty if not set) |
| `user.Id` | Their global user ID |
| `member.Id` | Their member ID on this planet |
| `member.Roles` | The list of roles they have on this planet |
| `user.TimeJoined` | When they created their Valour account |
| `user.Bot` | Whether they are a bot account |
### Handling nicknames
A member may or may not have a nickname set on the planet. We fall back to their username when there isn't one.
```c#
// Use their nickname if they have one, otherwise fall back to their username
string displayName = string.IsNullOrWhiteSpace(member.Nickname) ? user.Name : member.Nickname;
```
### Getting role names
`member.Roles` gives us the list of roles the member has. We can use LINQ to pull out each role's name and join them into a single string.
```c#
// Build a comma-separated list of the member's role names
string roleNames = string.Join(", ", member.Roles.Select(r => r.Name));
```
### Putting it together
Here is the full `whoami` command using everything above:
```c#
else if (command == "whoami")
{
// Fetch the member object for the message author
PlanetMember member = await message.FetchAuthorMemberAsync();
if (member is null)
{
await channel.SendMessageAsync("Could not find your member info!");
return;
}
// Get the linked user account
User user = member.User;
// Use their nickname if they have one, otherwise fall back to their username
string displayName = string.IsNullOrWhiteSpace(member.Nickname) ? user.Name : member.Nickname;
// Build a comma-separated list of the member's role names
string roleNames = string.Join(", ", member.Roles.Select(r => r.Name));
// Build and send the info reply
await channel.SendMessageAsync($@"
**Username:** {user.Name}
**Display Name:** {displayName}
**User ID:** {user.Id}
**Member ID:** {member.Id}
**Roles:** {roleNames}
**Joined Valour:** {user.TimeJoined}
**Bot:** {user.Bot}
");
}
```
<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;
string withoutPrefix = content.Substring(prefix.Length);
string[] parts = withoutPrefix.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0) return;
string command = parts[0].ToLower();
string[] args = parts.Skip(1).ToArray();
if (command == "ping")
{
await channel.SendMessageAsync("Pong!");
}
else if (command == "whoami")
{
// Fetch the member object for the message author
PlanetMember member = await message.FetchAuthorMemberAsync();
if (member is null)
{
await channel.SendMessageAsync("Could not find your member info!");
return;
}
// Get the linked user account
User user = member.User;
// Use their nickname if they have one, otherwise fall back to their username
string displayName = string.IsNullOrWhiteSpace(member.Nickname) ? user.Name : member.Nickname;
// Build a comma-separated list of the member's role names
string roleNames = string.Join(", ", member.Roles.Select(r => r.Name));
// Build and send the info reply
await channel.SendMessageAsync($@"
**Username:** {user.Name}
**Display Name:** {displayName}
**User ID:** {user.Id}
**Member ID:** {member.Id}
**Roles:** {roleNames}
**Joined Valour:** {user.TimeJoined}
**Bot:** {user.Bot}
");
}
}
await Task.Delay(Timeout.Infinite);
```
---
## [The Next step is Permission Checking](7.PermissionChecking.md)