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.3 kB

8 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. OverwritePermissions? perms;
  113. //Start with this user's guild permissions
  114. resolvedPermissions = guildPermissions;
  115. //Give/Take Everyone permissions
  116. perms = channel.GetPermissionOverwrite(guild.EveryoneRole);
  117. if (perms != null)
  118. resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
  119. //Give/Take Role permissions
  120. ulong deniedPermissions = 0UL, allowedPermissions = 0UL;
  121. foreach (var roleId in user.RoleIds)
  122. {
  123. IRole role = null;
  124. if (roleId != guild.EveryoneRole.Id && (role = guild.GetRole(roleId)) != null)
  125. {
  126. perms = channel.GetPermissionOverwrite(role);
  127. if (perms != null)
  128. {
  129. allowedPermissions |= perms.Value.AllowValue;
  130. deniedPermissions |= perms.Value.DenyValue;
  131. }
  132. }
  133. }
  134. resolvedPermissions = (resolvedPermissions & ~deniedPermissions) | allowedPermissions;
  135. //Give/Take User permissions
  136. perms = channel.GetPermissionOverwrite(user);
  137. if (perms != null)
  138. resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;
  139. if (channel is ITextChannel textChannel)
  140. {
  141. if (!GetValue(resolvedPermissions, ChannelPermission.ViewChannel))
  142. {
  143. //No read permission on a text channel removes all other permissions
  144. resolvedPermissions = 0;
  145. }
  146. else if (!GetValue(resolvedPermissions, ChannelPermission.SendMessages))
  147. {
  148. //No send permissions on a text channel removes all send-related permissions
  149. resolvedPermissions &= ~(ulong)ChannelPermission.SendTTSMessages;
  150. resolvedPermissions &= ~(ulong)ChannelPermission.MentionEveryone;
  151. resolvedPermissions &= ~(ulong)ChannelPermission.EmbedLinks;
  152. resolvedPermissions &= ~(ulong)ChannelPermission.AttachFiles;
  153. }
  154. }
  155. resolvedPermissions &= mask; //Ensure we didnt get any permissions this channel doesnt support (from guildPerms, for example)
  156. }
  157. return resolvedPermissions;
  158. }
  159. }
  160. }