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

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 returns true for 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);