7.8 KiB
Permission Checking
Now that we can fetch member info, we can use permissions to restrict commands to only members who have the right access. Valour has two types of permission checks — planet-level and channel-level.
How permissions work
Permissions in Valour are stored as flags on roles. When you call member.HasPermission() it calculates the combined permissions from all of the member's roles and checks if the requested permission is included.
Note: You do not need to separately check if a member is the planet owner or has an admin role.
HasPermission()handles both of these automatically — it always returnstruefor the planet owner and for any member with an admin role.
Planet permissions
Planet permissions are server-wide — they apply regardless of which channel the command is used in. To check one, call member.HasPermission() with a PlanetPermissions value.
// Check if the member has the Kick planet permission
// This also returns true for planet owners and members with an admin role
if (!member.HasPermission(PlanetPermissions.Kick))
{
await channel.SendMessageAsync("You do not have permission to use this command!");
return;
}
Here are all the available planet permissions:
| Permission | Description |
|---|---|
PlanetPermissions.Kick |
Can kick members |
PlanetPermissions.Ban |
Can ban members |
PlanetPermissions.Manage |
Can edit planet settings |
PlanetPermissions.Invite |
Can send invites |
PlanetPermissions.CreateChannels |
Can create channels |
PlanetPermissions.ManageRoles |
Can manage roles |
PlanetPermissions.MentionAll |
Can @mention all roles |
PlanetPermissions.BypassAutomod |
Bypasses automod |
PlanetPermissions.FullControl |
Full owner-level control |
Channel permissions
Channel permissions are specific to a single channel — a member may have different permissions in different channels depending on their role overrides. To check one, call await member.HasPermission(channel, ...) with a ChatChannelPermissions value. Note that this one is async so needs await.
// Check if the member has the ManageMessages permission in this specific channel
if (!await member.HasPermission(channel, ChatChannelPermissions.ManageMessages))
{
await channel.SendMessageAsync("You do not have permission to manage messages in this channel!");
return;
}
Here are all the available channel permissions:
| Permission | Description |
|---|---|
ChatChannelPermissions.View |
Can see the channel in the list |
ChatChannelPermissions.ViewMessages |
Can read messages |
ChatChannelPermissions.PostMessages |
Can send messages |
ChatChannelPermissions.ManageMessages |
Can delete/manage messages |
ChatChannelPermissions.ManageChannel |
Can edit channel settings |
ChatChannelPermissions.ManagePermissions |
Can manage channel permission overrides |
ChatChannelPermissions.Embed |
Can post embedded content |
ChatChannelPermissions.AttachContent |
Can upload files |
ChatChannelPermissions.UseReactions |
Can use reactions |
Putting it together
Here are both commands using everything above:
else if (command == "planetperms")
{
// 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;
}
// Check if the member has the Kick planet permission
// This also returns true for planet owners and members with an admin role
if (!member.HasPermission(PlanetPermissions.Kick))
{
await channel.SendMessageAsync("You do not have permission to use this command!");
return;
}
await channel.SendMessageAsync("Hello, you have permission to kick members!");
}
else if (command == "channelperms")
{
// 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;
}
// Check if the member has the ManageMessages permission in this specific channel
if (!await member.HasPermission(channel, ChatChannelPermissions.ManageMessages))
{
await channel.SendMessageAsync("You do not have permission to manage messages in this channel!");
return;
}
await channel.SendMessageAsync("Hello, you can manage messages in this channel!");
}
Full code below
using Valour.Sdk.Client;
using Valour.Shared;
using DotNetEnv;
using Valour.Sdk.Models;
using Valour.Shared.Models;
using Valour.Shared.Authorization;
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 == "planetperms")
{
// 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;
}
// Check if the member has the Kick planet permission
// This also returns true for planet owners and members with a role with the Administrator Permission
if (!member.HasPermission(PlanetPermissions.Kick))
{
await channel.SendMessageAsync("You do not have permission to use this command!");
return;
}
await channel.SendMessageAsync("Hello, you have permission to kick members!");
}
else if (command == "channelperms")
{
// 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;
}
// Check if the member has the ManageMessages permission in this specific channel
if (!await member.HasPermission(channel, ChatChannelPermissions.ManageMessages))
{
await channel.SendMessageAsync("You do not have permission to manage messages in this channel!");
return;
}
await channel.SendMessageAsync("Hello, you can manage messages in this channel!");
}
}
await Task.Delay(Timeout.Infinite);