| @@ -0,0 +1,68 @@ | |||
| --- | |||
| uid: Guides.BearerToken | |||
| title: Working with Bearer token | |||
| --- | |||
| # Working with Bearer token | |||
| Some endpoints in Discord API require a Bearer token, which can be obtained through [OAuth2 flow](https://discord.com/developers/docs/topics/oauth2). Discord.Net allows you to interact with these endpoints using the [DiscordRestClient]. | |||
| ## Initializing a new instance of the client | |||
| [!code-csharp[Initialize DiscordRestClient](samples/rest_client_init.cs)] | |||
| ## Getting current user | |||
| The [DiscordRestClient] gets the current user when `LoginAsync()` is called. The user object can be found in the `CurrentUser` property. | |||
| If you need to fetch the user again, the `GetCurrentUserAsync()` method can be used. | |||
| [!code-csharp[Get current user](samples/current_user.cs)] | |||
| > [!NOTE] | |||
| > Some properties might be `null` depending on which scopes users authorized your app with. | |||
| > For example: `email` scope is required to fetch current user's email address. | |||
| ## Fetching current user's guilds | |||
| The `GetGuildSummariesAsync()` method is used to fetch current user's guilds. Since it returns an `IAsyncEnumerable` you need to call `FlattenAsync()` to get a plain `IEnumerable` containing [RestUserGuild] objects. | |||
| [!code-csharp[Get current user's guilds](samples/current_user_guilds.cs)] | |||
| > [!WARNING] | |||
| > This method requires `guilds` scope | |||
| ## Fetching current user's guild member object | |||
| To fetch the current user's guild member object, the `GetCurrentUserGuildMemberAsync()` method can be used. | |||
| [!code-csharp[Get current user's guild member](samples/current_user_guild_member.cs)] | |||
| > [!WARNING] | |||
| > This method requires `guilds.members.read` scope | |||
| ## Get user connections | |||
| The `GetConnectionsAsync` method can be used to fetch current user's connections to other platforms. | |||
| [!code-csharp[Get current user's connections](samples/current_user_connections.cs)] | |||
| > [!WARNING] | |||
| > This method requires `connections` scope | |||
| ## Application role connection | |||
| In addition to previous features, Discord.Net supports fetching & updating user's application role connection metadata values. `GetUserApplicationRoleConnectionAsync()` returns a [RoleConnection] object of the current user for the given application id. | |||
| The `ModifyUserApplicationRoleConnectionAsync()` method is used to update current user's role connection metadata values. A new set of values can be created with [RoleConnectionProperties] object. | |||
| [!code-csharp[Get current user's connections](samples/app_role_connection.cs)] | |||
| > [!WARNING] | |||
| > This method requires `role_connections.write` scope | |||
| [DiscordRestClient]: xref:Discord.Rest.DiscordRestClient | |||
| [RestUserGuild]: xref:Discord.Rest.RestUserGuild | |||
| [RoleConnection]: xref:Discord.RoleConnection | |||
| [RoleConnectionProperties]: xref:Discord.RoleConnectionProperties | |||
| @@ -0,0 +1,11 @@ | |||
| // fetch application role connection of the current user for the app with provided id. | |||
| var roleConnection = await client.GetUserApplicationRoleConnectionAsync(applicationid); | |||
| // create a new role connection metadata properties object & set some values. | |||
| var properties = new RoleConnectionProperties("Discord.Net Docs", "Cool Coding Guy") | |||
| .WithNumber("eaten_cookies", 69) | |||
| .WithBool("loves_cookies", true) | |||
| .WithDate("last_eaten_cookie", DateTimeOffset.UtcNow); | |||
| // update current user's values with the given properties. | |||
| await client.ModifyUserApplicationRoleConnectionAsync(applicationId, properties); | |||
| @@ -0,0 +1,5 @@ | |||
| // gets the user object stored in the DiscordRestClient. | |||
| var user = client.CurrentUser; | |||
| // fetches the current user with a REST call & updates the CurrentUser property. | |||
| var refreshedUser = await client.GetCurrentUserAsync(); | |||
| @@ -0,0 +1,2 @@ | |||
| // fetches the current user's connections. | |||
| var connections = await client.GetConnectionsAsync(); | |||
| @@ -0,0 +1,6 @@ | |||
| // fetches the current user's guild member object in a guild with provided id. | |||
| var member = await client.GetCurrentUserGuildMemberAsync(guildId); | |||
| // fetches the current user's guild member object in a RestUserGuild. | |||
| var guild = await client.GetGuildSummariesAsync().FlattenAsync().First(); | |||
| var member = await guild.GetCurrentUserGuildMemberAsync(); | |||
| @@ -0,0 +1,2 @@ | |||
| // fetches the guilds the current user participate in. | |||
| var guilds = await client.GetGuildSummariesAsync().FlattenAsync(); | |||
| @@ -0,0 +1,5 @@ | |||
| using Discord; | |||
| using Discord.Rest; | |||
| await using var client = new DiscordRestClient(); | |||
| await client.LoginAsync(TokenType.Bearer, "bearer token obtained through oauth2 flow"); | |||
| @@ -7,8 +7,8 @@ discordClient.ButtonExecuted += async (interaction) => | |||
| public class MessageComponentModule : InteractionModuleBase<SocketInteractionContext<SocketMessageComponent>> | |||
| { | |||
| [ComponentInteraction("custom_id")] | |||
| public async Command() | |||
| public async Task Command() | |||
| { | |||
| Context.Interaction.UpdateAsync(...); | |||
| await Context.Interaction.UpdateAsync(...); | |||
| } | |||
| } | |||
| @@ -126,6 +126,8 @@ | |||
| topicUid: Guides.OtherLibs.MediatR | |||
| - name: Emoji | |||
| topicUid: Guides.Emoji | |||
| - name: Bearer Tokens | |||
| topicUid: Guides.BearerToken | |||
| - name: Voice | |||
| topicUid: Guides.Voice.SendingVoice | |||
| - name: Deployment | |||
| @@ -48,8 +48,8 @@ namespace Discord | |||
| { | |||
| 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); | |||
| result.Id = obj["id"].ToObject<Guid>(); | |||
| @@ -100,14 +100,14 @@ namespace Discord | |||
| /// Gets a read-only dictionary containing the currently loaded overrides. | |||
| /// </summary> | |||
| 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 List<Func<Override, string, Task>> _logEvents = new(); | |||
| private static ConcurrentDictionary<Override, List<LoadedOverride>> _loadedOverrides = new ConcurrentDictionary<Override, List<LoadedOverride>>(); | |||
| private const string ApiUrl = "https://overrides.discordnet.dev"; | |||
| static BuildOverrides() | |||
| { | |||
| _overrideDomain = new AssemblyLoadContext("Discord.Net.Overrides.Runtime"); | |||
| @@ -258,14 +258,14 @@ namespace Discord | |||
| 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")); | |||
| if (!result.IsSuccessStatusCode) | |||
| throw new Exception("Failed to get dependency"); | |||
| using(var ms = new MemoryStream()) | |||
| using (var ms = new MemoryStream()) | |||
| { | |||
| var innerStream = await result.Content.ReadAsStreamAsync(); | |||
| await innerStream.CopyToAsync(ms); | |||
| @@ -1,8 +1,8 @@ | |||
| using Discord; | |||
| using Discord.WebSocket; | |||
| using System; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| using Discord; | |||
| using Discord.WebSocket; | |||
| namespace BasicBot | |||
| { | |||
| @@ -112,7 +112,8 @@ namespace BasicBot | |||
| if (component.Data.CustomId == "unique-id") | |||
| 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.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 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) | |||
| { | |||
| @@ -26,7 +26,7 @@ namespace InteractionFramework.Modules | |||
| // [Summary] lets you customize the name and the description of a parameter | |||
| [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)); | |||
| [SlashCommand("ping", "Pings the bot and returns its latency.")] | |||
| @@ -64,11 +64,11 @@ namespace InteractionFramework | |||
| public static bool IsDebug() | |||
| { | |||
| #if DEBUG | |||
| return true; | |||
| #else | |||
| return false; | |||
| #endif | |||
| #if DEBUG | |||
| return true; | |||
| #else | |||
| return false; | |||
| #endif | |||
| } | |||
| } | |||
| } | |||
| @@ -1,11 +1,11 @@ | |||
| using System; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using Discord.Commands; | |||
| using Microsoft.CodeAnalysis; | |||
| using Microsoft.CodeAnalysis.CSharp; | |||
| using Microsoft.CodeAnalysis.CSharp.Syntax; | |||
| using Microsoft.CodeAnalysis.Diagnostics; | |||
| using Discord.Commands; | |||
| using System; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| namespace Discord.Analyzers | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| using System; | |||
| using Microsoft.CodeAnalysis; | |||
| using Discord.Commands; | |||
| using Microsoft.CodeAnalysis; | |||
| using System; | |||
| namespace Discord.Analyzers | |||
| { | |||
| @@ -43,8 +43,8 @@ namespace Discord.Commands | |||
| { | |||
| if (!TypeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo())) | |||
| throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}."); | |||
| TypeReader = overridenTypeReader; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -61,7 +61,7 @@ namespace Discord.Commands | |||
| if (GuildPermission.HasValue) | |||
| { | |||
| 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)) | |||
| return Task.FromResult(PreconditionResult.FromError(ErrorMessage ?? $"User requires guild permission {GuildPermission.Value}.")); | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Threading.Tasks; | |||
| using System.Collections.Generic; | |||
| namespace Discord.Commands.Builders | |||
| { | |||
| @@ -20,7 +20,9 @@ namespace Discord.Commands.Builders | |||
| public string Name { get; set; } | |||
| public string Summary { get; set; } | |||
| public string Remarks { get; set; } | |||
| public string Group { get => _group; | |||
| public string Group | |||
| { | |||
| get => _group; | |||
| set | |||
| { | |||
| _aliases.Remove(_group); | |||
| @@ -1,11 +1,10 @@ | |||
| using Discord.Commands.Builders; | |||
| using System; | |||
| using System.Linq; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using System.Threading.Tasks; | |||
| using Discord.Commands.Builders; | |||
| namespace Discord.Commands | |||
| { | |||
| internal static class ModuleClassBuilder | |||
| @@ -80,11 +79,11 @@ namespace Discord.Commands | |||
| { | |||
| if (!IsValidModuleDefinition(typeInfo)) | |||
| continue; | |||
| if (builtTypes.Contains(typeInfo)) | |||
| continue; | |||
| builder.AddModule((module) => | |||
| builder.AddModule((module) => | |||
| { | |||
| BuildModule(module, typeInfo, service, services); | |||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services); | |||
| @@ -139,7 +138,7 @@ namespace Discord.Commands | |||
| foreach (var method in validCommands) | |||
| { | |||
| builder.AddCommand((command) => | |||
| builder.AddCommand((command) => | |||
| { | |||
| 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) | |||
| { | |||
| var attributes = method.GetCustomAttributes(); | |||
| foreach (var attribute in attributes) | |||
| { | |||
| switch (attribute) | |||
| @@ -191,7 +190,7 @@ namespace Discord.Commands | |||
| int pos = 0, count = parameters.Length; | |||
| foreach (var paramInfo in parameters) | |||
| { | |||
| builder.AddParameter((parameter) => | |||
| builder.AddParameter((parameter) => | |||
| { | |||
| BuildParameter(parameter, paramInfo, pos++, count, service, serviceprovider); | |||
| }); | |||
| @@ -1,9 +1,8 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using System.Collections.Generic; | |||
| namespace Discord.Commands.Builders | |||
| { | |||
| public class ParameterBuilder | |||
| @@ -25,7 +24,7 @@ namespace Discord.Commands.Builders | |||
| public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions; | |||
| public IReadOnlyList<Attribute> Attributes => _attributes; | |||
| #endregion | |||
| #endregion | |||
| #region Automatic | |||
| internal ParameterBuilder(CommandBuilder command) | |||
| @@ -1,3 +1,5 @@ | |||
| using Discord.Commands.Builders; | |||
| using Discord.Logging; | |||
| using System; | |||
| using System.Collections.Concurrent; | |||
| using System.Collections.Generic; | |||
| @@ -6,8 +8,6 @@ using System.Linq; | |||
| using System.Reflection; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| using Discord.Commands.Builders; | |||
| using Discord.Logging; | |||
| namespace Discord.Commands | |||
| { | |||
| @@ -653,7 +653,7 @@ namespace Discord.Commands | |||
| var bestCandidate = preconditionResults | |||
| .OrderByDescending(x => x.Key.Command.Priority) | |||
| .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>(); | |||
| @@ -685,7 +685,7 @@ namespace Discord.Commands | |||
| .Where(x => x.Value.IsSuccess) | |||
| .ToArray(); | |||
| if(successfulParses.Length == 0) | |||
| if (successfulParses.Length == 0) | |||
| { | |||
| var bestMatch = parseResults | |||
| .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. | |||
| /// </summary> | |||
| public char SeparatorChar { get; set; } = ' '; | |||
| /// <summary> | |||
| /// Gets or sets whether commands should be case-sensitive. | |||
| /// </summary> | |||
| @@ -5,7 +5,7 @@ namespace Discord.Commands | |||
| internal class EmptyServiceProvider : IServiceProvider | |||
| { | |||
| public static readonly EmptyServiceProvider Instance = new EmptyServiceProvider(); | |||
| 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) | |||
| { | |||
| 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('>'); | |||
| 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) | |||
| { | |||
| argPos = endPos + 2; | |||
| @@ -1,8 +1,8 @@ | |||
| using Discord.Commands.Builders; | |||
| using System; | |||
| using System.Collections.Concurrent; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Collections.Concurrent; | |||
| using System.Diagnostics; | |||
| using System.Linq; | |||
| 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); | |||
| } | |||
| public Task<IResult> ExecuteAsync(ICommandContext context, ParseResult parseResult, IServiceProvider services) | |||
| { | |||
| if (!parseResult.IsSuccess) | |||
| @@ -1,8 +1,8 @@ | |||
| using Discord.Commands.Builders; | |||
| using System; | |||
| using System.Linq; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using Discord.Commands.Builders; | |||
| using System.Linq; | |||
| namespace Discord.Commands | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| using Discord.Commands.Builders; | |||
| using System; | |||
| using System.Threading.Tasks; | |||
| using Discord.Commands.Builders; | |||
| namespace Discord.Commands | |||
| { | |||
| @@ -23,7 +23,7 @@ namespace Discord.Commands | |||
| private readonly IReadOnlyDictionary<T, object> _enumsByValue; | |||
| private readonly Type _enumType; | |||
| private readonly TryParseDelegate<T> _tryParse; | |||
| public EnumTypeReader(Type type, TryParseDelegate<T> parser) | |||
| { | |||
| _enumType = type; | |||
| @@ -33,7 +33,7 @@ namespace Discord.Commands | |||
| var byValueBuilder = ImmutableDictionary.CreateBuilder<T, object>(); | |||
| foreach (var v in Enum.GetNames(_enumType)) | |||
| { | |||
| { | |||
| var parsedValue = Enum.Parse(_enumType, v); | |||
| byNameBuilder.Add(v.ToLower(), parsedValue); | |||
| if (!byValueBuilder.ContainsKey((T)parsedValue)) | |||
| @@ -116,7 +116,7 @@ namespace Discord.Commands | |||
| argv = input.Substring(beginRead + 1, currentRead - beginRead - 1).Trim(); | |||
| currentRead++; | |||
| } | |||
| else | |||
| else | |||
| argv = input.Substring(beginRead, currentRead - beginRead); | |||
| return _tProps[currentParam]; | |||
| @@ -27,7 +27,7 @@ namespace Discord.Commands | |||
| //By Id (0.9) | |||
| 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) | |||
| 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)) | |||
| .ForEachAsync(channelUser => AddResult(results, channelUser as T, channelUser.Username == input ? 0.65f : 0.55f)) | |||
| .ConfigureAwait(false); | |||
| 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); | |||
| } | |||
| @@ -30,13 +30,13 @@ namespace Discord.Commands | |||
| } | |||
| 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) | |||
| => new MatchResult(null,null,error, reason); | |||
| => new MatchResult(null, null, error, reason); | |||
| public static MatchResult FromError(Exception ex) | |||
| => FromError(CommandError.Exception, ex.Message); | |||
| 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) | |||
| => new MatchResult(null, pipeline, error, reason); | |||
| @@ -24,7 +24,7 @@ namespace Discord.Commands | |||
| args[i] = GetMember(commands, services, parameters[i].ParameterType, 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)); | |||
| return obj; | |||
| }; | |||
| @@ -6,4 +6,4 @@ namespace Discord.Audio | |||
| Music, | |||
| Mixed | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| using System; | |||
| using System; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| @@ -9,7 +9,7 @@ namespace Discord.Audio | |||
| public abstract int AvailableFrames { get; } | |||
| public override bool CanRead => true; | |||
| public override bool CanWrite => true; | |||
| public override bool CanWrite => true; | |||
| public abstract Task<RTPFrame> ReadFrameAsync(CancellationToken cancelToken); | |||
| public abstract bool TryReadFrame(CancellationToken cancelToken, out RTPFrame frame); | |||
| @@ -12,7 +12,7 @@ namespace Discord.Audio | |||
| public override bool CanWrite => false; | |||
| /// <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."); | |||
| public override void Write(byte[] buffer, int offset, int count) | |||
| { | |||
| @@ -31,7 +31,7 @@ namespace Discord.Audio | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Reading stream length is not supported.</exception> | |||
| public override long Length => | |||
| public override long Length => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| @@ -15,4 +15,4 @@ namespace Discord.Audio | |||
| Missed = missed; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -146,10 +146,10 @@ namespace Discord | |||
| /// </returns> | |||
| 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> | |||
| /// Returns an emoji URL. | |||
| @@ -218,7 +218,7 @@ namespace Discord | |||
| /// <param name="size">The size of the image.</param> | |||
| /// <returns></returns> | |||
| public static string GetEventCoverImageUrl(ulong guildId, ulong eventId, string assetId, ImageFormat format = ImageFormat.Auto, ushort size = 1024) | |||
| => $"{DiscordConfig.CDNUrl}guild-events/{guildId}/{eventId}/{assetId}.{FormatToExtension(format, assetId)}?size={size}"; | |||
| => $"{DiscordConfig.CDNUrl}guild-events/{eventId}/{assetId}.{FormatToExtension(format, assetId)}?size={size}"; | |||
| private static string FormatToExtension(StickerFormatType format) | |||
| { | |||
| @@ -11,7 +11,7 @@ | |||
| <TreatWarningsAsErrors>True</TreatWarningsAsErrors> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | |||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> | |||
| <PackageReference Include="System.Interactive.Async" Version="5.0.0" /> | |||
| <PackageReference Include="IDisposableAnalyzers" Version="3.4.15"> | |||
| <PrivateAssets>all</PrivateAssets> | |||
| @@ -175,23 +175,23 @@ namespace Discord | |||
| /// </remarks> | |||
| 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> | |||
| /// Gets or sets whether or not the internal experation check uses the system date | |||
| @@ -214,5 +214,13 @@ namespace Discord | |||
| /// If set to <see langword="false"/>, this value will be "Discord#1234". | |||
| /// </remarks> | |||
| public bool FormatUsersInBidirectionalUnicode { get; set; } = true; | |||
| /// <summary> | |||
| /// Returns the max thread members allowed to be in a request. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// The maximum number of thread members that can be gotten per-batch. | |||
| /// </returns> | |||
| public const int MaxThreadMembersPerBatch = 100; | |||
| } | |||
| } | |||
| @@ -30,7 +30,7 @@ namespace Discord | |||
| Flags = flags; | |||
| Details = details; | |||
| } | |||
| /// <summary> Returns the name of the <see cref="Game"/>. </summary> | |||
| public override string ToString() => Name; | |||
| private string DebuggerDisplay => Name; | |||
| @@ -1,5 +1,5 @@ | |||
| using System.Collections.Generic; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| namespace Discord; | |||
| @@ -38,7 +38,7 @@ public class RoleConnectionProperties | |||
| get => _platformUsername; | |||
| 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}"); | |||
| _platformUsername = value; | |||
| } | |||
| @@ -103,7 +103,7 @@ public class RoleConnectionProperties | |||
| internal RoleConnectionProperties AddMetadataRecord(string key, string value) | |||
| { | |||
| 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}"); | |||
| _metadata[key] = value; | |||
| @@ -126,7 +126,7 @@ public class RoleConnectionProperties | |||
| /// <summary> | |||
| /// Initializes a new instance of <see cref="RoleConnectionProperties"/>. | |||
| /// </summary> | |||
| public RoleConnectionProperties() {} | |||
| public RoleConnectionProperties() { } | |||
| /// <summary> | |||
| /// Initializes a new <see cref="RoleConnectionProperties"/> with the data from provided <see cref="RoleConnection"/>. | |||
| @@ -1,4 +1,4 @@ | |||
| namespace Discord | |||
| namespace Discord | |||
| { | |||
| /// <summary> | |||
| /// Provides properties that are used to modify an <see cref="IAudioChannel" /> with the specified changes. | |||
| @@ -7,7 +7,10 @@ using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| public interface IForumChannel : IGuildChannel, IMentionable, INestedChannel | |||
| /// <summary> | |||
| /// Represents a forum channel in a guild that can create posts. | |||
| /// </summary> | |||
| public interface IForumChannel : IMentionable, INestedChannel, IIntegrationChannel | |||
| { | |||
| /// <summary> | |||
| /// Gets a value that indicates whether the channel is NSFW. | |||
| @@ -169,7 +172,7 @@ namespace Discord | |||
| 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, | |||
| 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> | |||
| /// Creates a new post (thread) within the forum. | |||
| @@ -0,0 +1,44 @@ | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Threading.Tasks; | |||
| namespace Discord; | |||
| /// <summary> | |||
| /// Represents a channel in a guild that can create webhooks. | |||
| /// </summary> | |||
| public interface IIntegrationChannel : IGuildChannel | |||
| { | |||
| /// <summary> | |||
| /// Creates a webhook in this channel. | |||
| /// </summary> | |||
| /// <param name="name">The name of the webhook.</param> | |||
| /// <param name="avatar">The avatar of the webhook.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the newly created | |||
| /// webhook. | |||
| /// </returns> | |||
| Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets a webhook available in this channel. | |||
| /// </summary> | |||
| /// <param name="id">The identifier of the webhook.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous get operation. The task result contains a webhook associated | |||
| /// with the identifier; <c>null</c> if the webhook is not found. | |||
| /// </returns> | |||
| Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets the webhooks available in this channel. | |||
| /// </summary> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous get operation. The task result contains a read-only collection | |||
| /// of webhooks that is available in this channel. | |||
| /// </returns> | |||
| Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | |||
| } | |||
| @@ -222,7 +222,7 @@ namespace Discord | |||
| /// <returns> | |||
| /// Paged collection of messages. | |||
| /// </returns> | |||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, | |||
| IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, | |||
| CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets a collection of messages in this channel. | |||
| @@ -263,7 +263,7 @@ namespace Discord | |||
| /// <returns> | |||
| /// Paged collection of messages. | |||
| /// </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); | |||
| /// <summary> | |||
| /// Gets a collection of messages in this channel. | |||
| @@ -300,7 +300,7 @@ namespace Discord | |||
| /// <returns> | |||
| /// Paged collection of messages. | |||
| /// </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); | |||
| /// <summary> | |||
| /// Gets a collection of pinned messages in this channel. | |||
| @@ -1,3 +1,5 @@ | |||
| using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| /// <summary> | |||
| @@ -5,5 +7,12 @@ namespace Discord | |||
| /// </summary> | |||
| public interface INewsChannel : ITextChannel | |||
| { | |||
| /// <summary> | |||
| /// Follow this channel to send messages to a target channel. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// The Id of the created webhook. | |||
| /// </returns> | |||
| Task<ulong> FollowAnnouncementChannelAsync(ulong channelId, RequestOptions options); | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Represents a generic channel in a guild that can send and receive messages. | |||
| /// </summary> | |||
| public interface ITextChannel : IMessageChannel, IMentionable, INestedChannel | |||
| public interface ITextChannel : IMessageChannel, IMentionable, INestedChannel, IIntegrationChannel | |||
| { | |||
| /// <summary> | |||
| /// Gets a value that indicates whether the channel is NSFW. | |||
| @@ -94,37 +94,6 @@ namespace Discord | |||
| /// </returns> | |||
| /// <seealso cref="TextChannelProperties"/> | |||
| Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Creates a webhook in this text channel. | |||
| /// </summary> | |||
| /// <param name="name">The name of the webhook.</param> | |||
| /// <param name="avatar">The avatar of the webhook.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the newly created | |||
| /// webhook. | |||
| /// </returns> | |||
| Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets a webhook available in this text channel. | |||
| /// </summary> | |||
| /// <param name="id">The identifier of the webhook.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous get operation. The task result contains a webhook associated | |||
| /// with the identifier; <c>null</c> if the webhook is not found. | |||
| /// </returns> | |||
| Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets the webhooks available in this text channel. | |||
| /// </summary> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous get operation. The task result contains a read-only collection | |||
| /// of webhooks that is available in this channel. | |||
| /// </returns> | |||
| Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | |||
| /// <summary> | |||
| /// Creates a thread within this <see cref="ITextChannel"/>. | |||
| @@ -26,6 +26,11 @@ namespace Discord | |||
| /// </returns> | |||
| int? UserLimit { get; } | |||
| /// <summary> | |||
| /// Gets the video quality mode for this channel. | |||
| /// </summary> | |||
| VideoQualityMode VideoQualityMode { get; } | |||
| /// <summary> | |||
| /// Bulk-deletes multiple messages. | |||
| /// </summary> | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Discord; | |||
| /// <summary> | |||
| /// Represents a video quality mode for voice channels. | |||
| /// </summary> | |||
| public enum VideoQualityMode | |||
| { | |||
| /// <summary> | |||
| /// Discord chooses the quality for optimal performance. | |||
| /// </summary> | |||
| Auto = 1, | |||
| /// <summary> | |||
| /// 720p. | |||
| /// </summary> | |||
| Full = 2 | |||
| } | |||
| @@ -17,5 +17,10 @@ namespace Discord | |||
| /// Gets or sets the channel voice region id, automatic when set to <see langword="null"/>. | |||
| /// </summary> | |||
| public Optional<string> RTCRegion { get; set; } | |||
| /// <summary> | |||
| /// Get or sets the video quality mode for this channel. | |||
| /// </summary> | |||
| public Optional<VideoQualityMode> VideoQualityMode { get; set; } | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| using System; | |||
| using System.Globalization; | |||
| using System.Diagnostics; | |||
| using System.Globalization; | |||
| namespace Discord | |||
| { | |||
| @@ -44,11 +44,14 @@ namespace Discord | |||
| /// <param name="other">The object to compare with the current object.</param> | |||
| 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; | |||
| if (otherEmote == null) return false; | |||
| if (otherEmote == null) | |||
| return false; | |||
| return Id == otherEmote.Id; | |||
| } | |||
| @@ -45,7 +45,7 @@ namespace Discord | |||
| } | |||
| public override int GetHashCode() => (Id, Name, Emoji, IsModerated).GetHashCode(); | |||
| public override bool Equals(object? obj) | |||
| => 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) | |||
| { | |||
| 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; | |||
| Id = id; | |||
| } | |||
| @@ -180,12 +180,12 @@ public class ForumTagBuilder | |||
| => builder is not null && | |||
| Id == builder.Id && | |||
| 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)) && | |||
| IsModerated == builder.IsModerated; | |||
| 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); | |||
| } | |||
| @@ -18,5 +18,13 @@ namespace Discord | |||
| /// Returns the current user's permissions for this guild. | |||
| /// </summary> | |||
| GuildPermissions Permissions { get; } | |||
| /// <summary> | |||
| /// Gets the features for this guild. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// A flags enum containing all the features for the guild. | |||
| /// </returns> | |||
| GuildFeatures Features { get; } | |||
| } | |||
| } | |||
| @@ -19,4 +19,4 @@ namespace Discord | |||
| /// </summary> | |||
| AgeRestricted = 3 | |||
| } | |||
| } | |||
| } | |||
| @@ -50,5 +50,5 @@ public class WelcomeScreenChannelProperties : ISnowflakeEntity | |||
| /// <param name="channel">A welcome screen channel to modify.</param> | |||
| /// <returns>A new instance of <see cref="WelcomeScreenChannelProperties"/>.</returns> | |||
| 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> | |||
| /// Gets the icon URL of the application. | |||
| /// </summary> | |||
| string IconUrl { get; } | |||
| string IconUrl { get; } | |||
| /// <summary> | |||
| /// Gets if the bot is public. | |||
| /// </summary> | |||
| @@ -90,7 +90,7 @@ namespace Discord | |||
| /// Gets the bot/OAuth2 application for a discord integration. | |||
| /// </summary> | |||
| IIntegrationApplication Application { get; } | |||
| IGuild Guild { get; } | |||
| ulong GuildId { get; } | |||
| } | |||
| @@ -110,7 +110,7 @@ namespace Discord | |||
| { | |||
| 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)); | |||
| EnsureValidOptionName(name); | |||
| @@ -134,7 +134,7 @@ namespace Discord | |||
| { | |||
| 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)); | |||
| EnsureValidOptionDescription(description); | |||
| @@ -45,7 +45,7 @@ namespace Discord | |||
| public object Value | |||
| { | |||
| get => _value; | |||
| set | |||
| set | |||
| { | |||
| if (value is not string && !value.IsNumericType()) | |||
| throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!"); | |||
| @@ -49,7 +49,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Gets or sets whether or not this command is age restricted. | |||
| /// </summary> | |||
| public bool IsNsfw{ get; set; } = false; | |||
| public bool IsNsfw { get; set; } = false; | |||
| /// <summary> | |||
| /// Gets or sets the default permission required to use this slash command. | |||
| @@ -118,7 +118,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandName(name); | |||
| @@ -159,7 +159,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| EnsureValidCommandName(name); | |||
| @@ -116,7 +116,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandName(name); | |||
| @@ -125,7 +125,7 @@ namespace Discord | |||
| _nameLocalizations = new Dictionary<string, string>(nameLocalizations); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets whether or not this command can be used in dms. | |||
| /// </summary> | |||
| @@ -157,7 +157,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| 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, | |||
| 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); | |||
| } | |||
| @@ -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, | |||
| 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); | |||
| } | |||
| @@ -46,7 +46,7 @@ namespace Discord | |||
| /// </summary> | |||
| 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) | |||
| { | |||
| CustomId = customId; | |||
| @@ -1,4 +1,4 @@ | |||
| namespace Discord | |||
| namespace Discord | |||
| { | |||
| public enum TextInputStyle | |||
| { | |||
| @@ -93,7 +93,7 @@ namespace Discord | |||
| /// <param name="maxLength">The input's maximum length.</param> | |||
| /// <param name="style">The input's style.</param> | |||
| /// <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) | |||
| => 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="style">The input's style.</param> | |||
| /// <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 value = null) | |||
| => WithTextInput(new(label, customId, style, placeholder, minLength, maxLength, required, value), row); | |||
| @@ -263,6 +263,6 @@ namespace Discord | |||
| /// </summary> | |||
| /// <returns>A <see cref="ModalComponent"/> representing the builder.</returns> | |||
| 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. | |||
| /// </summary> | |||
| public bool IsDMEnabled { get; set; } = true; | |||
| /// <summary> | |||
| /// Gets or sets whether or not this command is age restricted. | |||
| /// </summary> | |||
| @@ -312,7 +312,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandName(name); | |||
| @@ -336,7 +336,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandDescription(description); | |||
| @@ -355,7 +355,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| EnsureValidCommandName(name); | |||
| @@ -375,7 +375,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| EnsureValidCommandDescription(description); | |||
| @@ -549,7 +549,7 @@ namespace Discord | |||
| if (isIntType && MaxValue != null && MaxValue % 1 != 0) | |||
| 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."); | |||
| if (isStrType && MaxLength is not null && MaxLength < 1) | |||
| @@ -627,10 +627,10 @@ namespace Discord | |||
| ChannelTypes = channelTypes, | |||
| }; | |||
| if(nameLocalizations is not null) | |||
| if (nameLocalizations is not null) | |||
| option.WithNameLocalizations(nameLocalizations); | |||
| if(descriptionLocalizations is not null) | |||
| if (descriptionLocalizations is not null) | |||
| option.WithDescriptionLocalizations(descriptionLocalizations); | |||
| return AddOption(option); | |||
| @@ -749,7 +749,7 @@ namespace Discord | |||
| Preconditions.AtLeast(name.Length, 1, 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.AtMost(str.Length, 100, nameof(value)); | |||
| @@ -904,7 +904,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandOptionName(name); | |||
| @@ -928,7 +928,7 @@ namespace Discord | |||
| 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)); | |||
| EnsureValidCommandOptionDescription(description); | |||
| @@ -947,7 +947,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| EnsureValidCommandOptionName(name); | |||
| @@ -967,7 +967,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException">Thrown if <paramref name="locale"/> is an invalid locale string.</exception> | |||
| 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)); | |||
| 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. | |||
| /// </returns> | |||
| public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); | |||
| /// <summary> | |||
| /// | |||
| /// 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; } | |||
| 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) | |||
| { | |||
| Id = id; | |||
| @@ -17,18 +17,18 @@ namespace Discord | |||
| /// It will always be present and does not mean mentions will not be allowed. | |||
| /// </note> | |||
| /// </remarks> | |||
| None = 0, | |||
| None = 0, | |||
| /// <summary> | |||
| /// Controls role mentions. | |||
| /// </summary> | |||
| Roles = 1, | |||
| Roles = 1, | |||
| /// <summary> | |||
| /// Controls user mentions. | |||
| /// </summary> | |||
| Users = 2, | |||
| Users = 2, | |||
| /// <summary> | |||
| /// Controls <code>@everyone</code> and <code>@here</code> mentions. | |||
| /// </summary> | |||
| Everyone = 4, | |||
| Everyone = 4, | |||
| } | |||
| } | |||
| @@ -44,7 +44,7 @@ namespace Discord | |||
| Type = type; | |||
| Fields = ImmutableArray.Create<EmbedField>(); | |||
| } | |||
| internal Embed(EmbedType type, | |||
| internal Embed(EmbedType type, | |||
| string title, | |||
| string description, | |||
| string url, | |||
| @@ -52,10 +52,10 @@ namespace Discord | |||
| Color? color, | |||
| EmbedImage? image, | |||
| EmbedVideo? video, | |||
| EmbedAuthor? author, | |||
| EmbedFooter? footer, | |||
| EmbedProvider? provider, | |||
| EmbedThumbnail? thumbnail, | |||
| EmbedAuthor? author, | |||
| EmbedFooter? footer, | |||
| EmbedProvider? provider, | |||
| EmbedThumbnail? thumbnail, | |||
| ImmutableArray<EmbedField> fields) | |||
| { | |||
| Type = type; | |||
| @@ -128,7 +128,7 @@ namespace Discord | |||
| { | |||
| var hash = 17; | |||
| 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(); | |||
| return hash; | |||
| } | |||
| @@ -1,9 +1,9 @@ | |||
| using Discord.Utils; | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Linq; | |||
| using Discord.Utils; | |||
| using Newtonsoft.Json; | |||
| namespace Discord | |||
| { | |||
| @@ -50,7 +50,8 @@ namespace Discord | |||
| get => _title; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -63,7 +64,8 @@ namespace Discord | |||
| get => _description; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -100,8 +102,10 @@ namespace Discord | |||
| get => _fields; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -470,7 +474,7 @@ namespace Discord | |||
| if (!string.IsNullOrEmpty(Author.IconUrl)) | |||
| UrlValidation.Validate(Author.IconUrl, true); | |||
| } | |||
| if(Footer != null) | |||
| if (Footer != null) | |||
| { | |||
| if (!string.IsNullOrEmpty(Footer.IconUrl)) | |||
| UrlValidation.Validate(Footer.IconUrl, true); | |||
| @@ -564,8 +568,10 @@ namespace Discord | |||
| get => _name; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -587,8 +593,10 @@ namespace Discord | |||
| set | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| @@ -704,7 +712,8 @@ namespace Discord | |||
| get => _name; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -836,7 +845,8 @@ namespace Discord | |||
| get => _text; | |||
| 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; | |||
| } | |||
| } | |||
| @@ -79,7 +79,7 @@ namespace Discord | |||
| /// Time of when the message was last edited; <c>null</c> if the message is never edited. | |||
| /// </returns> | |||
| DateTimeOffset? EditedTimestamp { get; } | |||
| /// <summary> | |||
| /// Gets the source channel of the message. | |||
| /// </summary> | |||
| @@ -89,6 +89,14 @@ namespace Discord | |||
| /// </summary> | |||
| IUser Author { get; } | |||
| /// <summary> | |||
| /// Gets the thread that was started from this message. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// An <see cref="IThreadChannel"/> object if this message has thread attached; otherwise <see langword="null"/>. | |||
| /// </returns> | |||
| IThreadChannel Thread { get; } | |||
| /// <summary> | |||
| /// Gets all attachments included in this message. | |||
| /// </summary> | |||
| @@ -189,7 +197,7 @@ namespace Discord | |||
| /// A read-only collection of sticker item objects. | |||
| /// </returns> | |||
| IReadOnlyCollection<IStickerItem> Stickers { get; } | |||
| /// <summary> | |||
| /// Gets the flags related to this message. | |||
| /// </summary> | |||
| @@ -1,4 +1,4 @@ | |||
| namespace Discord | |||
| namespace Discord | |||
| { | |||
| public interface ITag | |||
| { | |||
| @@ -43,6 +43,14 @@ namespace Discord | |||
| /// <summary> | |||
| /// Flag given to messages that is an Interaction Response and the bot is "thinking" | |||
| /// </summary> | |||
| Loading = 1 << 7 | |||
| Loading = 1 << 7, | |||
| /// <summary> | |||
| /// Flag given to messages that failed to mention some roles and add their members to the thread. | |||
| /// </summary> | |||
| FailedToMentionRolesInThread = 1 << 8, | |||
| /// <summary> | |||
| /// Flag give to messages that will not trigger push and desktop notifications. | |||
| /// </summary> | |||
| SuppressNotification = 1 << 12 | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| using System.Diagnostics; | |||
| using System.Diagnostics; | |||
| namespace Discord | |||
| { | |||
| @@ -12,6 +12,10 @@ namespace Discord | |||
| /// <summary> | |||
| /// The target of the permission is a user. | |||
| /// </summary> | |||
| User = 2 | |||
| User = 2, | |||
| /// <summary> | |||
| /// The target of the permission is a channel. | |||
| /// </summary> | |||
| Channel = 3 | |||
| } | |||
| } | |||
| @@ -58,5 +58,61 @@ namespace Discord | |||
| Permission = allow; | |||
| TargetType = ApplicationCommandPermissionTarget.Role; | |||
| } | |||
| /// <summary> | |||
| /// Creates a new <see cref="ApplicationCommandPermission"/> targeting <see cref="ApplicationCommandPermissionTarget.Channel"/>. | |||
| /// </summary> | |||
| /// <param name="channel">The channel you want to target this permission value for.</param> | |||
| /// <param name="allow">The value of this permission.</param> | |||
| public ApplicationCommandPermission(IChannel channel, bool allow) | |||
| { | |||
| TargetId = channel.Id; | |||
| Permission = allow; | |||
| TargetType = ApplicationCommandPermissionTarget.Channel; | |||
| } | |||
| /// <summary> | |||
| /// Creates a new <see cref="ApplicationCommandPermission"/> targeting @everyone in a guild. | |||
| /// </summary> | |||
| /// <param name="guildId">Id of the target guild.</param> | |||
| /// <param name="allow">The value of this permission.</param> | |||
| /// <returns> | |||
| /// Instance of <see cref="ApplicationCommandPermission"/> targeting @everyone in a guild. | |||
| /// </returns> | |||
| public static ApplicationCommandPermission ForEveryone(ulong guildId, bool allow) => | |||
| new(guildId, ApplicationCommandPermissionTarget.User, allow); | |||
| /// <summary> | |||
| /// Creates a new <see cref="ApplicationCommandPermission"/> targeting @everyone in a guild. | |||
| /// </summary> | |||
| /// <param name="guild">Target guild.</param> | |||
| /// <param name="allow">The value of this permission.</param> | |||
| /// <returns> | |||
| /// Instance of <see cref="ApplicationCommandPermission"/> targeting @everyone in a guild. | |||
| /// </returns> | |||
| public static ApplicationCommandPermission ForEveryone(IGuild guild, bool allow) => | |||
| ForEveryone(guild.Id, allow); | |||
| /// <summary> | |||
| /// Creates a new <see cref="ApplicationCommandPermission"/> targeting every channel in a guild. | |||
| /// </summary> | |||
| /// <param name="guildId">Id of the target guild.</param> | |||
| /// <param name="allow">The value of this permission.</param> | |||
| /// <returns> | |||
| /// Instance of <see cref="ApplicationCommandPermission"/> targeting everychannel in a guild. | |||
| /// </returns> | |||
| public static ApplicationCommandPermission ForAllChannels(ulong guildId, bool allow) => | |||
| new(guildId - 1, ApplicationCommandPermissionTarget.Channel, allow); | |||
| /// <summary> | |||
| /// Creates a new <see cref="ApplicationCommandPermission"/> targeting every channel in a guild. | |||
| /// </summary> | |||
| /// <param name="guild">Target guild.</param> | |||
| /// <param name="allow">The value of this permission.</param> | |||
| /// <returns> | |||
| /// Instance of <see cref="ApplicationCommandPermission"/> targeting everychannel in a guild. | |||
| /// </returns> | |||
| public static ApplicationCommandPermission ForAllChannels(IGuild guild, bool allow) => | |||
| ForAllChannels(guild.Id, allow); | |||
| } | |||
| } | |||
| @@ -10,105 +10,105 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows creation of instant invites. | |||
| /// </summary> | |||
| CreateInstantInvite = 0x00_00_00_00_01, | |||
| CreateInstantInvite = 0x00_00_00_00_01, | |||
| /// <summary> | |||
| /// Allows management and editing of channels. | |||
| /// </summary> | |||
| ManageChannels = 0x00_00_00_00_10, | |||
| ManageChannels = 0x00_00_00_00_10, | |||
| // Text | |||
| /// <summary> | |||
| /// Allows for the addition of reactions to messages. | |||
| /// </summary> | |||
| AddReactions = 0x00_00_00_00_40, | |||
| AddReactions = 0x00_00_00_00_40, | |||
| /// <summary> | |||
| /// Allows guild members to view a channel, which includes reading messages in text channels. | |||
| /// </summary> | |||
| ViewChannel = 0x00_00_00_04_00, | |||
| ViewChannel = 0x00_00_00_04_00, | |||
| /// <summary> | |||
| /// Allows for sending messages in a channel. | |||
| /// </summary> | |||
| SendMessages = 0x00_00_00_08_00, | |||
| SendMessages = 0x00_00_00_08_00, | |||
| /// <summary> | |||
| /// Allows for sending of text-to-speech messages. | |||
| /// </summary> | |||
| SendTTSMessages = 0x00_00_00_10_00, | |||
| SendTTSMessages = 0x00_00_00_10_00, | |||
| /// <summary> | |||
| /// Allows for deletion of other users messages. | |||
| /// </summary> | |||
| ManageMessages = 0x00_00_00_20_00, | |||
| ManageMessages = 0x00_00_00_20_00, | |||
| /// <summary> | |||
| /// Allows links sent by users with this permission will be auto-embedded. | |||
| /// </summary> | |||
| EmbedLinks = 0x00_00_00_40_00, | |||
| EmbedLinks = 0x00_00_00_40_00, | |||
| /// <summary> | |||
| /// Allows for uploading images and files. | |||
| /// </summary> | |||
| AttachFiles = 0x00_00_00_80_00, | |||
| AttachFiles = 0x00_00_00_80_00, | |||
| /// <summary> | |||
| /// Allows for reading of message history. | |||
| /// </summary> | |||
| ReadMessageHistory = 0x00_00_01_00_00, | |||
| ReadMessageHistory = 0x00_00_01_00_00, | |||
| /// <summary> | |||
| /// 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. | |||
| /// </summary> | |||
| MentionEveryone = 0x00_00_02_00_00, | |||
| MentionEveryone = 0x00_00_02_00_00, | |||
| /// <summary> | |||
| /// Allows the usage of custom emojis from other servers. | |||
| /// </summary> | |||
| UseExternalEmojis = 0x00_00_04_00_00, | |||
| UseExternalEmojis = 0x00_00_04_00_00, | |||
| // Voice | |||
| /// <summary> | |||
| /// Allows for joining of a voice channel. | |||
| /// </summary> | |||
| Connect = 0x00_00_10_00_00, | |||
| Connect = 0x00_00_10_00_00, | |||
| /// <summary> | |||
| /// Allows for speaking in a voice channel. | |||
| /// </summary> | |||
| Speak = 0x00_00_20_00_00, | |||
| Speak = 0x00_00_20_00_00, | |||
| /// <summary> | |||
| /// Allows for muting members in a voice channel. | |||
| /// </summary> | |||
| MuteMembers = 0x00_00_40_00_00, | |||
| MuteMembers = 0x00_00_40_00_00, | |||
| /// <summary> | |||
| /// Allows for deafening of members in a voice channel. | |||
| /// </summary> | |||
| DeafenMembers = 0x00_00_80_00_00, | |||
| DeafenMembers = 0x00_00_80_00_00, | |||
| /// <summary> | |||
| /// Allows for moving of members between voice channels. | |||
| /// </summary> | |||
| MoveMembers = 0x00_01_00_00_00, | |||
| MoveMembers = 0x00_01_00_00_00, | |||
| /// <summary> | |||
| /// Allows for using voice-activity-detection in a voice channel. | |||
| /// </summary> | |||
| UseVAD = 0x00_02_00_00_00, | |||
| UseVAD = 0x00_02_00_00_00, | |||
| /// <summary> | |||
| /// Allows for using priority speaker in a voice channel. | |||
| /// </summary> | |||
| PrioritySpeaker = 0x00_00_00_01_00, | |||
| PrioritySpeaker = 0x00_00_00_01_00, | |||
| /// <summary> | |||
| /// Allows video streaming in a voice channel. | |||
| /// </summary> | |||
| Stream = 0x00_00_00_02_00, | |||
| Stream = 0x00_00_00_02_00, | |||
| // More General | |||
| /// <summary> | |||
| /// Allows management and editing of roles. | |||
| /// </summary> | |||
| ManageRoles = 0x00_10_00_00_00, | |||
| ManageRoles = 0x00_10_00_00_00, | |||
| /// <summary> | |||
| /// Allows management and editing of webhooks. | |||
| /// </summary> | |||
| ManageWebhooks = 0x00_20_00_00_00, | |||
| ManageWebhooks = 0x00_20_00_00_00, | |||
| /// <summary> | |||
| /// Allows management and editing of emojis. | |||
| /// </summary> | |||
| ManageEmojis = 0x00_40_00_00_00, | |||
| ManageEmojis = 0x00_40_00_00_00, | |||
| /// <summary> | |||
| /// Allows members to use slash commands in text channels. | |||
| @@ -118,12 +118,12 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows for requesting to speak in stage channels. (This permission is under active development and may be changed or removed.) | |||
| /// </summary> | |||
| RequestToSpeak = 0x01_00_00_00_00, | |||
| RequestToSpeak = 0x01_00_00_00_00, | |||
| /// <summary> | |||
| /// Allows for deleting and archiving threads, and viewing all private threads | |||
| /// </summary> | |||
| ManageThreads = 0x04_00_00_00_00, | |||
| ManageThreads = 0x04_00_00_00_00, | |||
| /// <summary> | |||
| /// Allows for creating public threads. | |||
| @@ -10,7 +10,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows creation of instant invites. | |||
| /// </summary> | |||
| CreateInstantInvite = 0x00_00_00_01, | |||
| CreateInstantInvite = 0x00_00_00_01, | |||
| /// <summary> | |||
| /// Allows kicking members. | |||
| /// </summary> | |||
| @@ -18,7 +18,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| KickMembers = 0x00_00_00_02, | |||
| KickMembers = 0x00_00_00_02, | |||
| /// <summary> | |||
| /// Allows banning members. | |||
| /// </summary> | |||
| @@ -26,7 +26,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| BanMembers = 0x00_00_00_04, | |||
| BanMembers = 0x00_00_00_04, | |||
| /// <summary> | |||
| /// Allows all permissions and bypasses channel permission overwrites. | |||
| /// </summary> | |||
| @@ -34,7 +34,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| Administrator = 0x00_00_00_08, | |||
| Administrator = 0x00_00_00_08, | |||
| /// <summary> | |||
| /// Allows management and editing of channels. | |||
| /// </summary> | |||
| @@ -42,7 +42,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageChannels = 0x00_00_00_10, | |||
| ManageChannels = 0x00_00_00_10, | |||
| /// <summary> | |||
| /// Allows management and editing of the guild. | |||
| /// </summary> | |||
| @@ -50,33 +50,33 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageGuild = 0x00_00_00_20, | |||
| ManageGuild = 0x00_00_00_20, | |||
| /// <summary> | |||
| /// Allows for viewing of guild insights | |||
| /// </summary> | |||
| ViewGuildInsights = 0x00_08_00_00, | |||
| ViewGuildInsights = 0x00_08_00_00, | |||
| // 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> | |||
| /// Allows guild members to view a channel, which includes reading messages in text channels. | |||
| /// </summary> | |||
| ViewChannel = 0x00_00_04_00, | |||
| ViewChannel = 0x00_00_04_00, | |||
| /// <summary> | |||
| /// Allows for sending messages in a channel | |||
| /// </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> | |||
| /// Allows for deletion of other users messages. | |||
| /// </summary> | |||
| @@ -84,55 +84,55 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageMessages = 0x00_00_20_00, | |||
| ManageMessages = 0x00_00_20_00, | |||
| /// <summary> | |||
| /// Allows links sent by users with this permission will be auto-embedded. | |||
| /// </summary> | |||
| EmbedLinks = 0x00_00_40_00, | |||
| EmbedLinks = 0x00_00_40_00, | |||
| /// <summary> | |||
| /// Allows for uploading images and files. | |||
| /// </summary> | |||
| AttachFiles = 0x00_00_80_00, | |||
| AttachFiles = 0x00_00_80_00, | |||
| /// <summary> | |||
| /// Allows for reading of message history. | |||
| /// </summary> | |||
| ReadMessageHistory = 0x00_01_00_00, | |||
| ReadMessageHistory = 0x00_01_00_00, | |||
| /// <summary> | |||
| /// 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. | |||
| /// </summary> | |||
| MentionEveryone = 0x00_02_00_00, | |||
| MentionEveryone = 0x00_02_00_00, | |||
| /// <summary> | |||
| /// Allows the usage of custom emojis from other servers. | |||
| /// </summary> | |||
| UseExternalEmojis = 0x00_04_00_00, | |||
| UseExternalEmojis = 0x00_04_00_00, | |||
| // Voice | |||
| /// <summary> | |||
| /// Allows for joining of a voice channel. | |||
| /// </summary> | |||
| Connect = 0x00_10_00_00, | |||
| Connect = 0x00_10_00_00, | |||
| /// <summary> | |||
| /// Allows for speaking in a voice channel. | |||
| /// </summary> | |||
| Speak = 0x00_20_00_00, | |||
| Speak = 0x00_20_00_00, | |||
| /// <summary> | |||
| /// Allows for muting members in a voice channel. | |||
| /// </summary> | |||
| MuteMembers = 0x00_40_00_00, | |||
| MuteMembers = 0x00_40_00_00, | |||
| /// <summary> | |||
| /// Allows for deafening of members in a voice channel. | |||
| /// </summary> | |||
| DeafenMembers = 0x00_80_00_00, | |||
| DeafenMembers = 0x00_80_00_00, | |||
| /// <summary> | |||
| /// Allows for moving of members between voice channels. | |||
| /// </summary> | |||
| MoveMembers = 0x01_00_00_00, | |||
| MoveMembers = 0x01_00_00_00, | |||
| /// <summary> | |||
| /// Allows for using voice-activity-detection in a voice channel. | |||
| /// </summary> | |||
| UseVAD = 0x02_00_00_00, | |||
| UseVAD = 0x02_00_00_00, | |||
| /// <summary> | |||
| /// Allows for using priority speaker in a voice channel. | |||
| /// </summary> | |||
| @@ -140,17 +140,17 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows video streaming in a voice channel. | |||
| /// </summary> | |||
| Stream = 0x00_00_02_00, | |||
| Stream = 0x00_00_02_00, | |||
| // General 2 | |||
| /// <summary> | |||
| /// Allows for modification of own nickname. | |||
| /// </summary> | |||
| ChangeNickname = 0x04_00_00_00, | |||
| ChangeNickname = 0x04_00_00_00, | |||
| /// <summary> | |||
| /// Allows for modification of other users nicknames. | |||
| /// </summary> | |||
| ManageNicknames = 0x08_00_00_00, | |||
| ManageNicknames = 0x08_00_00_00, | |||
| /// <summary> | |||
| /// Allows management and editing of roles. | |||
| /// </summary> | |||
| @@ -158,7 +158,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageRoles = 0x10_00_00_00, | |||
| ManageRoles = 0x10_00_00_00, | |||
| /// <summary> | |||
| /// Allows management and editing of webhooks. | |||
| /// </summary> | |||
| @@ -166,7 +166,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageWebhooks = 0x20_00_00_00, | |||
| ManageWebhooks = 0x20_00_00_00, | |||
| /// <summary> | |||
| /// Allows management and editing of emojis and stickers. | |||
| /// </summary> | |||
| @@ -182,7 +182,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows for requesting to speak in stage channels. | |||
| /// </summary> | |||
| RequestToSpeak = 0x01_00_00_00_00, | |||
| RequestToSpeak = 0x01_00_00_00_00, | |||
| /// <summary> | |||
| /// Allows for creating, editing, and deleting guild scheduled events. | |||
| /// </summary> | |||
| @@ -194,7 +194,7 @@ namespace Discord | |||
| /// This permission requires the owner account to use two-factor | |||
| /// authentication when used on a guild that has server-wide 2FA enabled. | |||
| /// </remarks> | |||
| ManageThreads = 0x04_00_00_00_00, | |||
| ManageThreads = 0x04_00_00_00_00, | |||
| /// <summary> | |||
| /// Allows for creating public threads. | |||
| /// </summary> | |||
| @@ -206,7 +206,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Allows the usage of custom stickers from other servers. | |||
| /// </summary> | |||
| UseExternalStickers = 0x20_00_00_00_00, | |||
| UseExternalStickers = 0x20_00_00_00_00, | |||
| /// <summary> | |||
| /// Allows for sending messages in threads. | |||
| /// </summary> | |||
| @@ -281,7 +281,7 @@ namespace Discord | |||
| manageThreads: manageThreads, | |||
| createPublicThreads: createPublicThreads, | |||
| createPrivateThreads: createPrivateThreads, | |||
| useExternalStickers: useExternalStickers, | |||
| useExternalStickers: useExternalStickers, | |||
| sendMessagesInThreads: sendMessagesInThreads, | |||
| startEmbeddedActivities: startEmbeddedActivities, | |||
| moderateMembers: moderateMembers) | |||
| @@ -19,7 +19,7 @@ namespace Discord | |||
| /// Gets a <see cref="OverwritePermissions" /> that grants all permissions for the given channel. | |||
| /// </summary> | |||
| /// <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); | |||
| /// <summary> | |||
| /// 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, | |||
| PermValue? createInstantInvite = null, | |||
| PermValue? manageChannel = null, | |||
| PermValue? manageChannel = null, | |||
| PermValue? addReactions = null, | |||
| PermValue? viewChannel = null, | |||
| PermValue? sendMessages = null, | |||
| PermValue? sendTTSMessages = null, | |||
| PermValue? manageMessages = null, | |||
| PermValue? manageMessages = null, | |||
| PermValue? embedLinks = null, | |||
| PermValue? attachFiles = null, | |||
| PermValue? readMessageHistory = null, | |||
| PermValue? mentionEveryone = null, | |||
| PermValue? mentionEveryone = null, | |||
| PermValue? useExternalEmojis = null, | |||
| PermValue? connect = null, | |||
| PermValue? speak = null, | |||
| PermValue? muteMembers = null, | |||
| PermValue? muteMembers = null, | |||
| PermValue? deafenMembers = null, | |||
| PermValue? moveMembers = null, | |||
| PermValue? useVoiceActivation = null, | |||
| PermValue? manageRoles = null, | |||
| PermValue? manageRoles = null, | |||
| PermValue? manageWebhooks = null, | |||
| PermValue? prioritySpeaker = null, | |||
| PermValue? stream = null, | |||
| @@ -194,7 +194,7 @@ namespace Discord | |||
| PermValue viewChannel = PermValue.Inherit, | |||
| PermValue sendMessages = PermValue.Inherit, | |||
| PermValue sendTTSMessages = PermValue.Inherit, | |||
| PermValue manageMessages = PermValue.Inherit, | |||
| PermValue manageMessages = PermValue.Inherit, | |||
| PermValue embedLinks = PermValue.Inherit, | |||
| PermValue attachFiles = PermValue.Inherit, | |||
| PermValue readMessageHistory = PermValue.Inherit, | |||
| @@ -221,11 +221,12 @@ namespace Discord | |||
| PermValue useExternalStickers = PermValue.Inherit, | |||
| PermValue sendMessagesInThreads = 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, | |||
| requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | |||
| sendMessagesInThreads, startEmbeddedActivities) { } | |||
| sendMessagesInThreads, startEmbeddedActivities) | |||
| { } | |||
| /// <summary> | |||
| /// Initializes a new <see cref="OverwritePermissions" /> from the current one, changing the provided | |||
| @@ -238,11 +239,11 @@ namespace Discord | |||
| PermValue? viewChannel = null, | |||
| PermValue? sendMessages = null, | |||
| PermValue? sendTTSMessages = null, | |||
| PermValue? manageMessages = null, | |||
| PermValue? manageMessages = null, | |||
| PermValue? embedLinks = null, | |||
| PermValue? attachFiles = null, | |||
| PermValue? readMessageHistory = null, | |||
| PermValue? mentionEveryone = null, | |||
| PermValue? mentionEveryone = null, | |||
| PermValue? useExternalEmojis = null, | |||
| PermValue? connect = null, | |||
| PermValue? speak = null, | |||
| @@ -265,8 +266,8 @@ namespace Discord | |||
| PermValue? useExternalStickers = null, | |||
| PermValue? sendMessagesInThreads = 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, | |||
| requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, usePublicThreads, usePrivateThreads, useExternalStickers, | |||
| sendMessagesInThreads, startEmbeddedActivities); | |||
| @@ -305,7 +306,7 @@ namespace Discord | |||
| } | |||
| public override string ToString() => $"Allow {AllowValue}, Deny {DenyValue}"; | |||
| private string DebuggerDisplay => | |||
| private string DebuggerDisplay => | |||
| $"Allow {string.Join(", ", ToAllowList())}, " + | |||
| $"Deny {string.Join(", ", ToDenyList())}"; | |||
| } | |||
| @@ -21,5 +21,10 @@ namespace Discord | |||
| /// Gets the guild this thread was created in. | |||
| /// </summary> | |||
| IGuild Guild { get; } | |||
| /// <summary> | |||
| /// Gets the <see cref="IGuildUser"/> on the server this thread was created in. | |||
| /// </summary> | |||
| IGuildUser GuildUser { get; } | |||
| } | |||
| } | |||
| @@ -10,7 +10,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Gets the identifier of this user's avatar. | |||
| /// </summary> | |||
| string AvatarId { get; } | |||
| string AvatarId { get; } | |||
| /// <summary> | |||
| /// Gets the avatar URL for this user. | |||
| /// </summary> | |||
| @@ -29,7 +29,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Gets the channel for this webhook. | |||
| /// </summary> | |||
| ITextChannel Channel { get; } | |||
| IIntegrationChannel Channel { get; } | |||
| /// <summary> | |||
| /// Gets the ID of the channel for this webhook. | |||
| /// </summary> | |||
| @@ -1,4 +1,4 @@ | |||
| using System; | |||
| using System; | |||
| using System.Threading.Tasks; | |||
| namespace Discord | |||
| @@ -1,7 +1,7 @@ | |||
| using System; | |||
| using System.Threading.Tasks; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| @@ -80,7 +80,7 @@ namespace Discord | |||
| return result.ToString(); | |||
| } | |||
| /// <summary> | |||
| /// Formats a string as a block quote. | |||
| /// </summary> | |||
| @@ -34,7 +34,7 @@ namespace Discord.Logging | |||
| try | |||
| { | |||
| 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 | |||
| { | |||
| @@ -52,7 +52,7 @@ namespace Discord | |||
| Message = message; | |||
| Exception = exception; | |||
| } | |||
| public override string ToString() => ToString(); | |||
| 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 exMessage = fullException ? Exception?.ToString() : Exception?.Message; | |||
| int maxLength = 1 + | |||
| int maxLength = 1 + | |||
| (prependTimestamp ? 8 : 0) + 1 + | |||
| (padSource.HasValue ? padSource.Value : sourceName?.Length ?? 0) + 1 + | |||
| (padSource.HasValue ? padSource.Value : sourceName?.Length ?? 0) + 1 + | |||
| (message?.Length ?? 0) + | |||
| (exMessage?.Length ?? 0) + 3; | |||
| @@ -81,17 +81,8 @@ namespace Discord | |||
| now = DateTime.UtcNow; | |||
| else | |||
| now = DateTime.Now; | |||
| if (now.Hour < 10) | |||
| builder.Append('0'); | |||
| builder.Append(now.Hour); | |||
| builder.Append(':'); | |||
| if (now.Minute < 10) | |||
| builder.Append('0'); | |||
| builder.Append(now.Minute); | |||
| builder.Append(':'); | |||
| if (now.Second < 10) | |||
| builder.Append('0'); | |||
| builder.Append(now.Second); | |||
| string format = "HH:mm:ss"; | |||
| builder.Append(now.ToString(format)); | |||
| builder.Append(' '); | |||
| } | |||
| if (sourceName != null) | |||
| @@ -9,7 +9,7 @@ namespace Discord.Net | |||
| public ApplicationCommandException(HttpException httpError) | |||
| : base(httpError.HttpCode, httpError.Request, httpError.DiscordCode, httpError.Reason, httpError.Errors.ToArray()) | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -99,7 +99,7 @@ namespace Discord.Net | |||
| => Equals(obj as BucketId); | |||
| 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() | |||
| => GetBucketHash() ?? GetUniqueEndpoint(); | |||
| @@ -113,6 +113,6 @@ namespace Discord.Net | |||
| if (GetType() != other.GetType()) | |||
| return false; | |||
| return ToString() == other.ToString(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| namespace Discord.Net.Rest | |||
| namespace Discord.Net.Rest | |||
| { | |||
| public delegate IRestClient RestClientProvider(string baseUrl); | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| using System.Collections.Generic; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Net; | |||