Skip to content

Commit

Permalink
Remove permission overrides from db on channel delete
Browse files Browse the repository at this point in the history
  • Loading branch information
FloatingMilkshake committed Jul 4, 2024
1 parent a8813a9 commit 8b41ed3
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
5 changes: 3 additions & 2 deletions Commands/Debug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ public async Task Refresh(CommandContext ctx)
bool reminders = await Tasks.ReminderTasks.CheckRemindersAsync();
bool raidmode = await Tasks.RaidmodeTasks.CheckRaidmodeAsync(ctx.Guild.Id);
bool unlocks = await Tasks.LockdownTasks.CheckUnlocksAsync();
bool channelEvents = await Tasks.EventTasks.HandlePendingChannelUpdateEventsAsync();
bool channelUpdateEvents = await Tasks.EventTasks.HandlePendingChannelUpdateEventsAsync();
bool channelDeleteEvents = await Tasks.EventTasks.HandlePendingChannelDeleteEventsAsync();

await msg.ModifyAsync($"Unban check result: `{bans}`\nUnmute check result: `{mutes}`\nAutomatic warning message check result: `{warns}`\nReminders check result: `{reminders}`\nRaidmode check result: `{raidmode}`\nUnlocks check result: `{unlocks}`\nPending channel events check result: `{channelEvents}`");
await msg.ModifyAsync($"Unban check result: `{bans}`\nUnmute check result: `{mutes}`\nAutomatic warning message check result: `{warns}`\nReminders check result: `{reminders}`\nRaidmode check result: `{raidmode}`\nUnlocks check result: `{unlocks}`\nPending Channel Update events check result: `{channelUpdateEvents}`\nPending Channel Delete events check result: `{channelDeleteEvents}`");
}

[Command("sh")]
Expand Down
10 changes: 9 additions & 1 deletion Events/ChannelEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@
{
public class ChannelEvents
{
public static async Task ChannelUpdated(DiscordClient _, ChannelUpdatedEventArgs e)
public static async Task ChannelUpdated(DiscordClient _, ChannelUpdatedEventArgs e)
{
// Add this event to the pending events list. These are handled in a task later, see Tasks/EventTasks/HandlePendingChannelUpdateEventsAsync
// using DateTime might seem weird, but it's something that is unique for each event
var timestamp = DateTime.Now;
Tasks.EventTasks.PendingChannelUpdateEvents.Add(timestamp, e);
}

public static async Task ChannelDeleted(DiscordClient client, ChannelDeletedEventArgs e)
{
// see above

var timestamp = DateTime.Now;
Tasks.EventTasks.PendingChannelDeleteEvents.Add(timestamp, e);
}
}
}
2 changes: 2 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static async Task Main(string[] _)
.HandleGuildBanRemoved(UnbanEvent.OnUnban)
.HandleVoiceStateUpdated(VoiceEvents.VoiceStateUpdate)
.HandleChannelUpdated(ChannelEvents.ChannelUpdated)
.HandleChannelDeleted(ChannelEvents.ChannelDeleted)
);

discord = discordBuilder.Build();
Expand Down Expand Up @@ -205,6 +206,7 @@ static async Task Main(string[] _)
Tasks.RaidmodeTasks.CheckRaidmodeAsync(cfgjson.ServerID),
Tasks.LockdownTasks.CheckUnlocksAsync(),
Tasks.EventTasks.HandlePendingChannelUpdateEventsAsync(),
Tasks.EventTasks.HandlePendingChannelDeleteEventsAsync(),
];

// To prevent a future issue if checks take longer than 10 seconds,
Expand Down
90 changes: 90 additions & 0 deletions Tasks/EventTasks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ namespace Cliptok.Tasks
public class EventTasks
{
public static Dictionary<DateTime, ChannelUpdatedEventArgs> PendingChannelUpdateEvents = new();
public static Dictionary<DateTime, ChannelDeletedEventArgs> PendingChannelDeleteEvents = new();

public static async Task<bool> HandlePendingChannelUpdateEventsAsync()
{
// Wait for there to be no pending Channel Delete events to be handled, to avoid conflicts
while (PendingChannelDeleteEvents.Count > 0)
{
await Task.Delay(500);
}

bool success = false;

try
Expand Down Expand Up @@ -154,6 +161,89 @@ public static async Task<bool> HandlePendingChannelUpdateEventsAsync()
Program.discord.Logger.LogDebug(Program.CliptokEventID, "Checked pending channel update events at {time} with result: {success}", DateTime.Now, success);
return success;
}

public static async Task<bool> HandlePendingChannelDeleteEventsAsync()
{
// Wait for there to be no pending Channel Update events to be handled, to avoid conflicts
while (PendingChannelUpdateEvents.Count > 0)
{
await Task.Delay(500);
}

bool success = false;

try
{
foreach (var pendingEvent in PendingChannelDeleteEvents)
{
// This is the timestamp on this event, used to identify it / keep events in order in the list
var timestamp = pendingEvent.Key;

// This is a set of ChannelDeletedEventArgs for the event we are processing
var e = pendingEvent.Value;

try
{
// Purge all overwrites from db for this channel

// Get all overwrites
var dbOverwrites = await Program.db.HashGetAllAsync("overrides");

// Overwrites are stored by user ID, then as a dict with channel ID as key & overwrite as value, so we can't just delete by channel ID.
// We need to loop through all overwrites and delete the ones that match the channel ID, then put everything back together.

foreach (var userOverwrites in dbOverwrites)
{
var overwriteDict = JsonConvert.DeserializeObject<Dictionary<ulong, DiscordOverwrite>>(userOverwrites.Value);

// Now overwriteDict is a dict of this user's overwrites, with channel ID as key & overwrite as value

// Loop through these; for any with a matching channel ID to the channel that was deleted, remove them
foreach (var overwrite in overwriteDict)
{
if (overwrite.Key == e.Channel.Id)
{
overwriteDict.Remove(overwrite.Key);
}
}

// Now we have a modified overwriteDict (ulong, DiscordOverwrite)
// Now we put everything back together

// If the user now has no overrides, remove them from the db entirely
if (overwriteDict.Count == 0)
{
await Program.db.HashDeleteAsync("overrides", userOverwrites.Name);
}
else
{
// Otherwise, update the user's overrides in the db
await Program.db.HashSetAsync("overrides", userOverwrites.Name, JsonConvert.SerializeObject(overwriteDict));
}
}

PendingChannelDeleteEvents.Remove(timestamp);
success = true;
}
catch (Exception ex)
{
// Log the exception
Program.discord.Logger.LogWarning(ex,
"Failed to process pending channel delete event for channel {channel}", e.Channel.Id);

// Always remove the event from the pending list, even if we failed to process it
PendingChannelDeleteEvents.Remove(timestamp);
}
}
}
catch (InvalidOperationException ex)
{
Program.discord.Logger.LogDebug(ex, "Failed to enumerate pending channel delete events; this usually means a Channel Delete event was just added to the list, or one was processed and removed from the list. Will try again on next task run.");
}

Program.discord.Logger.LogDebug(Program.CliptokEventID, "Checked pending channel delete events at {time} with result: {success}", DateTime.Now, success);
return success;
}

private static bool CompareOverwrites(DiscordOverwrite a, DiscordOverwrite b)
{
Expand Down

0 comments on commit 8b41ed3

Please sign in to comment.