You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Permissions.cs 8.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System.Runtime.CompilerServices;
  2. namespace Discord
  3. {
  4. internal static class Permissions
  5. {
  6. public const int MaxBits = 53;
  7. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  8. public static PermValue GetValue(ulong allow, ulong deny, ChannelPermission flag)
  9. => GetValue(allow, deny, (ulong)flag);
  10. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  11. public static PermValue GetValue(ulong allow, ulong deny, GuildPermission flag)
  12. => GetValue(allow, deny, (ulong)flag);
  13. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  14. public static PermValue GetValue(ulong allow, ulong deny, ulong flag)
  15. {
  16. if (HasFlag(allow, flag))
  17. return PermValue.Allow;
  18. else if (HasFlag(deny, flag))
  19. return PermValue.Deny;
  20. else
  21. return PermValue.Inherit;
  22. }
  23. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  24. public static bool GetValue(ulong value, ChannelPermission flag)
  25. => GetValue(value, (ulong)flag);
  26. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  27. public static bool GetValue(ulong value, GuildPermission flag)
  28. => GetValue(value, (ulong)flag);
  29. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  30. public static bool GetValue(ulong value, ulong flag) => HasFlag(value, flag);
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. public static void SetValue(ref ulong rawValue, bool? value, ChannelPermission flag)
  33. => SetValue(ref rawValue, value, (ulong)flag);
  34. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  35. public static void SetValue(ref ulong rawValue, bool? value, GuildPermission flag)
  36. => SetValue(ref rawValue, value, (ulong)flag);
  37. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  38. public static void SetValue(ref ulong rawValue, bool? value, ulong flag)
  39. {
  40. if (value.HasValue)
  41. {
  42. if (value == true)
  43. SetFlag(ref rawValue, flag);
  44. else
  45. UnsetFlag(ref rawValue, flag);
  46. }
  47. }
  48. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  49. public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ChannelPermission flag)
  50. => SetValue(ref allow, ref deny, value, (ulong)flag);
  51. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  52. public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, GuildPermission flag)
  53. => SetValue(ref allow, ref deny, value, (ulong)flag);
  54. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  55. public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ulong flag)
  56. {
  57. if (value.HasValue)
  58. {
  59. switch (value)
  60. {
  61. case PermValue.Allow:
  62. SetFlag(ref allow, flag);
  63. UnsetFlag(ref deny, flag);
  64. break;
  65. case PermValue.Deny:
  66. UnsetFlag(ref allow, flag);
  67. SetFlag(ref deny, flag);
  68. break;
  69. default:
  70. UnsetFlag(ref allow, flag);
  71. UnsetFlag(ref deny, flag);
  72. break;
  73. }
  74. }
  75. }
  76. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  77. private static bool HasFlag(ulong value, ulong flag) => (value & flag) == flag;
  78. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  79. public static void SetFlag(ref ulong value, ulong flag) => value |= flag;
  80. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  81. public static void UnsetFlag(ref ulong value, ulong flag) => value &= ~flag;
  82. public static ChannelPermissions ToChannelPerms(IGuildChannel channel, ulong guildPermissions)
  83. => new ChannelPermissions(guildPermissions & ChannelPermissions.All(channel).RawValue);
  84. public static ulong ResolveGuild(IGuild guild, IGuildUser user)
  85. {
  86. ulong resolvedPermissions = 0;
  87. if (user.Id == guild.OwnerId)
  88. resolvedPermissions = GuildPermissions.All.RawValue; //Owners always have all permissions
  89. else if (user.IsWebhook)
  90. resolvedPermissions = GuildPermissions.Webhook.RawValue;
  91. else
  92. {
  93. foreach (var roleId in user.RoleIds)
  94. resolvedPermissions |= guild.GetRole(roleId)?.Permissions.RawValue ?? 0;
  95. if (GetValue(resolvedPermissions, GuildPermission.Administrator))
  96. resolvedPermissions = GuildPermissions.All.RawValue; //Administrators always have all permissions
  97. }
  98. return resolvedPermissions;
  99. }
  100. /*public static ulong ResolveChannel(IGuildUser user, IGuildChannel channel)
  101. {
  102. return ResolveChannel(user, channel, ResolveGuild(user));
  103. }*/
  104. public static ulong ResolveChannel(IGuild guild, IGuildUser user, IGuildChannel channel, ulong guildPermissions)
  105. {
  106. ulong resolvedPermissions = 0;
  107. ulong mask = ChannelPermissions.All(channel).RawValue;
  108. if (GetValue(guildPermissions, GuildPermission.Administrator)) //Includes owner
  109. resolvedPermissions = mask; //Owners and administrators always have all permissions
  110. else
  111. {
  112. //Start with this user's guild permissions
  113. resolvedPermissions = guildPermissions;
  114. //Give/Take Everyone permissions
  115. var perms = channel.GetPermissionOverwrite(guild.EveryoneRole);
  116. if (perms != null)
  117. resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
  118. //Give/Take Role permissions
  119. ulong deniedPermissions = 0UL, allowedPermissions = 0UL;
  120. foreach (var roleId in user.RoleIds)
  121. {
  122. IRole role;
  123. if (roleId != guild.EveryoneRole.Id && (role = guild.GetRole(roleId)) != null)
  124. {
  125. perms = channel.GetPermissionOverwrite(role);
  126. if (perms != null)
  127. {
  128. allowedPermissions |= perms.Value.AllowValue;
  129. deniedPermissions |= perms.Value.DenyValue;
  130. }
  131. }
  132. }
  133. resolvedPermissions = (resolvedPermissions & ~deniedPermissions) | allowedPermissions;
  134. //Give/Take User permissions
  135. perms = channel.GetPermissionOverwrite(user);
  136. if (perms != null)
  137. resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
  138. if (channel is ITextChannel)
  139. {
  140. if (!GetValue(resolvedPermissions, ChannelPermission.ViewChannel))
  141. {
  142. //No read permission on a text channel removes all other permissions
  143. resolvedPermissions = 0;
  144. }
  145. else if (!GetValue(resolvedPermissions, ChannelPermission.SendMessages))
  146. {
  147. //No send permissions on a text channel removes all send-related permissions
  148. resolvedPermissions &= ~(ulong)ChannelPermission.SendTTSMessages;
  149. resolvedPermissions &= ~(ulong)ChannelPermission.MentionEveryone;
  150. resolvedPermissions &= ~(ulong)ChannelPermission.EmbedLinks;
  151. resolvedPermissions &= ~(ulong)ChannelPermission.AttachFiles;
  152. }
  153. }
  154. resolvedPermissions &= mask; //Ensure we didnt get any permissions this channel doesnt support (from guildPerms, for example)
  155. }
  156. return resolvedPermissions;
  157. }
  158. }
  159. }