Add workaround for DSP internal member cache error

This commit is contained in:
Fennel 2020-05-10 18:44:59 -04:00
parent 9a761ed7e4
commit 8467f4f681

View File

@ -1,4 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using DSharpPlus; using DSharpPlus;
@ -16,7 +19,9 @@ namespace PluralKit.Bot
public static DiscordColor Gray = new DiscordColor(0x979c9f); public static DiscordColor Gray = new DiscordColor(0x979c9f);
public static Permissions DM_PERMISSIONS = (Permissions) 0b00000_1000110_1011100110000_000000; public static Permissions DM_PERMISSIONS = (Permissions) 0b00000_1000110_1011100110000_000000;
private static readonly FieldInfo _roleIdsField = typeof(DiscordMember).GetField("_role_ids", BindingFlags.NonPublic | BindingFlags.Instance);
public static string NameAndMention(this DiscordUser user) { public static string NameAndMention(this DiscordUser user) {
return $"{user.Username}#{user.Discriminator} ({user.Mention})"; return $"{user.Username}#{user.Discriminator} ({user.Mention})";
} }
@ -25,6 +30,7 @@ namespace PluralKit.Bot
// This way we can ensure we do the read permission correction everywhere // This way we can ensure we do the read permission correction everywhere
private static Permissions PermissionsInGuild(DiscordChannel channel, DiscordMember member) private static Permissions PermissionsInGuild(DiscordChannel channel, DiscordMember member)
{ {
ValidateCachedRoles(member);
var permissions = channel.PermissionsFor(member); var permissions = channel.PermissionsFor(member);
// This method doesn't account for channels without read permissions // This method doesn't account for channels without read permissions
@ -35,6 +41,15 @@ namespace PluralKit.Bot
return permissions; return permissions;
} }
// Workaround for DSP internal error
private static void ValidateCachedRoles(DiscordMember member)
{
var roleIdCache = _roleIdsField.GetValue(member) as List<ulong>;
var currentRoleIds = member.Roles.Where(x => x != null).Select(x => x.Id);
var invalidRoleIds = roleIdCache.Where(x => !currentRoleIds.Contains(x));
roleIdCache.RemoveAll(x => invalidRoleIds.Contains(x));
}
public static async Task<Permissions> PermissionsIn(this DiscordChannel channel, DiscordUser user) public static async Task<Permissions> PermissionsIn(this DiscordChannel channel, DiscordUser user)
{ {
// Just delegates to PermissionsInSync, but handles the case of a non-member User in a guild properly // Just delegates to PermissionsInSync, but handles the case of a non-member User in a guild properly