| @@ -1,8 +1,10 @@ | |||||
| <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=Cacheable/@EntryIndexedValue">True</s:Boolean> | |||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=Downloader/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=Downloader/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=Emoji/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=Emoji/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=libsodium/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=libsodium/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=NSFW/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=NSFW/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=Ratelimit/@EntryIndexedValue">True</s:Boolean> | |||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=seeked/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=seeked/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=sharded/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=sharded/@EntryIndexedValue">True</s:Boolean> | ||||
| <s:Boolean x:Key="/Default/UserDictionary/Words/=Spotify/@EntryIndexedValue">True</s:Boolean> | <s:Boolean x:Key="/Default/UserDictionary/Words/=Spotify/@EntryIndexedValue">True</s:Boolean> | ||||
| @@ -66,7 +66,7 @@ namespace Discord.Commands | |||||
| if (isValid) | if (isValid) | ||||
| return Task.FromResult(PreconditionResult.FromSuccess()); | return Task.FromResult(PreconditionResult.FromSuccess()); | ||||
| else | else | ||||
| return Task.FromResult(PreconditionResult.FromError($"Invalid context for command; accepted contexts: {Contexts}")); | |||||
| return Task.FromResult(PreconditionResult.FromError($"Invalid context for command; accepted contexts: {Contexts}.")); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -6,6 +6,11 @@ namespace Discord.Commands | |||||
| /// <summary> | /// <summary> | ||||
| /// Requires the command to be invoked in a channel marked NSFW. | /// Requires the command to be invoked in a channel marked NSFW. | ||||
| /// </summary> | /// </summary> | ||||
| /// <remarks> | |||||
| /// The precondition will restrict the access of the command or module to be accessed within a guild channel | |||||
| /// that has been marked as mature or NSFW. If the channel is not of type <see cref="ITextChannel"/> or the | |||||
| /// channel is not marked as NSFW, the precondition will fail with an erroneous <see cref="PreconditionResult"/>. | |||||
| /// </remarks> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
| public class RequireNsfwAttribute : PreconditionAttribute | public class RequireNsfwAttribute : PreconditionAttribute | ||||
| { | { | ||||
| @@ -4,9 +4,17 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Requires the command to be invoked by the owner of the bot. | |||||
| /// Requires the command to be invoked by the owner of the bot. | |||||
| /// </summary> | /// </summary> | ||||
| /// <remarks>This precondition will only work if the bot is a bot account.</remarks> | |||||
| /// <remarks> | |||||
| /// This precondition will restrict the access of the command or module to the owner of the Discord application. | |||||
| /// If the precondition fails to be met, an erroneous <see cref="PreconditionResult"/> will be returned with the | |||||
| /// message "Command can only be run by the owner of the bot." | |||||
| /// <note> | |||||
| /// This precondition will only work if the account has a <see cref="TokenType"/> of <see cref="TokenType.Bot"/> | |||||
| /// ;otherwise, this precondition will always fail. | |||||
| /// </note> | |||||
| /// </remarks> | |||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
| public class RequireOwnerAttribute : PreconditionAttribute | public class RequireOwnerAttribute : PreconditionAttribute | ||||
| { | { | ||||
| @@ -4,7 +4,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Requires the user invoking the command to have a specified permission. | |||||
| /// Requires the user invoking the command to have a specified permission. | |||||
| /// </summary> | /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] | ||||
| public class RequireUserPermissionAttribute : PreconditionAttribute | public class RequireUserPermissionAttribute : PreconditionAttribute | ||||
| @@ -47,6 +47,13 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Creates a new invite to this channel. | /// Creates a new invite to this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <example> | |||||
| /// The following example creates a new invite to this channel; the invite lasts for 12 hours and can only | |||||
| /// be used 3 times throughout its lifespan. | |||||
| /// <code language="cs"> | |||||
| /// await guildChannel.CreateInviteAsync(maxAge: 43200, maxUses: 3); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <param name="maxAge">The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.</param> | /// <param name="maxAge">The time (in seconds) until the invite expires. Set to <c>null</c> to never expire.</param> | ||||
| /// <param name="maxUses">The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.</param> | /// <param name="maxUses">The max amount of times this invite may be used. Set to <c>null</c> to have unlimited uses.</param> | ||||
| /// <param name="isTemporary">If <c>true</c>, the user accepting this invite will be kicked from the guild after closing their client.</param> | /// <param name="isTemporary">If <c>true</c>, the user accepting this invite will be kicked from the guild after closing their client.</param> | ||||
| @@ -60,6 +67,15 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of all invites to this channel. | /// Gets a collection of all invites to this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <example> | |||||
| /// The following example gets all of the invites that have been created in this channel and selects the | |||||
| /// most used invite. | |||||
| /// <code language="cs"> | |||||
| /// var invites = await channel.GetInvitesAsync(); | |||||
| /// if (invites.Count == 0) return; | |||||
| /// var invite = invites.OrderByDescending(x => x.Uses).FirstOrDefault(); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | /// <returns> | ||||
| /// A task that represents the asynchronous get operation. The task result contains a read-only collection | /// A task that represents the asynchronous get operation. The task result contains a read-only collection | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -12,7 +12,7 @@ namespace Discord | |||||
| RetryTimeouts = 0x1, | RetryTimeouts = 0x1, | ||||
| // /// <summary> Retry if a request failed due to a network error. </summary> | // /// <summary> Retry if a request failed due to a network error. </summary> | ||||
| //RetryErrors = 0x2, | //RetryErrors = 0x2, | ||||
| /// <summary> Retry if a request failed due to a ratelimit. </summary> | |||||
| /// <summary> Retry if a request failed due to a rate-limit. </summary> | |||||
| RetryRatelimit = 0x4, | RetryRatelimit = 0x4, | ||||
| /// <summary> Retry if a request failed due to an HTTP error 502. </summary> | /// <summary> Retry if a request failed due to an HTTP error 502. </summary> | ||||
| Retry502 = 0x8, | Retry502 = 0x8, | ||||
| @@ -1,11 +1,10 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Provides a series of helper methods for handling Discord login tokens. | |||||
| /// </summary> | |||||
| public static class TokenUtils | public static class TokenUtils | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| @@ -20,6 +20,14 @@ namespace Discord.WebSocket | |||||
| Permissions.ResolveChannel(Guild, x, this, Permissions.ResolveGuild(Guild, x)), | Permissions.ResolveChannel(Guild, x, this, Permissions.ResolveGuild(Guild, x)), | ||||
| ChannelPermission.ViewChannel)).ToImmutableArray(); | ChannelPermission.ViewChannel)).ToImmutableArray(); | ||||
| /// <summary> | |||||
| /// Gets the child channels of this category. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A read-only collection of <see cref="SocketGuildChannel" /> whose | |||||
| /// <see cref="Discord.INestedChannel.CategoryId" /> matches the snowflake identifier of this category | |||||
| /// channel. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<SocketGuildChannel> Channels | public IReadOnlyCollection<SocketGuildChannel> Channels | ||||
| => Guild.Channels.Where(x => x is INestedChannel nestedChannel && nestedChannel.CategoryId == Id).ToImmutableArray(); | => Guild.Channels.Where(x => x is INestedChannel nestedChannel && nestedChannel.CategoryId == Id).ToImmutableArray(); | ||||
| @@ -35,6 +43,7 @@ namespace Discord.WebSocket | |||||
| } | } | ||||
| //Users | //Users | ||||
| /// <inheritdoc /> | |||||
| public override SocketGuildUser GetUser(ulong id) | public override SocketGuildUser GetUser(ulong id) | ||||
| { | { | ||||
| var user = Guild.GetUser(id); | var user = Guild.GetUser(id); | ||||
| @@ -52,8 +61,10 @@ namespace Discord.WebSocket | |||||
| internal new SocketCategoryChannel Clone() => MemberwiseClone() as SocketCategoryChannel; | internal new SocketCategoryChannel Clone() => MemberwiseClone() as SocketCategoryChannel; | ||||
| // IGuildChannel | // IGuildChannel | ||||
| /// <inheritdoc /> | |||||
| IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | ||||
| => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | ||||
| /// <inheritdoc /> | |||||
| Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | ||||
| => Task.FromResult<IGuildUser>(GetUser(id)); | => Task.FromResult<IGuildUser>(GetUser(id)); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -66,8 +77,10 @@ namespace Discord.WebSocket | |||||
| => throw new NotSupportedException(); | => throw new NotSupportedException(); | ||||
| //IChannel | //IChannel | ||||
| /// <inheritdoc /> | |||||
| IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | ||||
| => ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); | => ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); | ||||
| /// <inheritdoc /> | |||||
| Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | ||||
| => Task.FromResult<IUser>(GetUser(id)); | => Task.FromResult<IUser>(GetUser(id)); | ||||
| } | } | ||||
| @@ -119,8 +119,10 @@ namespace Discord.WebSocket | |||||
| public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) | public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) | ||||
| => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); | => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); | ||||
| /// <inheritdoc /> | |||||
| public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) | public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) | ||||
| => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); | => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); | ||||
| /// <inheritdoc /> | |||||
| public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) | public Task DeleteMessageAsync(IMessage message, RequestOptions options = null) | ||||
| => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); | => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); | ||||
| @@ -219,7 +219,6 @@ namespace Discord.WebSocket | |||||
| /// </returns> | /// </returns> | ||||
| public override string ToString() => Name; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => $"{Name} ({Id}, Guild)"; | private string DebuggerDisplay => $"{Name} ({Id}, Guild)"; | ||||
| /// <inheritdoc /> | |||||
| internal new SocketGuildChannel Clone() => MemberwiseClone() as SocketGuildChannel; | internal new SocketGuildChannel Clone() => MemberwiseClone() as SocketGuildChannel; | ||||
| //SocketChannel | //SocketChannel | ||||