|
- using System.Runtime.CompilerServices;
-
- namespace Discord
- {
- internal static class Permissions
- {
- public const int MaxBits = 53;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PermValue GetValue(ulong allow, ulong deny, ChannelPermission flag)
- => GetValue(allow, deny, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PermValue GetValue(ulong allow, ulong deny, GuildPermission flag)
- => GetValue(allow, deny, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static PermValue GetValue(ulong allow, ulong deny, ulong flag)
- {
- if (HasFlag(allow, flag))
- return PermValue.Allow;
- else if (HasFlag(deny, flag))
- return PermValue.Deny;
- else
- return PermValue.Inherit;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool GetValue(ulong value, ChannelPermission flag)
- => GetValue(value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool GetValue(ulong value, GuildPermission flag)
- => GetValue(value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool GetValue(ulong value, ulong flag) => HasFlag(value, flag);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong rawValue, bool? value, ChannelPermission flag)
- => SetValue(ref rawValue, value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong rawValue, bool? value, GuildPermission flag)
- => SetValue(ref rawValue, value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong rawValue, bool? value, ulong flag)
- {
- if (value.HasValue)
- {
- if (value == true)
- SetFlag(ref rawValue, flag);
- else
- UnsetFlag(ref rawValue, flag);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ChannelPermission flag)
- => SetValue(ref allow, ref deny, value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, GuildPermission flag)
- => SetValue(ref allow, ref deny, value, (ulong)flag);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ulong flag)
- {
- if (value.HasValue)
- {
- switch (value)
- {
- case PermValue.Allow:
- SetFlag(ref allow, flag);
- UnsetFlag(ref deny, flag);
- break;
- case PermValue.Deny:
- UnsetFlag(ref allow, flag);
- SetFlag(ref deny, flag);
- break;
- default:
- UnsetFlag(ref allow, flag);
- UnsetFlag(ref deny, flag);
- break;
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static bool HasFlag(ulong value, ulong flag) => (value & flag) != 0;
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void SetFlag(ref ulong value, ulong flag) => value |= flag;
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void UnsetFlag(ref ulong value, ulong flag) => value &= ~flag;
-
- public static ChannelPermissions ToChannelPerms(IGuildChannel channel, ulong guildPermissions)
- => new ChannelPermissions(guildPermissions & ChannelPermissions.All(channel).RawValue);
- public static ulong ResolveGuild(IGuild guild, IGuildUser user)
- {
- ulong resolvedPermissions = 0;
-
- if (user.Id == guild.OwnerId)
- resolvedPermissions = GuildPermissions.All.RawValue; //Owners always have all permissions
- else if (user.IsWebhook)
- resolvedPermissions = GuildPermissions.Webhook.RawValue;
- else
- {
- foreach (var roleId in user.RoleIds)
- resolvedPermissions |= guild.GetRole(roleId)?.Permissions.RawValue ?? 0;
- if (GetValue(resolvedPermissions, GuildPermission.Administrator))
- resolvedPermissions = GuildPermissions.All.RawValue; //Administrators always have all permissions
- }
- return resolvedPermissions;
- }
-
- /*public static ulong ResolveChannel(IGuildUser user, IGuildChannel channel)
- {
- return ResolveChannel(user, channel, ResolveGuild(user));
- }*/
- public static ulong ResolveChannel(IGuild guild, IGuildUser user, IGuildChannel channel, ulong guildPermissions)
- {
- ulong resolvedPermissions = 0;
-
- ulong mask = ChannelPermissions.All(channel).RawValue;
- if (GetValue(guildPermissions, GuildPermission.Administrator)) //Includes owner
- resolvedPermissions = mask; //Owners and administrators always have all permissions
- else
- {
- OverwritePermissions? perms;
-
- //Start with this user's guild permissions
- resolvedPermissions = guildPermissions;
-
- //Give/Take Everyone permissions
- perms = channel.GetPermissionOverwrite(guild.EveryoneRole);
- if (perms != null)
- resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
-
- //Give/Take Role permissions
- ulong deniedPermissions = 0UL, allowedPermissions = 0UL;
- foreach (var roleId in user.RoleIds)
- {
- IRole role = null;
- if (roleId != guild.EveryoneRole.Id && (role = guild.GetRole(roleId)) != null)
- {
- perms = channel.GetPermissionOverwrite(role);
- if (perms != null)
- {
- allowedPermissions |= perms.Value.AllowValue;
- deniedPermissions |= perms.Value.DenyValue;
- }
- }
- }
- resolvedPermissions = (resolvedPermissions & ~deniedPermissions) | allowedPermissions;
-
- //Give/Take User permissions
- perms = channel.GetPermissionOverwrite(user);
- if (perms != null)
- resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
-
- if (channel is ITextChannel textChannel)
- {
- if (!GetValue(resolvedPermissions, ChannelPermission.ViewChannel))
- {
- //No read permission on a text channel removes all other permissions
- resolvedPermissions = 0;
- }
- else if (!GetValue(resolvedPermissions, ChannelPermission.SendMessages))
- {
- //No send permissions on a text channel removes all send-related permissions
- resolvedPermissions &= ~(1UL << (int)ChannelPermission.SendTTSMessages);
- resolvedPermissions &= ~(1UL << (int)ChannelPermission.MentionEveryone);
- resolvedPermissions &= ~(1UL << (int)ChannelPermission.EmbedLinks);
- resolvedPermissions &= ~(1UL << (int)ChannelPermission.AttachFiles);
- }
- }
- resolvedPermissions &= mask; //Ensure we didnt get any permissions this channel doesnt support (from guildPerms, for example)
- }
-
- return resolvedPermissions;
- }
- }
- }
|