Browse Source

Merge remote-tracking branch 'origin/dev' into dev

tags/2.0.0-beta
Christopher F 7 years ago
parent
commit
623d60fe51
19 changed files with 270 additions and 195 deletions
  1. +1
    -1
      docs/guides/getting_started/intro.md
  2. +4
    -3
      docs/guides/getting_started/samples/intro/structure.cs
  3. +1
    -1
      docs/guides/getting_started/samples/project.csproj
  4. +4
    -5
      docs/guides/voice/samples/audio_create_ffmpeg.cs
  5. +7
    -5
      docs/guides/voice/samples/audio_ffmpeg.cs
  6. +1
    -1
      docs/guides/voice/samples/joining_audio.cs
  7. +29
    -33
      src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs
  8. +15
    -15
      src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
  9. +37
    -33
      src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
  10. +40
    -28
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  11. +19
    -18
      src/Discord.Net.Core/Entities/Permissions/OverwritePermissions.cs
  12. +1
    -1
      src/Discord.Net.Core/Utils/Optional.cs
  13. +33
    -33
      src/Discord.Net.Core/Utils/Permissions.cs
  14. +2
    -2
      src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
  15. +4
    -4
      src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
  16. +35
    -0
      src/Discord.Net.Rest/Extensions/EmbedBuilderExtensions.cs
  17. +0
    -2
      src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs
  18. +35
    -8
      src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
  19. +2
    -2
      src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs

+ 1
- 1
docs/guides/getting_started/intro.md View File

@@ -74,7 +74,7 @@ async main.


[!code-csharp[Async Context](samples/intro/async-context.cs)] [!code-csharp[Async Context](samples/intro/async-context.cs)]


As a result of this, your program will now start and immidiately
As a result of this, your program will now start and immediately
jump into an async context. This will allow us to create a connection jump into an async context. This will allow us to create a connection
to Discord later on without needing to worry about setting up the to Discord later on without needing to worry about setting up the
correct async implementation. correct async implementation.


+ 4
- 3
docs/guides/getting_started/samples/intro/structure.cs View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Discord; using Discord;
@@ -80,7 +81,7 @@ class Program


private async Task MainAsync() private async Task MainAsync()
{ {
// Centralize the logic for commands into a seperate method.
// Centralize the logic for commands into a separate method.
await InitCommands(); await InitCommands();


// Login and connect. // Login and connect.
@@ -88,7 +89,7 @@ class Program
await _client.StartAsync(); await _client.StartAsync();


// Wait infinitely so your bot actually stays connected. // Wait infinitely so your bot actually stays connected.
await Task.Delay(-1);
await Task.Delay(Timeout.Infinite);
} }


private IServiceProvider _services; private IServiceProvider _services;
@@ -138,7 +139,7 @@ class Program
var context = new SocketCommandContext(_client, msg); var context = new SocketCommandContext(_client, msg);
// Execute the command. (result does not indicate a return value, // Execute the command. (result does not indicate a return value,
// rather an object stating if the command executed succesfully).
// rather an object stating if the command executed successfully).
var result = await _commands.ExecuteAsync(context, pos, _services); var result = await _commands.ExecuteAsync(context, pos, _services);


// Uncomment the following lines if you want the bot // Uncomment the following lines if you want the bot


+ 1
- 1
docs/guides/getting_started/samples/project.csproj View File

@@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>


<ItemGroup> <ItemGroup>
<PackageReference Include="Discord.Net" Version="1.0.0-rc-00617" />
<PackageReference Include="Discord.Net" Version="1.*" />
</ItemGroup> </ItemGroup>


</Project> </Project>

+ 4
- 5
docs/guides/voice/samples/audio_create_ffmpeg.cs View File

@@ -1,11 +1,10 @@
private Process CreateStream(string path) private Process CreateStream(string path)
{ {
var ffmpeg = new ProcessStartInfo
return Process.Start(new ProcessStartInfo
{ {
FileName = "ffmpeg", FileName = "ffmpeg",
Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1",
Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1",
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
};
return Process.Start(ffmpeg);
}
});
}

+ 7
- 5
docs/guides/voice/samples/audio_ffmpeg.cs View File

@@ -1,9 +1,11 @@
private async Task SendAsync(IAudioClient client, string path) private async Task SendAsync(IAudioClient client, string path)
{ {
// Create FFmpeg using the previous example // Create FFmpeg using the previous example
var ffmpeg = CreateStream(path);
var output = ffmpeg.StandardOutput.BaseStream;
var discord = client.CreatePCMStream(AudioApplication.Mixed);
await output.CopyToAsync(discord);
await discord.FlushAsync();
using (var ffmpeg = CreateStream(path))
using (var output = ffmpeg.StandardOutput.BaseStream)
using (var discord = client.CreatePCMStream(AudioApplication.Mixed))
{
try { await output.CopyToAsync(discord); }
finally { await discord.FlushAsync(); }
}
} }

+ 1
- 1
docs/guides/voice/samples/joining_audio.cs View File

@@ -7,4 +7,4 @@ public async Task JoinChannel(IVoiceChannel channel = null)


// For the next step with transmitting audio, you would want to pass this Audio Client in to a service. // For the next step with transmitting audio, you would want to pass this Audio Client in to a service.
var audioClient = await channel.ConnectAsync(); var audioClient = await channel.ConnectAsync();
}
}

+ 29
- 33
src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs View File

@@ -1,40 +1,36 @@
namespace Discord
using System;

namespace Discord
{ {
public enum ChannelPermission : byte
[FlagsAttribute]
public enum ChannelPermission : ulong
{ {
//General
CreateInstantInvite = 0,
//KickMembers = 1,
//BanMembers = 2,
//Administrator = 3,
ManageChannel = 4,
//ManageGuild = 5,
// General
CreateInstantInvite = 0x00_00_00_01,
ManageChannels = 0x00_00_00_10,


//Text
AddReactions = 6,
ReadMessages = 10,
SendMessages = 11,
SendTTSMessages = 12,
ManageMessages = 13,
EmbedLinks = 14,
AttachFiles = 15,
ReadMessageHistory = 16,
MentionEveryone = 17,
UseExternalEmojis = 18,
// Text
AddReactions = 0x00_00_00_40,
ReadMessages = 0x00_00_04_00,
SendMessages = 0x00_00_08_00,
SendTTSMessages = 0x00_00_10_00,
ManageMessages = 0x00_00_20_00,
EmbedLinks = 0x00_00_40_00,
AttachFiles = 0x00_00_80_00,
ReadMessageHistory = 0x00_01_00_00,
MentionEveryone = 0x00_02_00_00,
UseExternalEmojis = 0x00_04_00_00,


//Voice
Connect = 20,
Speak = 21,
MuteMembers = 22,
DeafenMembers = 23,
MoveMembers = 24,
UseVAD = 25,
// Voice
Connect = 0x00_10_00_00,
Speak = 0x00_20_00_00,
MuteMembers = 0x00_40_00_00,
DeafenMembers = 0x00_80_00_00,
MoveMembers = 0x01_00_00_00,
UseVAD = 0x02_00_00_00,


//General2
//ChangeNickname = 26,
//ManageNicknames = 27,
ManagePermissions = 28,
ManageWebhooks = 29,
//ManageEmojis = 30
// More General
ManageRoles = 0x10_00_00_00,
ManageWebhooks = 0x20_00_00_00,
} }
} }

+ 15
- 15
src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs View File

@@ -10,7 +10,7 @@ namespace Discord
/// <summary> Gets a blank ChannelPermissions that grants no permissions. </summary> /// <summary> Gets a blank ChannelPermissions that grants no permissions. </summary>
public static readonly ChannelPermissions None = new ChannelPermissions(); public static readonly ChannelPermissions None = new ChannelPermissions();
/// <summary> Gets a ChannelPermissions that grants all permissions for text channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for text channels. </summary>
public static readonly ChannelPermissions Text = new ChannelPermissions(0b00100_0000000_1111111110001_010001);
public static readonly ChannelPermissions Text = new ChannelPermissions(0b01100_0000000_1111111110001_010001);
/// <summary> Gets a ChannelPermissions that grants all permissions for voice channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for voice channels. </summary>
public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000000000_010001); public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000000000_010001);
/// <summary> Gets a ChannelPermissions that grants all permissions for direct message channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for direct message channels. </summary>
@@ -36,7 +36,7 @@ namespace Discord
/// <summary> If True, a user may create invites. </summary> /// <summary> If True, a user may create invites. </summary>
public bool CreateInstantInvite => Permissions.GetValue(RawValue, ChannelPermission.CreateInstantInvite); public bool CreateInstantInvite => Permissions.GetValue(RawValue, ChannelPermission.CreateInstantInvite);
/// <summary> If True, a user may create, delete and modify this channel. </summary> /// <summary> If True, a user may create, delete and modify this channel. </summary>
public bool ManageChannel => Permissions.GetValue(RawValue, ChannelPermission.ManageChannel);
public bool ManageChannel => Permissions.GetValue(RawValue, ChannelPermission.ManageChannels);


/// <summary> If true, a user may add reactions. </summary> /// <summary> If true, a user may add reactions. </summary>
public bool AddReactions => Permissions.GetValue(RawValue, ChannelPermission.AddReactions); public bool AddReactions => Permissions.GetValue(RawValue, ChannelPermission.AddReactions);
@@ -72,8 +72,8 @@ namespace Discord
/// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary>
public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD); public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD);


/// <summary> If True, a user may adjust permissions. This also implictly grants all other permissions. </summary>
public bool ManagePermissions => Permissions.GetValue(RawValue, ChannelPermission.ManagePermissions);
/// <summary> If True, a user may adjust role permissions. This also implictly grants all other permissions. </summary>
public bool ManageRoles => Permissions.GetValue(RawValue, ChannelPermission.ManageRoles);
/// <summary> If True, a user may edit the webhooks for this channel. </summary> /// <summary> If True, a user may edit the webhooks for this channel. </summary>
public bool ManageWebhooks => Permissions.GetValue(RawValue, ChannelPermission.ManageWebhooks); public bool ManageWebhooks => Permissions.GetValue(RawValue, ChannelPermission.ManageWebhooks);


@@ -85,12 +85,12 @@ namespace Discord
bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null, bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null, bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null, bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? managePermissions = null, bool? manageWebhooks = null)
bool? moveMembers = null, bool? useVoiceActivation = null, bool? manageRoles = null, bool? manageWebhooks = null)
{ {
ulong value = initialValue; ulong value = initialValue;


Permissions.SetValue(ref value, createInstantInvite, ChannelPermission.CreateInstantInvite); Permissions.SetValue(ref value, createInstantInvite, ChannelPermission.CreateInstantInvite);
Permissions.SetValue(ref value, manageChannel, ChannelPermission.ManageChannel);
Permissions.SetValue(ref value, manageChannel, ChannelPermission.ManageChannels);
Permissions.SetValue(ref value, addReactions, ChannelPermission.AddReactions); Permissions.SetValue(ref value, addReactions, ChannelPermission.AddReactions);
Permissions.SetValue(ref value, readMessages, ChannelPermission.ReadMessages); Permissions.SetValue(ref value, readMessages, ChannelPermission.ReadMessages);
Permissions.SetValue(ref value, sendMessages, ChannelPermission.SendMessages); Permissions.SetValue(ref value, sendMessages, ChannelPermission.SendMessages);
@@ -107,7 +107,7 @@ namespace Discord
Permissions.SetValue(ref value, deafenMembers, ChannelPermission.DeafenMembers); Permissions.SetValue(ref value, deafenMembers, ChannelPermission.DeafenMembers);
Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers); Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers);
Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD); Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD);
Permissions.SetValue(ref value, managePermissions, ChannelPermission.ManagePermissions);
Permissions.SetValue(ref value, manageRoles, ChannelPermission.ManageRoles);
Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks); Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks);


RawValue = value; RawValue = value;
@@ -119,10 +119,10 @@ namespace Discord
bool readMessages = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false, bool readMessages = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false,
bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false, bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false,
bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false, bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool useVoiceActivation = false, bool managePermissions = false, bool manageWebhooks = false)
bool moveMembers = false, bool useVoiceActivation = false, bool manageRoles = false, bool manageWebhooks = false)
: this(0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, : this(0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, managePermissions, manageWebhooks)
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks)
{ } { }


/// <summary> Creates a new ChannelPermissions from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new ChannelPermissions from this one, changing the provided non-null permissions. </summary>
@@ -131,21 +131,21 @@ namespace Discord
bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null, bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null, bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool useExternalEmojis = false, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null, bool useExternalEmojis = false, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? managePermissions = null, bool? manageWebhooks = null)
bool? moveMembers = null, bool? useVoiceActivation = null, bool? manageRoles = null, bool? manageWebhooks = null)
=> new ChannelPermissions(RawValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, => new ChannelPermissions(RawValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, managePermissions, manageWebhooks);
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks);


public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission);


public List<ChannelPermission> ToList() public List<ChannelPermission> ToList()
{ {
var perms = new List<ChannelPermission>(); var perms = new List<ChannelPermission>();
ulong x = 1;
for (byte i = 0; i < Permissions.MaxBits; i++, x <<= 1)
for (byte i = 0; i < Permissions.MaxBits; i++)
{ {
if ((RawValue & x) != 0)
perms.Add((ChannelPermission)i);
ulong flag = ((ulong)1 << i);
if ((RawValue & flag) != 0)
perms.Add((ChannelPermission)flag);
} }
return perms; return perms;
} }


+ 37
- 33
src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs View File

@@ -1,40 +1,44 @@
namespace Discord
using System;

namespace Discord
{ {
public enum GuildPermission : byte
[FlagsAttribute]
public enum GuildPermission : ulong
{ {
//General
CreateInstantInvite = 0,
KickMembers = 1,
BanMembers = 2,
Administrator = 3,
ManageChannels = 4,
ManageGuild = 5,
// General
CreateInstantInvite = 0x00_00_00_01,
KickMembers = 0x00_00_00_02,
BanMembers = 0x00_00_00_04,
Administrator = 0x00_00_00_08,
ManageChannels = 0x00_00_00_10,
ManageGuild = 0x00_00_00_20,


//Text
AddReactions = 6,
ReadMessages = 10,
SendMessages = 11,
SendTTSMessages = 12,
ManageMessages = 13,
EmbedLinks = 14,
AttachFiles = 15,
ReadMessageHistory = 16,
MentionEveryone = 17,
UseExternalEmojis = 18,
// Text
AddReactions = 0x00_00_00_40,
ViewAuditLog = 0x00_00_00_80,
ReadMessages = 0x00_00_04_00,
SendMessages = 0x00_00_08_00,
SendTTSMessages = 0x00_00_10_00,
ManageMessages = 0x00_00_20_00,
EmbedLinks = 0x00_00_40_00,
AttachFiles = 0x00_00_80_00,
ReadMessageHistory = 0x00_01_00_00,
MentionEveryone = 0x00_02_00_00,
UseExternalEmojis = 0x00_04_00_00,


//Voice
Connect = 20,
Speak = 21,
MuteMembers = 22,
DeafenMembers = 23,
MoveMembers = 24,
UseVAD = 25,
// Voice
Connect = 0x00_10_00_00,
Speak = 0x00_20_00_00,
MuteMembers = 0x00_40_00_00,
DeafenMembers = 0x00_80_00_00,
MoveMembers = 0x01_00_00_00,
UseVAD = 0x02_00_00_00,


//General2
ChangeNickname = 26,
ManageNicknames = 27,
ManageRoles = 28,
ManageWebhooks = 29,
ManageEmojis = 30
// General 2
ChangeNickname = 0x04_00_00_00,
ManageNicknames = 0x08_00_00_00,
ManageRoles = 0x10_00_00_00,
ManageWebhooks = 0x20_00_00_00,
ManageEmojis = 0x40_00_00_00
} }
} }

+ 40
- 28
src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs View File

@@ -11,7 +11,7 @@ namespace Discord
/// <summary> Gets a GuildPermissions that grants all guild permissions for webhook users. </summary> /// <summary> Gets a GuildPermissions that grants all guild permissions for webhook users. </summary>
public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000); public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000);
/// <summary> Gets a GuildPermissions that grants all guild permissions. </summary> /// <summary> Gets a GuildPermissions that grants all guild permissions. </summary>
public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_0111111110001_111111);
public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_11111111110011_111111);


/// <summary> Gets a packed value representing all the permissions in this GuildPermissions. </summary> /// <summary> Gets a packed value representing all the permissions in this GuildPermissions. </summary>
public ulong RawValue { get; } public ulong RawValue { get; }
@@ -28,9 +28,12 @@ namespace Discord
public bool ManageChannels => Permissions.GetValue(RawValue, GuildPermission.ManageChannels); public bool ManageChannels => Permissions.GetValue(RawValue, GuildPermission.ManageChannels);
/// <summary> If True, a user may adjust guild properties. </summary> /// <summary> If True, a user may adjust guild properties. </summary>
public bool ManageGuild => Permissions.GetValue(RawValue, GuildPermission.ManageGuild); public bool ManageGuild => Permissions.GetValue(RawValue, GuildPermission.ManageGuild);
/// <summary> If true, a user may add reactions. </summary> /// <summary> If true, a user may add reactions. </summary>
public bool AddReactions => Permissions.GetValue(RawValue, GuildPermission.AddReactions); public bool AddReactions => Permissions.GetValue(RawValue, GuildPermission.AddReactions);
/// <summary> If true, a user may view the audit log. </summary>
public bool ViewAuditLog => Permissions.GetValue(RawValue, GuildPermission.ViewAuditLog);

/// <summary> If True, a user may join channels. </summary> /// <summary> If True, a user may join channels. </summary>
public bool ReadMessages => Permissions.GetValue(RawValue, GuildPermission.ReadMessages); public bool ReadMessages => Permissions.GetValue(RawValue, GuildPermission.ReadMessages);
/// <summary> If True, a user may send messages. </summary> /// <summary> If True, a user may send messages. </summary>
@@ -77,13 +80,13 @@ namespace Discord
/// <summary> Creates a new GuildPermissions with the provided packed value. </summary> /// <summary> Creates a new GuildPermissions with the provided packed value. </summary>
public GuildPermissions(ulong rawValue) { RawValue = rawValue; } public GuildPermissions(ulong rawValue) { RawValue = rawValue; }


private GuildPermissions(ulong initialValue, bool? createInstantInvite = null, bool? kickMembers = null,
bool? banMembers = null, bool? administrator = null, bool? manageChannel = null, bool? manageGuild = null,
bool? addReactions = null,
bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? userExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
private GuildPermissions(ulong initialValue, bool? createInstantInvite = null, bool? kickMembers = null,
bool? banMembers = null, bool? administrator = null, bool? manageChannels = null, bool? manageGuild = null,
bool? addReactions = null, bool? viewAuditLog = null,
bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null) bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null)
{ {
ulong value = initialValue; ulong value = initialValue;
@@ -92,9 +95,10 @@ namespace Discord
Permissions.SetValue(ref value, banMembers, GuildPermission.BanMembers); Permissions.SetValue(ref value, banMembers, GuildPermission.BanMembers);
Permissions.SetValue(ref value, kickMembers, GuildPermission.KickMembers); Permissions.SetValue(ref value, kickMembers, GuildPermission.KickMembers);
Permissions.SetValue(ref value, administrator, GuildPermission.Administrator); Permissions.SetValue(ref value, administrator, GuildPermission.Administrator);
Permissions.SetValue(ref value, manageChannel, GuildPermission.ManageChannels);
Permissions.SetValue(ref value, manageChannels, GuildPermission.ManageChannels);
Permissions.SetValue(ref value, manageGuild, GuildPermission.ManageGuild); Permissions.SetValue(ref value, manageGuild, GuildPermission.ManageGuild);
Permissions.SetValue(ref value, addReactions, GuildPermission.AddReactions); Permissions.SetValue(ref value, addReactions, GuildPermission.AddReactions);
Permissions.SetValue(ref value, viewAuditLog, GuildPermission.ViewAuditLog);
Permissions.SetValue(ref value, readMessages, GuildPermission.ReadMessages); Permissions.SetValue(ref value, readMessages, GuildPermission.ReadMessages);
Permissions.SetValue(ref value, sendMessages, GuildPermission.SendMessages); Permissions.SetValue(ref value, sendMessages, GuildPermission.SendMessages);
Permissions.SetValue(ref value, sendTTSMessages, GuildPermission.SendTTSMessages); Permissions.SetValue(ref value, sendTTSMessages, GuildPermission.SendTTSMessages);
@@ -103,7 +107,7 @@ namespace Discord
Permissions.SetValue(ref value, attachFiles, GuildPermission.AttachFiles); Permissions.SetValue(ref value, attachFiles, GuildPermission.AttachFiles);
Permissions.SetValue(ref value, readMessageHistory, GuildPermission.ReadMessageHistory); Permissions.SetValue(ref value, readMessageHistory, GuildPermission.ReadMessageHistory);
Permissions.SetValue(ref value, mentionEveryone, GuildPermission.MentionEveryone); Permissions.SetValue(ref value, mentionEveryone, GuildPermission.MentionEveryone);
Permissions.SetValue(ref value, userExternalEmojis, GuildPermission.UseExternalEmojis);
Permissions.SetValue(ref value, useExternalEmojis, GuildPermission.UseExternalEmojis);
Permissions.SetValue(ref value, connect, GuildPermission.Connect); Permissions.SetValue(ref value, connect, GuildPermission.Connect);
Permissions.SetValue(ref value, speak, GuildPermission.Speak); Permissions.SetValue(ref value, speak, GuildPermission.Speak);
Permissions.SetValue(ref value, muteMembers, GuildPermission.MuteMembers); Permissions.SetValue(ref value, muteMembers, GuildPermission.MuteMembers);
@@ -120,42 +124,50 @@ namespace Discord
} }


/// <summary> Creates a new GuildPermissions with the provided permissions. </summary> /// <summary> Creates a new GuildPermissions with the provided permissions. </summary>
public GuildPermissions(bool createInstantInvite = false, bool kickMembers = false,
public GuildPermissions(bool createInstantInvite = false, bool kickMembers = false,
bool banMembers = false, bool administrator = false, bool manageChannels = false, bool manageGuild = false, bool banMembers = false, bool administrator = false, bool manageChannels = false, bool manageGuild = false,
bool addReactions = false,
bool addReactions = false, bool viewAuditLog = false,
bool readMessages = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false, bool readMessages = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false,
bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false, bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false,
bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false, bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool useVoiceActivation = false, bool? changeNickname = false, bool? manageNicknames = false,
bool moveMembers = false, bool useVoiceActivation = false, bool? changeNickname = false, bool? manageNicknames = false,
bool manageRoles = false, bool manageWebhooks = false, bool manageEmojis = false) bool manageRoles = false, bool manageWebhooks = false, bool manageEmojis = false)
: this(0, createInstantInvite, manageRoles, kickMembers, banMembers, manageChannels, manageGuild, addReactions,
readMessages, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, mentionEveryone, useExternalEmojis, connect,
manageWebhooks, manageEmojis) { }
: this(0, createInstantInvite: createInstantInvite, manageRoles: manageRoles, kickMembers: kickMembers, banMembers: banMembers,
administrator: administrator, manageChannels: manageChannels, manageGuild: manageGuild, addReactions: addReactions,
viewAuditLog: viewAuditLog, readMessages: readMessages, sendMessages: sendMessages, sendTTSMessages: sendTTSMessages,
manageMessages: manageMessages, embedLinks: embedLinks, attachFiles: attachFiles, readMessageHistory: readMessageHistory,
mentionEveryone: mentionEveryone, useExternalEmojis: useExternalEmojis, connect: connect, speak: speak, muteMembers: muteMembers,
deafenMembers: deafenMembers, moveMembers: moveMembers, useVoiceActivation: useVoiceActivation, changeNickname: changeNickname,
manageNicknames: manageNicknames, manageWebhooks: manageWebhooks, manageEmojis: manageEmojis)
{ }


/// <summary> Creates a new GuildPermissions from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new GuildPermissions from this one, changing the provided non-null permissions. </summary>
public GuildPermissions Modify(bool? createInstantInvite = null, bool? kickMembers = null,
public GuildPermissions Modify(bool? createInstantInvite = null, bool? kickMembers = null,
bool? banMembers = null, bool? administrator = null, bool? manageChannels = null, bool? manageGuild = null, bool? banMembers = null, bool? administrator = null, bool? manageChannels = null, bool? manageGuild = null,
bool? addReactions = null,
bool? addReactions = null, bool? viewAuditLog = null,
bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null, bool? readMessages = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null, bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null, bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null) bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null)
=> new GuildPermissions(RawValue, createInstantInvite, manageRoles, kickMembers, banMembers, manageChannels, manageGuild, addReactions,
readMessages, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, changeNickname, manageNicknames, manageRoles,
manageWebhooks, manageEmojis);
=> new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions,
viewAuditLog, readMessages, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,
useVoiceActivation, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis);


public bool Has(GuildPermission permission) => Permissions.GetValue(RawValue, permission); public bool Has(GuildPermission permission) => Permissions.GetValue(RawValue, permission);


public List<GuildPermission> ToList() public List<GuildPermission> ToList()
{ {
var perms = new List<GuildPermission>(); var perms = new List<GuildPermission>();
ulong x = 1;
for (byte i = 0; i < Permissions.MaxBits; i++, x <<= 1)

// bitwise operations on raw value
// each of the GuildPermissions increments by 2^i from 0 to MaxBits
for (byte i = 0; i < Permissions.MaxBits; i++)
{ {
if ((RawValue & x) != 0)
perms.Add((GuildPermission)i);
ulong flag = ((ulong)1 << i);
if ((RawValue & flag) != 0)
perms.Add((GuildPermission)flag);
} }
return perms; return perms;
} }


+ 19
- 18
src/Discord.Net.Core/Entities/Permissions/OverwritePermissions.cs View File

@@ -23,7 +23,7 @@ namespace Discord
/// <summary> If Allowed, a user may create invites. </summary> /// <summary> If Allowed, a user may create invites. </summary>
public PermValue CreateInstantInvite => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.CreateInstantInvite); public PermValue CreateInstantInvite => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.CreateInstantInvite);
/// <summary> If Allowed, a user may create, delete and modify this channel. </summary> /// <summary> If Allowed, a user may create, delete and modify this channel. </summary>
public PermValue ManageChannel => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManageChannel);
public PermValue ManageChannel => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManageChannels);
/// <summary> If Allowed, a user may add reactions. </summary> /// <summary> If Allowed, a user may add reactions. </summary>
public PermValue AddReactions => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.AddReactions); public PermValue AddReactions => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.AddReactions);
/// <summary> If Allowed, a user may join channels. </summary> /// <summary> If Allowed, a user may join channels. </summary>
@@ -58,8 +58,8 @@ namespace Discord
/// <summary> If Allowed, a user may use voice-activity-detection rather than push-to-talk. </summary> /// <summary> If Allowed, a user may use voice-activity-detection rather than push-to-talk. </summary>
public PermValue UseVAD => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.UseVAD); public PermValue UseVAD => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.UseVAD);


/// <summary> If Allowed, a user may adjust permissions. This also implictly grants all other permissions. </summary>
public PermValue ManagePermissions => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManagePermissions);
/// <summary> If Allowed, a user may adjust role permissions. This also implictly grants all other permissions. </summary>
public PermValue ManageRoles => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManageRoles);
/// <summary> If True, a user may edit the webhooks for this channel. </summary> /// <summary> If True, a user may edit the webhooks for this channel. </summary>
public PermValue ManageWebhooks => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManageWebhooks); public PermValue ManageWebhooks => Permissions.GetValue(AllowValue, DenyValue, ChannelPermission.ManageWebhooks);


@@ -75,11 +75,11 @@ namespace Discord
PermValue? readMessages = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null, PermValue? readMessages = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null,
PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null, PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null, PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null,
PermValue? deafenMembers = null, PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? managePermissions = null,
PermValue? deafenMembers = null, PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? manageRoles = null,
PermValue? manageWebhooks = null) PermValue? manageWebhooks = null)
{ {
Permissions.SetValue(ref allowValue, ref denyValue, createInstantInvite, ChannelPermission.CreateInstantInvite); Permissions.SetValue(ref allowValue, ref denyValue, createInstantInvite, ChannelPermission.CreateInstantInvite);
Permissions.SetValue(ref allowValue, ref denyValue, manageChannel, ChannelPermission.ManageChannel);
Permissions.SetValue(ref allowValue, ref denyValue, manageChannel, ChannelPermission.ManageChannels);
Permissions.SetValue(ref allowValue, ref denyValue, addReactions, ChannelPermission.AddReactions); Permissions.SetValue(ref allowValue, ref denyValue, addReactions, ChannelPermission.AddReactions);
Permissions.SetValue(ref allowValue, ref denyValue, readMessages, ChannelPermission.ReadMessages); Permissions.SetValue(ref allowValue, ref denyValue, readMessages, ChannelPermission.ReadMessages);
Permissions.SetValue(ref allowValue, ref denyValue, sendMessages, ChannelPermission.SendMessages); Permissions.SetValue(ref allowValue, ref denyValue, sendMessages, ChannelPermission.SendMessages);
@@ -96,7 +96,7 @@ namespace Discord
Permissions.SetValue(ref allowValue, ref denyValue, deafenMembers, ChannelPermission.DeafenMembers); Permissions.SetValue(ref allowValue, ref denyValue, deafenMembers, ChannelPermission.DeafenMembers);
Permissions.SetValue(ref allowValue, ref denyValue, moveMembers, ChannelPermission.MoveMembers); Permissions.SetValue(ref allowValue, ref denyValue, moveMembers, ChannelPermission.MoveMembers);
Permissions.SetValue(ref allowValue, ref denyValue, useVoiceActivation, ChannelPermission.UseVAD); Permissions.SetValue(ref allowValue, ref denyValue, useVoiceActivation, ChannelPermission.UseVAD);
Permissions.SetValue(ref allowValue, ref denyValue, managePermissions, ChannelPermission.ManagePermissions);
Permissions.SetValue(ref allowValue, ref denyValue, manageRoles, ChannelPermission.ManageRoles);
Permissions.SetValue(ref allowValue, ref denyValue, manageWebhooks, ChannelPermission.ManageWebhooks); Permissions.SetValue(ref allowValue, ref denyValue, manageWebhooks, ChannelPermission.ManageWebhooks);


AllowValue = allowValue; AllowValue = allowValue;
@@ -109,10 +109,10 @@ namespace Discord
PermValue readMessages = PermValue.Inherit, PermValue sendMessages = PermValue.Inherit, PermValue sendTTSMessages = PermValue.Inherit, PermValue manageMessages = PermValue.Inherit, PermValue readMessages = PermValue.Inherit, PermValue sendMessages = PermValue.Inherit, PermValue sendTTSMessages = PermValue.Inherit, PermValue manageMessages = PermValue.Inherit,
PermValue embedLinks = PermValue.Inherit, PermValue attachFiles = PermValue.Inherit, PermValue readMessageHistory = PermValue.Inherit, PermValue mentionEveryone = PermValue.Inherit, PermValue embedLinks = PermValue.Inherit, PermValue attachFiles = PermValue.Inherit, PermValue readMessageHistory = PermValue.Inherit, PermValue mentionEveryone = PermValue.Inherit,
PermValue useExternalEmojis = PermValue.Inherit, PermValue connect = PermValue.Inherit, PermValue speak = PermValue.Inherit, PermValue muteMembers = PermValue.Inherit, PermValue deafenMembers = PermValue.Inherit, PermValue useExternalEmojis = PermValue.Inherit, PermValue connect = PermValue.Inherit, PermValue speak = PermValue.Inherit, PermValue muteMembers = PermValue.Inherit, PermValue deafenMembers = PermValue.Inherit,
PermValue moveMembers = PermValue.Inherit, PermValue useVoiceActivation = PermValue.Inherit, PermValue managePermissions = PermValue.Inherit, PermValue manageWebhooks = PermValue.Inherit)
PermValue moveMembers = PermValue.Inherit, PermValue useVoiceActivation = PermValue.Inherit, PermValue manageRoles = PermValue.Inherit, PermValue manageWebhooks = PermValue.Inherit)
: this(0, 0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, : this(0, 0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers,
moveMembers, useVoiceActivation, managePermissions, manageWebhooks) { }
moveMembers, useVoiceActivation, manageRoles, manageWebhooks) { }


/// <summary> Creates a new OverwritePermissions from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new OverwritePermissions from this one, changing the provided non-null permissions. </summary>
public OverwritePermissions Modify(PermValue? createInstantInvite = null, PermValue? manageChannel = null, public OverwritePermissions Modify(PermValue? createInstantInvite = null, PermValue? manageChannel = null,
@@ -120,30 +120,31 @@ namespace Discord
PermValue? readMessages = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null, PermValue? readMessages = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null,
PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null, PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null, PermValue? deafenMembers = null, PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null, PermValue? deafenMembers = null,
PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? managePermissions = null, PermValue? manageWebhooks = null)
PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? manageRoles = null, PermValue? manageWebhooks = null)
=> new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, => new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers,
moveMembers, useVoiceActivation, managePermissions, manageWebhooks);
moveMembers, useVoiceActivation, manageRoles, manageWebhooks);


public List<ChannelPermission> ToAllowList() public List<ChannelPermission> ToAllowList()
{ {
var perms = new List<ChannelPermission>(); var perms = new List<ChannelPermission>();
ulong x = 1;
for (byte i = 0; i < Permissions.MaxBits; i++, x <<= 1)
for (byte i = 0; i < Permissions.MaxBits; i++)
{ {
if ((AllowValue & x) != 0)
perms.Add((ChannelPermission)i);
// first operand must be long or ulong to shift >31 bits
ulong flag = ((ulong)1 << i);
if ((AllowValue & flag) != 0)
perms.Add((ChannelPermission)flag);
} }
return perms; return perms;
} }
public List<ChannelPermission> ToDenyList() public List<ChannelPermission> ToDenyList()
{ {
var perms = new List<ChannelPermission>(); var perms = new List<ChannelPermission>();
ulong x = 1;
for (byte i = 0; i < Permissions.MaxBits; i++, x <<= 1)
for (byte i = 0; i < Permissions.MaxBits; i++)
{ {
if ((DenyValue & x) != 0)
perms.Add((ChannelPermission)i);
ulong flag = ((ulong)1 << i);
if ((DenyValue & flag) != 0)
perms.Add((ChannelPermission)flag);
} }
return perms; return perms;
} }


+ 1
- 1
src/Discord.Net.Core/Utils/Optional.cs View File

@@ -10,7 +10,7 @@ namespace Discord
public static Optional<T> Unspecified => default(Optional<T>); public static Optional<T> Unspecified => default(Optional<T>);
private readonly T _value; private readonly T _value;


/// <summary> Gets the value for this paramter. </summary>
/// <summary> Gets the value for this parameter. </summary>
public T Value public T Value
{ {
get get


+ 33
- 33
src/Discord.Net.Core/Utils/Permissions.cs View File

@@ -7,84 +7,84 @@ namespace Discord
public const int MaxBits = 53; public const int MaxBits = 53;


[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PermValue GetValue(ulong allow, ulong deny, ChannelPermission bit)
=> GetValue(allow, deny, (byte)bit);
public static PermValue GetValue(ulong allow, ulong deny, ChannelPermission flag)
=> GetValue(allow, deny, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PermValue GetValue(ulong allow, ulong deny, GuildPermission bit)
=> GetValue(allow, deny, (byte)bit);
public static PermValue GetValue(ulong allow, ulong deny, GuildPermission flag)
=> GetValue(allow, deny, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PermValue GetValue(ulong allow, ulong deny, byte bit)
public static PermValue GetValue(ulong allow, ulong deny, ulong flag)
{ {
if (HasBit(allow, bit))
if (HasFlag(allow, flag))
return PermValue.Allow; return PermValue.Allow;
else if (HasBit(deny, bit))
else if (HasFlag(deny, flag))
return PermValue.Deny; return PermValue.Deny;
else else
return PermValue.Inherit; return PermValue.Inherit;
} }


[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool GetValue(ulong value, ChannelPermission bit)
=> GetValue(value, (byte)bit);
public static bool GetValue(ulong value, ChannelPermission flag)
=> GetValue(value, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool GetValue(ulong value, GuildPermission bit)
=> GetValue(value, (byte)bit);
public static bool GetValue(ulong value, GuildPermission flag)
=> GetValue(value, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool GetValue(ulong value, byte bit) => HasBit(value, bit);
public static bool GetValue(ulong value, ulong flag) => HasFlag(value, flag);


[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong rawValue, bool? value, ChannelPermission bit)
=> SetValue(ref rawValue, value, (byte)bit);
public static void SetValue(ref ulong rawValue, bool? value, ChannelPermission flag)
=> SetValue(ref rawValue, value, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong rawValue, bool? value, GuildPermission bit)
=> SetValue(ref rawValue, value, (byte)bit);
public static void SetValue(ref ulong rawValue, bool? value, GuildPermission flag)
=> SetValue(ref rawValue, value, (ulong)flag);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong rawValue, bool? value, byte bit)
public static void SetValue(ref ulong rawValue, bool? value, ulong flag)
{ {
if (value.HasValue) if (value.HasValue)
{ {
if (value == true) if (value == true)
SetBit(ref rawValue, bit);
SetFlag(ref rawValue, flag);
else else
UnsetBit(ref rawValue, bit);
UnsetFlag(ref rawValue, flag);
} }
} }


[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ChannelPermission bit)
=> SetValue(ref allow, ref deny, value, (byte)bit);
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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, GuildPermission bit)
=> SetValue(ref allow, ref deny, value, (byte)bit);
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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, byte bit)
public static void SetValue(ref ulong allow, ref ulong deny, PermValue? value, ulong flag)
{ {
if (value.HasValue) if (value.HasValue)
{ {
switch (value) switch (value)
{ {
case PermValue.Allow: case PermValue.Allow:
SetBit(ref allow, bit);
UnsetBit(ref deny, bit);
SetFlag(ref allow, flag);
UnsetFlag(ref deny, flag);
break; break;
case PermValue.Deny: case PermValue.Deny:
UnsetBit(ref allow, bit);
SetBit(ref deny, bit);
UnsetFlag(ref allow, flag);
SetFlag(ref deny, flag);
break; break;
default: default:
UnsetBit(ref allow, bit);
UnsetBit(ref deny, bit);
UnsetFlag(ref allow, flag);
UnsetFlag(ref deny, flag);
break; break;
} }
} }
} }


[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool HasBit(ulong value, byte bit) => (value & (1U << bit)) != 0;
private static bool HasFlag(ulong value, ulong flag) => (value & flag) != 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetBit(ref ulong value, byte bit) => value |= (1U << bit);
public static void SetFlag(ref ulong value, ulong flag) => value |= flag;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnsetBit(ref ulong value, byte bit) => value &= ~(1U << bit);
public static void UnsetFlag(ref ulong value, ulong flag) => value &= ~flag;


public static ChannelPermissions ToChannelPerms(IGuildChannel channel, ulong guildPermissions) public static ChannelPermissions ToChannelPerms(IGuildChannel channel, ulong guildPermissions)
=> new ChannelPermissions(guildPermissions & ChannelPermissions.All(channel).RawValue); => new ChannelPermissions(guildPermissions & ChannelPermissions.All(channel).RawValue);


+ 2
- 2
src/Discord.Net.Rest/Entities/Channels/RestChannel.cs View File

@@ -48,8 +48,8 @@ namespace Discord.Rest
string IChannel.Name => null; string IChannel.Name => null;


Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IUser>(null); //Overriden
=> Task.FromResult<IUser>(null); //Overridden
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> AsyncEnumerable.Empty<IReadOnlyCollection<IUser>>(); //Overriden
=> AsyncEnumerable.Empty<IReadOnlyCollection<IUser>>(); //Overridden
} }
} }

+ 4
- 4
src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs View File

@@ -154,14 +154,14 @@ namespace Discord.Rest
=> await RemovePermissionOverwriteAsync(user, options).ConfigureAwait(false); => await RemovePermissionOverwriteAsync(user, options).ConfigureAwait(false);
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); //Overriden //Overriden in Text/Voice
=> AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); //Overridden //Overridden in Text/Voice
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuildUser>(null); //Overriden in Text/Voice
=> Task.FromResult<IGuildUser>(null); //Overridden in Text/Voice


//IChannel //IChannel
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> AsyncEnumerable.Empty<IReadOnlyCollection<IUser>>(); //Overriden in Text/Voice
=> AsyncEnumerable.Empty<IReadOnlyCollection<IUser>>(); //Overridden in Text/Voice
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IUser>(null); //Overriden in Text/Voice
=> Task.FromResult<IUser>(null); //Overridden in Text/Voice
} }
} }

+ 35
- 0
src/Discord.Net.Rest/Extensions/EmbedBuilderExtensions.cs View File

@@ -1,3 +1,5 @@
using System;

namespace Discord namespace Discord
{ {
public static class EmbedBuilderExtensions public static class EmbedBuilderExtensions
@@ -19,5 +21,38 @@ namespace Discord


public static EmbedBuilder WithAuthor(this EmbedBuilder builder, IGuildUser user) => public static EmbedBuilder WithAuthor(this EmbedBuilder builder, IGuildUser user) =>
builder.WithAuthor($"{user.Nickname ?? user.Username}#{user.Discriminator}", user.GetAvatarUrl()); builder.WithAuthor($"{user.Nickname ?? user.Username}#{user.Discriminator}", user.GetAvatarUrl());

public static EmbedBuilder ToEmbedBuilder(this IEmbed embed)
{
if (embed.Type != EmbedType.Rich)
throw new InvalidOperationException($"Only {nameof(EmbedType.Rich)} embeds may be built.");

var builder = new EmbedBuilder
{
Author = new EmbedAuthorBuilder
{
Name = embed.Author?.Name,
IconUrl = embed.Author?.IconUrl,
Url = embed.Author?.Url
},
Color = embed.Color ?? Color.Default,
Description = embed.Description,
Footer = new EmbedFooterBuilder
{
Text = embed.Footer?.Text,
IconUrl = embed.Footer?.IconUrl
},
ImageUrl = embed.Image?.Url,
ThumbnailUrl = embed.Thumbnail?.Url,
Timestamp = embed.Timestamp,
Title = embed.Title,
Url = embed.Url
};

foreach (var field in embed.Fields)
builder.AddField(field.Name, field.Value, field.Inline);

return builder;
}
} }
} }

+ 0
- 2
src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs View File

@@ -13,8 +13,6 @@ namespace Discord.API.Gateway
public IDictionary<string, string> Properties { get; set; } public IDictionary<string, string> Properties { get; set; }
[JsonProperty("large_threshold")] [JsonProperty("large_threshold")]
public int LargeThreshold { get; set; } public int LargeThreshold { get; set; }
[JsonProperty("compress")]
public bool UseCompression { get; set; }
[JsonProperty("shard")] [JsonProperty("shard")]
public Optional<int[]> ShardingParams { get; set; } public Optional<int[]> ShardingParams { get; set; }
} }


+ 35
- 8
src/Discord.Net.WebSocket/DiscordSocketApiClient.cs View File

@@ -29,7 +29,11 @@ namespace Discord.API
private CancellationTokenSource _connectCancelToken; private CancellationTokenSource _connectCancelToken;
private string _gatewayUrl; private string _gatewayUrl;
private bool _isExplicitUrl; private bool _isExplicitUrl;

//Store our decompression streams for zlib shared state
private MemoryStream _compressed;
private DeflateStream _decompressor;

internal IWebSocketClient WebSocketClient { get; } internal IWebSocketClient WebSocketClient { get; }


public ConnectionState ConnectionState { get; private set; } public ConnectionState ConnectionState { get; private set; }
@@ -43,14 +47,29 @@ namespace Discord.API
_isExplicitUrl = true; _isExplicitUrl = true;
WebSocketClient = webSocketProvider(); WebSocketClient = webSocketProvider();
//WebSocketClient.SetHeader("user-agent", DiscordConfig.UserAgent); (Causes issues in .NET Framework 4.6+) //WebSocketClient.SetHeader("user-agent", DiscordConfig.UserAgent); (Causes issues in .NET Framework 4.6+)

WebSocketClient.BinaryMessage += async (data, index, count) => WebSocketClient.BinaryMessage += async (data, index, count) =>
{ {
using (var compressed = new MemoryStream(data, index + 2, count - 2))
using (var decompressed = new MemoryStream()) using (var decompressed = new MemoryStream())
{ {
using (var zlib = new DeflateStream(compressed, CompressionMode.Decompress))
zlib.CopyTo(decompressed);
if (data[0] == 0x78)
{
//Strip the zlib header
_compressed.Write(data, index + 2, count - 2);
_compressed.SetLength(count - 2);
}
else
{
_compressed.Write(data, index, count);
_compressed.SetLength(count);
}

//Reset positions so we don't run out of memory
_compressed.Position = 0;
_decompressor.CopyTo(decompressed);
_compressed.Position = 0;
decompressed.Position = 0; decompressed.Position = 0;

using (var reader = new StreamReader(decompressed)) using (var reader = new StreamReader(decompressed))
using (var jsonReader = new JsonTextReader(reader)) using (var jsonReader = new JsonTextReader(reader))
{ {
@@ -76,6 +95,7 @@ namespace Discord.API
await _disconnectedEvent.InvokeAsync(ex).ConfigureAwait(false); await _disconnectedEvent.InvokeAsync(ex).ConfigureAwait(false);
}; };
} }

internal override void Dispose(bool disposing) internal override void Dispose(bool disposing)
{ {
if (!_isDisposed) if (!_isDisposed)
@@ -84,6 +104,8 @@ namespace Discord.API
{ {
_connectCancelToken?.Dispose(); _connectCancelToken?.Dispose();
(WebSocketClient as IDisposable)?.Dispose(); (WebSocketClient as IDisposable)?.Dispose();
_decompressor?.Dispose();
_compressed?.Dispose();
} }
_isDisposed = true; _isDisposed = true;
} }
@@ -105,6 +127,12 @@ namespace Discord.API
if (WebSocketClient == null) if (WebSocketClient == null)
throw new NotSupportedException("This client is not configured with websocket support."); throw new NotSupportedException("This client is not configured with websocket support.");


//Re-create streams to reset the zlib state
_compressed?.Dispose();
_decompressor?.Dispose();
_compressed = new MemoryStream();
_decompressor = new DeflateStream(_compressed, CompressionMode.Decompress);

ConnectionState = ConnectionState.Connecting; ConnectionState = ConnectionState.Connecting;
try try
{ {
@@ -115,7 +143,7 @@ namespace Discord.API
if (!_isExplicitUrl) if (!_isExplicitUrl)
{ {
var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false); var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false);
_gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}";
_gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}&compress=zlib-stream";
} }
await WebSocketClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false); await WebSocketClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false);


@@ -191,7 +219,7 @@ namespace Discord.API
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
return await SendAsync<GetBotGatewayResponse>("GET", () => "gateway/bot", new BucketIds(), options: options).ConfigureAwait(false); return await SendAsync<GetBotGatewayResponse>("GET", () => "gateway/bot", new BucketIds(), options: options).ConfigureAwait(false);
} }
public async Task SendIdentifyAsync(int largeThreshold = 100, bool useCompression = true, int shardID = 0, int totalShards = 1, RequestOptions options = null)
public async Task SendIdentifyAsync(int largeThreshold = 100, int shardID = 0, int totalShards = 1, RequestOptions options = null)
{ {
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
var props = new Dictionary<string, string> var props = new Dictionary<string, string>
@@ -202,8 +230,7 @@ namespace Discord.API
{ {
Token = AuthToken, Token = AuthToken,
Properties = props, Properties = props,
LargeThreshold = largeThreshold,
UseCompression = useCompression,
LargeThreshold = largeThreshold
}; };
if (totalShards > 1) if (totalShards > 1)
msg.ShardingParams = new int[] { shardID, totalShards }; msg.ShardingParams = new int[] { shardID, totalShards };


+ 2
- 2
src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs View File

@@ -154,8 +154,8 @@ namespace Discord.WebSocket


//IChannel //IChannel
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); //Overriden in Text/Voice
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); //Overridden in Text/Voice
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IUser>(GetUser(id)); //Overriden in Text/Voice
=> Task.FromResult<IUser>(GetUser(id)); //Overridden in Text/Voice
} }
} }

Loading…
Cancel
Save