| @@ -48,8 +48,8 @@ namespace Discord | |||||
| { | { | ||||
| var result = new Override(); | var result = new Override(); | ||||
| using(var textReader = new StringReader(json)) | |||||
| using(var reader = new JsonTextReader(textReader)) | |||||
| using (var textReader = new StringReader(json)) | |||||
| using (var reader = new JsonTextReader(textReader)) | |||||
| { | { | ||||
| var obj = JObject.ReadFrom(reader); | var obj = JObject.ReadFrom(reader); | ||||
| result.Id = obj["id"].ToObject<Guid>(); | result.Id = obj["id"].ToObject<Guid>(); | ||||
| @@ -100,14 +100,14 @@ namespace Discord | |||||
| /// Gets a read-only dictionary containing the currently loaded overrides. | /// Gets a read-only dictionary containing the currently loaded overrides. | ||||
| /// </summary> | /// </summary> | ||||
| public IReadOnlyDictionary<Override, IReadOnlyCollection<LoadedOverride>> LoadedOverrides | public IReadOnlyDictionary<Override, IReadOnlyCollection<LoadedOverride>> LoadedOverrides | ||||
| => _loadedOverrides.Select(x => new KeyValuePair<Override, IReadOnlyCollection<LoadedOverride>> (x.Key, x.Value)).ToDictionary(x => x.Key, x => x.Value); | |||||
| => _loadedOverrides.Select(x => new KeyValuePair<Override, IReadOnlyCollection<LoadedOverride>>(x.Key, x.Value)).ToDictionary(x => x.Key, x => x.Value); | |||||
| private static AssemblyLoadContext _overrideDomain; | private static AssemblyLoadContext _overrideDomain; | ||||
| private static List<Func<Override, string, Task>> _logEvents = new(); | private static List<Func<Override, string, Task>> _logEvents = new(); | ||||
| private static ConcurrentDictionary<Override, List<LoadedOverride>> _loadedOverrides = new ConcurrentDictionary<Override, List<LoadedOverride>>(); | private static ConcurrentDictionary<Override, List<LoadedOverride>> _loadedOverrides = new ConcurrentDictionary<Override, List<LoadedOverride>>(); | ||||
| private const string ApiUrl = "https://overrides.discordnet.dev"; | private const string ApiUrl = "https://overrides.discordnet.dev"; | ||||
| static BuildOverrides() | static BuildOverrides() | ||||
| { | { | ||||
| _overrideDomain = new AssemblyLoadContext("Discord.Net.Overrides.Runtime"); | _overrideDomain = new AssemblyLoadContext("Discord.Net.Overrides.Runtime"); | ||||
| @@ -258,14 +258,14 @@ namespace Discord | |||||
| private static async Task<Assembly> GetDependencyAsync(Guid id, string name) | private static async Task<Assembly> GetDependencyAsync(Guid id, string name) | ||||
| { | { | ||||
| using(var client = new HttpClient()) | |||||
| using (var client = new HttpClient()) | |||||
| { | { | ||||
| var result = await client.PostAsync($"{ApiUrl}/overrides/{id}/dependency", new StringContent($"{{ \"info\": \"{name}\"}}", Encoding.UTF8, "application/json")); | var result = await client.PostAsync($"{ApiUrl}/overrides/{id}/dependency", new StringContent($"{{ \"info\": \"{name}\"}}", Encoding.UTF8, "application/json")); | ||||
| if (!result.IsSuccessStatusCode) | if (!result.IsSuccessStatusCode) | ||||
| throw new Exception("Failed to get dependency"); | throw new Exception("Failed to get dependency"); | ||||
| using(var ms = new MemoryStream()) | |||||
| using (var ms = new MemoryStream()) | |||||
| { | { | ||||
| var innerStream = await result.Content.ReadAsStreamAsync(); | var innerStream = await result.Content.ReadAsStreamAsync(); | ||||
| await innerStream.CopyToAsync(ms); | await innerStream.CopyToAsync(ms); | ||||
| @@ -1,8 +1,8 @@ | |||||
| using Discord; | |||||
| using Discord.WebSocket; | |||||
| using System; | using System; | ||||
| using System.Threading; | using System.Threading; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Discord; | |||||
| using Discord.WebSocket; | |||||
| namespace BasicBot | namespace BasicBot | ||||
| { | { | ||||
| @@ -112,7 +112,8 @@ namespace BasicBot | |||||
| if (component.Data.CustomId == "unique-id") | if (component.Data.CustomId == "unique-id") | ||||
| await interaction.RespondAsync("Thank you for clicking my button!"); | await interaction.RespondAsync("Thank you for clicking my button!"); | ||||
| else Console.WriteLine("An ID has been received that has no handler!"); | |||||
| else | |||||
| Console.WriteLine("An ID has been received that has no handler!"); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -30,7 +30,8 @@ namespace InteractionFramework.Attributes | |||||
| ? Task.FromResult(PreconditionResult.FromSuccess()) | ? Task.FromResult(PreconditionResult.FromSuccess()) | ||||
| : Task.FromResult(PreconditionResult.FromError("User ID does not match component ID!")); | : Task.FromResult(PreconditionResult.FromError("User ID does not match component ID!")); | ||||
| else return Task.FromResult(PreconditionResult.FromError("Parse cannot be done if no userID exists.")); | |||||
| else | |||||
| return Task.FromResult(PreconditionResult.FromError("Parse cannot be done if no userID exists.")); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -10,7 +10,7 @@ namespace InteractionFramework.Attributes | |||||
| { | { | ||||
| public class RequireOwnerAttribute : PreconditionAttribute | public class RequireOwnerAttribute : PreconditionAttribute | ||||
| { | { | ||||
| public override async Task<PreconditionResult> CheckRequirementsAsync (IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services) | |||||
| public override async Task<PreconditionResult> CheckRequirementsAsync(IInteractionContext context, ICommandInfo commandInfo, IServiceProvider services) | |||||
| { | { | ||||
| switch (context.Client.TokenType) | switch (context.Client.TokenType) | ||||
| { | { | ||||
| @@ -26,7 +26,7 @@ namespace InteractionFramework.Modules | |||||
| // [Summary] lets you customize the name and the description of a parameter | // [Summary] lets you customize the name and the description of a parameter | ||||
| [SlashCommand("echo", "Repeat the input")] | [SlashCommand("echo", "Repeat the input")] | ||||
| public async Task Echo(string echo, [Summary(description: "mention the user")]bool mention = false) | |||||
| public async Task Echo(string echo, [Summary(description: "mention the user")] bool mention = false) | |||||
| => await RespondAsync(echo + (mention ? Context.User.Mention : string.Empty)); | => await RespondAsync(echo + (mention ? Context.User.Mention : string.Empty)); | ||||
| [SlashCommand("ping", "Pings the bot and returns its latency.")] | [SlashCommand("ping", "Pings the bot and returns its latency.")] | ||||
| @@ -64,11 +64,11 @@ namespace InteractionFramework | |||||
| public static bool IsDebug() | public static bool IsDebug() | ||||
| { | { | ||||
| #if DEBUG | |||||
| return true; | |||||
| #else | |||||
| #if DEBUG | |||||
| return true; | |||||
| #else | |||||
| return false; | return false; | ||||
| #endif | |||||
| #endif | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,11 +1,11 @@ | |||||
| using System; | |||||
| using System.Collections.Immutable; | |||||
| using System.Linq; | |||||
| using Discord.Commands; | |||||
| using Microsoft.CodeAnalysis; | using Microsoft.CodeAnalysis; | ||||
| using Microsoft.CodeAnalysis.CSharp; | using Microsoft.CodeAnalysis.CSharp; | ||||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | using Microsoft.CodeAnalysis.CSharp.Syntax; | ||||
| using Microsoft.CodeAnalysis.Diagnostics; | using Microsoft.CodeAnalysis.Diagnostics; | ||||
| using Discord.Commands; | |||||
| using System; | |||||
| using System.Collections.Immutable; | |||||
| using System.Linq; | |||||
| namespace Discord.Analyzers | namespace Discord.Analyzers | ||||
| { | { | ||||
| @@ -13,7 +13,14 @@ namespace Discord.Analyzers | |||||
| public sealed class GuildAccessAnalyzer : DiagnosticAnalyzer | public sealed class GuildAccessAnalyzer : DiagnosticAnalyzer | ||||
| { | { | ||||
| private const string DiagnosticId = "DNET0001"; | private const string DiagnosticId = "DNET0001"; | ||||
| /* Unmerged change from project 'Discord.Net.Analyzers(netstandard2.1)' | |||||
| Before: | |||||
| private const string Title = "Limit command to Guild contexts."; | private const string Title = "Limit command to Guild contexts."; | ||||
| After: | |||||
| private const string Title = "Limit command to Guild contexts"; | |||||
| */ | |||||
| private const string Title = "Limit command to Guild contexts"; | |||||
| private const string MessageFormat = "Command method '{0}' is accessing 'Context.Guild' but is not restricted to Guild contexts."; | private const string MessageFormat = "Command method '{0}' is accessing 'Context.Guild' but is not restricted to Guild contexts."; | ||||
| private const string Description = "Accessing 'Context.Guild' in a command without limiting the command to run only in guilds."; | private const string Description = "Accessing 'Context.Guild' in a command without limiting the command to run only in guilds."; | ||||
| private const string Category = "API Usage"; | private const string Category = "API Usage"; | ||||
| @@ -1,6 +1,6 @@ | |||||
| using System; | |||||
| using Microsoft.CodeAnalysis; | |||||
| using Discord.Commands; | using Discord.Commands; | ||||
| using Microsoft.CodeAnalysis; | |||||
| using System; | |||||
| namespace Discord.Analyzers | namespace Discord.Analyzers | ||||
| { | { | ||||
| @@ -43,8 +43,8 @@ namespace Discord.Commands | |||||
| { | { | ||||
| if (!TypeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo())) | if (!TypeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo())) | ||||
| throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}."); | throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}."); | ||||
| TypeReader = overridenTypeReader; | TypeReader = overridenTypeReader; | ||||
| } | } | ||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -61,7 +61,7 @@ namespace Discord.Commands | |||||
| if (GuildPermission.HasValue) | if (GuildPermission.HasValue) | ||||
| { | { | ||||
| if (guildUser == null) | if (guildUser == null) | ||||
| return Task.FromResult(PreconditionResult.FromError(NotAGuildErrorMessage ?? "Command must be used in a guild channel.")); | |||||
| return Task.FromResult(PreconditionResult.FromError(NotAGuildErrorMessage ?? "Command must be used in a guild channel.")); | |||||
| if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) | if (!guildUser.GuildPermissions.Has(GuildPermission.Value)) | ||||
| return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"User requires guild permission {GuildPermission.Value}.")); | return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"User requires guild permission {GuildPermission.Value}.")); | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using System.Collections.Generic; | |||||
| namespace Discord.Commands.Builders | namespace Discord.Commands.Builders | ||||
| { | { | ||||
| @@ -20,7 +20,9 @@ namespace Discord.Commands.Builders | |||||
| public string Name { get; set; } | public string Name { get; set; } | ||||
| public string Summary { get; set; } | public string Summary { get; set; } | ||||
| public string Remarks { get; set; } | public string Remarks { get; set; } | ||||
| public string Group { get => _group; | |||||
| public string Group | |||||
| { | |||||
| get => _group; | |||||
| set | set | ||||
| { | { | ||||
| _aliases.Remove(_group); | _aliases.Remove(_group); | ||||
| @@ -1,11 +1,10 @@ | |||||
| using Discord.Commands.Builders; | |||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | |||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Discord.Commands.Builders; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| internal static class ModuleClassBuilder | internal static class ModuleClassBuilder | ||||
| @@ -80,11 +79,11 @@ namespace Discord.Commands | |||||
| { | { | ||||
| if (!IsValidModuleDefinition(typeInfo)) | if (!IsValidModuleDefinition(typeInfo)) | ||||
| continue; | continue; | ||||
| if (builtTypes.Contains(typeInfo)) | if (builtTypes.Contains(typeInfo)) | ||||
| continue; | continue; | ||||
| builder.AddModule((module) => | |||||
| builder.AddModule((module) => | |||||
| { | { | ||||
| BuildModule(module, typeInfo, service, services); | BuildModule(module, typeInfo, service, services); | ||||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services); | BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services); | ||||
| @@ -139,7 +138,7 @@ namespace Discord.Commands | |||||
| foreach (var method in validCommands) | foreach (var method in validCommands) | ||||
| { | { | ||||
| builder.AddCommand((command) => | |||||
| builder.AddCommand((command) => | |||||
| { | { | ||||
| BuildCommand(command, typeInfo, method, service, services); | BuildCommand(command, typeInfo, method, service, services); | ||||
| }); | }); | ||||
| @@ -149,7 +148,7 @@ namespace Discord.Commands | |||||
| private static void BuildCommand(CommandBuilder builder, TypeInfo typeInfo, MethodInfo method, CommandService service, IServiceProvider serviceprovider) | private static void BuildCommand(CommandBuilder builder, TypeInfo typeInfo, MethodInfo method, CommandService service, IServiceProvider serviceprovider) | ||||
| { | { | ||||
| var attributes = method.GetCustomAttributes(); | var attributes = method.GetCustomAttributes(); | ||||
| foreach (var attribute in attributes) | foreach (var attribute in attributes) | ||||
| { | { | ||||
| switch (attribute) | switch (attribute) | ||||
| @@ -191,7 +190,7 @@ namespace Discord.Commands | |||||
| int pos = 0, count = parameters.Length; | int pos = 0, count = parameters.Length; | ||||
| foreach (var paramInfo in parameters) | foreach (var paramInfo in parameters) | ||||
| { | { | ||||
| builder.AddParameter((parameter) => | |||||
| builder.AddParameter((parameter) => | |||||
| { | { | ||||
| BuildParameter(parameter, paramInfo, pos++, count, service, serviceprovider); | BuildParameter(parameter, paramInfo, pos++, count, service, serviceprovider); | ||||
| }); | }); | ||||
| @@ -1,9 +1,8 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Collections.Generic; | |||||
| namespace Discord.Commands.Builders | namespace Discord.Commands.Builders | ||||
| { | { | ||||
| public class ParameterBuilder | public class ParameterBuilder | ||||
| @@ -25,7 +24,7 @@ namespace Discord.Commands.Builders | |||||
| public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions; | public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions; | ||||
| public IReadOnlyList<Attribute> Attributes => _attributes; | public IReadOnlyList<Attribute> Attributes => _attributes; | ||||
| #endregion | |||||
| #endregion | |||||
| #region Automatic | #region Automatic | ||||
| internal ParameterBuilder(CommandBuilder command) | internal ParameterBuilder(CommandBuilder command) | ||||
| @@ -1,3 +1,5 @@ | |||||
| using Discord.Commands.Builders; | |||||
| using Discord.Logging; | |||||
| using System; | using System; | ||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| @@ -6,8 +8,6 @@ using System.Linq; | |||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Threading; | using System.Threading; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Discord.Commands.Builders; | |||||
| using Discord.Logging; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -653,7 +653,7 @@ namespace Discord.Commands | |||||
| var bestCandidate = preconditionResults | var bestCandidate = preconditionResults | ||||
| .OrderByDescending(x => x.Key.Command.Priority) | .OrderByDescending(x => x.Key.Command.Priority) | ||||
| .FirstOrDefault(x => !x.Value.IsSuccess); | .FirstOrDefault(x => !x.Value.IsSuccess); | ||||
| return MatchResult.FromSuccess(bestCandidate.Key,bestCandidate.Value); | |||||
| return MatchResult.FromSuccess(bestCandidate.Key, bestCandidate.Value); | |||||
| } | } | ||||
| var parseResults = new Dictionary<CommandMatch, ParseResult>(); | var parseResults = new Dictionary<CommandMatch, ParseResult>(); | ||||
| @@ -685,7 +685,7 @@ namespace Discord.Commands | |||||
| .Where(x => x.Value.IsSuccess) | .Where(x => x.Value.IsSuccess) | ||||
| .ToArray(); | .ToArray(); | ||||
| if(successfulParses.Length == 0) | |||||
| if (successfulParses.Length == 0) | |||||
| { | { | ||||
| var bestMatch = parseResults | var bestMatch = parseResults | ||||
| .FirstOrDefault(x => !x.Value.IsSuccess); | .FirstOrDefault(x => !x.Value.IsSuccess); | ||||
| @@ -17,7 +17,7 @@ namespace Discord.Commands | |||||
| /// Gets or sets the <see cref="char"/> that separates an argument with another. | /// Gets or sets the <see cref="char"/> that separates an argument with another. | ||||
| /// </summary> | /// </summary> | ||||
| public char SeparatorChar { get; set; } = ' '; | public char SeparatorChar { get; set; } = ' '; | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets whether commands should be case-sensitive. | /// Gets or sets whether commands should be case-sensitive. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -5,7 +5,7 @@ namespace Discord.Commands | |||||
| internal class EmptyServiceProvider : IServiceProvider | internal class EmptyServiceProvider : IServiceProvider | ||||
| { | { | ||||
| public static readonly EmptyServiceProvider Instance = new EmptyServiceProvider(); | public static readonly EmptyServiceProvider Instance = new EmptyServiceProvider(); | ||||
| public object GetService(Type serviceType) => null; | public object GetService(Type serviceType) => null; | ||||
| } | } | ||||
| } | } | ||||
| @@ -19,4 +19,4 @@ namespace Discord.Commands | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -45,13 +45,17 @@ namespace Discord.Commands | |||||
| public static bool HasMentionPrefix(this IUserMessage msg, IUser user, ref int argPos) | public static bool HasMentionPrefix(this IUserMessage msg, IUser user, ref int argPos) | ||||
| { | { | ||||
| var text = msg.Content; | var text = msg.Content; | ||||
| if (string.IsNullOrEmpty(text) || text.Length <= 3 || text[0] != '<' || text[1] != '@') return false; | |||||
| if (string.IsNullOrEmpty(text) || text.Length <= 3 || text[0] != '<' || text[1] != '@') | |||||
| return false; | |||||
| int endPos = text.IndexOf('>'); | int endPos = text.IndexOf('>'); | ||||
| if (endPos == -1) return false; | |||||
| if (text.Length < endPos + 2 || text[endPos + 1] != ' ') return false; //Must end in "> " | |||||
| if (endPos == -1) | |||||
| return false; | |||||
| if (text.Length < endPos + 2 || text[endPos + 1] != ' ') | |||||
| return false; //Must end in "> " | |||||
| if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 1), out ulong userId)) return false; | |||||
| if (!MentionUtils.TryParseUser(text.Substring(0, endPos + 1), out ulong userId)) | |||||
| return false; | |||||
| if (userId == user.Id) | if (userId == user.Id) | ||||
| { | { | ||||
| argPos = endPos + 2; | argPos = endPos + 2; | ||||
| @@ -1,8 +1,8 @@ | |||||
| using Discord.Commands.Builders; | using Discord.Commands.Builders; | ||||
| using System; | using System; | ||||
| using System.Collections.Concurrent; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Collections.Concurrent; | |||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| @@ -175,7 +175,7 @@ namespace Discord.Commands | |||||
| return await CommandParser.ParseArgsAsync(this, context, _commandService._ignoreExtraArgs, services, input, 0, _commandService._quotationMarkAliasMap).ConfigureAwait(false); | return await CommandParser.ParseArgsAsync(this, context, _commandService._ignoreExtraArgs, services, input, 0, _commandService._quotationMarkAliasMap).ConfigureAwait(false); | ||||
| } | } | ||||
| public Task<IResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IServiceProvider services) | public Task<IResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IServiceProvider services) | ||||
| { | { | ||||
| if (!parseResult.IsSuccess) | if (!parseResult.IsSuccess) | ||||
| @@ -1,8 +1,8 @@ | |||||
| using Discord.Commands.Builders; | |||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using Discord.Commands.Builders; | |||||
| using System.Linq; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -1,6 +1,6 @@ | |||||
| using Discord.Commands.Builders; | |||||
| using System; | using System; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Discord.Commands.Builders; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| @@ -23,7 +23,7 @@ namespace Discord.Commands | |||||
| private readonly IReadOnlyDictionary<T, object> _enumsByValue; | private readonly IReadOnlyDictionary<T, object> _enumsByValue; | ||||
| private readonly Type _enumType; | private readonly Type _enumType; | ||||
| private readonly TryParseDelegate<T> _tryParse; | private readonly TryParseDelegate<T> _tryParse; | ||||
| public EnumTypeReader(Type type, TryParseDelegate<T> parser) | public EnumTypeReader(Type type, TryParseDelegate<T> parser) | ||||
| { | { | ||||
| _enumType = type; | _enumType = type; | ||||
| @@ -33,7 +33,7 @@ namespace Discord.Commands | |||||
| var byValueBuilder = ImmutableDictionary.CreateBuilder<T, object>(); | var byValueBuilder = ImmutableDictionary.CreateBuilder<T, object>(); | ||||
| foreach (var v in Enum.GetNames(_enumType)) | foreach (var v in Enum.GetNames(_enumType)) | ||||
| { | |||||
| { | |||||
| var parsedValue = Enum.Parse(_enumType, v); | var parsedValue = Enum.Parse(_enumType, v); | ||||
| byNameBuilder.Add(v.ToLower(), parsedValue); | byNameBuilder.Add(v.ToLower(), parsedValue); | ||||
| if (!byValueBuilder.ContainsKey((T)parsedValue)) | if (!byValueBuilder.ContainsKey((T)parsedValue)) | ||||
| @@ -116,7 +116,7 @@ namespace Discord.Commands | |||||
| argv = input.Substring(beginRead + 1, currentRead - beginRead - 1).Trim(); | argv = input.Substring(beginRead + 1, currentRead - beginRead - 1).Trim(); | ||||
| currentRead++; | currentRead++; | ||||
| } | } | ||||
| else | |||||
| else | |||||
| argv = input.Substring(beginRead, currentRead - beginRead); | argv = input.Substring(beginRead, currentRead - beginRead); | ||||
| return _tProps[currentParam]; | return _tProps[currentParam]; | ||||
| @@ -27,7 +27,7 @@ namespace Discord.Commands | |||||
| //By Id (0.9) | //By Id (0.9) | ||||
| if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id)) | if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id)) | ||||
| AddResult(results, context.Guild.GetRole(id) as T, 0.90f); | |||||
| AddResult(results, context.Guild.GetRole(id) as T, 0.90f); | |||||
| //By Name (0.7-0.8) | //By Name (0.7-0.8) | ||||
| foreach (var role in roles.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase))) | foreach (var role in roles.Where(x => string.Equals(input, x.Name, StringComparison.OrdinalIgnoreCase))) | ||||
| @@ -65,7 +65,7 @@ namespace Discord.Commands | |||||
| .Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)) | .Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)) | ||||
| .ForEachAsync(channelUser => AddResult(results, channelUser as T, channelUser.Username == input ? 0.65f : 0.55f)) | .ForEachAsync(channelUser => AddResult(results, channelUser as T, channelUser.Username == input ? 0.65f : 0.55f)) | ||||
| .ConfigureAwait(false); | .ConfigureAwait(false); | ||||
| foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase))) | foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase))) | ||||
| AddResult(results, guildUser as T, guildUser.Username == input ? 0.60f : 0.50f); | AddResult(results, guildUser as T, guildUser.Username == input ? 0.60f : 0.50f); | ||||
| } | } | ||||
| @@ -30,13 +30,13 @@ namespace Discord.Commands | |||||
| } | } | ||||
| public static MatchResult FromSuccess(CommandMatch match, IResult pipeline) | public static MatchResult FromSuccess(CommandMatch match, IResult pipeline) | ||||
| => new MatchResult(match,pipeline,null, null); | |||||
| => new MatchResult(match, pipeline, null, null); | |||||
| public static MatchResult FromError(CommandError error, string reason) | public static MatchResult FromError(CommandError error, string reason) | ||||
| => new MatchResult(null,null,error, reason); | |||||
| => new MatchResult(null, null, error, reason); | |||||
| public static MatchResult FromError(Exception ex) | public static MatchResult FromError(Exception ex) | ||||
| => FromError(CommandError.Exception, ex.Message); | => FromError(CommandError.Exception, ex.Message); | ||||
| public static MatchResult FromError(IResult result) | public static MatchResult FromError(IResult result) | ||||
| => new MatchResult(null, null,result.Error, result.ErrorReason); | |||||
| => new MatchResult(null, null, result.Error, result.ErrorReason); | |||||
| public static MatchResult FromError(IResult pipeline, CommandError error, string reason) | public static MatchResult FromError(IResult pipeline, CommandError error, string reason) | ||||
| => new MatchResult(null, pipeline, error, reason); | => new MatchResult(null, pipeline, error, reason); | ||||
| @@ -24,7 +24,7 @@ namespace Discord.Commands | |||||
| args[i] = GetMember(commands, services, parameters[i].ParameterType, typeInfo); | args[i] = GetMember(commands, services, parameters[i].ParameterType, typeInfo); | ||||
| var obj = InvokeConstructor<T>(constructor, args, typeInfo); | var obj = InvokeConstructor<T>(constructor, args, typeInfo); | ||||
| foreach(var property in properties) | |||||
| foreach (var property in properties) | |||||
| property.SetValue(obj, GetMember(commands, services, property.PropertyType, typeInfo)); | property.SetValue(obj, GetMember(commands, services, property.PropertyType, typeInfo)); | ||||
| return obj; | return obj; | ||||
| }; | }; | ||||
| @@ -6,4 +6,4 @@ namespace Discord.Audio | |||||
| Music, | Music, | ||||
| Mixed | Mixed | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Threading; | using System.Threading; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -9,7 +9,7 @@ namespace Discord.Audio | |||||
| public abstract int AvailableFrames { get; } | public abstract int AvailableFrames { get; } | ||||
| public override bool CanRead => true; | public override bool CanRead => true; | ||||
| public override bool CanWrite => true; | |||||
| public override bool CanWrite => true; | |||||
| public abstract Task<RTPFrame> ReadFrameAsync(CancellationToken cancelToken); | public abstract Task<RTPFrame> ReadFrameAsync(CancellationToken cancelToken); | ||||
| public abstract bool TryReadFrame(CancellationToken cancelToken, out RTPFrame frame); | public abstract bool TryReadFrame(CancellationToken cancelToken, out RTPFrame frame); | ||||
| @@ -12,7 +12,7 @@ namespace Discord.Audio | |||||
| public override bool CanWrite => false; | public override bool CanWrite => false; | ||||
| /// <exception cref="InvalidOperationException">This stream does not accept headers.</exception> | /// <exception cref="InvalidOperationException">This stream does not accept headers.</exception> | ||||
| public virtual void WriteHeader(ushort seq, uint timestamp, bool missed) => | |||||
| public virtual void WriteHeader(ushort seq, uint timestamp, bool missed) => | |||||
| throw new InvalidOperationException("This stream does not accept headers."); | throw new InvalidOperationException("This stream does not accept headers."); | ||||
| public override void Write(byte[] buffer, int offset, int count) | public override void Write(byte[] buffer, int offset, int count) | ||||
| { | { | ||||
| @@ -31,7 +31,7 @@ namespace Discord.Audio | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| /// <exception cref="NotSupportedException">Reading stream length is not supported.</exception> | /// <exception cref="NotSupportedException">Reading stream length is not supported.</exception> | ||||
| public override long Length => | |||||
| public override long Length => | |||||
| throw new NotSupportedException(); | throw new NotSupportedException(); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -15,4 +15,4 @@ namespace Discord.Audio | |||||
| Missed = missed; | Missed = missed; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -146,10 +146,10 @@ namespace Discord | |||||
| /// </returns> | /// </returns> | ||||
| public static string GetGuildBannerUrl(ulong guildId, string bannerId, ImageFormat format, ushort? size = null) | public static string GetGuildBannerUrl(ulong guildId, string bannerId, ImageFormat format, ushort? size = null) | ||||
| { | { | ||||
| if (string.IsNullOrEmpty(bannerId)) | |||||
| return null; | |||||
| string extension = FormatToExtension(format, bannerId); | |||||
| return $"{DiscordConfig.CDNUrl}banners/{guildId}/{bannerId}.{extension}" + (size.HasValue ? $"?size={size}" : string.Empty); | |||||
| if (string.IsNullOrEmpty(bannerId)) | |||||
| return null; | |||||
| string extension = FormatToExtension(format, bannerId); | |||||
| return $"{DiscordConfig.CDNUrl}banners/{guildId}/{bannerId}.{extension}" + (size.HasValue ? $"?size={size}" : string.Empty); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns an emoji URL. | /// Returns an emoji URL. | ||||
| @@ -175,23 +175,23 @@ namespace Discord | |||||
| /// </remarks> | /// </remarks> | ||||
| internal bool DisplayInitialLog { get; set; } = true; | internal bool DisplayInitialLog { get; set; } = true; | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not rate-limits should use the system clock. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If set to <c>false</c>, we will use the X-RateLimit-Reset-After header | |||||
| /// to determine when a rate-limit expires, rather than comparing the | |||||
| /// X-RateLimit-Reset timestamp to the system time. | |||||
| /// | |||||
| /// This should only be changed to false if the system is known to have | |||||
| /// a clock that is out of sync. Relying on the Reset-After header will | |||||
| /// incur network lag. | |||||
| /// | |||||
| /// Regardless of this property, we still rely on the system's wall-clock | |||||
| /// to determine if a bucket is rate-limited; we do not use any monotonic | |||||
| /// clock. Your system will still need a stable clock. | |||||
| /// </remarks> | |||||
| public bool UseSystemClock { get; set; } = true; | |||||
| /// <summary> | |||||
| /// Gets or sets whether or not rate-limits should use the system clock. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If set to <c>false</c>, we will use the X-RateLimit-Reset-After header | |||||
| /// to determine when a rate-limit expires, rather than comparing the | |||||
| /// X-RateLimit-Reset timestamp to the system time. | |||||
| /// | |||||
| /// This should only be changed to false if the system is known to have | |||||
| /// a clock that is out of sync. Relying on the Reset-After header will | |||||
| /// incur network lag. | |||||
| /// | |||||
| /// Regardless of this property, we still rely on the system's wall-clock | |||||
| /// to determine if a bucket is rate-limited; we do not use any monotonic | |||||
| /// clock. Your system will still need a stable clock. | |||||
| /// </remarks> | |||||
| public bool UseSystemClock { get; set; } = true; | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets whether or not the internal experation check uses the system date | /// Gets or sets whether or not the internal experation check uses the system date | ||||
| @@ -30,7 +30,7 @@ namespace Discord | |||||
| Flags = flags; | Flags = flags; | ||||
| Details = details; | Details = details; | ||||
| } | } | ||||
| /// <summary> Returns the name of the <see cref="Game"/>. </summary> | /// <summary> Returns the name of the <see cref="Game"/>. </summary> | ||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => Name; | private string DebuggerDisplay => Name; | ||||
| @@ -1,5 +1,5 @@ | |||||
| using System.Collections.Generic; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| namespace Discord; | namespace Discord; | ||||
| @@ -38,7 +38,7 @@ public class RoleConnectionProperties | |||||
| get => _platformUsername; | get => _platformUsername; | ||||
| set | set | ||||
| { | { | ||||
| if(value is not null) | |||||
| if (value is not null) | |||||
| Preconditions.AtMost(value.Length, MaxPlatformUsernameLength, nameof(PlatformUsername), $"Platform username length must be less or equal to {MaxPlatformUsernameLength}"); | Preconditions.AtMost(value.Length, MaxPlatformUsernameLength, nameof(PlatformUsername), $"Platform username length must be less or equal to {MaxPlatformUsernameLength}"); | ||||
| _platformUsername = value; | _platformUsername = value; | ||||
| } | } | ||||
| @@ -103,7 +103,7 @@ public class RoleConnectionProperties | |||||
| internal RoleConnectionProperties AddMetadataRecord(string key, string value) | internal RoleConnectionProperties AddMetadataRecord(string key, string value) | ||||
| { | { | ||||
| Metadata ??= new Dictionary<string, string>(); | Metadata ??= new Dictionary<string, string>(); | ||||
| if(!Metadata.ContainsKey(key)) | |||||
| if (!Metadata.ContainsKey(key)) | |||||
| Preconditions.AtMost(Metadata.Count + 1, MaxPlatformUsernameLength, nameof(Metadata), $"Metadata records count must be less or equal to {MaxMetadataRecords}"); | Preconditions.AtMost(Metadata.Count + 1, MaxPlatformUsernameLength, nameof(Metadata), $"Metadata records count must be less or equal to {MaxMetadataRecords}"); | ||||
| _metadata[key] = value; | _metadata[key] = value; | ||||
| @@ -126,7 +126,7 @@ public class RoleConnectionProperties | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new instance of <see cref="RoleConnectionProperties"/>. | /// Initializes a new instance of <see cref="RoleConnectionProperties"/>. | ||||
| /// </summary> | /// </summary> | ||||
| public RoleConnectionProperties() {} | |||||
| public RoleConnectionProperties() { } | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new <see cref="RoleConnectionProperties"/> with the data from provided <see cref="RoleConnection"/>. | /// Initializes a new <see cref="RoleConnectionProperties"/> with the data from provided <see cref="RoleConnection"/>. | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Provides properties that are used to modify an <see cref="IAudioChannel" /> with the specified changes. | /// Provides properties that are used to modify an <see cref="IAudioChannel" /> with the specified changes. | ||||
| @@ -172,7 +172,7 @@ namespace Discord | |||||
| public Task<IThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, | public Task<IThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, | ||||
| int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, | int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, | ||||
| AllowedMentions allowedMentions = null, MessageComponent components = null, | AllowedMentions allowedMentions = null, MessageComponent components = null, | ||||
| ISticker[] stickers = null, Embed[] embeds = null,MessageFlags flags = MessageFlags.None, ForumTag[] tags = null); | |||||
| ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null); | |||||
| /// <summary> | /// <summary> | ||||
| /// Creates a new post (thread) within the forum. | /// Creates a new post (thread) within the forum. | ||||
| @@ -222,7 +222,7 @@ namespace Discord | |||||
| /// <returns> | /// <returns> | ||||
| /// Paged collection of messages. | /// Paged collection of messages. | ||||
| /// </returns> | /// </returns> | ||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of messages in this channel. | /// Gets a collection of messages in this channel. | ||||
| @@ -263,7 +263,7 @@ namespace Discord | |||||
| /// <returns> | /// <returns> | ||||
| /// Paged collection of messages. | /// Paged collection of messages. | ||||
| /// </returns> | /// </returns> | ||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of messages in this channel. | /// Gets a collection of messages in this channel. | ||||
| @@ -300,7 +300,7 @@ namespace Discord | |||||
| /// <returns> | /// <returns> | ||||
| /// Paged collection of messages. | /// Paged collection of messages. | ||||
| /// </returns> | /// </returns> | ||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, | |||||
| CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of pinned messages in this channel. | /// Gets a collection of pinned messages in this channel. | ||||
| @@ -1,6 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Globalization; | |||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| using System.Globalization; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -44,11 +44,14 @@ namespace Discord | |||||
| /// <param name="other">The object to compare with the current object.</param> | /// <param name="other">The object to compare with the current object.</param> | ||||
| public override bool Equals(object other) | public override bool Equals(object other) | ||||
| { | { | ||||
| if (other == null) return false; | |||||
| if (other == this) return true; | |||||
| if (other == null) | |||||
| return false; | |||||
| if (other == this) | |||||
| return true; | |||||
| var otherEmote = other as Emote; | var otherEmote = other as Emote; | ||||
| if (otherEmote == null) return false; | |||||
| if (otherEmote == null) | |||||
| return false; | |||||
| return Id == otherEmote.Id; | return Id == otherEmote.Id; | ||||
| } | } | ||||
| @@ -45,7 +45,7 @@ namespace Discord | |||||
| } | } | ||||
| public override int GetHashCode() => (Id, Name, Emoji, IsModerated).GetHashCode(); | public override int GetHashCode() => (Id, Name, Emoji, IsModerated).GetHashCode(); | ||||
| public override bool Equals(object? obj) | public override bool Equals(object? obj) | ||||
| => obj is ForumTag tag && Equals(tag); | => obj is ForumTag tag && Equals(tag); | ||||
| @@ -110,8 +110,8 @@ public class ForumTagBuilder | |||||
| public ForumTagBuilder(string name, ulong? id = null, bool isModerated = false, ulong? emoteId = null) | public ForumTagBuilder(string name, ulong? id = null, bool isModerated = false, ulong? emoteId = null) | ||||
| { | { | ||||
| Name = name; | Name = name; | ||||
| if(emoteId is not null) | |||||
| Emoji = new Emote(emoteId.Value, null, false); | |||||
| if (emoteId is not null) | |||||
| Emoji = new Emote(emoteId.Value, null, false); | |||||
| IsModerated = isModerated; | IsModerated = isModerated; | ||||
| Id = id; | Id = id; | ||||
| } | } | ||||
| @@ -180,12 +180,12 @@ public class ForumTagBuilder | |||||
| => builder is not null && | => builder is not null && | ||||
| Id == builder.Id && | Id == builder.Id && | ||||
| Name == builder.Name && | Name == builder.Name && | ||||
| (Emoji is Emoji emoji && builder.Emoji is Emoji otherEmoji && emoji.Equals(otherEmoji) || | |||||
| (Emoji is Emoji emoji && builder.Emoji is Emoji otherEmoji && emoji.Equals(otherEmoji) || | |||||
| Emoji is Emote emote && builder.Emoji is Emote otherEmote && emote.Equals(otherEmote)) && | Emoji is Emote emote && builder.Emoji is Emote otherEmote && emote.Equals(otherEmote)) && | ||||
| IsModerated == builder.IsModerated; | IsModerated == builder.IsModerated; | ||||
| public static bool operator ==(ForumTagBuilder? left, ForumTagBuilder? right) | public static bool operator ==(ForumTagBuilder? left, ForumTagBuilder? right) | ||||
| => left?.Equals(right) ?? right is null ; | |||||
| => left?.Equals(right) ?? right is null; | |||||
| public static bool operator !=(ForumTagBuilder? left, ForumTagBuilder? right) => !(left == right); | public static bool operator !=(ForumTagBuilder? left, ForumTagBuilder? right) => !(left == right); | ||||
| } | } | ||||
| @@ -19,4 +19,4 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| AgeRestricted = 3 | AgeRestricted = 3 | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -50,5 +50,5 @@ public class WelcomeScreenChannelProperties : ISnowflakeEntity | |||||
| /// <param name="channel">A welcome screen channel to modify.</param> | /// <param name="channel">A welcome screen channel to modify.</param> | ||||
| /// <returns>A new instance of <see cref="WelcomeScreenChannelProperties"/>.</returns> | /// <returns>A new instance of <see cref="WelcomeScreenChannelProperties"/>.</returns> | ||||
| public static WelcomeScreenChannelProperties FromWelcomeScreenChannel(WelcomeScreenChannel channel) | public static WelcomeScreenChannelProperties FromWelcomeScreenChannel(WelcomeScreenChannel channel) | ||||
| => new (channel.Id, channel.Description, channel.Emoji); | |||||
| => new(channel.Id, channel.Description, channel.Emoji); | |||||
| } | } | ||||
| @@ -34,7 +34,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the icon URL of the application. | /// Gets the icon URL of the application. | ||||
| /// </summary> | /// </summary> | ||||
| string IconUrl { get; } | |||||
| string IconUrl { get; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets if the bot is public. | /// Gets if the bot is public. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -90,7 +90,7 @@ namespace Discord | |||||
| /// Gets the bot/OAuth2 application for a discord integration. | /// Gets the bot/OAuth2 application for a discord integration. | ||||
| /// </summary> | /// </summary> | ||||
| IIntegrationApplication Application { get; } | IIntegrationApplication Application { get; } | ||||
| IGuild Guild { get; } | IGuild Guild { get; } | ||||
| ulong GuildId { get; } | ulong GuildId { get; } | ||||
| } | } | ||||
| @@ -110,7 +110,7 @@ namespace Discord | |||||
| { | { | ||||
| foreach (var (locale, name) in value) | foreach (var (locale, name) in value) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidOptionName(name); | EnsureValidOptionName(name); | ||||
| @@ -134,7 +134,7 @@ namespace Discord | |||||
| { | { | ||||
| foreach (var (locale, description) in value) | foreach (var (locale, description) in value) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidOptionDescription(description); | EnsureValidOptionDescription(description); | ||||
| @@ -45,7 +45,7 @@ namespace Discord | |||||
| public object Value | public object Value | ||||
| { | { | ||||
| get => _value; | get => _value; | ||||
| set | |||||
| set | |||||
| { | { | ||||
| if (value is not string && !value.IsNumericType()) | if (value is not string && !value.IsNumericType()) | ||||
| throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!"); | throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!"); | ||||
| @@ -49,7 +49,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets whether or not this command is age restricted. | /// Gets or sets whether or not this command is age restricted. | ||||
| /// </summary> | /// </summary> | ||||
| public bool IsNsfw{ get; set; } = false; | |||||
| public bool IsNsfw { get; set; } = false; | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets the default permission required to use this slash command. | /// Gets or sets the default permission required to use this slash command. | ||||
| @@ -118,7 +118,7 @@ namespace Discord | |||||
| foreach (var (locale, name) in nameLocalizations) | foreach (var (locale, name) in nameLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -159,7 +159,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public MessageCommandBuilder AddNameLocalization(string locale, string name) | public MessageCommandBuilder AddNameLocalization(string locale, string name) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -116,7 +116,7 @@ namespace Discord | |||||
| foreach (var (locale, name) in nameLocalizations) | foreach (var (locale, name) in nameLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -125,7 +125,7 @@ namespace Discord | |||||
| _nameLocalizations = new Dictionary<string, string>(nameLocalizations); | _nameLocalizations = new Dictionary<string, string>(nameLocalizations); | ||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Sets whether or not this command can be used in dms. | /// Sets whether or not this command can be used in dms. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -157,7 +157,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public UserCommandBuilder AddNameLocalization(string locale, string name) | public UserCommandBuilder AddNameLocalization(string locale, string name) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -130,7 +130,7 @@ namespace Discord | |||||
| async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, | async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, | ||||
| AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) | AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) | ||||
| { | { | ||||
| using(var file = new FileAttachment(fileStream, fileName)) | |||||
| using (var file = new FileAttachment(fileStream, fileName)) | |||||
| { | { | ||||
| await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); | await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); | ||||
| } | } | ||||
| @@ -249,7 +249,7 @@ namespace Discord | |||||
| async Task<IUserMessage> FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, | async Task<IUserMessage> FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, | ||||
| AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) | AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) | ||||
| { | { | ||||
| using(var file = new FileAttachment(fileStream, fileName)) | |||||
| using (var file = new FileAttachment(fileStream, fileName)) | |||||
| { | { | ||||
| return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); | return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); | ||||
| } | } | ||||
| @@ -46,7 +46,7 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| public string Value { get; } | public string Value { get; } | ||||
| internal TextInputComponent(string customId, string label, string placeholder, int? minLength, int? maxLength, | |||||
| internal TextInputComponent(string customId, string label, string placeholder, int? minLength, int? maxLength, | |||||
| TextInputStyle style, bool? required, string value) | TextInputStyle style, bool? required, string value) | ||||
| { | { | ||||
| CustomId = customId; | CustomId = customId; | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| public enum TextInputStyle | public enum TextInputStyle | ||||
| { | { | ||||
| @@ -93,7 +93,7 @@ namespace Discord | |||||
| /// <param name="maxLength">The input's maximum length.</param> | /// <param name="maxLength">The input's maximum length.</param> | ||||
| /// <param name="style">The input's style.</param> | /// <param name="style">The input's style.</param> | ||||
| /// <returns>The current builder.</returns> | /// <returns>The current builder.</returns> | ||||
| public ModalBuilder AddTextInput(string label, string customId, TextInputStyle style = TextInputStyle.Short, | |||||
| public ModalBuilder AddTextInput(string label, string customId, TextInputStyle style = TextInputStyle.Short, | |||||
| string placeholder = "", int? minLength = null, int? maxLength = null, bool? required = null, string value = null) | string placeholder = "", int? minLength = null, int? maxLength = null, bool? required = null, string value = null) | ||||
| => AddTextInput(new(label, customId, style, placeholder, minLength, maxLength, required, value)); | => AddTextInput(new(label, customId, style, placeholder, minLength, maxLength, required, value)); | ||||
| @@ -204,7 +204,7 @@ namespace Discord | |||||
| /// <param name="maxLength">The input's maximum length.</param> | /// <param name="maxLength">The input's maximum length.</param> | ||||
| /// <param name="style">The input's style.</param> | /// <param name="style">The input's style.</param> | ||||
| /// <returns>The current builder.</returns> | /// <returns>The current builder.</returns> | ||||
| public ModalComponentBuilder WithTextInput(string label, string customId, TextInputStyle style = TextInputStyle.Short, | |||||
| public ModalComponentBuilder WithTextInput(string label, string customId, TextInputStyle style = TextInputStyle.Short, | |||||
| string placeholder = null, int? minLength = null, int? maxLength = null, int row = 0, bool? required = null, | string placeholder = null, int? minLength = null, int? maxLength = null, int row = 0, bool? required = null, | ||||
| string value = null) | string value = null) | ||||
| => WithTextInput(new(label, customId, style, placeholder, minLength, maxLength, required, value), row); | => WithTextInput(new(label, customId, style, placeholder, minLength, maxLength, required, value), row); | ||||
| @@ -263,6 +263,6 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| /// <returns>A <see cref="ModalComponent"/> representing the builder.</returns> | /// <returns>A <see cref="ModalComponent"/> representing the builder.</returns> | ||||
| public ModalComponent Build() | public ModalComponent Build() | ||||
| => new (ActionRows?.Select(x => x.Build()).ToList()); | |||||
| => new(ActionRows?.Select(x => x.Build()).ToList()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -84,7 +84,7 @@ namespace Discord | |||||
| /// Gets or sets whether or not this command can be used in DMs. | /// Gets or sets whether or not this command can be used in DMs. | ||||
| /// </summary> | /// </summary> | ||||
| public bool IsDMEnabled { get; set; } = true; | public bool IsDMEnabled { get; set; } = true; | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets whether or not this command is age restricted. | /// Gets or sets whether or not this command is age restricted. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -312,7 +312,7 @@ namespace Discord | |||||
| foreach (var (locale, name) in nameLocalizations) | foreach (var (locale, name) in nameLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -336,7 +336,7 @@ namespace Discord | |||||
| foreach (var (locale, description) in descriptionLocalizations) | foreach (var (locale, description) in descriptionLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandDescription(description); | EnsureValidCommandDescription(description); | ||||
| @@ -355,7 +355,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public SlashCommandBuilder AddNameLocalization(string locale, string name) | public SlashCommandBuilder AddNameLocalization(string locale, string name) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandName(name); | EnsureValidCommandName(name); | ||||
| @@ -375,7 +375,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public SlashCommandBuilder AddDescriptionLocalization(string locale, string description) | public SlashCommandBuilder AddDescriptionLocalization(string locale, string description) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandDescription(description); | EnsureValidCommandDescription(description); | ||||
| @@ -549,7 +549,7 @@ namespace Discord | |||||
| if (isIntType && MaxValue != null && MaxValue % 1 != 0) | if (isIntType && MaxValue != null && MaxValue % 1 != 0) | ||||
| throw new InvalidOperationException("MaxValue cannot have decimals on Integer command options."); | throw new InvalidOperationException("MaxValue cannot have decimals on Integer command options."); | ||||
| if(isStrType && MinLength is not null && MinLength < 0) | |||||
| if (isStrType && MinLength is not null && MinLength < 0) | |||||
| throw new InvalidOperationException("MinLength cannot be smaller than 0."); | throw new InvalidOperationException("MinLength cannot be smaller than 0."); | ||||
| if (isStrType && MaxLength is not null && MaxLength < 1) | if (isStrType && MaxLength is not null && MaxLength < 1) | ||||
| @@ -627,10 +627,10 @@ namespace Discord | |||||
| ChannelTypes = channelTypes, | ChannelTypes = channelTypes, | ||||
| }; | }; | ||||
| if(nameLocalizations is not null) | |||||
| if (nameLocalizations is not null) | |||||
| option.WithNameLocalizations(nameLocalizations); | option.WithNameLocalizations(nameLocalizations); | ||||
| if(descriptionLocalizations is not null) | |||||
| if (descriptionLocalizations is not null) | |||||
| option.WithDescriptionLocalizations(descriptionLocalizations); | option.WithDescriptionLocalizations(descriptionLocalizations); | ||||
| return AddOption(option); | return AddOption(option); | ||||
| @@ -749,7 +749,7 @@ namespace Discord | |||||
| Preconditions.AtLeast(name.Length, 1, nameof(name)); | Preconditions.AtLeast(name.Length, 1, nameof(name)); | ||||
| Preconditions.AtMost(name.Length, 100, nameof(name)); | Preconditions.AtMost(name.Length, 100, nameof(name)); | ||||
| if(value is string str) | |||||
| if (value is string str) | |||||
| { | { | ||||
| Preconditions.AtLeast(str.Length, 1, nameof(value)); | Preconditions.AtLeast(str.Length, 1, nameof(value)); | ||||
| Preconditions.AtMost(str.Length, 100, nameof(value)); | Preconditions.AtMost(str.Length, 100, nameof(value)); | ||||
| @@ -904,7 +904,7 @@ namespace Discord | |||||
| foreach (var (locale, name) in nameLocalizations) | foreach (var (locale, name) in nameLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandOptionName(name); | EnsureValidCommandOptionName(name); | ||||
| @@ -928,7 +928,7 @@ namespace Discord | |||||
| foreach (var (locale, description) in descriptionLocalizations) | foreach (var (locale, description) in descriptionLocalizations) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandOptionDescription(description); | EnsureValidCommandOptionDescription(description); | ||||
| @@ -947,7 +947,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public SlashCommandOptionBuilder AddNameLocalization(string locale, string name) | public SlashCommandOptionBuilder AddNameLocalization(string locale, string name) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandOptionName(name); | EnsureValidCommandOptionName(name); | ||||
| @@ -967,7 +967,7 @@ namespace Discord | |||||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | ||||
| public SlashCommandOptionBuilder AddDescriptionLocalization(string locale, string description) | public SlashCommandOptionBuilder AddDescriptionLocalization(string locale, string description) | ||||
| { | { | ||||
| if(!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| if (!Regex.IsMatch(locale, @"^\w{2}(?:-\w{2})?$")) | |||||
| throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | throw new ArgumentException($"Invalid locale: {locale}", nameof(locale)); | ||||
| EnsureValidCommandOptionDescription(description); | EnsureValidCommandOptionDescription(description); | ||||
| @@ -81,7 +81,7 @@ public class InviteGuild : ISnowflakeEntity | |||||
| /// A URL pointing to the guild's icon; <see langword="null" /> if none is set. | /// A URL pointing to the guild's icon; <see langword="null" /> if none is set. | ||||
| /// </returns> | /// </returns> | ||||
| public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); | public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); | ||||
| /// <summary> | /// <summary> | ||||
| /// | /// | ||||
| /// Gets the level of requirements a user must fulfill before being allowed to post messages in this guild. | /// Gets the level of requirements a user must fulfill before being allowed to post messages in this guild. | ||||
| @@ -127,17 +127,17 @@ public class InviteGuild : ISnowflakeEntity | |||||
| public WelcomeScreen WelcomeScreen { get; private set; } | public WelcomeScreen WelcomeScreen { get; private set; } | ||||
| internal InviteGuild( | internal InviteGuild( | ||||
| ulong id, | |||||
| string name, | |||||
| string description, | |||||
| string splashId, | |||||
| string bannerId, | |||||
| GuildFeatures features, | |||||
| string iconId, | |||||
| VerificationLevel verificationLevel, | |||||
| string vanityURLCode, | |||||
| int premiumSubscriptionCount, | |||||
| NsfwLevel nsfwLevel, | |||||
| ulong id, | |||||
| string name, | |||||
| string description, | |||||
| string splashId, | |||||
| string bannerId, | |||||
| GuildFeatures features, | |||||
| string iconId, | |||||
| VerificationLevel verificationLevel, | |||||
| string vanityURLCode, | |||||
| int premiumSubscriptionCount, | |||||
| NsfwLevel nsfwLevel, | |||||
| WelcomeScreen welcomeScreen) | WelcomeScreen welcomeScreen) | ||||
| { | { | ||||
| Id = id; | Id = id; | ||||
| @@ -17,18 +17,18 @@ namespace Discord | |||||
| /// It will always be present and does not mean mentions will not be allowed. | /// It will always be present and does not mean mentions will not be allowed. | ||||
| /// </note> | /// </note> | ||||
| /// </remarks> | /// </remarks> | ||||
| None = 0, | |||||
| None = 0, | |||||
| /// <summary> | /// <summary> | ||||
| /// Controls role mentions. | /// Controls role mentions. | ||||
| /// </summary> | /// </summary> | ||||
| Roles = 1, | |||||
| Roles = 1, | |||||
| /// <summary> | /// <summary> | ||||
| /// Controls user mentions. | /// Controls user mentions. | ||||
| /// </summary> | /// </summary> | ||||
| Users = 2, | |||||
| Users = 2, | |||||
| /// <summary> | /// <summary> | ||||
| /// Controls <code>@everyone</code> and <code>@here</code> mentions. | /// Controls <code>@everyone</code> and <code>@here</code> mentions. | ||||
| /// </summary> | /// </summary> | ||||
| Everyone = 4, | |||||
| Everyone = 4, | |||||
| } | } | ||||
| } | } | ||||
| @@ -44,7 +44,7 @@ namespace Discord | |||||
| Type = type; | Type = type; | ||||
| Fields = ImmutableArray.Create<EmbedField>(); | Fields = ImmutableArray.Create<EmbedField>(); | ||||
| } | } | ||||
| internal Embed(EmbedType type, | |||||
| internal Embed(EmbedType type, | |||||
| string title, | string title, | ||||
| string description, | string description, | ||||
| string url, | string url, | ||||
| @@ -52,10 +52,10 @@ namespace Discord | |||||
| Color? color, | Color? color, | ||||
| EmbedImage? image, | EmbedImage? image, | ||||
| EmbedVideo? video, | EmbedVideo? video, | ||||
| EmbedAuthor? author, | |||||
| EmbedFooter? footer, | |||||
| EmbedProvider? provider, | |||||
| EmbedThumbnail? thumbnail, | |||||
| EmbedAuthor? author, | |||||
| EmbedFooter? footer, | |||||
| EmbedProvider? provider, | |||||
| EmbedThumbnail? thumbnail, | |||||
| ImmutableArray<EmbedField> fields) | ImmutableArray<EmbedField> fields) | ||||
| { | { | ||||
| Type = type; | Type = type; | ||||
| @@ -128,7 +128,7 @@ namespace Discord | |||||
| { | { | ||||
| var hash = 17; | var hash = 17; | ||||
| hash = hash * 23 + (Type, Title, Description, Timestamp, Color, Image, Video, Author, Footer, Provider, Thumbnail).GetHashCode(); | hash = hash * 23 + (Type, Title, Description, Timestamp, Color, Image, Video, Author, Footer, Provider, Thumbnail).GetHashCode(); | ||||
| foreach(var field in Fields) | |||||
| foreach (var field in Fields) | |||||
| hash = hash * 23 + field.GetHashCode(); | hash = hash * 23 + field.GetHashCode(); | ||||
| return hash; | return hash; | ||||
| } | } | ||||
| @@ -1,9 +1,9 @@ | |||||
| using Discord.Utils; | |||||
| using Newtonsoft.Json; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Linq; | using System.Linq; | ||||
| using Discord.Utils; | |||||
| using Newtonsoft.Json; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -50,7 +50,8 @@ namespace Discord | |||||
| get => _title; | get => _title; | ||||
| set | set | ||||
| { | { | ||||
| if (value?.Length > MaxTitleLength) throw new ArgumentException(message: $"Title length must be less than or equal to {MaxTitleLength}.", paramName: nameof(Title)); | |||||
| if (value?.Length > MaxTitleLength) | |||||
| throw new ArgumentException(message: $"Title length must be less than or equal to {MaxTitleLength}.", paramName: nameof(Title)); | |||||
| _title = value; | _title = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -63,7 +64,8 @@ namespace Discord | |||||
| get => _description; | get => _description; | ||||
| set | set | ||||
| { | { | ||||
| if (value?.Length > MaxDescriptionLength) throw new ArgumentException(message: $"Description length must be less than or equal to {MaxDescriptionLength}.", paramName: nameof(Description)); | |||||
| if (value?.Length > MaxDescriptionLength) | |||||
| throw new ArgumentException(message: $"Description length must be less than or equal to {MaxDescriptionLength}.", paramName: nameof(Description)); | |||||
| _description = value; | _description = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -100,8 +102,10 @@ namespace Discord | |||||
| get => _fields; | get => _fields; | ||||
| set | set | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException(paramName: nameof(Fields), message: "Cannot set an embed builder's fields collection to null."); | |||||
| if (value.Count > MaxFieldCount) throw new ArgumentException(message: $"Field count must be less than or equal to {MaxFieldCount}.", paramName: nameof(Fields)); | |||||
| if (value == null) | |||||
| throw new ArgumentNullException(paramName: nameof(Fields), message: "Cannot set an embed builder's fields collection to null."); | |||||
| if (value.Count > MaxFieldCount) | |||||
| throw new ArgumentException(message: $"Field count must be less than or equal to {MaxFieldCount}.", paramName: nameof(Fields)); | |||||
| _fields = value; | _fields = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -470,7 +474,7 @@ namespace Discord | |||||
| if (!string.IsNullOrEmpty(Author.IconUrl)) | if (!string.IsNullOrEmpty(Author.IconUrl)) | ||||
| UrlValidation.Validate(Author.IconUrl, true); | UrlValidation.Validate(Author.IconUrl, true); | ||||
| } | } | ||||
| if(Footer != null) | |||||
| if (Footer != null) | |||||
| { | { | ||||
| if (!string.IsNullOrEmpty(Footer.IconUrl)) | if (!string.IsNullOrEmpty(Footer.IconUrl)) | ||||
| UrlValidation.Validate(Footer.IconUrl, true); | UrlValidation.Validate(Footer.IconUrl, true); | ||||
| @@ -564,8 +568,10 @@ namespace Discord | |||||
| get => _name; | get => _name; | ||||
| set | set | ||||
| { | { | ||||
| if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(message: "Field name must not be null, empty or entirely whitespace.", paramName: nameof(Name)); | |||||
| if (value.Length > MaxFieldNameLength) throw new ArgumentException(message: $"Field name length must be less than or equal to {MaxFieldNameLength}.", paramName: nameof(Name)); | |||||
| if (string.IsNullOrWhiteSpace(value)) | |||||
| throw new ArgumentException(message: "Field name must not be null, empty or entirely whitespace.", paramName: nameof(Name)); | |||||
| if (value.Length > MaxFieldNameLength) | |||||
| throw new ArgumentException(message: $"Field name length must be less than or equal to {MaxFieldNameLength}.", paramName: nameof(Name)); | |||||
| _name = value; | _name = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -587,8 +593,10 @@ namespace Discord | |||||
| set | set | ||||
| { | { | ||||
| var stringValue = value?.ToString(); | var stringValue = value?.ToString(); | ||||
| if (string.IsNullOrWhiteSpace(stringValue)) throw new ArgumentException(message: "Field value must not be null or empty.", paramName: nameof(Value)); | |||||
| if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException(message: $"Field value length must be less than or equal to {MaxFieldValueLength}.", paramName: nameof(Value)); | |||||
| if (string.IsNullOrWhiteSpace(stringValue)) | |||||
| throw new ArgumentException(message: "Field value must not be null or empty.", paramName: nameof(Value)); | |||||
| if (stringValue.Length > MaxFieldValueLength) | |||||
| throw new ArgumentException(message: $"Field value length must be less than or equal to {MaxFieldValueLength}.", paramName: nameof(Value)); | |||||
| _value = stringValue; | _value = stringValue; | ||||
| } | } | ||||
| } | } | ||||
| @@ -704,7 +712,8 @@ namespace Discord | |||||
| get => _name; | get => _name; | ||||
| set | set | ||||
| { | { | ||||
| if (value?.Length > MaxAuthorNameLength) throw new ArgumentException(message: $"Author name length must be less than or equal to {MaxAuthorNameLength}.", paramName: nameof(Name)); | |||||
| if (value?.Length > MaxAuthorNameLength) | |||||
| throw new ArgumentException(message: $"Author name length must be less than or equal to {MaxAuthorNameLength}.", paramName: nameof(Name)); | |||||
| _name = value; | _name = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -836,7 +845,8 @@ namespace Discord | |||||
| get => _text; | get => _text; | ||||
| set | set | ||||
| { | { | ||||
| if (value?.Length > MaxFooterTextLength) throw new ArgumentException(message: $"Footer text length must be less than or equal to {MaxFooterTextLength}.", paramName: nameof(Text)); | |||||
| if (value?.Length > MaxFooterTextLength) | |||||
| throw new ArgumentException(message: $"Footer text length must be less than or equal to {MaxFooterTextLength}.", paramName: nameof(Text)); | |||||
| _text = value; | _text = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -79,7 +79,7 @@ namespace Discord | |||||
| /// Time of when the message was last edited; <c>null</c> if the message is never edited. | /// Time of when the message was last edited; <c>null</c> if the message is never edited. | ||||
| /// </returns> | /// </returns> | ||||
| DateTimeOffset? EditedTimestamp { get; } | DateTimeOffset? EditedTimestamp { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets the source channel of the message. | /// Gets the source channel of the message. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -197,7 +197,7 @@ namespace Discord | |||||
| /// A read-only collection of sticker item objects. | /// A read-only collection of sticker item objects. | ||||
| /// </returns> | /// </returns> | ||||
| IReadOnlyCollection<IStickerItem> Stickers { get; } | IReadOnlyCollection<IStickerItem> Stickers { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets the flags related to this message. | /// Gets the flags related to this message. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| public interface ITag | public interface ITag | ||||
| { | { | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Diagnostics; | |||||
| using System.Diagnostics; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -10,105 +10,105 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows creation of instant invites. | /// Allows creation of instant invites. | ||||
| /// </summary> | /// </summary> | ||||
| CreateInstantInvite = 0x00_00_00_00_01, | |||||
| CreateInstantInvite = 0x00_00_00_00_01, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of channels. | /// Allows management and editing of channels. | ||||
| /// </summary> | /// </summary> | ||||
| ManageChannels = 0x00_00_00_00_10, | |||||
| ManageChannels = 0x00_00_00_00_10, | |||||
| // Text | // Text | ||||
| /// <summary> | /// <summary> | ||||
| /// Allows for the addition of reactions to messages. | /// Allows for the addition of reactions to messages. | ||||
| /// </summary> | /// </summary> | ||||
| AddReactions = 0x00_00_00_00_40, | |||||
| AddReactions = 0x00_00_00_00_40, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows guild members to view a channel, which includes reading messages in text channels. | /// Allows guild members to view a channel, which includes reading messages in text channels. | ||||
| /// </summary> | /// </summary> | ||||
| ViewChannel = 0x00_00_00_04_00, | |||||
| ViewChannel = 0x00_00_00_04_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for sending messages in a channel. | /// Allows for sending messages in a channel. | ||||
| /// </summary> | /// </summary> | ||||
| SendMessages = 0x00_00_00_08_00, | |||||
| SendMessages = 0x00_00_00_08_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for sending of text-to-speech messages. | /// Allows for sending of text-to-speech messages. | ||||
| /// </summary> | /// </summary> | ||||
| SendTTSMessages = 0x00_00_00_10_00, | |||||
| SendTTSMessages = 0x00_00_00_10_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for deletion of other users messages. | /// Allows for deletion of other users messages. | ||||
| /// </summary> | /// </summary> | ||||
| ManageMessages = 0x00_00_00_20_00, | |||||
| ManageMessages = 0x00_00_00_20_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows links sent by users with this permission will be auto-embedded. | /// Allows links sent by users with this permission will be auto-embedded. | ||||
| /// </summary> | /// </summary> | ||||
| EmbedLinks = 0x00_00_00_40_00, | |||||
| EmbedLinks = 0x00_00_00_40_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for uploading images and files. | /// Allows for uploading images and files. | ||||
| /// </summary> | /// </summary> | ||||
| AttachFiles = 0x00_00_00_80_00, | |||||
| AttachFiles = 0x00_00_00_80_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for reading of message history. | /// Allows for reading of message history. | ||||
| /// </summary> | /// </summary> | ||||
| ReadMessageHistory = 0x00_00_01_00_00, | |||||
| ReadMessageHistory = 0x00_00_01_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | /// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | ||||
| /// online users in a channel. | /// online users in a channel. | ||||
| /// </summary> | /// </summary> | ||||
| MentionEveryone = 0x00_00_02_00_00, | |||||
| MentionEveryone = 0x00_00_02_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows the usage of custom emojis from other servers. | /// Allows the usage of custom emojis from other servers. | ||||
| /// </summary> | /// </summary> | ||||
| UseExternalEmojis = 0x00_00_04_00_00, | |||||
| UseExternalEmojis = 0x00_00_04_00_00, | |||||
| // Voice | // Voice | ||||
| /// <summary> | /// <summary> | ||||
| /// Allows for joining of a voice channel. | /// Allows for joining of a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Connect = 0x00_00_10_00_00, | |||||
| Connect = 0x00_00_10_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for speaking in a voice channel. | /// Allows for speaking in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Speak = 0x00_00_20_00_00, | |||||
| Speak = 0x00_00_20_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for muting members in a voice channel. | /// Allows for muting members in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| MuteMembers = 0x00_00_40_00_00, | |||||
| MuteMembers = 0x00_00_40_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for deafening of members in a voice channel. | /// Allows for deafening of members in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| DeafenMembers = 0x00_00_80_00_00, | |||||
| DeafenMembers = 0x00_00_80_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for moving of members between voice channels. | /// Allows for moving of members between voice channels. | ||||
| /// </summary> | /// </summary> | ||||
| MoveMembers = 0x00_01_00_00_00, | |||||
| MoveMembers = 0x00_01_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using voice-activity-detection in a voice channel. | /// Allows for using voice-activity-detection in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| UseVAD = 0x00_02_00_00_00, | |||||
| UseVAD = 0x00_02_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using priority speaker in a voice channel. | /// Allows for using priority speaker in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| PrioritySpeaker = 0x00_00_00_01_00, | |||||
| PrioritySpeaker = 0x00_00_00_01_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows video streaming in a voice channel. | /// Allows video streaming in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Stream = 0x00_00_00_02_00, | |||||
| Stream = 0x00_00_00_02_00, | |||||
| // More General | // More General | ||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of roles. | /// Allows management and editing of roles. | ||||
| /// </summary> | /// </summary> | ||||
| ManageRoles = 0x00_10_00_00_00, | |||||
| ManageRoles = 0x00_10_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of webhooks. | /// Allows management and editing of webhooks. | ||||
| /// </summary> | /// </summary> | ||||
| ManageWebhooks = 0x00_20_00_00_00, | |||||
| ManageWebhooks = 0x00_20_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of emojis. | /// Allows management and editing of emojis. | ||||
| /// </summary> | /// </summary> | ||||
| ManageEmojis = 0x00_40_00_00_00, | |||||
| ManageEmojis = 0x00_40_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows members to use slash commands in text channels. | /// Allows members to use slash commands in text channels. | ||||
| @@ -118,12 +118,12 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for requesting to speak in stage channels. (This permission is under active development and may be changed or removed.) | /// Allows for requesting to speak in stage channels. (This permission is under active development and may be changed or removed.) | ||||
| /// </summary> | /// </summary> | ||||
| RequestToSpeak = 0x01_00_00_00_00, | |||||
| RequestToSpeak = 0x01_00_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for deleting and archiving threads, and viewing all private threads | /// Allows for deleting and archiving threads, and viewing all private threads | ||||
| /// </summary> | /// </summary> | ||||
| ManageThreads = 0x04_00_00_00_00, | |||||
| ManageThreads = 0x04_00_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for creating public threads. | /// Allows for creating public threads. | ||||
| @@ -10,7 +10,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows creation of instant invites. | /// Allows creation of instant invites. | ||||
| /// </summary> | /// </summary> | ||||
| CreateInstantInvite = 0x00_00_00_01, | |||||
| CreateInstantInvite = 0x00_00_00_01, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows kicking members. | /// Allows kicking members. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -18,7 +18,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| KickMembers = 0x00_00_00_02, | |||||
| KickMembers = 0x00_00_00_02, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows banning members. | /// Allows banning members. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -26,7 +26,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| BanMembers = 0x00_00_00_04, | |||||
| BanMembers = 0x00_00_00_04, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows all permissions and bypasses channel permission overwrites. | /// Allows all permissions and bypasses channel permission overwrites. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -34,7 +34,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| Administrator = 0x00_00_00_08, | |||||
| Administrator = 0x00_00_00_08, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of channels. | /// Allows management and editing of channels. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -42,7 +42,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageChannels = 0x00_00_00_10, | |||||
| ManageChannels = 0x00_00_00_10, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of the guild. | /// Allows management and editing of the guild. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -50,33 +50,33 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageGuild = 0x00_00_00_20, | |||||
| ManageGuild = 0x00_00_00_20, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for viewing of guild insights | /// Allows for viewing of guild insights | ||||
| /// </summary> | /// </summary> | ||||
| ViewGuildInsights = 0x00_08_00_00, | |||||
| ViewGuildInsights = 0x00_08_00_00, | |||||
| // Text | // Text | ||||
| /// <summary> | |||||
| /// Allows for the addition of reactions to messages. | |||||
| /// </summary> | |||||
| AddReactions = 0x00_00_00_40, | |||||
| /// <summary> | |||||
| /// Allows for viewing of audit logs. | |||||
| /// </summary> | |||||
| ViewAuditLog = 0x00_00_00_80, | |||||
| /// <summary> | |||||
| /// Allows for the addition of reactions to messages. | |||||
| /// </summary> | |||||
| AddReactions = 0x00_00_00_40, | |||||
| /// <summary> | |||||
| /// Allows for viewing of audit logs. | |||||
| /// </summary> | |||||
| ViewAuditLog = 0x00_00_00_80, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows guild members to view a channel, which includes reading messages in text channels. | /// Allows guild members to view a channel, which includes reading messages in text channels. | ||||
| /// </summary> | /// </summary> | ||||
| ViewChannel = 0x00_00_04_00, | |||||
| ViewChannel = 0x00_00_04_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for sending messages in a channel | /// Allows for sending messages in a channel | ||||
| /// </summary> | /// </summary> | ||||
| SendMessages = 0x00_00_08_00, | |||||
| /// <summary> | |||||
| /// Allows for sending of text-to-speech messages. | |||||
| /// </summary> | |||||
| SendTTSMessages = 0x00_00_10_00, | |||||
| SendMessages = 0x00_00_08_00, | |||||
| /// <summary> | |||||
| /// Allows for sending of text-to-speech messages. | |||||
| /// </summary> | |||||
| SendTTSMessages = 0x00_00_10_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for deletion of other users messages. | /// Allows for deletion of other users messages. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -84,55 +84,55 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageMessages = 0x00_00_20_00, | |||||
| ManageMessages = 0x00_00_20_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows links sent by users with this permission will be auto-embedded. | /// Allows links sent by users with this permission will be auto-embedded. | ||||
| /// </summary> | /// </summary> | ||||
| EmbedLinks = 0x00_00_40_00, | |||||
| EmbedLinks = 0x00_00_40_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for uploading images and files. | /// Allows for uploading images and files. | ||||
| /// </summary> | /// </summary> | ||||
| AttachFiles = 0x00_00_80_00, | |||||
| AttachFiles = 0x00_00_80_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for reading of message history. | /// Allows for reading of message history. | ||||
| /// </summary> | /// </summary> | ||||
| ReadMessageHistory = 0x00_01_00_00, | |||||
| ReadMessageHistory = 0x00_01_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | /// Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all | ||||
| /// online users in a channel. | /// online users in a channel. | ||||
| /// </summary> | /// </summary> | ||||
| MentionEveryone = 0x00_02_00_00, | |||||
| MentionEveryone = 0x00_02_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows the usage of custom emojis from other servers. | /// Allows the usage of custom emojis from other servers. | ||||
| /// </summary> | /// </summary> | ||||
| UseExternalEmojis = 0x00_04_00_00, | |||||
| UseExternalEmojis = 0x00_04_00_00, | |||||
| // Voice | // Voice | ||||
| /// <summary> | /// <summary> | ||||
| /// Allows for joining of a voice channel. | /// Allows for joining of a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Connect = 0x00_10_00_00, | |||||
| Connect = 0x00_10_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for speaking in a voice channel. | /// Allows for speaking in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Speak = 0x00_20_00_00, | |||||
| Speak = 0x00_20_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for muting members in a voice channel. | /// Allows for muting members in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| MuteMembers = 0x00_40_00_00, | |||||
| MuteMembers = 0x00_40_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for deafening of members in a voice channel. | /// Allows for deafening of members in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| DeafenMembers = 0x00_80_00_00, | |||||
| DeafenMembers = 0x00_80_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for moving of members between voice channels. | /// Allows for moving of members between voice channels. | ||||
| /// </summary> | /// </summary> | ||||
| MoveMembers = 0x01_00_00_00, | |||||
| MoveMembers = 0x01_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using voice-activity-detection in a voice channel. | /// Allows for using voice-activity-detection in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| UseVAD = 0x02_00_00_00, | |||||
| UseVAD = 0x02_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for using priority speaker in a voice channel. | /// Allows for using priority speaker in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -140,17 +140,17 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows video streaming in a voice channel. | /// Allows video streaming in a voice channel. | ||||
| /// </summary> | /// </summary> | ||||
| Stream = 0x00_00_02_00, | |||||
| Stream = 0x00_00_02_00, | |||||
| // General 2 | // General 2 | ||||
| /// <summary> | /// <summary> | ||||
| /// Allows for modification of own nickname. | /// Allows for modification of own nickname. | ||||
| /// </summary> | /// </summary> | ||||
| ChangeNickname = 0x04_00_00_00, | |||||
| ChangeNickname = 0x04_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for modification of other users nicknames. | /// Allows for modification of other users nicknames. | ||||
| /// </summary> | /// </summary> | ||||
| ManageNicknames = 0x08_00_00_00, | |||||
| ManageNicknames = 0x08_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of roles. | /// Allows management and editing of roles. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -158,7 +158,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageRoles = 0x10_00_00_00, | |||||
| ManageRoles = 0x10_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of webhooks. | /// Allows management and editing of webhooks. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -166,7 +166,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageWebhooks = 0x20_00_00_00, | |||||
| ManageWebhooks = 0x20_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows management and editing of emojis and stickers. | /// Allows management and editing of emojis and stickers. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -182,7 +182,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for requesting to speak in stage channels. | /// Allows for requesting to speak in stage channels. | ||||
| /// </summary> | /// </summary> | ||||
| RequestToSpeak = 0x01_00_00_00_00, | |||||
| RequestToSpeak = 0x01_00_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for creating, editing, and deleting guild scheduled events. | /// Allows for creating, editing, and deleting guild scheduled events. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -194,7 +194,7 @@ namespace Discord | |||||
| /// This permission requires the owner account to use two-factor | /// This permission requires the owner account to use two-factor | ||||
| /// authentication when used on a guild that has server-wide 2FA enabled. | /// authentication when used on a guild that has server-wide 2FA enabled. | ||||
| /// </remarks> | /// </remarks> | ||||
| ManageThreads = 0x04_00_00_00_00, | |||||
| ManageThreads = 0x04_00_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for creating public threads. | /// Allows for creating public threads. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -206,7 +206,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows the usage of custom stickers from other servers. | /// Allows the usage of custom stickers from other servers. | ||||
| /// </summary> | /// </summary> | ||||
| UseExternalStickers = 0x20_00_00_00_00, | |||||
| UseExternalStickers = 0x20_00_00_00_00, | |||||
| /// <summary> | /// <summary> | ||||
| /// Allows for sending messages in threads. | /// Allows for sending messages in threads. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -281,7 +281,7 @@ namespace Discord | |||||
| manageThreads: manageThreads, | manageThreads: manageThreads, | ||||
| createPublicThreads: createPublicThreads, | createPublicThreads: createPublicThreads, | ||||
| createPrivateThreads: createPrivateThreads, | createPrivateThreads: createPrivateThreads, | ||||
| useExternalStickers: useExternalStickers, | |||||
| useExternalStickers: useExternalStickers, | |||||
| sendMessagesInThreads: sendMessagesInThreads, | sendMessagesInThreads: sendMessagesInThreads, | ||||
| startEmbeddedActivities: startEmbeddedActivities, | startEmbeddedActivities: startEmbeddedActivities, | ||||
| moderateMembers: moderateMembers) | moderateMembers: moderateMembers) | ||||
| @@ -19,7 +19,7 @@ namespace Discord | |||||
| /// Gets a <see cref="OverwritePermissions" /> that grants all permissions for the given channel. | /// Gets a <see cref="OverwritePermissions" /> that grants all permissions for the given channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <exception cref="ArgumentException">Unknown channel type.</exception> | /// <exception cref="ArgumentException">Unknown channel type.</exception> | ||||
| public static OverwritePermissions AllowAll(IChannel channel) | |||||
| public static OverwritePermissions AllowAll(IChannel channel) | |||||
| => new OverwritePermissions(ChannelPermissions.All(channel).RawValue, 0); | => new OverwritePermissions(ChannelPermissions.All(channel).RawValue, 0); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a <see cref="OverwritePermissions" /> that denies all permissions for the given channel. | /// Gets a <see cref="OverwritePermissions" /> that denies all permissions for the given channel. | ||||
| @@ -116,24 +116,24 @@ namespace Discord | |||||
| private OverwritePermissions(ulong allowValue, ulong denyValue, | private OverwritePermissions(ulong allowValue, ulong denyValue, | ||||
| PermValue? createInstantInvite = null, | PermValue? createInstantInvite = null, | ||||
| PermValue? manageChannel = null, | |||||
| PermValue? manageChannel = null, | |||||
| PermValue? addReactions = null, | PermValue? addReactions = null, | ||||
| PermValue? viewChannel = null, | PermValue? viewChannel = null, | ||||
| PermValue? sendMessages = null, | PermValue? sendMessages = null, | ||||
| PermValue? sendTTSMessages = null, | PermValue? sendTTSMessages = null, | ||||
| PermValue? manageMessages = null, | |||||
| PermValue? manageMessages = null, | |||||
| PermValue? embedLinks = null, | PermValue? embedLinks = null, | ||||
| PermValue? attachFiles = null, | PermValue? attachFiles = null, | ||||
| PermValue? readMessageHistory = null, | PermValue? readMessageHistory = null, | ||||
| PermValue? mentionEveryone = null, | |||||
| PermValue? mentionEveryone = null, | |||||
| PermValue? useExternalEmojis = null, | PermValue? useExternalEmojis = null, | ||||
| PermValue? connect = null, | PermValue? connect = null, | ||||
| PermValue? speak = null, | PermValue? speak = null, | ||||
| PermValue? muteMembers = null, | |||||
| PermValue? muteMembers = null, | |||||
| PermValue? deafenMembers = null, | PermValue? deafenMembers = null, | ||||
| PermValue? moveMembers = null, | PermValue? moveMembers = null, | ||||
| PermValue? useVoiceActivation = null, | PermValue? useVoiceActivation = null, | ||||
| PermValue? manageRoles = null, | |||||
| PermValue? manageRoles = null, | |||||
| PermValue? manageWebhooks = null, | PermValue? manageWebhooks = null, | ||||
| PermValue? prioritySpeaker = null, | PermValue? prioritySpeaker = null, | ||||
| PermValue? stream = null, | PermValue? stream = null, | ||||
| @@ -194,7 +194,7 @@ namespace Discord | |||||
| PermValue viewChannel = PermValue.Inherit, | PermValue viewChannel = PermValue.Inherit, | ||||
| PermValue sendMessages = PermValue.Inherit, | PermValue sendMessages = PermValue.Inherit, | ||||
| PermValue sendTTSMessages = PermValue.Inherit, | PermValue sendTTSMessages = PermValue.Inherit, | ||||
| PermValue manageMessages = PermValue.Inherit, | |||||
| PermValue manageMessages = PermValue.Inherit, | |||||
| PermValue embedLinks = PermValue.Inherit, | PermValue embedLinks = PermValue.Inherit, | ||||
| PermValue attachFiles = PermValue.Inherit, | PermValue attachFiles = PermValue.Inherit, | ||||
| PermValue readMessageHistory = PermValue.Inherit, | PermValue readMessageHistory = PermValue.Inherit, | ||||
| @@ -221,11 +221,12 @@ namespace Discord | |||||
| PermValue useExternalStickers = PermValue.Inherit, | PermValue useExternalStickers = PermValue.Inherit, | ||||
| PermValue sendMessagesInThreads = PermValue.Inherit, | PermValue sendMessagesInThreads = PermValue.Inherit, | ||||
| PermValue startEmbeddedActivities = PermValue.Inherit) | PermValue startEmbeddedActivities = PermValue.Inherit) | ||||
| : this(0, 0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, | |||||
| embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, | |||||
| : this(0, 0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, | |||||
| embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, | |||||
| moveMembers, useVoiceActivation, manageRoles, manageWebhooks, prioritySpeaker, stream, useSlashCommands, useApplicationCommands, | moveMembers, useVoiceActivation, manageRoles, manageWebhooks, prioritySpeaker, stream, useSlashCommands, useApplicationCommands, | ||||
| requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | ||||
| sendMessagesInThreads, startEmbeddedActivities) { } | |||||
| sendMessagesInThreads, startEmbeddedActivities) | |||||
| { } | |||||
| /// <summary> | /// <summary> | ||||
| /// Initializes a new <see cref="OverwritePermissions" /> from the current one, changing the provided | /// Initializes a new <see cref="OverwritePermissions" /> from the current one, changing the provided | ||||
| @@ -238,11 +239,11 @@ namespace Discord | |||||
| PermValue? viewChannel = null, | PermValue? viewChannel = null, | ||||
| PermValue? sendMessages = null, | PermValue? sendMessages = null, | ||||
| PermValue? sendTTSMessages = null, | PermValue? sendTTSMessages = null, | ||||
| PermValue? manageMessages = null, | |||||
| PermValue? manageMessages = null, | |||||
| PermValue? embedLinks = null, | PermValue? embedLinks = null, | ||||
| PermValue? attachFiles = null, | PermValue? attachFiles = null, | ||||
| PermValue? readMessageHistory = null, | PermValue? readMessageHistory = null, | ||||
| PermValue? mentionEveryone = null, | |||||
| PermValue? mentionEveryone = null, | |||||
| PermValue? useExternalEmojis = null, | PermValue? useExternalEmojis = null, | ||||
| PermValue? connect = null, | PermValue? connect = null, | ||||
| PermValue? speak = null, | PermValue? speak = null, | ||||
| @@ -265,8 +266,8 @@ namespace Discord | |||||
| PermValue? useExternalStickers = null, | PermValue? useExternalStickers = null, | ||||
| PermValue? sendMessagesInThreads = null, | PermValue? sendMessagesInThreads = null, | ||||
| PermValue? startEmbeddedActivities = null) | PermValue? startEmbeddedActivities = null) | ||||
| => new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, | |||||
| embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, | |||||
| => new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, | |||||
| embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, | |||||
| moveMembers, useVoiceActivation, manageRoles, manageWebhooks, prioritySpeaker, stream, useSlashCommands, useApplicationCommands, | moveMembers, useVoiceActivation, manageRoles, manageWebhooks, prioritySpeaker, stream, useSlashCommands, useApplicationCommands, | ||||
| requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | ||||
| sendMessagesInThreads, startEmbeddedActivities); | sendMessagesInThreads, startEmbeddedActivities); | ||||
| @@ -305,7 +306,7 @@ namespace Discord | |||||
| } | } | ||||
| public override string ToString() => $"Allow {AllowValue}, Deny {DenyValue}"; | public override string ToString() => $"Allow {AllowValue}, Deny {DenyValue}"; | ||||
| private string DebuggerDisplay => | |||||
| private string DebuggerDisplay => | |||||
| $"Allow {string.Join(", ", ToAllowList())}, " + | $"Allow {string.Join(", ", ToAllowList())}, " + | ||||
| $"Deny {string.Join(", ", ToDenyList())}"; | $"Deny {string.Join(", ", ToDenyList())}"; | ||||
| } | } | ||||
| @@ -10,7 +10,7 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the identifier of this user's avatar. | /// Gets the identifier of this user's avatar. | ||||
| /// </summary> | /// </summary> | ||||
| string AvatarId { get; } | |||||
| string AvatarId { get; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the avatar URL for this user. | /// Gets the avatar URL for this user. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord | namespace Discord | ||||
| @@ -1,7 +1,7 @@ | |||||
| using System; | using System; | ||||
| using System.Threading.Tasks; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.IO; | using System.IO; | ||||
| using System.Threading.Tasks; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -80,7 +80,7 @@ namespace Discord | |||||
| return result.ToString(); | return result.ToString(); | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Formats a string as a block quote. | /// Formats a string as a block quote. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -34,7 +34,7 @@ namespace Discord.Logging | |||||
| try | try | ||||
| { | { | ||||
| if (severity <= Level) | if (severity <= Level) | ||||
| await _messageEvent.InvokeAsync(new LogMessage(severity, source, message, ex)).ConfigureAwait(false); | |||||
| await _messageEvent.InvokeAsync(new LogMessage(severity, source, message, ex)).ConfigureAwait(false); | |||||
| } | } | ||||
| catch | catch | ||||
| { | { | ||||
| @@ -52,7 +52,7 @@ namespace Discord | |||||
| Message = message; | Message = message; | ||||
| Exception = exception; | Exception = exception; | ||||
| } | } | ||||
| public override string ToString() => ToString(); | public override string ToString() => ToString(); | ||||
| public string ToString(StringBuilder builder = null, bool fullException = true, bool prependTimestamp = true, DateTimeKind timestampKind = DateTimeKind.Local, int? padSource = 11) | public string ToString(StringBuilder builder = null, bool fullException = true, bool prependTimestamp = true, DateTimeKind timestampKind = DateTimeKind.Local, int? padSource = 11) | ||||
| { | { | ||||
| @@ -60,9 +60,9 @@ namespace Discord | |||||
| string message = Message; | string message = Message; | ||||
| string exMessage = fullException ? Exception?.ToString() : Exception?.Message; | string exMessage = fullException ? Exception?.ToString() : Exception?.Message; | ||||
| int maxLength = 1 + | |||||
| int maxLength = 1 + | |||||
| (prependTimestamp ? 8 : 0) + 1 + | (prependTimestamp ? 8 : 0) + 1 + | ||||
| (padSource.HasValue ? padSource.Value : sourceName?.Length ?? 0) + 1 + | |||||
| (padSource.HasValue ? padSource.Value : sourceName?.Length ?? 0) + 1 + | |||||
| (message?.Length ?? 0) + | (message?.Length ?? 0) + | ||||
| (exMessage?.Length ?? 0) + 3; | (exMessage?.Length ?? 0) + 3; | ||||
| @@ -9,7 +9,7 @@ namespace Discord.Net | |||||
| public ApplicationCommandException(HttpException httpError) | public ApplicationCommandException(HttpException httpError) | ||||
| : base(httpError.HttpCode, httpError.Request, httpError.DiscordCode, httpError.Reason, httpError.Errors.ToArray()) | : base(httpError.HttpCode, httpError.Request, httpError.DiscordCode, httpError.Reason, httpError.Errors.ToArray()) | ||||
| { | { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -99,7 +99,7 @@ namespace Discord.Net | |||||
| => Equals(obj as BucketId); | => Equals(obj as BucketId); | ||||
| public override int GetHashCode() | public override int GetHashCode() | ||||
| => IsHashBucket ? (BucketHash, string.Join("/", MajorParameters.Select(x => x.Value))).GetHashCode() : (HttpMethod, Endpoint).GetHashCode(); | |||||
| => IsHashBucket ? (BucketHash, string.Join("/", MajorParameters.Select(x => x.Value))).GetHashCode() : (HttpMethod, Endpoint).GetHashCode(); | |||||
| public override string ToString() | public override string ToString() | ||||
| => GetBucketHash() ?? GetUniqueEndpoint(); | => GetBucketHash() ?? GetUniqueEndpoint(); | ||||
| @@ -113,6 +113,6 @@ namespace Discord.Net | |||||
| if (GetType() != other.GetType()) | if (GetType() != other.GetType()) | ||||
| return false; | return false; | ||||
| return ToString() == other.ToString(); | return ToString() == other.ToString(); | ||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord.Net.Rest | |||||
| namespace Discord.Net.Rest | |||||
| { | { | ||||
| public delegate IRestClient RestClientProvider(string baseUrl); | public delegate IRestClient RestClientProvider(string baseUrl); | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | using System.IO; | ||||
| using System.Net; | using System.Net; | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Threading; | using System.Threading; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord.Net.Udp | |||||
| namespace Discord.Net.Udp | |||||
| { | { | ||||
| public delegate IUdpSocket UdpSocketProvider(); | public delegate IUdpSocket UdpSocketProvider(); | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Threading; | using System.Threading; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord.Net.WebSockets | |||||
| namespace Discord.Net.WebSockets | |||||
| { | { | ||||
| public delegate IWebSocketClient WebSocketProvider(); | public delegate IWebSocketClient WebSocketProvider(); | ||||
| } | } | ||||
| @@ -48,17 +48,17 @@ namespace Discord | |||||
| /// to all actions. | /// to all actions. | ||||
| /// </remarks> | /// </remarks> | ||||
| public string AuditLogReason { get; set; } | public string AuditLogReason { get; set; } | ||||
| /// <summary> | |||||
| /// Gets or sets whether or not this request should use the system | |||||
| /// clock for rate-limiting. Defaults to <c>true</c>. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This property can also be set in <see cref="DiscordConfig"/>. | |||||
| /// On a per-request basis, the system clock should only be disabled | |||||
| /// when millisecond precision is especially important, and the | |||||
| /// hosting system is known to have a desynced clock. | |||||
| /// </remarks> | |||||
| public bool? UseSystemClock { get; set; } | |||||
| /// <summary> | |||||
| /// Gets or sets whether or not this request should use the system | |||||
| /// clock for rate-limiting. Defaults to <c>true</c>. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This property can also be set in <see cref="DiscordConfig"/>. | |||||
| /// On a per-request basis, the system clock should only be disabled | |||||
| /// when millisecond precision is especially important, and the | |||||
| /// hosting system is known to have a desynced clock. | |||||
| /// </remarks> | |||||
| public bool? UseSystemClock { get; set; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets or sets the callback to execute regarding ratelimits for this request. | /// Gets or sets the callback to execute regarding ratelimits for this request. | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -34,7 +34,7 @@ namespace Discord | |||||
| } | } | ||||
| internal static class EventExtensions | internal static class EventExtensions | ||||
| { | |||||
| { | |||||
| public static async Task InvokeAsync(this AsyncEvent<Func<Task>> eventHandler) | public static async Task InvokeAsync(this AsyncEvent<Func<Task>> eventHandler) | ||||
| { | { | ||||
| var subscribers = eventHandler.Subscriptions; | var subscribers = eventHandler.Subscriptions; | ||||
| @@ -30,7 +30,7 @@ namespace Discord | |||||
| public TEntity Value { get; } | public TEntity Value { get; } | ||||
| private Func<Task<TEntity>> DownloadFunc { get; } | private Func<Task<TEntity>> DownloadFunc { get; } | ||||
| internal Cacheable(TEntity value, TId id, bool hasValue , Func<Task<TEntity>> downloadFunc) | |||||
| internal Cacheable(TEntity value, TId id, bool hasValue, Func<Task<TEntity>> downloadFunc) | |||||
| { | { | ||||
| Value = value; | Value = value; | ||||
| Id = id; | Id = id; | ||||
| @@ -38,9 +38,9 @@ namespace Discord | |||||
| return (x, y) switch | return (x, y) switch | ||||
| { | { | ||||
| (null, null) => true, | (null, null) => true, | ||||
| (null, _) => false, | |||||
| (_, null) => false, | |||||
| _ => x.Id.Equals(y.Id) | |||||
| (null, _) => false, | |||||
| (_, null) => false, | |||||
| _ => x.Id.Equals(y.Id) | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -79,9 +79,9 @@ namespace Discord | |||||
| private static int DefaultConcurrencyLevel => ConcurrentHashSet.DefaultConcurrencyLevel; | private static int DefaultConcurrencyLevel => ConcurrentHashSet.DefaultConcurrencyLevel; | ||||
| private volatile Tables _tables; | private volatile Tables _tables; | ||||
| private readonly IEqualityComparer<T> _comparer; | |||||
| private readonly IEqualityComparer<T> _comparer; | |||||
| private readonly bool _growLockArray; | private readonly bool _growLockArray; | ||||
| private int _budget; | |||||
| private int _budget; | |||||
| public int Count | public int Count | ||||
| { | { | ||||
| @@ -149,19 +149,20 @@ namespace Discord | |||||
| } | } | ||||
| } | } | ||||
| public ConcurrentHashSet() | |||||
| public ConcurrentHashSet() | |||||
| : this(DefaultConcurrencyLevel, DefaultCapacity, true, EqualityComparer<T>.Default) { } | : this(DefaultConcurrencyLevel, DefaultCapacity, true, EqualityComparer<T>.Default) { } | ||||
| public ConcurrentHashSet(int concurrencyLevel, int capacity) | |||||
| public ConcurrentHashSet(int concurrencyLevel, int capacity) | |||||
| : this(concurrencyLevel, capacity, false, EqualityComparer<T>.Default) { } | : this(concurrencyLevel, capacity, false, EqualityComparer<T>.Default) { } | ||||
| public ConcurrentHashSet(IEnumerable<T> collection) | |||||
| public ConcurrentHashSet(IEnumerable<T> collection) | |||||
| : this(collection, EqualityComparer<T>.Default) { } | : this(collection, EqualityComparer<T>.Default) { } | ||||
| public ConcurrentHashSet(IEqualityComparer<T> comparer) | |||||
| public ConcurrentHashSet(IEqualityComparer<T> comparer) | |||||
| : this(DefaultConcurrencyLevel, DefaultCapacity, true, comparer) { } | : this(DefaultConcurrencyLevel, DefaultCapacity, true, comparer) { } | ||||
| /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c></exception> | /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c></exception> | ||||
| public ConcurrentHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) | |||||
| public ConcurrentHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) | |||||
| : this(comparer) | : this(comparer) | ||||
| { | { | ||||
| if (collection == null) throw new ArgumentNullException(paramName: nameof(collection)); | |||||
| if (collection == null) | |||||
| throw new ArgumentNullException(paramName: nameof(collection)); | |||||
| InitializeFromCollection(collection); | InitializeFromCollection(collection); | ||||
| } | } | ||||
| /// <exception cref="ArgumentNullException"> | /// <exception cref="ArgumentNullException"> | ||||
| @@ -170,18 +171,23 @@ namespace Discord | |||||
| public ConcurrentHashSet(int concurrencyLevel, IEnumerable<T> collection, IEqualityComparer<T> comparer) | public ConcurrentHashSet(int concurrencyLevel, IEnumerable<T> collection, IEqualityComparer<T> comparer) | ||||
| : this(concurrencyLevel, DefaultCapacity, false, comparer) | : this(concurrencyLevel, DefaultCapacity, false, comparer) | ||||
| { | { | ||||
| if (collection == null) throw new ArgumentNullException(paramName: nameof(collection)); | |||||
| if (comparer == null) throw new ArgumentNullException(paramName: nameof(comparer)); | |||||
| if (collection == null) | |||||
| throw new ArgumentNullException(paramName: nameof(collection)); | |||||
| if (comparer == null) | |||||
| throw new ArgumentNullException(paramName: nameof(comparer)); | |||||
| InitializeFromCollection(collection); | InitializeFromCollection(collection); | ||||
| } | |||||
| } | |||||
| public ConcurrentHashSet(int concurrencyLevel, int capacity, IEqualityComparer<T> comparer) | public ConcurrentHashSet(int concurrencyLevel, int capacity, IEqualityComparer<T> comparer) | ||||
| : this(concurrencyLevel, capacity, false, comparer) { } | : this(concurrencyLevel, capacity, false, comparer) { } | ||||
| internal ConcurrentHashSet(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<T> comparer) | internal ConcurrentHashSet(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<T> comparer) | ||||
| { | { | ||||
| if (concurrencyLevel < 1) throw new ArgumentOutOfRangeException(paramName: nameof(concurrencyLevel)); | |||||
| if (capacity < 0) throw new ArgumentOutOfRangeException(paramName: nameof(capacity)); | |||||
| if (comparer == null) throw new ArgumentNullException(paramName: nameof(comparer)); | |||||
| if (concurrencyLevel < 1) | |||||
| throw new ArgumentOutOfRangeException(paramName: nameof(concurrencyLevel)); | |||||
| if (capacity < 0) | |||||
| throw new ArgumentOutOfRangeException(paramName: nameof(capacity)); | |||||
| if (comparer == null) | |||||
| throw new ArgumentNullException(paramName: nameof(comparer)); | |||||
| if (capacity < concurrencyLevel) | if (capacity < concurrencyLevel) | ||||
| capacity = concurrencyLevel; | capacity = concurrencyLevel; | ||||
| @@ -201,7 +207,8 @@ namespace Discord | |||||
| { | { | ||||
| foreach (var value in collection) | foreach (var value in collection) | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException(paramName: "key"); | |||||
| if (value == null) | |||||
| throw new ArgumentNullException(paramName: "key"); | |||||
| if (!TryAddInternal(value, _comparer.GetHashCode(value), false)) | if (!TryAddInternal(value, _comparer.GetHashCode(value), false)) | ||||
| throw new ArgumentException(); | throw new ArgumentException(); | ||||
| @@ -213,7 +220,8 @@ namespace Discord | |||||
| /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | ||||
| public bool ContainsKey(T value) | public bool ContainsKey(T value) | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException(paramName: "key"); | |||||
| if (value == null) | |||||
| throw new ArgumentNullException(paramName: "key"); | |||||
| return ContainsKeyInternal(value, _comparer.GetHashCode(value)); | return ContainsKeyInternal(value, _comparer.GetHashCode(value)); | ||||
| } | } | ||||
| private bool ContainsKeyInternal(T value, int hashcode) | private bool ContainsKeyInternal(T value, int hashcode) | ||||
| @@ -221,7 +229,7 @@ namespace Discord | |||||
| Tables tables = _tables; | Tables tables = _tables; | ||||
| int bucketNo = GetBucket(hashcode, tables._buckets.Length); | int bucketNo = GetBucket(hashcode, tables._buckets.Length); | ||||
| Node n = Volatile.Read(ref tables._buckets[bucketNo]); | Node n = Volatile.Read(ref tables._buckets[bucketNo]); | ||||
| while (n != null) | while (n != null) | ||||
| @@ -230,14 +238,15 @@ namespace Discord | |||||
| return true; | return true; | ||||
| n = n._next; | n = n._next; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | ||||
| public bool TryAdd(T value) | public bool TryAdd(T value) | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException(paramName: "key"); | |||||
| if (value == null) | |||||
| throw new ArgumentNullException(paramName: "key"); | |||||
| return TryAddInternal(value, _comparer.GetHashCode(value), true); | return TryAddInternal(value, _comparer.GetHashCode(value), true); | ||||
| } | } | ||||
| private bool TryAddInternal(T value, int hashcode, bool acquireLock) | private bool TryAddInternal(T value, int hashcode, bool acquireLock) | ||||
| @@ -266,7 +275,8 @@ namespace Discord | |||||
| } | } | ||||
| Volatile.Write(ref tables._buckets[bucketNo], new Node(value, hashcode, tables._buckets[bucketNo])); | Volatile.Write(ref tables._buckets[bucketNo], new Node(value, hashcode, tables._buckets[bucketNo])); | ||||
| checked { tables._countPerLock[lockNo]++; } | |||||
| checked | |||||
| { tables._countPerLock[lockNo]++; } | |||||
| if (tables._countPerLock[lockNo] > _budget) | if (tables._countPerLock[lockNo] > _budget) | ||||
| resizeDesired = true; | resizeDesired = true; | ||||
| @@ -279,7 +289,7 @@ namespace Discord | |||||
| if (resizeDesired) | if (resizeDesired) | ||||
| GrowTable(tables); | GrowTable(tables); | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| @@ -287,9 +297,10 @@ namespace Discord | |||||
| /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c></exception> | ||||
| public bool TryRemove(T value) | public bool TryRemove(T value) | ||||
| { | { | ||||
| if (value == null) throw new ArgumentNullException(paramName: "key"); | |||||
| if (value == null) | |||||
| throw new ArgumentNullException(paramName: "key"); | |||||
| return TryRemoveInternal(value); | return TryRemoveInternal(value); | ||||
| } | |||||
| } | |||||
| private bool TryRemoveInternal(T value) | private bool TryRemoveInternal(T value) | ||||
| { | { | ||||
| int hashcode = _comparer.GetHashCode(value); | int hashcode = _comparer.GetHashCode(value); | ||||
| @@ -325,7 +336,7 @@ namespace Discord | |||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| public void Clear() | public void Clear() | ||||
| { | { | ||||
| int locksAcquired = 0; | int locksAcquired = 0; | ||||
| @@ -342,7 +353,7 @@ namespace Discord | |||||
| ReleaseLocks(0, locksAcquired); | ReleaseLocks(0, locksAcquired); | ||||
| } | } | ||||
| } | } | ||||
| public IEnumerator<T> GetEnumerator() | public IEnumerator<T> GetEnumerator() | ||||
| { | { | ||||
| Node[] buckets = _tables._buckets; | Node[] buckets = _tables._buckets; | ||||
| @@ -432,7 +443,8 @@ namespace Discord | |||||
| newBuckets[newBucketNo] = new Node(current._value, current._hashcode, newBuckets[newBucketNo]); | newBuckets[newBucketNo] = new Node(current._value, current._hashcode, newBuckets[newBucketNo]); | ||||
| checked { newCountPerLock[newLockNo]++; } | |||||
| checked | |||||
| { newCountPerLock[newLockNo]++; } | |||||
| current = next; | current = next; | ||||
| } | } | ||||
| @@ -471,6 +483,6 @@ namespace Discord | |||||
| { | { | ||||
| for (int i = fromInclusive; i < toExclusive; i++) | for (int i = fromInclusive; i < toExclusive; i++) | ||||
| Monitor.Exit(_tables._locks[i]); | Monitor.Exit(_tables._locks[i]); | ||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -61,7 +61,7 @@ namespace Discord | |||||
| text = text.Substring(3, text.Length - 4); //<@!123> | text = text.Substring(3, text.Length - 4); //<@!123> | ||||
| else | else | ||||
| text = text.Substring(2, text.Length - 3); //<@123> | text = text.Substring(2, text.Length - 3); //<@123> | ||||
| if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out userId)) | if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out userId)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -87,7 +87,7 @@ namespace Discord | |||||
| if (text.Length >= 3 && text[0] == '<' && text[1] == '#' && text[text.Length - 1] == '>') | if (text.Length >= 3 && text[0] == '<' && text[1] == '#' && text[text.Length - 1] == '>') | ||||
| { | { | ||||
| text = text.Substring(2, text.Length - 3); //<#123> | text = text.Substring(2, text.Length - 3); //<#123> | ||||
| if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out channelId)) | if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out channelId)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -113,7 +113,7 @@ namespace Discord | |||||
| if (text.Length >= 4 && text[0] == '<' && text[1] == '@' && text[2] == '&' && text[text.Length - 1] == '>') | if (text.Length >= 4 && text[0] == '<' && text[1] == '@' && text[2] == '&' && text[text.Length - 1] == '>') | ||||
| { | { | ||||
| text = text.Substring(3, text.Length - 4); //<@&123> | text = text.Substring(3, text.Length - 4); //<@&123> | ||||
| if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out roleId)) | if (ulong.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out roleId)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -136,27 +136,33 @@ namespace Discord | |||||
| switch (tag.Type) | switch (tag.Type) | ||||
| { | { | ||||
| case TagType.UserMention: | case TagType.UserMention: | ||||
| if (userHandling == TagHandling.Ignore) continue; | |||||
| if (userHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveUserMention(tag, userHandling); | newText = ResolveUserMention(tag, userHandling); | ||||
| break; | break; | ||||
| case TagType.ChannelMention: | case TagType.ChannelMention: | ||||
| if (channelHandling == TagHandling.Ignore) continue; | |||||
| if (channelHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveChannelMention(tag, channelHandling); | newText = ResolveChannelMention(tag, channelHandling); | ||||
| break; | break; | ||||
| case TagType.RoleMention: | case TagType.RoleMention: | ||||
| if (roleHandling == TagHandling.Ignore) continue; | |||||
| if (roleHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveRoleMention(tag, roleHandling); | newText = ResolveRoleMention(tag, roleHandling); | ||||
| break; | break; | ||||
| case TagType.EveryoneMention: | case TagType.EveryoneMention: | ||||
| if (everyoneHandling == TagHandling.Ignore) continue; | |||||
| if (everyoneHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveEveryoneMention(tag, everyoneHandling); | newText = ResolveEveryoneMention(tag, everyoneHandling); | ||||
| break; | break; | ||||
| case TagType.HereMention: | case TagType.HereMention: | ||||
| if (everyoneHandling == TagHandling.Ignore) continue; | |||||
| if (everyoneHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveHereMention(tag, everyoneHandling); | newText = ResolveHereMention(tag, everyoneHandling); | ||||
| break; | break; | ||||
| case TagType.Emoji: | case TagType.Emoji: | ||||
| if (emojiHandling == TagHandling.Ignore) continue; | |||||
| if (emojiHandling == TagHandling.Ignore) | |||||
| continue; | |||||
| newText = ResolveEmoji(tag, emojiHandling); | newText = ResolveEmoji(tag, emojiHandling); | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -36,8 +36,10 @@ namespace Discord | |||||
| public override bool Equals(object other) | public override bool Equals(object other) | ||||
| { | { | ||||
| if (!IsSpecified) return other == null; | |||||
| if (other == null) return false; | |||||
| if (!IsSpecified) | |||||
| return other == null; | |||||
| if (other == null) | |||||
| return false; | |||||
| return _value.Equals(other); | return _value.Equals(other); | ||||
| } | } | ||||
| public override int GetHashCode() => IsSpecified ? _value.GetHashCode() : 0; | public override int GetHashCode() => IsSpecified ? _value.GetHashCode() : 0; | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Collections; | |||||
| using System.Collections; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| @@ -1,4 +1,4 @@ | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| internal class PageInfo | internal class PageInfo | ||||
| { | { | ||||
| @@ -72,7 +72,7 @@ namespace Discord | |||||
| return true; | return true; | ||||
| } | } | ||||
| public ValueTask DisposeAsync() | public ValueTask DisposeAsync() | ||||
| { | { | ||||
| Current = null; | Current = null; | ||||
| @@ -147,7 +147,7 @@ namespace Discord | |||||
| //Give/Take User permissions | //Give/Take User permissions | ||||
| perms = channel.GetPermissionOverwrite(user); | perms = channel.GetPermissionOverwrite(user); | ||||
| if (perms != null) | if (perms != null) | ||||
| resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue; | |||||
| resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue; | |||||
| if (channel is ITextChannel) | if (channel is ITextChannel) | ||||
| { | { | ||||
| @@ -12,8 +12,10 @@ namespace Discord | |||||
| private static ArgumentNullException CreateNotNullException(string name, string msg) | private static ArgumentNullException CreateNotNullException(string name, string msg) | ||||
| { | { | ||||
| if (msg == null) return new ArgumentNullException(paramName: name); | |||||
| else return new ArgumentNullException(paramName: name, message: msg); | |||||
| if (msg == null) | |||||
| return new ArgumentNullException(paramName: name); | |||||
| else | |||||
| return new ArgumentNullException(paramName: name, message: msg); | |||||
| } | } | ||||
| #endregion | #endregion | ||||
| @@ -26,8 +28,10 @@ namespace Discord | |||||
| /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | ||||
| public static void NotNullOrEmpty(string obj, string name, string msg = null) | public static void NotNullOrEmpty(string obj, string name, string msg = null) | ||||
| { | { | ||||
| if (obj == null) throw CreateNotNullException(name, msg); | |||||
| if (obj.Length == 0) throw CreateNotEmptyException(name, msg); | |||||
| if (obj == null) | |||||
| throw CreateNotNullException(name, msg); | |||||
| if (obj.Length == 0) | |||||
| throw CreateNotEmptyException(name, msg); | |||||
| } | } | ||||
| /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | ||||
| /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | ||||
| @@ -35,16 +39,20 @@ namespace Discord | |||||
| { | { | ||||
| if (obj.IsSpecified) | if (obj.IsSpecified) | ||||
| { | { | ||||
| if (obj.Value == null) throw CreateNotNullException(name, msg); | |||||
| if (obj.Value.Length == 0) throw CreateNotEmptyException(name, msg); | |||||
| if (obj.Value == null) | |||||
| throw CreateNotNullException(name, msg); | |||||
| if (obj.Value.Length == 0) | |||||
| throw CreateNotEmptyException(name, msg); | |||||
| } | } | ||||
| } | } | ||||
| /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | ||||
| /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | ||||
| public static void NotNullOrWhitespace(string obj, string name, string msg = null) | public static void NotNullOrWhitespace(string obj, string name, string msg = null) | ||||
| { | { | ||||
| if (obj == null) throw CreateNotNullException(name, msg); | |||||
| if (obj.Trim().Length == 0) throw CreateNotEmptyException(name, msg); | |||||
| if (obj == null) | |||||
| throw CreateNotNullException(name, msg); | |||||
| if (obj.Trim().Length == 0) | |||||
| throw CreateNotEmptyException(name, msg); | |||||
| } | } | ||||
| /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> | ||||
| /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | /// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> | ||||
| @@ -52,8 +60,10 @@ namespace Discord | |||||
| { | { | ||||
| if (obj.IsSpecified) | if (obj.IsSpecified) | ||||
| { | { | ||||
| if (obj.Value == null) throw CreateNotNullException(name, msg); | |||||
| if (obj.Value.Trim().Length == 0) throw CreateNotEmptyException(name, msg); | |||||
| if (obj.Value == null) | |||||
| throw CreateNotNullException(name, msg); | |||||
| if (obj.Value.Trim().Length == 0) | |||||
| throw CreateNotEmptyException(name, msg); | |||||
| } | } | ||||
| } | } | ||||
| @@ -282,7 +292,8 @@ namespace Discord | |||||
| var minimum = SnowflakeUtils.ToSnowflake(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays(14))); | var minimum = SnowflakeUtils.ToSnowflake(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays(14))); | ||||
| for (var i = 0; i < collection.Length; i++) | for (var i = 0; i < collection.Length; i++) | ||||
| { | { | ||||
| if (collection[i] == 0) continue; | |||||
| if (collection[i] == 0) | |||||
| continue; | |||||
| if (collection[i] <= minimum) | if (collection[i] <= minimum) | ||||
| throw new ArgumentOutOfRangeException(name, "Messages must be younger than two weeks old."); | throw new ArgumentOutOfRangeException(name, "Messages must be younger than two weeks old."); | ||||
| } | } | ||||
| @@ -19,7 +19,7 @@ namespace Discord.Interactions | |||||
| /// Specify the target channel types for a <see cref="ApplicationCommandOptionType.Channel"/> option. | /// Specify the target channel types for a <see cref="ApplicationCommandOptionType.Channel"/> option. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="channelTypes">The allowed channel types for this option.</param> | /// <param name="channelTypes">The allowed channel types for this option.</param> | ||||
| public ChannelTypesAttribute (params ChannelType[] channelTypes) | |||||
| public ChannelTypesAttribute(params ChannelType[] channelTypes) | |||||
| { | { | ||||
| if (channelTypes is null) | if (channelTypes is null) | ||||
| throw new ArgumentNullException(nameof(channelTypes)); | throw new ArgumentNullException(nameof(channelTypes)); | ||||
| @@ -23,7 +23,7 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| public object Value { get; } | public object Value { get; } | ||||
| private ChoiceAttribute (string name) | |||||
| private ChoiceAttribute(string name) | |||||
| { | { | ||||
| Name = name; | Name = name; | ||||
| } | } | ||||
| @@ -33,7 +33,7 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="name">Name of the choice.</param> | /// <param name="name">Name of the choice.</param> | ||||
| /// <param name="value">Predefined value of the choice.</param> | /// <param name="value">Predefined value of the choice.</param> | ||||
| public ChoiceAttribute (string name, string value) : this(name) | |||||
| public ChoiceAttribute(string name, string value) : this(name) | |||||
| { | { | ||||
| Type = SlashCommandChoiceType.String; | Type = SlashCommandChoiceType.String; | ||||
| Value = value; | Value = value; | ||||
| @@ -44,7 +44,7 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="name">Name of the choice.</param> | /// <param name="name">Name of the choice.</param> | ||||
| /// <param name="value">Predefined value of the choice.</param> | /// <param name="value">Predefined value of the choice.</param> | ||||
| public ChoiceAttribute (string name, int value) : this(name) | |||||
| public ChoiceAttribute(string name, int value) : this(name) | |||||
| { | { | ||||
| Type = SlashCommandChoiceType.Integer; | Type = SlashCommandChoiceType.Integer; | ||||
| Value = value; | Value = value; | ||||
| @@ -55,7 +55,7 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="name">Name of the choice.</param> | /// <param name="name">Name of the choice.</param> | ||||
| /// <param name="value">Predefined value of the choice.</param> | /// <param name="value">Predefined value of the choice.</param> | ||||
| public ChoiceAttribute (string name, double value) : this(name) | |||||
| public ChoiceAttribute(string name, double value) : this(name) | |||||
| { | { | ||||
| Type = SlashCommandChoiceType.Number; | Type = SlashCommandChoiceType.Number; | ||||
| Value = value; | Value = value; | ||||
| @@ -43,7 +43,7 @@ namespace Discord.Interactions | |||||
| /// <param name="customId">String to compare the Message Component CustomIDs with.</param> | /// <param name="customId">String to compare the Message Component CustomIDs with.</param> | ||||
| /// <param name="ignoreGroupNames">If <see langword="true"/> <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command.</param> | /// <param name="ignoreGroupNames">If <see langword="true"/> <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command.</param> | ||||
| /// <param name="runMode">Set the run mode of the command.</param> | /// <param name="runMode">Set the run mode of the command.</param> | ||||
| public ComponentInteractionAttribute (string customId, bool ignoreGroupNames = false, RunMode runMode = RunMode.Default) | |||||
| public ComponentInteractionAttribute(string customId, bool ignoreGroupNames = false, RunMode runMode = RunMode.Default) | |||||
| { | { | ||||
| CustomId = customId; | CustomId = customId; | ||||
| IgnoreGroupNames = ignoreGroupNames; | IgnoreGroupNames = ignoreGroupNames; | ||||
| @@ -24,13 +24,13 @@ namespace Discord.Interactions | |||||
| /// </summary> | /// </summary> | ||||
| public RunMode RunMode { get; } | public RunMode RunMode { get; } | ||||
| internal ContextCommandAttribute (string name, ApplicationCommandType commandType, RunMode runMode = RunMode.Default) | |||||
| internal ContextCommandAttribute(string name, ApplicationCommandType commandType, RunMode runMode = RunMode.Default) | |||||
| { | { | ||||
| Name = name; | Name = name; | ||||
| CommandType = commandType; | CommandType = commandType; | ||||
| RunMode = runMode; | RunMode = runMode; | ||||
| } | } | ||||
| internal virtual void CheckMethodDefinition (MethodInfo methodInfo) { } | |||||
| internal virtual void CheckMethodDefinition(MethodInfo methodInfo) { } | |||||
| } | } | ||||
| } | } | ||||
| @@ -16,9 +16,9 @@ namespace Discord.Interactions | |||||
| /// Register a method as a Message Context Command. | /// Register a method as a Message Context Command. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="name">Name of the context command.</param> | /// <param name="name">Name of the context command.</param> | ||||
| public MessageCommandAttribute (string name) : base(name, ApplicationCommandType.Message) { } | |||||
| public MessageCommandAttribute(string name) : base(name, ApplicationCommandType.Message) { } | |||||
| internal override void CheckMethodDefinition (MethodInfo methodInfo) | |||||
| internal override void CheckMethodDefinition(MethodInfo methodInfo) | |||||
| { | { | ||||
| var parameters = methodInfo.GetParameters(); | var parameters = methodInfo.GetParameters(); | ||||
| @@ -17,7 +17,7 @@ namespace Discord.Interactions | |||||
| /// Gets the string to compare the Modal CustomIDs with. | /// Gets the string to compare the Modal CustomIDs with. | ||||
| /// </summary> | /// </summary> | ||||
| public string CustomId { get; } | public string CustomId { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets <see langword="true"/> if <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command. | /// Gets <see langword="true"/> if <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -38,7 +38,7 @@ namespace Discord.Interactions | |||||
| /// <param name="description">Description of the command.</param> | /// <param name="description">Description of the command.</param> | ||||
| /// <param name="ignoreGroupNames"> If <see langword="true"/>, <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command.</param> | /// <param name="ignoreGroupNames"> If <see langword="true"/>, <see cref="GroupAttribute"/>s will be ignored while creating this command and this method will be treated as a top level command.</param> | ||||
| /// <param name="runMode">Set the run mode of the command.</param> | /// <param name="runMode">Set the run mode of the command.</param> | ||||
| public SlashCommandAttribute (string name, string description, bool ignoreGroupNames = false, RunMode runMode = RunMode.Default) | |||||
| public SlashCommandAttribute(string name, string description, bool ignoreGroupNames = false, RunMode runMode = RunMode.Default) | |||||
| { | { | ||||
| Name = name; | Name = name; | ||||
| Description = description; | Description = description; | ||||