| @@ -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. | ||||
| @@ -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 | ||||
| @@ -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> | ||||
| @@ -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); | |||||
| } | |||||
| }); | |||||
| } | |||||
| @@ -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(); } | |||||
| } | |||||
| } | } | ||||
| @@ -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(); | ||||
| } | |||||
| } | |||||
| @@ -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, | |||||
| } | } | ||||
| } | } | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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 | |||||
| } | } | ||||
| } | } | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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; | ||||
| } | } | ||||
| @@ -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 | ||||
| @@ -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); | ||||
| @@ -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 | |||||
| } | } | ||||
| } | } | ||||
| @@ -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 | |||||
| } | } | ||||
| } | } | ||||
| @@ -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; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -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; } | ||||
| } | } | ||||
| @@ -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 }; | ||||
| @@ -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 | |||||
| } | } | ||||
| } | } | ||||