diff --git a/src/CB.Bot/Commands/Application/CustomizationCommands.cs b/src/CB.Bot/Commands/Application/CustomizationCommands.cs index f2161ed..cc89eeb 100644 --- a/src/CB.Bot/Commands/Application/CustomizationCommands.cs +++ b/src/CB.Bot/Commands/Application/CustomizationCommands.cs @@ -1,6 +1,8 @@ using CB.Accessors.Contracts; using Discord; using Discord.Interactions; +// ReSharper disable UnusedMember.Local +// ReSharper disable UnusedMember.Global namespace CB.Bot.Commands.Application; diff --git a/src/CB.Bot/Commands/Application/MessageSlashCommands.cs b/src/CB.Bot/Commands/Application/MessageSlashCommands.cs index 861c360..e481d22 100644 --- a/src/CB.Bot/Commands/Application/MessageSlashCommands.cs +++ b/src/CB.Bot/Commands/Application/MessageSlashCommands.cs @@ -2,6 +2,8 @@ using CB.Shared.Enums; using CB.Shared.Utilities; using Discord.Interactions; +// ReSharper disable UnusedMember.Local +// ReSharper disable UnusedMember.Global namespace CB.Bot.Commands.Application; diff --git a/src/CB.Bot/Commands/Application/RoleSlashCommands.cs b/src/CB.Bot/Commands/Application/RoleSlashCommands.cs new file mode 100644 index 0000000..c2863c4 --- /dev/null +++ b/src/CB.Bot/Commands/Application/RoleSlashCommands.cs @@ -0,0 +1,139 @@ +using CB.Accessors.Contracts; +using Discord; +using Discord.Interactions; +using RunMode = Discord.Interactions.RunMode; +// ReSharper disable UnusedMember.Local +// ReSharper disable UnusedMember.Global + +namespace CB.Bot.Commands.Application; + +[Group("role", "Role commands")] +public class RoleSlashCommands(IGuildAccessor guildAccessor, + IRoleConfigurationAccessor roleConfigurationAccessor) + : BaseSlashCommands +{ + [SlashCommand("live", + "Set your discovery live role command.", + false, + RunMode.Async)] + private async Task SetLiveRoleAsync(IRole role) + { + await SocketInteraction.DeferAsync(true); + + if (!await IsUserAdmin()) + { + return; + } + + var guild = await guildAccessor.GetConfigurationSummaryByIdAsync(Context.Guild.Id.ToString()); + + if (!await ValidateBotRoleFunctionality(role)) + { + return; + } + + guild.RoleConfiguration.LiveDiscoveryRoleId = role.Id.ToString(); + + await roleConfigurationAccessor.UpdateAsync(guild.RoleConfiguration); + await SocketInteraction.FollowupAsync($"When users go live they will get the {role.Name} role."); + } + + [SlashCommand("join", + "Set your join role command.", + false, + RunMode.Async)] + private async Task SetJoinRoleAsync(IRole role) + { + await SocketInteraction.DeferAsync(true); + + if (!await IsUserAdmin()) + { + return; + } + + var guild = await guildAccessor.GetConfigurationSummaryByIdAsync(Context.Guild.Id.ToString()); + + if (!await ValidateBotRoleFunctionality(role)) + { + return; + } + + guild.RoleConfiguration.JoinRoleId = role.Id.ToString(); + + await roleConfigurationAccessor.UpdateAsync(guild.RoleConfiguration); + await SocketInteraction.FollowupAsync($"When users join they will get the {role.Name} role."); + } + + [SlashCommand("livenone", + "Reset your discovery live role.", + false, + RunMode.Async)] + private async Task ClearLiveRoleAsync() + { + await SocketInteraction.DeferAsync(true); + + if (!await IsUserAdmin()) + { + return; + } + + var guild = await guildAccessor.GetConfigurationSummaryByIdAsync(Context.Guild.Id.ToString()); + guild.RoleConfiguration.LiveDiscoveryRoleId = null; + + await roleConfigurationAccessor.UpdateAsync(guild.RoleConfiguration); + await SocketInteraction.FollowupAsync($"Your live role has been cleared."); + } + + [SlashCommand("joinnone", + "Reset your discovery live role.", + false, + RunMode.Async)] + private async Task ClearJoinRoleAsync() + { + await SocketInteraction.DeferAsync(true); + + if (!await IsUserAdmin()) + { + return; + } + + var guild = await guildAccessor.GetConfigurationSummaryByIdAsync(Context.Guild.Id.ToString()); + guild.RoleConfiguration.JoinRoleId = null; + + await roleConfigurationAccessor.UpdateAsync(guild.RoleConfiguration); + await SocketInteraction.FollowupAsync("Your join role has been cleared."); + } + + private async Task ValidateBotRoleFunctionality(IRole role) + { + if (!await BotHasManageRoles(Context.Guild, Context.Client.CurrentUser)) + { + await SocketInteraction.FollowupAsync("Sorry, I do not have 'Manage Roles' permission on this server. Fix that, and retry."); + + return false; + } + + if (await BotHasHigherRole(Context.Guild, Context.Client.CurrentUser, role)) + { + return true; + } + + await SocketInteraction.FollowupAsync("Sorry, my current role is lower in the server role list than the role I will be assigning. Fix that, and retry."); + + return false; + } + + private async Task BotHasManageRoles(IGuild guild, IUser user) + { + var u = await guild.GetUserAsync(user.Id); + + return u is { GuildPermissions.ManageRoles: true }; + } + + private async Task BotHasHigherRole(IGuild guild, IUser user, IRole role) + { + var u = await guild.GetUserAsync(user.Id); + + return u.RoleIds.Select(guild.GetRole).Any(guildRole => guildRole.CompareTo(role) > 0); + } +} \ No newline at end of file diff --git a/src/CB.Bot/Commands/Application/UtilityApplicationCommands.cs b/src/CB.Bot/Commands/Application/UtilityApplicationCommands.cs index 3a1cb3a..a895b92 100644 --- a/src/CB.Bot/Commands/Application/UtilityApplicationCommands.cs +++ b/src/CB.Bot/Commands/Application/UtilityApplicationCommands.cs @@ -1,4 +1,6 @@ using Discord.Interactions; +// ReSharper disable UnusedMember.Local +// ReSharper disable UnusedMember.Global namespace CB.Bot.Commands.Application;