diff --git a/src/Mewdeko/Modules/Server Management/ChannelCommands.cs b/src/Mewdeko/Modules/Server Management/ChannelCommands.cs index 6a812546a..eaa3bc0a4 100644 --- a/src/Mewdeko/Modules/Server Management/ChannelCommands.cs +++ b/src/Mewdeko/Modules/Server Management/ChannelCommands.cs @@ -3,6 +3,7 @@ using Humanizer; using Mewdeko.Common.Attributes.TextCommands; using Mewdeko.Common.TypeReaders.Models; +using Mewdeko.Modules.Server_Management.Services; using Mewdeko.Services.Settings; using PermValue = Discord.PermValue; @@ -140,6 +141,7 @@ public async Task LiftLockdown(LockdownType lockdownType = LockdownType.Readonly break; case LockdownType.Readonly: + await Service.LiftLockdown(ctx.Guild); await Service.RestoreOriginalPermissions(ctx.Guild).ConfigureAwait(false); embed.WithDescription(GetText("lockdown_readonly_disabled", ctx.Guild.Name)) @@ -148,6 +150,7 @@ public async Task LiftLockdown(LockdownType lockdownType = LockdownType.Readonly break; case LockdownType.Full: + await Service.LiftLockdown(ctx.Guild); await Service.RestoreOriginalPermissions(ctx.Guild).ConfigureAwait(false); embed.WithDescription(GetText("lockdown_full_disabled", ctx.Guild.Name)) .WithColor(Mewdeko.OkColor); diff --git a/src/Mewdeko/Modules/Server Management/Services/ChannelCommandService.cs b/src/Mewdeko/Modules/Server Management/Services/ChannelCommandService.cs index 2c327e82c..295e20040 100644 --- a/src/Mewdeko/Modules/Server Management/Services/ChannelCommandService.cs +++ b/src/Mewdeko/Modules/Server Management/Services/ChannelCommandService.cs @@ -1,9 +1,10 @@ using Mewdeko.Common.ModuleBehaviors; using Mewdeko.Database.DbContextStuff; -using Mewdeko.Modules.Server_Management; using Microsoft.EntityFrameworkCore; using StackExchange.Redis; +namespace Mewdeko.Modules.Server_Management.Services; + /// /// Service for managing channel commands and lockdowns, accounting for various channel types such as text, voice, and /// forum. @@ -22,6 +23,8 @@ public class ChannelCommandService : INService, IReadyExecutor /// /// The data cache for accessing Redis. /// The event handler. + /// The databse connection provider + /// The discord client public ChannelCommandService(IDataCache dataCache, EventHandler handler, DbContextProvider dbContext, DiscordShardedClient client) { @@ -194,21 +197,31 @@ private async Task RemovePermissions(IGuild guild) foreach (var overwrite in permissionOverrides) { - // Remove permission overrides for both roles and users - if (overwrite.TargetType == PermissionTarget.Role) + if (overwrite.TargetId == guild.EveryoneRole.Id) + continue; + + switch (overwrite.TargetType) { - var role = guild.GetRole(overwrite.TargetId); - if (role != null) + // Remove permission overrides for both roles and users + case PermissionTarget.Role: { - await channel.RemovePermissionOverwriteAsync(role).ConfigureAwait(false); + var role = guild.GetRole(overwrite.TargetId); + if (role != null) + { + await channel.RemovePermissionOverwriteAsync(role).ConfigureAwait(false); + } + + break; } - } - else if (overwrite.TargetType == PermissionTarget.User) - { - var user = await guild.GetUserAsync(overwrite.TargetId); - if (user != null) + case PermissionTarget.User: { - await channel.RemovePermissionOverwriteAsync(user).ConfigureAwait(false); + var user = await guild.GetUserAsync(overwrite.TargetId); + if (user != null) + { + await channel.RemovePermissionOverwriteAsync(user).ConfigureAwait(false); + } + + break; } } } @@ -225,38 +238,40 @@ private async Task RemovePermissions(IGuild guild) public async Task ApplyLockdown(IGuild guild) { await StoreOriginalPermissions(guild); // Store all permissions first - await RemovePermissions(guild); // Remove all permissions from the channels + await RemovePermissions(guild); // Remove all permissions from the channels, including @everyone var everyoneRole = guild.EveryoneRole; var channels = await guild.GetChannelsAsync(); + await using var context = await dbContext.GetContextAsync(); + foreach (var channel in channels) { if (!IsRelevantChannel(channel)) continue; - OverwritePermissions lockdownPerms; + // Retrieve the stored permissions for the @everyone role from the database + var storedPerm = await context.LockdownChannelPermissions.FirstOrDefaultAsync(p => + p.GuildId == guild.Id && p.ChannelId == channel.Id && p.TargetId == everyoneRole.Id && + p.TargetType == PermissionTarget.Role); - if (channel is IVoiceChannel) - { - // For voice channels, deny "Connect" and "Send Messages" - lockdownPerms = new OverwritePermissions(connect: PermValue.Deny, sendMessages: PermValue.Deny); - } - else if (channel is IForumChannel) - { - // For forum channels, deny "Send Messages" and "Create Threads" - lockdownPerms = new OverwritePermissions(sendMessages: PermValue.Deny, - createPublicThreads: PermValue.Deny, createPrivateThreads: PermValue.Deny); - } - else - { - // For text channels, deny "Send Messages" and "Create Threads" - lockdownPerms = new OverwritePermissions(sendMessages: PermValue.Deny, - createPublicThreads: PermValue.Deny, createPrivateThreads: PermValue.Deny); - } + var existingPerms = + // Reconstruct OverwritePermissions from stored permissions + storedPerm != null ? new OverwritePermissions(storedPerm.AllowPermissions, storedPerm.DenyPermissions) : + // No stored permissions; default to InheritAll + OverwritePermissions.InheritAll; - // Apply lockdown to the @everyone role - await ((IGuildChannel)channel).AddPermissionOverwriteAsync(everyoneRole, lockdownPerms) - .ConfigureAwait(false); + var lockdownPerms = channel switch + { + // Modify permissions based on channel type + IVoiceChannel => existingPerms.Modify(connect: PermValue.Deny, speak: PermValue.Deny), + IForumChannel => existingPerms.Modify(sendMessages: PermValue.Deny, createPublicThreads: PermValue.Deny, + createPrivateThreads: PermValue.Deny), + _ => existingPerms.Modify(sendMessages: PermValue.Deny, createPublicThreads: PermValue.Deny, + createPrivateThreads: PermValue.Deny) + }; + + // Apply the modified permissions to the @everyone role + await channel.AddPermissionOverwriteAsync(everyoneRole, lockdownPerms).ConfigureAwait(false); } } @@ -281,24 +296,31 @@ public async Task RestoreOriginalPermissions(IGuild guild) foreach (var storedPerm in storedPermissions) { - if (storedPerm.TargetType == PermissionTarget.Role) + switch (storedPerm.TargetType) { - var role = guild.GetRole(storedPerm.TargetId); - if (role != null) + case PermissionTarget.Role: { - var permissions = - new OverwritePermissions(storedPerm.AllowPermissions, storedPerm.DenyPermissions); - await channel.AddPermissionOverwriteAsync(role, permissions).ConfigureAwait(false); + var role = guild.GetRole(storedPerm.TargetId); + if (role != null) + { + var permissions = + new OverwritePermissions(storedPerm.AllowPermissions, storedPerm.DenyPermissions); + await channel.AddPermissionOverwriteAsync(role, permissions).ConfigureAwait(false); + } + + break; } - } - else if (storedPerm.TargetType == PermissionTarget.User) - { - var user = await guild.GetUserAsync(storedPerm.TargetId); - if (user != null) + case PermissionTarget.User: { - var permissions = - new OverwritePermissions(storedPerm.AllowPermissions, storedPerm.DenyPermissions); - await channel.AddPermissionOverwriteAsync(user, permissions).ConfigureAwait(false); + var user = await guild.GetUserAsync(storedPerm.TargetId); + if (user != null) + { + var permissions = + new OverwritePermissions(storedPerm.AllowPermissions, storedPerm.DenyPermissions); + await channel.AddPermissionOverwriteAsync(user, permissions).ConfigureAwait(false); + } + + break; } } } @@ -343,21 +365,16 @@ public async Task OnReadyAsync() var isInRedis = redisJoinBlockedGuilds.Any(g => g == (RedisValue)guildId.ToString()); var isInDb = dbLockdownGuilds.Contains(guildId); - // If the guild is only in Redis, it's in Joins lockdown - if (isInRedis && !isInDb) + lockdownGuilds[guildId] = isInRedis switch { - lockdownGuilds[guildId] = (ServerManagement.LockdownType.Joins, null); - } - // If the guild is only in the database, it's in Readonly lockdown - else if (!isInRedis && isInDb) - { - lockdownGuilds[guildId] = (ServerManagement.LockdownType.Readonly, null); - } - // If the guild is in both Redis and the database, it's in Full lockdown - else if (isInRedis && isInDb) - { - lockdownGuilds[guildId] = (ServerManagement.LockdownType.Full, null); - } + // If the guild is only in Redis, it's in Joins lockdown + true when !isInDb => (ServerManagement.LockdownType.Joins, null), + // If the guild is only in the database, it's in Readonly lockdown + false when isInDb => (ServerManagement.LockdownType.Readonly, null), + // If the guild is in both Redis and the database, it's in Full lockdown + true when isInDb => (ServerManagement.LockdownType.Full, null), + _ => lockdownGuilds[guildId] + }; } // If there are guilds in Redis but not in lockdownGuilds (not recognized during the loop), remove them from Redis