diff --git a/docs/guides/getting_started/samples/first-bot/structure.cs b/docs/guides/getting_started/samples/first-bot/structure.cs index a9a018c3a..9ec1043c9 100644 --- a/docs/guides/getting_started/samples/first-bot/structure.cs +++ b/docs/guides/getting_started/samples/first-bot/structure.cs @@ -36,7 +36,7 @@ class Program // you must set the MessageCacheSize. You may adjust the number as needed. //MessageCacheSize = 50, - // If your platform doesn't have native websockets, + // If your platform doesn't have native WebSockets, // add Discord.Net.Providers.WS4Net from NuGet, // add the `using` at the top, and uncomment this line: //WebSocketProvider = WS4NetProvider.Instance diff --git a/experiment/Discord.Net.Rpc/DiscordRpcApiClient.cs b/experiment/Discord.Net.Rpc/DiscordRpcApiClient.cs index 50d467054..300784f4e 100644 --- a/experiment/Discord.Net.Rpc/DiscordRpcApiClient.cs +++ b/experiment/Discord.Net.Rpc/DiscordRpcApiClient.cs @@ -192,7 +192,7 @@ namespace Discord.API internal override async Task DisconnectInternalAsync() { if (_webSocketClient == null) - throw new NotSupportedException("This client is not configured with websocket support."); + throw new NotSupportedException("This client is not configured with WebSocket support."); if (ConnectionState == ConnectionState.Disconnected) return; ConnectionState = ConnectionState.Disconnecting; diff --git a/experiment/Discord.Net.Rpc/DiscordRpcConfig.cs b/experiment/Discord.Net.Rpc/DiscordRpcConfig.cs index fd6b74ff1..90df8d1a7 100644 --- a/experiment/Discord.Net.Rpc/DiscordRpcConfig.cs +++ b/experiment/Discord.Net.Rpc/DiscordRpcConfig.cs @@ -14,7 +14,7 @@ namespace Discord.Rpc /// Gets or sets the time, in milliseconds, to wait for a connection to complete before aborting. public int ConnectionTimeout { get; set; } = 30000; - /// Gets or sets the provider used to generate new websocket connections. + /// Gets or sets the provider used to generate new WebSocket connections. public WebSocketProvider WebSocketProvider { get; set; } public DiscordRpcConfig() @@ -24,7 +24,7 @@ namespace Discord.Rpc #else WebSocketProvider = () => { - throw new InvalidOperationException("The default websocket provider is not supported on this platform.\n" + + throw new InvalidOperationException("The default WebSocket provider is not supported on this platform.\n" + "You must specify a WebSocketProvider or target a runtime supporting .NET Standard 1.3, such as .NET Framework 4.6+."); }; #endif diff --git a/src/Discord.Net.Commands/Builders/CommandBuilder.cs b/src/Discord.Net.Commands/Builders/CommandBuilder.cs index 70045453f..7dcba8362 100644 --- a/src/Discord.Net.Commands/Builders/CommandBuilder.cs +++ b/src/Discord.Net.Commands/Builders/CommandBuilder.cs @@ -117,6 +117,7 @@ namespace Discord.Commands.Builders return this; } + /// Only the last parameter in a command may have the Remainder or Multiple flag. internal CommandInfo Build(ModuleInfo info, CommandService service) { //Default name to primary alias diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 57809d78b..a8ef5b62a 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -40,17 +40,17 @@ namespace Discord.Commands internal readonly LogManager _logManager; /// - /// Represents all modules loaded within . + /// Represents all modules loaded within . /// public IEnumerable Modules => _moduleDefs.Select(x => x); /// - /// Represents all commands loaded within . + /// Represents all commands loaded within . /// public IEnumerable Commands => _moduleDefs.SelectMany(x => x.Commands); /// - /// Represents all loaded within . + /// Represents all loaded within . /// public ILookup TypeReaders => _typeReaders.SelectMany(x => x.Value.Select(y => new { y.Key, y.Value })).ToLookup(x => x.Key, x => x.Value); @@ -122,12 +122,12 @@ namespace Discord.Commands } /// - /// Add a command module from a . + /// Add a command module from a . /// /// The type of module. /// /// The for your dependency injection solution, if using one - otherwise, pass - /// . + /// . /// /// /// A built module. @@ -135,12 +135,12 @@ namespace Discord.Commands public Task AddModuleAsync(IServiceProvider services) => AddModuleAsync(typeof(T), services); /// - /// Adds a command module from a . + /// Adds a command module from a . /// /// The type of module. /// /// The for your dependency injection solution, if using one - otherwise, pass - /// . + /// . /// /// /// A built module. @@ -174,12 +174,12 @@ namespace Discord.Commands } } /// - /// Add command modules from an . + /// Add command modules from an . /// /// The containing command modules. /// /// An for your dependency injection solution, if using one - otherwise, pass - /// . + /// . /// /// /// A collection of built modules. diff --git a/src/Discord.Net.Commands/Info/CommandInfo.cs b/src/Discord.Net.Commands/Info/CommandInfo.cs index de1462a3f..65581dcc3 100644 --- a/src/Discord.Net.Commands/Info/CommandInfo.cs +++ b/src/Discord.Net.Commands/Info/CommandInfo.cs @@ -16,7 +16,7 @@ namespace Discord.Commands /// /// /// This object contains the information of a command. This can include the module of the command, various - /// descriptions regarding the command, and its . + /// descriptions regarding the command, and its . /// [DebuggerDisplay("{Name,nq}")] public class CommandInfo diff --git a/src/Discord.Net.Commands/Map/CommandMapNode.cs b/src/Discord.Net.Commands/Map/CommandMapNode.cs index db69af415..4f798e718 100644 --- a/src/Discord.Net.Commands/Map/CommandMapNode.cs +++ b/src/Discord.Net.Commands/Map/CommandMapNode.cs @@ -23,6 +23,7 @@ namespace Discord.Commands _commands = ImmutableArray.Create(); } + /// Cannot add commands to the root node. public void AddCommand(CommandService service, string text, int index, CommandInfo command) { int nextSegment = NextSegment(text, index, service._separatorChar); diff --git a/src/Discord.Net.Commands/Readers/PrimitiveTypeReader.cs b/src/Discord.Net.Commands/Readers/PrimitiveTypeReader.cs index 011854a23..cb74139df 100644 --- a/src/Discord.Net.Commands/Readers/PrimitiveTypeReader.cs +++ b/src/Discord.Net.Commands/Readers/PrimitiveTypeReader.cs @@ -17,10 +17,12 @@ namespace Discord.Commands private readonly TryParseDelegate _tryParse; private readonly float _score; + /// must be within the range [0, 1]. public PrimitiveTypeReader() : this(PrimitiveParsers.Get(), 1) { } + /// must be within the range [0, 1]. public PrimitiveTypeReader(TryParseDelegate tryParse, float score) { if (score < 0 || score > 1) diff --git a/src/Discord.Net.Core/Audio/IAudioClient.cs b/src/Discord.Net.Core/Audio/IAudioClient.cs index 9be8ceef5..018c8bc05 100644 --- a/src/Discord.Net.Core/Audio/IAudioClient.cs +++ b/src/Discord.Net.Core/Audio/IAudioClient.cs @@ -15,7 +15,7 @@ namespace Discord.Audio /// Gets the current connection state of this client. ConnectionState ConnectionState { get; } - /// Gets the estimated round-trip latency, in milliseconds, to the voice websocket server. + /// Gets the estimated round-trip latency, in milliseconds, to the voice WebSocket server. int Latency { get; } /// Gets the estimated round-trip latency, in milliseconds, to the voice UDP server. int UdpLatency { get; } diff --git a/src/Discord.Net.Core/CDN.cs b/src/Discord.Net.Core/CDN.cs index 0c713f135..bd83b64e9 100644 --- a/src/Discord.Net.Core/CDN.cs +++ b/src/Discord.Net.Core/CDN.cs @@ -13,7 +13,7 @@ namespace Discord public static string GetApplicationIconUrl(ulong appId, string iconId) => iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null; /// - /// Returns the user avatar URL based on the and . + /// Returns the user avatar URL based on the and . /// public static string GetUserAvatarUrl(ulong userId, string avatarId, ushort size, ImageFormat format) { @@ -52,7 +52,7 @@ namespace Discord => $"{DiscordConfig.CDNUrl}emojis/{emojiId}.{(animated ? "gif" : "png")}"; /// - /// Returns the rich presence asset URL based on the asset ID and . + /// Returns the rich presence asset URL based on the asset ID and . /// public static string GetRichAssetUrl(ulong appId, string assetId, ushort size, ImageFormat format) { diff --git a/src/Discord.Net.Core/Commands/ICommandContext.cs b/src/Discord.Net.Core/Commands/ICommandContext.cs index 8b682ba1c..d56eb38a0 100644 --- a/src/Discord.Net.Core/Commands/ICommandContext.cs +++ b/src/Discord.Net.Core/Commands/ICommandContext.cs @@ -1,7 +1,7 @@ namespace Discord.Commands { /// - /// Represents the context of a command. This may include the client, guild, channel, user, and message. + /// Represents a context of a command. This may include the client, guild, channel, user, and message. /// public interface ICommandContext { diff --git a/src/Discord.Net.Core/Entities/Activities/Game.cs b/src/Discord.Net.Core/Entities/Activities/Game.cs index 471cc9f64..62b2853d5 100644 --- a/src/Discord.Net.Core/Entities/Activities/Game.cs +++ b/src/Discord.Net.Core/Entities/Activities/Game.cs @@ -18,7 +18,7 @@ namespace Discord /// Creates a with the provided and . /// /// The name of the game. - /// The type of activity. Default is . + /// The type of activity. Default is . public Game(string name, ActivityType type = ActivityType.Playing) { Name = name; diff --git a/src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs b/src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs index 02cb2547c..255279fa8 100644 --- a/src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs +++ b/src/Discord.Net.Core/Entities/Channels/ReorderChannelProperties.cs @@ -1,7 +1,7 @@ namespace Discord { /// - /// Properties that are used to reorder an . + /// Properties that are used to reorder an . /// public class ReorderChannelProperties { diff --git a/src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs b/src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs index 255bf0721..721345afe 100644 --- a/src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs +++ b/src/Discord.Net.Core/Entities/Emotes/EmoteProperties.cs @@ -8,11 +8,11 @@ namespace Discord public class EmoteProperties { /// - /// Gets or sets the name of the . + /// Gets or sets the name of the . /// public Optional Name { get; set; } /// - /// Gets or sets the roles that can access this . + /// Gets or sets the roles that can access this . /// public Optional> Roles { get; set; } } diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 664ac017d..057b94788 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace Discord { /// - /// Represents a generic guild object. + /// Represents a generic guild/server. /// public interface IGuild : IDeletable, ISnowflakeEntity { @@ -23,7 +23,7 @@ namespace Discord /// Determines if this guild is embeddable (i.e. can use widget). /// /// - /// Returns if this guild can be embedded via widgets. + /// if this guild can be embedded via widgets; otherwise . /// bool IsEmbeddable { get; } /// @@ -91,58 +91,91 @@ namespace Discord /// /// Gets the currently associated with this guild. /// + /// + /// currently associated with this guild. + /// IAudioClient AudioClient { get; } /// /// Gets the built-in role containing all users in this guild. /// + /// + /// Built-in role that represents an @everyone role in this guild. + /// IRole EveryoneRole { get; } /// /// Gets a collection of all custom emotes for this guild. /// + /// + /// A collection of all custom emotes for this guild. + /// IReadOnlyCollection Emotes { get; } /// /// Gets a collection of all extra features added to this guild. /// + /// + /// A collection of enabled features in this guild. + /// IReadOnlyCollection Features { get; } /// /// Gets a collection of all roles in this guild. /// + /// + /// A collection of roles found within this guild. + /// IReadOnlyCollection Roles { get; } /// /// Modifies this guild. /// - /// The properties to modify the guild with. + /// The delegate containing the properties to modify the guild with. /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task ModifyAsync(Action func, RequestOptions options = null); /// /// Modifies this guild's embed channel. /// - /// The properties to modify the guild widget with. + /// The delegate containing the properties to modify the guild widget with. /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task ModifyEmbedAsync(Action func, RequestOptions options = null); /// /// Bulk modifies the order of channels in this guild. /// - /// The properties to modify the channel positions with. + /// The properties used to modify the channel positions with. /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task ReorderChannelsAsync(IEnumerable args, RequestOptions options = null); /// /// Bulk modifies the order of roles in this guild. /// - /// The properties to modify the role positions with. + /// The properties used to modify the role positions with. /// The options to be used when sending the request. Task ReorderRolesAsync(IEnumerable args, RequestOptions options = null); + /// + /// An awaitable . + /// /// /// Leaves this guild. If you are the owner, use instead. /// /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task LeaveAsync(RequestOptions options = null); /// /// Gets a collection of all users banned on this guild. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of banned users with reasons. + /// Task> GetBansAsync(RequestOptions options = null); /// /// Bans the provided user from this guild and optionally prunes their recent messages. @@ -154,6 +187,9 @@ namespace Discord /// The reason of the ban to be written in the audit log. /// The options to be used when sending the request. /// is not between 0 to 7. + /// + /// An awaitable . + /// Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null); /// /// Bans the provided user ID from this guild and optionally prunes their recent messages. @@ -165,14 +201,27 @@ namespace Discord /// The reason of the ban to be written in the audit log. /// The options to be used when sending the request. /// is not between 0 to 7. + /// + /// An awaitable . + /// Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null); /// /// Unbans the provided user if they are currently banned. /// + /// The user to be unbanned. + /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task RemoveBanAsync(IUser user, RequestOptions options = null); /// /// Unbans the provided user ID if it is currently banned. /// + /// The snowflake ID of the user to be unbanned. + /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task RemoveBanAsync(ulong userId, RequestOptions options = null); /// @@ -182,15 +231,22 @@ namespace Discord /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of generic channels found within this guild. + /// Task> GetChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the channel in this guild with the provided ID, or if not found. + /// Gets the channel in this guild with the provided ID. /// /// The channel ID. /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the generic channel with the specified ID, or + /// if none is found. + /// Task GetChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets a collection of all text channels in this guild. @@ -199,6 +255,9 @@ namespace Discord /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of text channels found within this guild. + /// Task> GetTextChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets a text channel in this guild with the provided ID, or if not found. @@ -208,6 +267,10 @@ namespace Discord /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the text channel with the specified ID, or + /// if none is found. + /// Task GetTextChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets a collection of all voice channels in this guild. @@ -216,6 +279,9 @@ namespace Discord /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of voice channels found within this guild. + /// Task> GetVoiceChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets a collection of all category channels in this guild. @@ -224,68 +290,97 @@ namespace Discord /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of category channels found within this guild. + /// Task> GetCategoriesAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the voice channel in this guild with the provided ID, or if not found. + /// Gets the voice channel in this guild with the provided ID. /// /// The text channel ID. /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the voice channel with the specified ID, or + /// if none is found. + /// Task GetVoiceChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the voice AFK channel in this guild with the provided ID, or if not found. + /// Gets the AFK voice channel in this guild. /// /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the AFK voice channel set within this guild, or + /// if none is set. + /// Task GetAFKChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the default system text channel in this guild with the provided ID, or if - /// none is set. + /// Gets the default system text channel in this guild with the provided ID. /// /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the system channel within this guild, or + /// if none is set. + /// Task GetSystemChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the top viewable text channel in this guild with the provided ID, or if not - /// found. + /// Gets the top viewable text channel in this guild with the provided ID. /// /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the first viewable text channel in this guild, or + /// if none is found. + /// Task GetDefaultChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// - /// Gets the embed channel (i.e. the channel set in the guild's widget settings) in this guild, or - /// if none is set. + /// Gets the embed channel (i.e. the channel set in the guild's widget settings) in this guild. /// /// /// The that determines whether the object should be fetched from cache. /// /// The options to be used when sending the request. + /// + /// An awaitable containing the embed channel set within the server's widget settings, or + /// if none is set. + /// Task GetEmbedChannelAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Creates a new text channel. /// /// The new name for the text channel. /// The options to be used when sending the request. + /// + /// An awaitable containing the newly created text channel. + /// Task CreateTextChannelAsync(string name, RequestOptions options = null); /// /// Creates a new voice channel. /// /// The new name for the voice channel. /// The options to be used when sending the request. + /// + /// An awaitable containing the newly created voice channel. + /// Task CreateVoiceChannelAsync(string name, RequestOptions options = null); /// /// Creates a new channel category. /// /// The new name for the category. /// The options to be used when sending the request. + /// + /// An awaitable containing the newly created category channel. + /// Task CreateCategoryAsync(string name, RequestOptions options = null); Task> GetIntegrationsAsync(RequestOptions options = null); @@ -309,13 +404,24 @@ namespace Discord /// The color of the role. /// Whether the role is separated from others on the sidebar. /// The options to be used when sending the request. + /// + /// An awaitable containing the newly crated role. + /// Task CreateRoleAsync(string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false, RequestOptions options = null); /// /// Gets a collection of all users in this guild. /// - /// The that determines whether the object should be fetched from cache. + /// The that determines whether the object should be fetched from + /// cache. /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of users found within this guild. + /// + /// + /// This may return an incomplete list on the WebSocket implementation because Discord only sends offline + /// users on large guilds. + /// Task> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets the user in this guild with the provided ID, or if not found. @@ -323,22 +429,34 @@ namespace Discord /// The user ID. /// The that determines whether the object should be fetched from cache. /// The options to be used when sending the request. + /// + /// An awaitable containing the guild user with the specified ID, otherwise . + /// Task GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets the current user for this guild. /// /// The that determines whether the object should be fetched from cache. /// The options to be used when sending the request. + /// + /// An awaitable containing the currently logged-in user within this guild. + /// Task GetCurrentUserAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Gets the owner of this guild. /// /// The that determines whether the object should be fetched from cache. /// The options to be used when sending the request. + /// + /// An awaitable containing the owner of this guild. + /// Task GetOwnerAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); /// /// Downloads all users for this guild if the current list is incomplete. /// + /// + /// An awaitable . + /// Task DownloadUsersAsync(); /// /// Removes all users from this guild if they have not logged on in a provided number of @@ -349,7 +467,7 @@ namespace Discord /// Whether this prune action is a simulation. /// The options to be used when sending the request. /// - /// The number of users removed from this guild. + /// An awaitable containing the number of users to be or has been removed from this guild. /// Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); @@ -358,11 +476,17 @@ namespace Discord /// /// The webhook ID. /// The options to be used when sending the request. + /// + /// An awaitable containing the webhook with the specified ID, otherwise . + /// Task GetWebhookAsync(ulong id, RequestOptions options = null); /// /// Gets a collection of all webhook from this guild. /// /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of webhooks found within the guild. + /// Task> GetWebhooksAsync(RequestOptions options = null); /// @@ -370,6 +494,9 @@ namespace Discord /// /// The guild emote ID. /// The options to be used when sending the request. + /// + /// An awaitable containing the emote found with the specified ID, or if not found. + /// Task GetEmoteAsync(ulong id, RequestOptions options = null); /// /// Creates a new in this guild. @@ -378,20 +505,29 @@ namespace Discord /// The image of the new emote. /// The roles to limit the emote usage to. /// The options to be used when sending the request. + /// + /// An awaitable containing the created emote. + /// Task CreateEmoteAsync(string name, Image image, Optional> roles = default(Optional>), RequestOptions options = null); /// /// Modifies an existing in this guild. /// /// The emote to be modified. - /// The properties to modify the emote with. + /// The delegate containing the properties to modify the emote with. /// The options to be used when sending the request. + /// + /// An awaitable containing the newly modified emote. + /// Task ModifyEmoteAsync(GuildEmote emote, Action func, RequestOptions options = null); /// /// Deletes an existing from this guild. /// /// The emote to delete. /// The options to be used when sending the request. + /// + /// An awaitable . + /// Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null); } } diff --git a/src/Discord.Net.Core/Entities/IUpdateable.cs b/src/Discord.Net.Core/Entities/IUpdateable.cs index b4bbe169a..3ae4613f5 100644 --- a/src/Discord.Net.Core/Entities/IUpdateable.cs +++ b/src/Discord.Net.Core/Entities/IUpdateable.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; namespace Discord { /// - /// Represents whether the object is updatable or not. + /// Defines whether the object is updateable or not. /// public interface IUpdateable { diff --git a/src/Discord.Net.Core/Entities/Image.cs b/src/Discord.Net.Core/Entities/Image.cs index 921902f5d..dd77ec6ae 100644 --- a/src/Discord.Net.Core/Entities/Image.cs +++ b/src/Discord.Net.Core/Entities/Image.cs @@ -33,9 +33,9 @@ namespace Discord /// The path to the file. /// /// is a zero-length string, contains only white space, or contains one or more invalid - /// characters as defined by . + /// characters as defined by . /// - /// is . + /// is . /// /// The specified path, file name, or both exceed the system-defined maximum length. For example, on /// Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 diff --git a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs index 4568bd56c..087b30993 100644 --- a/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs +++ b/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs @@ -172,7 +172,7 @@ namespace Discord } /// - /// Sets the title of an . + /// Sets the title of an . /// /// The title to be set. /// diff --git a/src/Discord.Net.Core/Entities/Messages/EmbedField.cs b/src/Discord.Net.Core/Entities/Messages/EmbedField.cs index d7f37befa..3ae000022 100644 --- a/src/Discord.Net.Core/Entities/Messages/EmbedField.cs +++ b/src/Discord.Net.Core/Entities/Messages/EmbedField.cs @@ -3,7 +3,7 @@ using System.Diagnostics; namespace Discord { /// - /// Represents a field for an . + /// Represents a field for an . /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public struct EmbedField diff --git a/src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs b/src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs index 525c25562..4368f74a4 100644 --- a/src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs +++ b/src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs @@ -3,7 +3,7 @@ using System.Diagnostics; namespace Discord { /// - /// A video featured in an . + /// A video featured in an . /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public struct EmbedVideo diff --git a/src/Discord.Net.Core/Entities/Messages/IMessage.cs b/src/Discord.Net.Core/Entities/Messages/IMessage.cs index e390fa682..d66a6b883 100644 --- a/src/Discord.Net.Core/Entities/Messages/IMessage.cs +++ b/src/Discord.Net.Core/Entities/Messages/IMessage.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Discord { /// - /// Represents a Discord message object. + /// Represents a message object. /// public interface IMessage : ISnowflakeEntity, IDeletable { diff --git a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs index 9daec32d3..d52b309b5 100644 --- a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs +++ b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs @@ -4,20 +4,21 @@ namespace Discord /// Properties that are used to modify an with the specified changes. /// /// - /// The content of a message can be cleared with String.Empty; if and only if an Embed is present. + /// The content of a message can be cleared with if and only if an is present. /// /// /// - /// var message = await ReplyAsync("abc"); - /// await message.ModifyAsync(x => - /// { - /// x.Content = ""; - /// x.Embed = new EmbedBuilder() - /// .WithColor(new Color(40, 40, 120)) - /// .WithAuthor(a => a.Name = "foxbot") - /// .WithTitle("Embed!") - /// .WithDescription("This is an embed."); - /// }); + /// var message = await ReplyAsync("abc"); + /// await message.ModifyAsync(x => + /// { + /// x.Content = ""; + /// x.Embed = new EmbedBuilder() + /// .WithColor(new Color(40, 40, 120)) + /// .WithAuthor(a => a.Name = "foxbot") + /// .WithTitle("Embed!") + /// .WithDescription("This is an embed.") + /// .Build(); + /// }); /// /// public class MessageProperties @@ -26,7 +27,7 @@ namespace Discord /// Gets or sets the content of the message. /// /// - /// This must be less than 2000 characters. + /// This must be less than the constant defined by . /// public Optional Content { get; set; } /// diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index 58d25daac..99134bb90 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -19,7 +19,8 @@ namespace Discord public static readonly ChannelPermissions DM = new ChannelPermissions(0b00000_1000110_1011100110000_000000); /// Gets a that grants all permissions for group channels. public static readonly ChannelPermissions Group = new ChannelPermissions(0b00000_1000110_0001101100000_000000); - /// Gets a that grants all permissions for a given channelType. + /// Gets a that grants all permissions for a given channel type. + /// Unknown channel type. public static ChannelPermissions All(IChannel channel) { switch (channel) diff --git a/src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs b/src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs index fcfa08da5..e13083f1d 100644 --- a/src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs +++ b/src/Discord.Net.Core/Entities/Roles/ReorderRoleProperties.cs @@ -1,7 +1,7 @@ namespace Discord { /// - /// Properties that are used to reorder an . + /// Properties that are used to reorder an . /// public class ReorderRoleProperties { diff --git a/src/Discord.Net.Core/Entities/Roles/RoleProperties.cs b/src/Discord.Net.Core/Entities/Roles/RoleProperties.cs index 7769a2a04..79372b86d 100644 --- a/src/Discord.Net.Core/Entities/Roles/RoleProperties.cs +++ b/src/Discord.Net.Core/Entities/Roles/RoleProperties.cs @@ -23,7 +23,7 @@ namespace Discord /// public Optional Name { get; set; } /// - /// Gets or sets the role's . + /// Gets or sets the role's . /// public Optional Permissions { get; set; } /// diff --git a/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs b/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs index c731f1459..beb2c392f 100644 --- a/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs +++ b/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs @@ -7,10 +7,10 @@ namespace Discord /// /// /// - /// await (Context.User as IGuildUser)?.ModifyAsync(x => - /// { - /// x.Nickname = $"festive {Context.User.Username}"; - /// }); + /// await guildUser.ModifyAsync(x => + /// { + /// x.Nickname = $"festive {guildUser.Username}"; + /// }); /// /// /// @@ -35,7 +35,7 @@ namespace Discord /// /// /// To clear the user's nickname, this value can be set to or - /// . + /// . /// public Optional Nickname { get; set; } /// diff --git a/src/Discord.Net.Core/Entities/Webhooks/WebhookProperties.cs b/src/Discord.Net.Core/Entities/Webhooks/WebhookProperties.cs index 52adbe99a..387ee6106 100644 --- a/src/Discord.Net.Core/Entities/Webhooks/WebhookProperties.cs +++ b/src/Discord.Net.Core/Entities/Webhooks/WebhookProperties.cs @@ -27,14 +27,14 @@ namespace Discord /// Gets or sets the channel for this webhook. /// /// - /// This field is not used when authenticated with . + /// This field is not used when authenticated with . /// public Optional Channel { get; set; } /// /// Gets or sets the channel ID for this webhook. /// /// - /// This field is not used when authenticated with . + /// This field is not used when authenticated with . /// public Optional ChannelId { get; set; } } diff --git a/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs b/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs index 1fc11587e..233d1b0b0 100644 --- a/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs +++ b/src/Discord.Net.Core/Utils/ConcurrentHashSet.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -157,12 +157,16 @@ namespace Discord : this(collection, EqualityComparer.Default) { } public ConcurrentHashSet(IEqualityComparer comparer) : this(DefaultConcurrencyLevel, DefaultCapacity, true, comparer) { } + /// is public ConcurrentHashSet(IEnumerable collection, IEqualityComparer comparer) : this(comparer) { if (collection == null) throw new ArgumentNullException(nameof(collection)); InitializeFromCollection(collection); } + /// + /// or is + /// public ConcurrentHashSet(int concurrencyLevel, IEnumerable collection, IEqualityComparer comparer) : this(concurrencyLevel, DefaultCapacity, false, comparer) { @@ -197,7 +201,7 @@ namespace Discord { foreach (var value in collection) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(nameof(value)); if (!TryAddInternal(value, _comparer.GetHashCode(value), false)) throw new ArgumentException(); @@ -206,10 +210,10 @@ namespace Discord if (_budget == 0) _budget = _tables._buckets.Length / _tables._locks.Length; } - + /// is public bool ContainsKey(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(nameof(value)); return ContainsKeyInternal(value, _comparer.GetHashCode(value)); } private bool ContainsKeyInternal(T value, int hashcode) @@ -230,9 +234,10 @@ namespace Discord return false; } + /// is public bool TryAdd(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(nameof(value)); return TryAddInternal(value, _comparer.GetHashCode(value), true); } private bool TryAddInternal(T value, int hashcode, bool acquireLock) @@ -279,9 +284,10 @@ namespace Discord } } + /// is public bool TryRemove(T value) { - if (value == null) throw new ArgumentNullException("key"); + if (value == null) throw new ArgumentNullException(nameof(value)); return TryRemoveInternal(value); } private bool TryRemoveInternal(T value) @@ -467,4 +473,4 @@ namespace Discord Monitor.Exit(_tables._locks[i]); } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Core/Utils/Optional.cs b/src/Discord.Net.Core/Utils/Optional.cs index 9284645f5..348179699 100644 --- a/src/Discord.Net.Core/Utils/Optional.cs +++ b/src/Discord.Net.Core/Utils/Optional.cs @@ -11,6 +11,7 @@ namespace Discord private readonly T _value; /// Gets the value for this parameter. + /// This property has no value set. public T Value { get diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs index 1af6dc35d..569917312 100644 --- a/src/Discord.Net.Core/Utils/Preconditions.cs +++ b/src/Discord.Net.Core/Utils/Preconditions.cs @@ -183,7 +183,7 @@ namespace Discord } // Bulk Delete - /// Messages are younger than 2 weeks.. + /// Messages are younger than 2 weeks. public static void YoungerThanTwoWeeks(ulong[] collection, string name) { var minimum = SnowflakeUtils.ToSnowflake(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays(14))); @@ -194,7 +194,7 @@ namespace Discord throw new ArgumentOutOfRangeException(name, "Messages must be younger than two weeks old."); } } - /// The everyone role cannot be assigned to a user + /// The everyone role cannot be assigned to a user. public static void NotEveryoneRole(ulong[] roles, ulong guildId, string name) { for (var i = 0; i < roles.Length; i++) diff --git a/src/Discord.Net.Rest/ClientHelper.cs b/src/Discord.Net.Rest/ClientHelper.cs index 73e1a08f0..155430a7f 100644 --- a/src/Discord.Net.Rest/ClientHelper.cs +++ b/src/Discord.Net.Rest/ClientHelper.cs @@ -1,3 +1,4 @@ +using System; using Discord.API.Rest; using System.Collections.Generic; using System.Collections.Immutable; @@ -24,6 +25,7 @@ namespace Discord.Rest return RestChannel.Create(client, model); return null; } + /// Unexpected channel type. public static async Task> GetPrivateChannelsAsync(BaseDiscordClient client, RequestOptions options) { var models = await client.ApiClient.GetMyPrivateChannelsAsync(options).ConfigureAwait(false); diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index c8ff616e2..8ffe7dbf9 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -58,6 +58,9 @@ namespace Discord.API SetBaseUrl(DiscordConfig.APIUrl); } + + /// Unknown OAuth token type. + /// A delegate callback throws an exception. internal void SetBaseUrl(string baseUrl) { RestClient = _restClientProvider(baseUrl); @@ -65,6 +68,7 @@ namespace Discord.API RestClient.SetHeader("user-agent", UserAgent); RestClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, AuthToken)); } + /// Unknown OAuth token type. internal static string GetPrefixedToken(TokenType tokenType, string token) { switch (tokenType) @@ -76,7 +80,7 @@ namespace Discord.API case TokenType.Bearer: return $"Bearer {token}"; default: - throw new ArgumentException("Unknown OAuth token type", nameof(tokenType)); + throw new ArgumentException("Unknown OAuth token type.", nameof(tokenType)); } } internal virtual void Dispose(bool disposing) @@ -463,6 +467,7 @@ namespace Discord.API endpoint = () => $"channels/{channelId}/messages?limit={limit}"; return await SendAsync>("GET", endpoint, ids, options: options).ConfigureAwait(false); } + /// Message content is too long, length must be less or equal to . public async Task CreateMessageAsync(ulong channelId, CreateMessageParams args, RequestOptions options = null) { Preconditions.NotNull(args, nameof(args)); @@ -471,12 +476,14 @@ namespace Discord.API Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); if (args.Content?.Length > DiscordConfig.MaxMessageSize) - throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); + throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); options = RequestOptions.CreateOrClone(options); var ids = new BucketIds(channelId: channelId); return await SendJsonAsync("POST", () => $"channels/{channelId}/messages", args, ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false); } + /// Message content is too long, length must be less or equal to . + /// This operation may only be called with a token. public async Task CreateWebhookMessageAsync(ulong webhookId, CreateWebhookMessageParams args, RequestOptions options = null) { if (AuthTokenType != TokenType.Webhook) @@ -488,11 +495,12 @@ namespace Discord.API Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); if (args.Content?.Length > DiscordConfig.MaxMessageSize) - throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); + throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); options = RequestOptions.CreateOrClone(options); return await SendJsonAsync("POST", () => $"webhooks/{webhookId}/{AuthToken}?wait=true", args, new BucketIds(), clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false); } + /// Message content is too long, length must be less or equal to . public async Task UploadFileAsync(ulong channelId, UploadFileParams args, RequestOptions options = null) { Preconditions.NotNull(args, nameof(args)); @@ -507,6 +515,9 @@ namespace Discord.API var ids = new BucketIds(channelId: channelId); return await SendMultipartAsync("POST", () => $"channels/{channelId}/messages", args.ToDictionary(), ids, clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false); } + + /// Message content is too long, length must be less or equal to . + /// This operation may only be called with a token. public async Task UploadWebhookFileAsync(ulong webhookId, UploadWebhookFileParams args, RequestOptions options = null) { if (AuthTokenType != TokenType.Webhook) @@ -559,6 +570,7 @@ namespace Discord.API break; } } + /// Message content is too long, length must be less or equal to . public async Task ModifyMessageAsync(ulong channelId, ulong messageId, Rest.ModifyMessageParams args, RequestOptions options = null) { Preconditions.NotEqual(channelId, 0, nameof(channelId)); @@ -1267,6 +1279,7 @@ namespace Discord.API } //Helpers + /// Client is not logged in. protected void CheckState() { if (LoginState != LoginState.LoggedIn) diff --git a/src/Discord.Net.Rest/DiscordRestClient.cs b/src/Discord.Net.Rest/DiscordRestClient.cs index 471f8ee6c..6092e008c 100644 --- a/src/Discord.Net.Rest/DiscordRestClient.cs +++ b/src/Discord.Net.Rest/DiscordRestClient.cs @@ -22,12 +22,14 @@ namespace Discord.Rest ApiClient.Dispose(); } + /// internal override async Task OnLoginAsync(TokenType tokenType, string token) { var user = await ApiClient.GetMyUserAsync(new RequestOptions { RetryMode = RetryMode.AlwaysRetry }).ConfigureAwait(false); ApiClient.CurrentUserId = user.Id; base.CurrentUser = RestSelfUser.Create(this, user); } + /// internal override Task OnLogoutAsync() { _applicationInfo = null; @@ -80,9 +82,11 @@ namespace Discord.Rest => ClientHelper.GetWebhookAsync(this, id, options); //IDiscordClient + /// async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) => await GetApplicationInfoAsync(options).ConfigureAwait(false); + /// async Task IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -90,6 +94,7 @@ namespace Discord.Rest else return null; } + /// async Task> IDiscordClient.GetPrivateChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -97,6 +102,7 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task> IDiscordClient.GetDMChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -104,6 +110,7 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task> IDiscordClient.GetGroupChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -112,12 +119,15 @@ namespace Discord.Rest return ImmutableArray.Create(); } + /// async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync(options).ConfigureAwait(false); + /// async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) => await GetInviteAsync(inviteId, options).ConfigureAwait(false); + /// async Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -125,6 +135,7 @@ namespace Discord.Rest else return null; } + /// async Task> IDiscordClient.GetGuildsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -132,9 +143,11 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) => await CreateGuildAsync(name, region, jpegIcon, options).ConfigureAwait(false); + /// async Task IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -143,11 +156,14 @@ namespace Discord.Rest return null; } + /// async Task> IDiscordClient.GetVoiceRegionsAsync(RequestOptions options) => await GetVoiceRegionsAsync(options).ConfigureAwait(false); + /// async Task IDiscordClient.GetVoiceRegionAsync(string id, RequestOptions options) => await GetVoiceRegionAsync(id, options).ConfigureAwait(false); + /// async Task IDiscordClient.GetWebhookAsync(ulong id, RequestOptions options) => await GetWebhookAsync(id, options).ConfigureAwait(false); } diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index 7723861fa..65b0da6a8 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using Model = Discord.API.Channel; using UserModel = Discord.API.User; -using WebhookModel = Discord.API.Webhook; namespace Discord.Rest { @@ -77,14 +76,8 @@ namespace Discord.Rest int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) { var args = new CreateChannelInviteParams { IsTemporary = isTemporary, IsUnique = isUnique }; - if (maxAge.HasValue) - args.MaxAge = maxAge.Value; - else - args.MaxAge = 0; - if (maxUses.HasValue) - args.MaxUses = maxUses.Value; - else - args.MaxUses = 0; + args.MaxAge = maxAge.GetValueOrDefault(0); + args.MaxUses = maxUses.GetValueOrDefault(0); var model = await client.ApiClient.CreateChannelInviteAsync(channel.Id, args, options).ConfigureAwait(false); return RestInviteMetadata.Create(client, null, channel, model); } @@ -160,6 +153,7 @@ namespace Discord.Rest return builder.ToImmutable(); } + /// Message content is too long, length must be less or equal to . public static async Task SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, string text, bool isTTS, Embed embed, RequestOptions options) { @@ -169,6 +163,30 @@ namespace Discord.Rest } #if FILESYSTEM + /// + /// is a zero-length string, contains only white space, or contains one or more + /// invalid characters as defined by . + /// + /// + /// is . + /// + /// + /// The specified path, file name, or both exceed the system-defined maximum length. For example, on + /// Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 + /// characters. + /// + /// + /// The specified path is invalid, (for example, it is on an unmapped drive). + /// + /// + /// specified a directory.-or- The caller does not have the required permission. + /// + /// + /// The file specified in was not found. + /// + /// is in an invalid format. + /// An I/O error occurred while opening the file. + /// Message content is too long, length must be less or equal to . public static async Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client, string filePath, string text, bool isTTS, Embed embed, RequestOptions options) { @@ -177,6 +195,7 @@ namespace Discord.Rest return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, options).ConfigureAwait(false); } #endif + /// Message content is too long, length must be less or equal to . public static async Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client, Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) { @@ -249,6 +268,7 @@ namespace Discord.Rest return user; } + /// Resolving permissions requires the parent guild to be downloaded. public static IAsyncEnumerable> GetUsersAsync(IGuildChannel channel, IGuild guild, BaseDiscordClient client, ulong? fromUserId, int? limit, RequestOptions options) { diff --git a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs index 8668d890a..2895dc17d 100644 --- a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace Discord.Rest { /// - /// Represents a REST channel that can send and receive messages. + /// Represents a REST-based channel that can send and receive messages. /// public interface IRestMessageChannel : IMessageChannel { diff --git a/src/Discord.Net.Rest/Entities/Channels/IRestPrivateChannel.cs b/src/Discord.Net.Rest/Entities/Channels/IRestPrivateChannel.cs index 628dcb776..f387ac2d4 100644 --- a/src/Discord.Net.Rest/Entities/Channels/IRestPrivateChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/IRestPrivateChannel.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Discord.Rest { /// - /// Represents a REST channel that is private to select recipients. + /// Represents a REST-based channel that is private to select recipients. /// public interface IRestPrivateChannel : IPrivateChannel { diff --git a/src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs index c6cbeeecc..eb3fdd94b 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs @@ -7,7 +7,7 @@ using Model = Discord.API.Channel; namespace Discord.Rest { /// - /// Represents a REST category channel. + /// Represents a REST-based category channel. /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestCategoryChannel : RestGuildChannel, ICategoryChannel diff --git a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs index 04cc5a937..c6d765787 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -8,12 +8,14 @@ namespace Discord.Rest { public class RestChannel : RestEntity, IChannel, IUpdateable { + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); internal RestChannel(BaseDiscordClient discord, ulong id) : base(discord, id) { } + /// Unexpected channel type. internal static RestChannel Create(BaseDiscordClient discord, Model model) { switch (model.Type) @@ -28,6 +30,7 @@ namespace Discord.Rest return new RestChannel(discord, model.Id); } } + /// Unexpected channel type. internal static IRestPrivateChannel CreatePrivate(BaseDiscordClient discord, Model model) { switch (model.Type) @@ -42,13 +45,17 @@ namespace Discord.Rest } internal virtual void Update(Model model) { } + /// public virtual Task UpdateAsync(RequestOptions options = null) => Task.Delay(0); //IChannel + /// string IChannel.Name => null; + /// Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(null); //Overridden + /// IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) => AsyncEnumerable.Empty>(); //Overridden } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs index ca71e719b..a3161c72c 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs @@ -10,7 +10,7 @@ using Model = Discord.API.Channel; namespace Discord.Rest { /// - /// Represents a REST DM channel. + /// Represents a REST-based DM channel. /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel @@ -37,6 +37,7 @@ namespace Discord.Rest Recipient.Update(model.Recipients.Value[0]); } + /// public override async Task UpdateAsync(RequestOptions options = null) { var model = await Discord.ApiClient.GetChannelAsync(Id, options).ConfigureAwait(false); @@ -93,16 +94,20 @@ namespace Discord.Rest public override string ToString() => $"@{Recipient}"; private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)"; - //IDMChannel + //IDMChannel + /// IUser IDMChannel.Recipient => Recipient; //IRestPrivateChannel + /// IReadOnlyCollection IRestPrivateChannel.Recipients => ImmutableArray.Create(Recipient); //IPrivateChannel + /// IReadOnlyCollection IPrivateChannel.Recipients => ImmutableArray.Create(Recipient); //IMessageChannel + /// async Task IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -110,6 +115,7 @@ namespace Discord.Rest else return null; } + /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -117,6 +123,7 @@ namespace Discord.Rest else return AsyncEnumerable.Empty>(); } + /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -124,6 +131,7 @@ namespace Discord.Rest else return AsyncEnumerable.Empty>(); } + /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -131,25 +139,33 @@ namespace Discord.Rest else return AsyncEnumerable.Empty>(); } + /// async Task> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) => await GetPinnedMessagesAsync(options).ConfigureAwait(false); #if FILESYSTEM + /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); #endif + /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); + /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) => await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false); + /// IDisposable IMessageChannel.EnterTypingState(RequestOptions options) => EnterTypingState(options); //IChannel + /// string IChannel.Name => $"@{Recipient}"; + /// Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetUser(id)); + /// IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) => ImmutableArray.Create>(Users).ToAsyncEnumerable(); } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs index c8eeabf00..7c3cc53c9 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs @@ -146,6 +146,7 @@ namespace Discord.Rest public override string ToString() => Name; //IGuildChannel + /// IGuild IGuildChannel.Guild { get @@ -156,32 +157,44 @@ namespace Discord.Rest } } + /// async Task> IGuildChannel.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(options).ConfigureAwait(false); + /// async Task IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) => await CreateInviteAsync(maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); + /// OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IRole role) => GetPermissionOverwrite(role); + /// OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IUser user) => GetPermissionOverwrite(user); + /// async Task IGuildChannel.AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options) => await AddPermissionOverwriteAsync(role, permissions, options).ConfigureAwait(false); + /// async Task IGuildChannel.AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options) => await AddPermissionOverwriteAsync(user, permissions, options).ConfigureAwait(false); + /// async Task IGuildChannel.RemovePermissionOverwriteAsync(IRole role, RequestOptions options) => await RemovePermissionOverwriteAsync(role, options).ConfigureAwait(false); + /// async Task IGuildChannel.RemovePermissionOverwriteAsync(IUser user, RequestOptions options) => await RemovePermissionOverwriteAsync(user, options).ConfigureAwait(false); + /// IAsyncEnumerable> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) => AsyncEnumerable.Empty>(); //Overridden //Overridden in Text/Voice + /// Task IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(null); //Overridden in Text/Voice //IChannel + /// IAsyncEnumerable> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) => AsyncEnumerable.Empty>(); //Overridden in Text/Voice + /// Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(null); //Overridden in Text/Voice } diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 38c5fe9e2..b279f06a3 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -1,4 +1,4 @@ -using Discord.API.Rest; +using Discord.API.Rest; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -14,10 +14,11 @@ namespace Discord.Rest internal static class GuildHelper { //General + /// is . public static async Task ModifyAsync(IGuild guild, BaseDiscordClient client, Action func, RequestOptions options) { - if (func == null) throw new NullReferenceException(nameof(func)); + if (func == null) throw new ArgumentNullException(nameof(func)); var args = new GuildProperties(); func(args); @@ -62,10 +63,11 @@ namespace Discord.Rest return await client.ApiClient.ModifyGuildAsync(guild.Id, apiArgs, options).ConfigureAwait(false); } + /// is . public static async Task ModifyEmbedAsync(IGuild guild, BaseDiscordClient client, Action func, RequestOptions options) { - if (func == null) throw new NullReferenceException(nameof(func)); + if (func == null) throw new ArgumentNullException(nameof(func)); var args = new GuildEmbedProperties(); func(args); @@ -139,6 +141,7 @@ namespace Discord.Rest var models = await client.ApiClient.GetGuildChannelsAsync(guild.Id, options).ConfigureAwait(false); return models.Select(x => RestGuildChannel.Create(client, guild, x)).ToImmutableArray(); } + /// is . public static async Task CreateTextChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options) { @@ -148,6 +151,7 @@ namespace Discord.Rest var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); return RestTextChannel.Create(client, guild, model); } + /// is . public static async Task CreateVoiceChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options) { @@ -157,6 +161,7 @@ namespace Discord.Rest var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); return RestVoiceChannel.Create(client, guild, model); } + /// is . public static async Task CreateCategoryChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options) { @@ -191,6 +196,7 @@ namespace Discord.Rest } //Roles + /// is . public static async Task CreateRoleAsync(IGuild guild, BaseDiscordClient client, string name, GuildPermissions? permissions, Color? color, bool isHoisted, RequestOptions options) { @@ -292,11 +298,12 @@ namespace Discord.Rest Image = image.ToModel() }; if (roles.IsSpecified) - apiargs.RoleIds = roles.Value?.Select(xr => xr.Id)?.ToArray(); + apiargs.RoleIds = roles.Value?.Select(xr => xr.Id).ToArray(); var emote = await client.ApiClient.CreateGuildEmoteAsync(guild.Id, apiargs, options).ConfigureAwait(false); return emote.ToEntity(); } + /// is . public static async Task ModifyEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, Action func, RequestOptions options) { @@ -310,7 +317,7 @@ namespace Discord.Rest Name = props.Name }; if (props.Roles.IsSpecified) - apiargs.RoleIds = props.Roles.Value?.Select(xr => xr.Id)?.ToArray(); + apiargs.RoleIds = props.Roles.Value?.Select(xr => xr.Id).ToArray(); var emote = await client.ApiClient.ModifyGuildEmoteAsync(guild.Id, id, apiargs, options).ConfigureAwait(false); return emote.ToEntity(); diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestBan.cs b/src/Discord.Net.Rest/Entities/Guilds/RestBan.cs index 104bec903..2c65c8b59 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestBan.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestBan.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Model = Discord.API.Ban; namespace Discord.Rest @@ -7,6 +7,7 @@ namespace Discord.Rest public class RestBan : IBan { public RestUser User { get; } + /// public string Reason { get; } internal RestBan(RestUser user, string reason) @@ -23,6 +24,7 @@ namespace Discord.Rest private string DebuggerDisplay => $"{User}: {Reason}"; //IBan + /// IUser IBan.User => User; } } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index fc5ef307f..5a79565ba 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -10,6 +10,9 @@ using Model = Discord.API.Guild; namespace Discord.Rest { + /// + /// Represents a REST-based guild/server. + /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestGuild : RestEntity, IGuild, IUpdateable { @@ -17,32 +20,50 @@ namespace Discord.Rest private ImmutableArray _emotes; private ImmutableArray _features; + /// public string Name { get; private set; } + /// public int AFKTimeout { get; private set; } + /// public bool IsEmbeddable { get; private set; } + /// public VerificationLevel VerificationLevel { get; private set; } + /// public MfaLevel MfaLevel { get; private set; } + /// public DefaultMessageNotifications DefaultMessageNotifications { get; private set; } + /// public ulong? AFKChannelId { get; private set; } + /// public ulong? EmbedChannelId { get; private set; } + /// public ulong? SystemChannelId { get; private set; } + /// public ulong OwnerId { get; private set; } + /// public string VoiceRegionId { get; private set; } + /// public string IconId { get; private set; } + /// public string SplashId { get; private set; } internal bool Available { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); [Obsolete("DefaultChannelId is deprecated, use GetDefaultChannelAsync")] public ulong DefaultChannelId => Id; + /// public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); + /// public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); public RestRole EveryoneRole => GetRole(Id); public IReadOnlyCollection Roles => _roles.ToReadOnlyCollection(); + /// public IReadOnlyCollection Emotes => _emotes; + /// public IReadOnlyCollection Features => _features; internal RestGuild(BaseDiscordClient client, ulong id) @@ -103,37 +124,48 @@ namespace Discord.Rest } //General + /// public async Task UpdateAsync(RequestOptions options = null) => Update(await Discord.ApiClient.GetGuildAsync(Id, options).ConfigureAwait(false)); + /// public Task DeleteAsync(RequestOptions options = null) => GuildHelper.DeleteAsync(this, Discord, options); + /// + /// is . public async Task ModifyAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } + + /// + /// is . public async Task ModifyEmbedAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyEmbedAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } + + /// + /// is . public async Task ReorderChannelsAsync(IEnumerable args, RequestOptions options = null) { var arr = args.ToArray(); await GuildHelper.ReorderChannelsAsync(this, Discord, arr, options).ConfigureAwait(false); } + /// public async Task ReorderRolesAsync(IEnumerable args, RequestOptions options = null) { var models = await GuildHelper.ReorderRolesAsync(this, Discord, args, options).ConfigureAwait(false); foreach (var model in models) { var role = GetRole(model.Id); - if (role != null) - role.Update(model); + role?.Update(model); } } - + + /// public Task LeaveAsync(RequestOptions options = null) => GuildHelper.LeaveAsync(this, Discord, options); @@ -141,13 +173,17 @@ namespace Discord.Rest public Task> GetBansAsync(RequestOptions options = null) => GuildHelper.GetBansAsync(this, Discord, options); + /// public Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, reason, options); + /// public Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, reason, options); + /// public Task RemoveBanAsync(IUser user, RequestOptions options = null) => GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); + /// public Task RemoveBanAsync(ulong userId, RequestOptions options = null) => GuildHelper.RemoveBanAsync(this, Discord, userId, options); @@ -261,6 +297,7 @@ namespace Discord.Rest public Task GetOwnerAsync(RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, OwnerId, options); + /// public Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null) => GuildHelper.PruneUsersAsync(this, Discord, days, simulate, options); @@ -270,28 +307,45 @@ namespace Discord.Rest public Task> GetWebhooksAsync(RequestOptions options = null) => GuildHelper.GetWebhooksAsync(this, Discord, options); + /// + /// Returns the name of the guild. + /// + /// + /// The name of the guild. + /// public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id})"; //Emotes + /// public Task GetEmoteAsync(ulong id, RequestOptions options = null) => GuildHelper.GetEmoteAsync(this, Discord, id, options); + /// public Task CreateEmoteAsync(string name, Image image, Optional> roles = default(Optional>), RequestOptions options = null) => GuildHelper.CreateEmoteAsync(this, Discord, name, image, roles, options); + /// + /// is . public Task ModifyEmoteAsync(GuildEmote emote, Action func, RequestOptions options = null) => GuildHelper.ModifyEmoteAsync(this, Discord, emote.Id, func, options); + /// public Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null) => GuildHelper.DeleteEmoteAsync(this, Discord, emote.Id, options); //IGuild + /// bool IGuild.Available => Available; + /// IAudioClient IGuild.AudioClient => null; + /// IRole IGuild.EveryoneRole => EveryoneRole; + /// IReadOnlyCollection IGuild.Roles => Roles; + /// async Task> IGuild.GetBansAsync(RequestOptions options) => await GetBansAsync(options).ConfigureAwait(false); + /// async Task> IGuild.GetChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -299,6 +353,7 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task IGuild.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -306,6 +361,7 @@ namespace Discord.Rest else return null; } + /// async Task> IGuild.GetTextChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -313,6 +369,7 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task IGuild.GetTextChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -320,6 +377,7 @@ namespace Discord.Rest else return null; } + /// async Task> IGuild.GetVoiceChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -327,6 +385,7 @@ namespace Discord.Rest else return ImmutableArray.Create(); } + /// async Task> IGuild.GetCategoriesAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -334,6 +393,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetVoiceChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -341,6 +401,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetAFKChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -348,6 +409,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetDefaultChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -355,6 +417,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetEmbedChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -362,6 +425,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetSystemChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -369,26 +433,35 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.CreateTextChannelAsync(string name, RequestOptions options) => await CreateTextChannelAsync(name, options).ConfigureAwait(false); + /// async Task IGuild.CreateVoiceChannelAsync(string name, RequestOptions options) => await CreateVoiceChannelAsync(name, options).ConfigureAwait(false); + /// async Task IGuild.CreateCategoryAsync(string name, RequestOptions options) => await CreateCategoryChannelAsync(name, options).ConfigureAwait(false); + /// async Task> IGuild.GetIntegrationsAsync(RequestOptions options) => await GetIntegrationsAsync(options).ConfigureAwait(false); + /// async Task IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options) => await CreateIntegrationAsync(id, type, options).ConfigureAwait(false); + /// async Task> IGuild.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(options).ConfigureAwait(false); + /// IRole IGuild.GetRole(ulong id) => GetRole(id); + /// async Task IGuild.CreateRoleAsync(string name, GuildPermissions? permissions, Color? color, bool isHoisted, RequestOptions options) => await CreateRoleAsync(name, permissions, color, isHoisted, options).ConfigureAwait(false); + /// async Task IGuild.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -396,6 +469,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetCurrentUserAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -403,6 +477,7 @@ namespace Discord.Rest else return null; } + /// async Task IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -410,6 +485,7 @@ namespace Discord.Rest else return null; } + /// async Task> IGuild.GetUsersAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) @@ -418,12 +494,14 @@ namespace Discord.Rest return ImmutableArray.Create(); } /// - /// Downloading users is not supported with a REST-based guild. + /// Downloading users is not supported for a REST-based guild. Task IGuild.DownloadUsersAsync() => throw new NotSupportedException(); + /// async Task IGuild.GetWebhookAsync(ulong id, RequestOptions options) => await GetWebhookAsync(id, options).ConfigureAwait(false); + /// async Task> IGuild.GetWebhooksAsync(RequestOptions options) => await GetWebhooksAsync(options).ConfigureAwait(false); } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs index f26a62d8d..00f3fae69 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Model = Discord.API.GuildEmbed; namespace Discord @@ -19,7 +19,7 @@ namespace Discord return new RestGuildEmbed(model.Enabled, model.ChannelId); } - public override string ToString() => ChannelId?.ToString(); + public override string ToString() => ChannelId?.ToString() ?? "Unknown"; private string DebuggerDisplay => $"{ChannelId} ({(IsEnabled ? "Enabled" : "Disabled")})"; } } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs index eadda53f2..9759e64d2 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.Integration; @@ -10,18 +10,28 @@ namespace Discord.Rest { private long _syncedAtTicks; + /// public string Name { get; private set; } + /// public string Type { get; private set; } + /// public bool IsEnabled { get; private set; } + /// public bool IsSyncing { get; private set; } + /// public ulong ExpireBehavior { get; private set; } + /// public ulong ExpireGracePeriod { get; private set; } + /// public ulong GuildId { get; private set; } + /// public ulong RoleId { get; private set; } public RestUser User { get; private set; } + /// public IntegrationAccount Account { get; private set; } internal IGuild Guild { get; private set; } + /// public DateTimeOffset SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks); internal RestGuildIntegration(BaseDiscordClient discord, IGuild guild, ulong id) @@ -78,6 +88,7 @@ namespace Discord.Rest public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id}{(IsEnabled ? ", Enabled" : "")})"; + /// IGuild IGuildIntegration.Guild { get @@ -87,6 +98,7 @@ namespace Discord.Rest throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object."); } } + /// IUser IGuildIntegration.User => User; } } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs index de5a5f7d9..b75d6288e 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs @@ -9,12 +9,17 @@ namespace Discord.Rest public class RestUserGuild : RestEntity, IUserGuild { private string _iconId; - + + /// public string Name { get; private set; } + /// public bool IsOwner { get; private set; } + /// public GuildPermissions Permissions { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + /// public string IconUrl => CDN.GetGuildIconUrl(Id, _iconId); internal RestUserGuild(BaseDiscordClient discord, ulong id) @@ -40,6 +45,7 @@ namespace Discord.Rest { await Discord.ApiClient.LeaveGuildAsync(Id, options).ConfigureAwait(false); } + /// public async Task DeleteAsync(RequestOptions options = null) { await Discord.ApiClient.DeleteGuildAsync(Id, options).ConfigureAwait(false); diff --git a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs index 6df97f6f7..62fdaeaba 100644 --- a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs +++ b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs @@ -59,7 +59,8 @@ namespace Discord.Rest public override string ToString() => Url; private string DebuggerDisplay => $"{Url} ({GuildName} / {ChannelName})"; - + + /// IGuild IInvite.Guild { get @@ -71,6 +72,7 @@ namespace Discord.Rest throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object."); } } + /// IChannel IInvite.Channel { get diff --git a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs index 071628da0..34e64cd5a 100644 --- a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs +++ b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs @@ -10,11 +10,13 @@ namespace Discord.Rest { internal static class MessageHelper { + /// Only the author of a message may modify the message. + /// Message content is too long, length must be less or equal to . public static async Task ModifyAsync(IMessage msg, BaseDiscordClient client, Action func, RequestOptions options) { if (msg.Author.Id != client.CurrentUser.Id) - throw new InvalidOperationException("Only the author of a message may change it."); + throw new InvalidOperationException("Only the author of a message may modify the message."); var args = new MessageProperties(); func(args); diff --git a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs index 84fef4c18..6d18beaad 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs @@ -35,6 +35,7 @@ namespace Discord.Rest /// public virtual IReadOnlyCollection MentionedRoleIds => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedUsers => ImmutableArray.Create(); + /// public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); /// @@ -75,10 +76,14 @@ namespace Discord.Rest public override string ToString() => Content; + /// MessageType IMessage.Type => MessageType.Default; IUser IMessage.Author => Author; + /// IReadOnlyCollection IMessage.Attachments => Attachments; + /// IReadOnlyCollection IMessage.Embeds => Embeds; + /// IReadOnlyCollection IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); } } diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs index 0d1f3be2b..de295af94 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs @@ -17,23 +17,33 @@ namespace Discord.Rest private ImmutableArray _embeds; private ImmutableArray _tags; private ImmutableArray _reactions; - + + /// public override bool IsTTS => _isTTS; + /// public override bool IsPinned => _isPinned; + /// public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks); + /// public override IReadOnlyCollection Attachments => _attachments; + /// public override IReadOnlyCollection Embeds => _embeds; + /// public override IReadOnlyCollection MentionedChannelIds => MessageHelper.FilterTagsByKey(TagType.ChannelMention, _tags); + /// public override IReadOnlyCollection MentionedRoleIds => MessageHelper.FilterTagsByKey(TagType.RoleMention, _tags); + /// public override IReadOnlyCollection MentionedUsers => MessageHelper.FilterTagsByValue(TagType.UserMention, _tags); + /// public override IReadOnlyCollection Tags => _tags; + /// public IReadOnlyDictionary Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) : base(discord, id, channel, author, source) { } - internal static new RestUserMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model) + internal new static RestUserMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model) { var entity = new RestUserMessage(discord, model.Id, channel, author, MessageHelper.GetSource(model)); entity.Update(model); @@ -124,30 +134,37 @@ namespace Discord.Rest } } + /// public async Task ModifyAsync(Action func, RequestOptions options = null) { var model = await MessageHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } + /// public Task AddReactionAsync(IEmote emote, RequestOptions options = null) => MessageHelper.AddReactionAsync(this, emote, Discord, options); + /// public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null) => MessageHelper.RemoveReactionAsync(this, user, emote, Discord, options); + /// public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); + /// public Task> GetReactionUsersAsync(IEmote emote, int limit = 100, ulong? afterUserId = null, RequestOptions options = null) => MessageHelper.GetReactionUsersAsync(this, emote, x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create(); }, Discord, options); - - + + /// public Task PinAsync(RequestOptions options = null) => MessageHelper.PinAsync(this, Discord, options); + /// public Task UnpinAsync(RequestOptions options = null) => MessageHelper.UnpinAsync(this, Discord, options); public string Resolve(int startIndex, TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) => MentionUtils.Resolve(this, startIndex, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); + /// public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); diff --git a/src/Discord.Net.Rest/Entities/RestApplication.cs b/src/Discord.Net.Rest/Entities/RestApplication.cs index d8986a470..198ce1a61 100644 --- a/src/Discord.Net.Rest/Entities/RestApplication.cs +++ b/src/Discord.Net.Rest/Entities/RestApplication.cs @@ -19,6 +19,7 @@ namespace Discord.Rest public string Description { get; private set; } /// public string[] RPCOrigins { get; private set; } + /// public ulong Flags { get; private set; } /// @@ -52,6 +53,7 @@ namespace Discord.Rest Owner = RestUser.Create(Discord, model.Owner.Value); } + /// Unable to update this object from a different application token. public async Task UpdateAsync() { var response = await Discord.ApiClient.GetMyApplicationAsync().ConfigureAwait(false); @@ -60,6 +62,12 @@ namespace Discord.Rest Update(response); } + /// + /// Gets the name of the application. + /// + /// + /// Name of the application. + /// public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id})"; } diff --git a/src/Discord.Net.Rest/Entities/Roles/RestRole.cs b/src/Discord.Net.Rest/Entities/Roles/RestRole.cs index 486f41b9e..5ea7f4462 100644 --- a/src/Discord.Net.Rest/Entities/Roles/RestRole.cs +++ b/src/Discord.Net.Rest/Entities/Roles/RestRole.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.Role; @@ -9,16 +9,25 @@ namespace Discord.Rest public class RestRole : RestEntity, IRole { internal IGuild Guild { get; } + /// public Color Color { get; private set; } + /// public bool IsHoisted { get; private set; } + /// public bool IsManaged { get; private set; } + /// public bool IsMentionable { get; private set; } + /// public string Name { get; private set; } + /// public GuildPermissions Permissions { get; private set; } + /// public int Position { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); public bool IsEveryone => Id == Guild.Id; + /// public string Mention => IsEveryone ? "@everyone" : MentionUtils.MentionRole(Id); internal RestRole(BaseDiscordClient discord, IGuild guild, ulong id) @@ -43,20 +52,24 @@ namespace Discord.Rest Permissions = new GuildPermissions(model.Permissions); } + /// public async Task ModifyAsync(Action func, RequestOptions options = null) { var model = await RoleHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } + /// public Task DeleteAsync(RequestOptions options = null) => RoleHelper.DeleteAsync(this, Discord, options); + /// public int CompareTo(IRole role) => RoleUtils.Compare(this, role); public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id})"; //IRole + /// IGuild IRole.Guild { get diff --git a/src/Discord.Net.Rest/Entities/Users/RestConnection.cs b/src/Discord.Net.Rest/Entities/Users/RestConnection.cs index b8b83be3e..0c91493d2 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestConnection.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestConnection.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using Model = Discord.API.Connection; @@ -8,10 +8,15 @@ namespace Discord [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestConnection : IConnection { + /// public string Id { get; } + /// public string Type { get; } + /// public string Name { get; } + /// public bool IsRevoked { get; } + /// public IReadOnlyCollection IntegrationIds { get; } internal RestConnection(string id, string type, string name, bool isRevoked, IReadOnlyCollection integrationIds) @@ -28,6 +33,12 @@ namespace Discord return new RestConnection(model.Id, model.Type, model.Name, model.Revoked, model.Integrations.ToImmutableArray()); } + /// + /// Gets the name of the connection. + /// + /// + /// Name of the connection. + /// public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id}, {Type}{(IsRevoked ? ", Revoked" : "")})"; } diff --git a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs index 051ed73d5..fdfe9b5a1 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs @@ -24,7 +24,9 @@ namespace Discord.Rest /// public ulong GuildId => Guild.Id; + /// + /// Resolving permissions requires the parent guild to be downloaded. public GuildPermissions GuildPermissions { get @@ -112,6 +114,7 @@ namespace Discord.Rest => UserHelper.RemoveRolesAsync(this, Discord, roles, options); /// + /// Resolving permissions requires the parent guild to be downloaded. public ChannelPermissions GetPermissions(IGuildChannel channel) { var guildPerms = GuildPermissions; @@ -119,6 +122,7 @@ namespace Discord.Rest } //IGuildUser + /// IGuild IGuildUser.Guild { get @@ -130,10 +134,15 @@ namespace Discord.Rest } //IVoiceState + /// bool IVoiceState.IsSelfDeafened => false; + /// bool IVoiceState.IsSelfMuted => false; + /// bool IVoiceState.IsSuppressed => false; + /// IVoiceChannel IVoiceState.VoiceChannel => null; + /// string IVoiceState.VoiceSessionId => null; } } diff --git a/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs b/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs index ab5ec4a3b..9f84306ea 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.User; @@ -8,8 +8,11 @@ namespace Discord.Rest [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestSelfUser : RestUser, ISelfUser { + /// public string Email { get; private set; } + /// public bool IsVerified { get; private set; } + /// public bool IsMfaEnabled { get; private set; } internal RestSelfUser(BaseDiscordClient discord, ulong id) @@ -22,6 +25,7 @@ namespace Discord.Rest entity.Update(model); return entity; } + /// internal override void Update(Model model) { base.Update(model); @@ -34,6 +38,8 @@ namespace Discord.Rest IsMfaEnabled = model.MfaEnabled.Value; } + /// + /// Unable to update this object using a different token. public override async Task UpdateAsync(RequestOptions options = null) { var model = await Discord.ApiClient.GetMyUserAsync(options).ConfigureAwait(false); @@ -42,6 +48,8 @@ namespace Discord.Rest Update(model); } + /// + /// Unable to modify this object using a different token. public async Task ModifyAsync(Action func, RequestOptions options = null) { if (Id != Discord.CurrentUser.Id) diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs index f0c771ae0..47c3f8b98 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs @@ -8,16 +8,26 @@ namespace Discord.Rest [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestUser : RestEntity, IUser, IUpdateable { + /// public bool IsBot { get; private set; } + /// public string Username { get; private set; } + /// public ushort DiscriminatorValue { get; private set; } + /// public string AvatarId { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + /// public string Discriminator => DiscriminatorValue.ToString("D4"); + /// public string Mention => MentionUtils.MentionUser(Id); + /// public virtual IActivity Activity => null; + /// public virtual UserStatus Status => UserStatus.Offline; + /// public virtual bool IsWebhook => false; internal RestUser(BaseDiscordClient discord, ulong id) @@ -48,6 +58,7 @@ namespace Discord.Rest Username = model.Username.Value; } + /// public virtual async Task UpdateAsync(RequestOptions options = null) { var model = await Discord.ApiClient.GetUserAsync(Id, options).ConfigureAwait(false); @@ -57,9 +68,11 @@ namespace Discord.Rest public Task GetOrCreateDMChannelAsync(RequestOptions options = null) => UserHelper.CreateDMChannelAsync(this, Discord, options); + /// public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) => CDN.GetUserAvatarUrl(Id, AvatarId, size, format); + /// public string GetDefaultAvatarUrl() => CDN.GetDefaultUserAvatarUrl(DiscriminatorValue); @@ -67,6 +80,7 @@ namespace Discord.Rest private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})"; //IUser + /// async Task IUser.GetOrCreateDMChannelAsync(RequestOptions options) => await GetOrCreateDMChannelAsync(options).ConfigureAwait(false); } diff --git a/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs b/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs index 47cc50a9c..1fdc95a63 100644 --- a/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs +++ b/src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.Webhook; @@ -11,14 +11,21 @@ namespace Discord.Rest internal IGuild Guild { get; private set; } internal ITextChannel Channel { get; private set; } + /// public ulong ChannelId { get; } + /// public string Token { get; } + /// public string Name { get; private set; } + /// public string AvatarId { get; private set; } + /// public ulong? GuildId { get; private set; } + /// public IUser Creator { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); internal RestWebhook(BaseDiscordClient discord, IGuild guild, ulong id, string token, ulong channelId) @@ -59,12 +66,14 @@ namespace Discord.Rest Name = model.Name.Value; } + /// public async Task UpdateAsync(RequestOptions options = null) { var model = await Discord.ApiClient.GetWebhookAsync(Id, options).ConfigureAwait(false); Update(model); } + /// public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) => CDN.GetUserAvatarUrl(Id, AvatarId, size, format); @@ -74,6 +83,7 @@ namespace Discord.Rest Update(model); } + /// public Task DeleteAsync(RequestOptions options = null) => WebhookHelper.DeleteAsync(this, Discord, options); @@ -81,10 +91,13 @@ namespace Discord.Rest private string DebuggerDisplay => $"Webhook: {Name} ({Id})"; //IWebhook + /// IGuild IWebhook.Guild => Guild ?? throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object."); + /// ITextChannel IWebhook.Channel => Channel ?? throw new InvalidOperationException("Unable to return this entity's parent unless it was fetched through that object."); + /// Task IWebhook.ModifyAsync(Action func, RequestOptions options) => ModifyAsync(func, options); } diff --git a/src/Discord.Net.Rest/Net/DefaultRestClient.cs b/src/Discord.Net.Rest/Net/DefaultRestClient.cs index ec789be59..4b4c1e045 100644 --- a/src/Discord.Net.Rest/Net/DefaultRestClient.cs +++ b/src/Discord.Net.Rest/Net/DefaultRestClient.cs @@ -82,6 +82,8 @@ namespace Discord.Net.Rest return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); } } + + /// Unsupported param type. public async Task SendAsync(string method, string endpoint, IReadOnlyDictionary multipartParams, CancellationToken cancelToken, bool headerOnly, string reason = null) { string uri = Path.Combine(_baseUrl, endpoint); @@ -111,7 +113,7 @@ namespace Discord.Net.Rest content.Add(new StreamContent(stream), p.Key, fileValue.Filename); continue; } - default: throw new InvalidOperationException($"Unsupported param type \"{p.Value.GetType().Name}\""); + default: throw new InvalidOperationException($"Unsupported param type \"{p.Value.GetType().Name}\"."); } } } diff --git a/src/Discord.Net.Rest/Net/DefaultRestClientProvider.cs b/src/Discord.Net.Rest/Net/DefaultRestClientProvider.cs index e0e776549..67b47096e 100644 --- a/src/Discord.Net.Rest/Net/DefaultRestClientProvider.cs +++ b/src/Discord.Net.Rest/Net/DefaultRestClientProvider.cs @@ -6,6 +6,7 @@ namespace Discord.Net.Rest { public static readonly RestClientProvider Instance = Create(); + /// The default RestClientProvider is not supported on this platform. public static RestClientProvider Create(bool useProxy = false) { return url => diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs index 3346681b5..5894aa768 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs @@ -126,7 +126,7 @@ namespace Discord.Net.Queue if ((request.Options.RetryMode & RetryMode.RetryTimeouts) == 0) throw; - await Task.Delay(500); + await Task.Delay(500).ConfigureAwait(false); continue; //Retry } /*catch (Exception) diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs index 9421221ed..e9a5fde9e 100644 --- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs +++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Discord.Net @@ -15,7 +15,7 @@ namespace Discord.Net internal RateLimitInfo(Dictionary headers) { IsGlobal = headers.TryGetValue("X-RateLimit-Global", out string temp) && - bool.TryParse(temp, out var isGlobal) ? isGlobal : false; + bool.TryParse(temp, out var isGlobal) && isGlobal; Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) && int.TryParse(temp, out var limit) ? limit : (int?)null; Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) && diff --git a/src/Discord.Net.WebSocket/Audio/Streams/OpusDecodeStream.cs b/src/Discord.Net.WebSocket/Audio/Streams/OpusDecodeStream.cs index 58c4f4c70..1861e3554 100644 --- a/src/Discord.Net.WebSocket/Audio/Streams/OpusDecodeStream.cs +++ b/src/Discord.Net.WebSocket/Audio/Streams/OpusDecodeStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; @@ -22,19 +22,22 @@ namespace Discord.Audio.Streams _decoder = new OpusDecoder(); } + /// Header received with no payload. public override void WriteHeader(ushort seq, uint timestamp, bool missed) { if (_hasHeader) - throw new InvalidOperationException("Header received with no payload"); + throw new InvalidOperationException("Header received with no payload."); _hasHeader = true; _nextMissed = missed; _next.WriteHeader(seq, timestamp, missed); } + + /// Received payload without an RTP header. public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) { if (!_hasHeader) - throw new InvalidOperationException("Received payload without an RTP header"); + throw new InvalidOperationException("Received payload without an RTP header."); _hasHeader = false; if (!_nextMissed) diff --git a/src/Discord.Net.WebSocket/Audio/Streams/RTPReadStream.cs b/src/Discord.Net.WebSocket/Audio/Streams/RTPReadStream.cs index 2cedea114..120f67e0d 100644 --- a/src/Discord.Net.WebSocket/Audio/Streams/RTPReadStream.cs +++ b/src/Discord.Net.WebSocket/Audio/Streams/RTPReadStream.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System; +using System.Threading; using System.Threading.Tasks; namespace Discord.Audio.Streams @@ -20,6 +21,8 @@ namespace Discord.Audio.Streams _nonce = new byte[24]; } + /// The token has had cancellation requested. + /// The associated has been disposed. public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) { cancelToken.ThrowIfCancellationRequested(); diff --git a/src/Discord.Net.WebSocket/Audio/Streams/SodiumEncryptStream.cs b/src/Discord.Net.WebSocket/Audio/Streams/SodiumEncryptStream.cs index bacc9be47..2b5cc0a18 100644 --- a/src/Discord.Net.WebSocket/Audio/Streams/SodiumEncryptStream.cs +++ b/src/Discord.Net.WebSocket/Audio/Streams/SodiumEncryptStream.cs @@ -20,21 +20,25 @@ namespace Discord.Audio.Streams _client = (AudioClient)client; _nonce = new byte[24]; } - + + /// Header received with no payload. public override void WriteHeader(ushort seq, uint timestamp, bool missed) { if (_hasHeader) - throw new InvalidOperationException("Header received with no payload"); + throw new InvalidOperationException("Header received with no payload."); _nextSeq = seq; _nextTimestamp = timestamp; _hasHeader = true; } + /// Received payload without an RTP header. + /// The token has had cancellation requested. + /// The associated has been disposed. public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) { cancelToken.ThrowIfCancellationRequested(); if (!_hasHeader) - throw new InvalidOperationException("Received payload without an RTP header"); + throw new InvalidOperationException("Received payload without an RTP header."); _hasHeader = false; if (_client.SecretKey == null) diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs index e881a7855..304592442 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; namespace Discord.WebSocket diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.cs b/src/Discord.Net.WebSocket/BaseSocketClient.cs index 6393005ac..9a47d0881 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.cs @@ -10,42 +10,174 @@ namespace Discord.WebSocket { protected readonly DiscordSocketConfig BaseConfig; - /// Gets the estimated round-trip latency, in milliseconds, to the gateway server. + /// + /// Gets the estimated round-trip latency, in milliseconds, to the gateway server. + /// public abstract int Latency { get; protected set; } - public abstract UserStatus Status { get; protected set; } + /// + /// Gets the status for the logged-in user. + /// + public abstract UserStatus Status { get; protected set; } + /// + /// Gets the activity for the logged-in user. + /// public abstract IActivity Activity { get; protected set; } internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; + /// + /// Gets the current logged-in user. + /// public new SocketSelfUser CurrentUser { get => base.CurrentUser as SocketSelfUser; protected set => base.CurrentUser = value; } + /// + /// Gets a collection of guilds that the logged-in user is currently in. + /// public abstract IReadOnlyCollection Guilds { get; } + /// + /// Gets a collection of private channels that are currently open for the logged-in user. + /// public abstract IReadOnlyCollection PrivateChannels { get; } + /// + /// Gets a collection of available voice regions for the logged-in user. + /// public abstract IReadOnlyCollection VoiceRegions { get; } internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client) : base(config, client) => BaseConfig = config; private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) => new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent); - + + /// + /// Gets a Discord application information for the logged-in user. + /// + /// The options to be used when sending the request. + /// + /// Application information. This reflects your application information you submitted when creating a + /// Discord application via the Developer Portal. + /// public abstract Task GetApplicationInfoAsync(RequestOptions options = null); + /// + /// Gets a user who shares a mutual guild with logged-in user with the provided snowflake ID. + /// + /// The user snowflake ID. + /// + /// A user who shares a mutual guild with the logged-in user and who is also present in the WebSocket cache; + /// or when the user cannot be found. + /// public abstract SocketUser GetUser(ulong id); + + /// + /// Gets a user who shares a mutual guild with the logged-in user with the provided username and discriminator value combo. + /// + /// The name of the user. + /// The discriminator value of the user. + /// + /// A user who shares a mutual guild with the logged-in user and who is also present in the WebSocket cache; + /// or when the user cannot be found. + /// public abstract SocketUser GetUser(string username, string discriminator); + /// + /// Gets a channel that the logged-in user is accessible to with the provided ID. + /// + /// The channel snowflake ID. + /// + /// A generic channel object (voice, text, category, etc.); or when the channel + /// cannot be found. + /// public abstract SocketChannel GetChannel(ulong id); + /// + /// Gets a guild that the logged-in user is accessible to with the provided ID. + /// + /// The guild snowflake ID. + /// + /// A guild; or when the guild cannot be found. + /// public abstract SocketGuild GetGuild(ulong id); + /// + /// Gets a voice region with the provided ID. + /// + /// The unique identifier of the voice region. + /// + /// A voice region; or if none can be found. + /// public abstract RestVoiceRegion GetVoiceRegion(string id); /// public abstract Task StartAsync(); /// public abstract Task StopAsync(); + /// + /// Sets the current status of the logged-in user (e.g. Online, Do not Disturb). + /// + /// The new status to be set. + /// + /// An awaitable . + /// public abstract Task SetStatusAsync(UserStatus status); + /// + /// Sets the game of the logged-in user. + /// + /// The name of the game. + /// If streaming, the URL of the stream. Must be a valid Twitch URL. + /// The type of the game. + /// + /// An awaitable . + /// public abstract Task SetGameAsync(string name, string streamUrl = null, ActivityType type = ActivityType.Playing); + /// + /// Sets the of the logged-in user. + /// + /// + /// This method sets the of the user. Please note that Rich Presence cannot be + /// set via this method or client. Rich Presence is strictly limited to RPC clients only. Furthermore, + /// Discord will only accept setting of name and the type of activity. + /// + /// The activty to be set. + /// + /// An awaitable . + /// public abstract Task SetActivityAsync(IActivity activity); - public abstract Task DownloadUsersAsync(IEnumerable guilds); - + /// + /// Attempts to download users into the user cache for the selected guilds. + /// + /// The guilds to download the members from. + /// + /// An awaitable . + /// + public abstract Task DownloadUsersAsync(IEnumerable guilds); + + /// + /// Creates a guild for the logged-in user who is in less than 10 active guilds. + /// + /// + /// This method creates a new guild on behalf of the logged-in user. Note that due to Discord's limitation, + /// this method will only work for users that are in less than 10 guilds. + /// + /// The name of the new guild. + /// The voice region to create the guild with. + /// The icon of the guild. + /// The options to be used when sending the request. + /// + /// An awaitable containing the newly created guild. + /// public Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null) => ClientHelper.CreateGuildAsync(this, name, region, jpegIcon, options ?? RequestOptions.Default); + /// + /// Gets the connections that the logged-in user has set up. + /// + /// The options to be used when sending the request. + /// + /// An awaitable containing a collection of connections. + /// public Task> GetConnectionsAsync(RequestOptions options = null) => ClientHelper.GetConnectionsAsync(this, options ?? RequestOptions.Default); + /// + /// Gets an invite with the provided invite identifier. + /// + /// The invitation identifier. + /// The options to be used when sending the request. + /// + /// An awaitable containing the invite information. + /// public Task GetInviteAsync(string inviteId, RequestOptions options = null) => ClientHelper.GetInviteAsync(this, inviteId, options ?? RequestOptions.Default); diff --git a/src/Discord.Net.WebSocket/ClientState.cs b/src/Discord.Net.WebSocket/ClientState.cs index f07976a0a..44b44e689 100644 --- a/src/Discord.Net.WebSocket/ClientState.cs +++ b/src/Discord.Net.WebSocket/ClientState.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -72,9 +72,9 @@ namespace Discord.WebSocket switch (channel) { case SocketDMChannel dmChannel: - _dmChannels.TryRemove(dmChannel.Recipient.Id, out var ignored); + _dmChannels.TryRemove(dmChannel.Recipient.Id, out var _); break; - case SocketGroupChannel groupChannel: + case SocketGroupChannel _: _groupChannels.TryRemove(id); break; } diff --git a/src/Discord.Net.WebSocket/Commands/SocketCommandContext.cs b/src/Discord.Net.WebSocket/Commands/SocketCommandContext.cs index 0fb47ceff..f4d517909 100644 --- a/src/Discord.Net.WebSocket/Commands/SocketCommandContext.cs +++ b/src/Discord.Net.WebSocket/Commands/SocketCommandContext.cs @@ -2,7 +2,9 @@ using Discord.WebSocket; namespace Discord.Commands { - /// The WebSocket variant of , which may contain the client, user, guild, channel, and message. + /// + /// Represents a WebSocket-based context of a command. This may include the client, guild, channel, user, and message. + /// public class SocketCommandContext : ICommandContext { /// diff --git a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs index 8ae41cc59..20ff85be6 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs @@ -120,12 +120,14 @@ namespace Discord.API } finally { _stateLock.Release(); } } + /// The client must be logged in before connecting. + /// This client is not configured with WebSocket support. internal override async Task ConnectInternalAsync() { if (LoginState != LoginState.LoggedIn) - throw new InvalidOperationException("You must log in before connecting."); + throw new InvalidOperationException("The client must be logged in before connecting."); if (WebSocketClient == null) - throw new NotSupportedException("This client is not configured with websocket support."); + throw new NotSupportedException("This client is not configured with WebSocket support."); //Re-create streams to reset the zlib state _compressed?.Dispose(); @@ -176,10 +178,11 @@ namespace Discord.API } finally { _stateLock.Release(); } } + /// This client is not configured with WebSocket support. internal override async Task DisconnectInternalAsync() { if (WebSocketClient == null) - throw new NotSupportedException("This client is not configured with websocket support."); + throw new NotSupportedException("This client is not configured with WebSocket support."); if (ConnectionState == ConnectionState.Disconnected) return; ConnectionState = ConnectionState.Disconnecting; diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index c9f8fa5f5..64f254782 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -46,7 +46,9 @@ namespace Discord.WebSocket public ConnectionState ConnectionState => _connection.State; /// public override int Latency { get; protected set; } + /// public override UserStatus Status { get; protected set; } = UserStatus.Online; + /// public override IActivity Activity { get; protected set; } //From DiscordSocketConfig @@ -58,14 +60,17 @@ namespace Discord.WebSocket internal WebSocketProvider WebSocketProvider { get; private set; } internal bool AlwaysDownloadUsers { get; private set; } internal int? HandlerTimeout { get; private set; } - + internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; + /// public override IReadOnlyCollection Guilds => State.Guilds; + /// public override IReadOnlyCollection PrivateChannels => State.PrivateChannels; public IReadOnlyCollection DMChannels => State.PrivateChannels.Select(x => x as SocketDMChannel).Where(x => x != null).ToImmutableArray(); public IReadOnlyCollection GroupChannels => State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray(); + /// public override IReadOnlyCollection VoiceRegions => _voiceRegions.ToReadOnlyCollection(); /// Creates a new REST/WebSocket Discord client. @@ -128,6 +133,7 @@ namespace Discord.WebSocket } private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) => new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayHost); + /// internal override void Dispose(bool disposing) { if (disposing) @@ -136,7 +142,8 @@ namespace Discord.WebSocket ApiClient.Dispose(); } } - + + /// internal override async Task OnLoginAsync(TokenType tokenType, string token) { if (_parentClient == null) @@ -147,6 +154,7 @@ namespace Discord.WebSocket else _voiceRegions = _parentClient._voiceRegions; } + /// internal override async Task OnLogoutAsync() { await StopAsync().ConfigureAwait(false); @@ -154,8 +162,10 @@ namespace Discord.WebSocket _voiceRegions = ImmutableDictionary.Create(); } + /// public override async Task StartAsync() => await _connection.StartAsync().ConfigureAwait(false); + /// public override async Task StopAsync() => await _connection.StopAsync().ConfigureAwait(false); @@ -277,7 +287,7 @@ namespace Discord.WebSocket return null; } - /// Downloads the users list for the provided guilds, if they don't have a complete list. + /// public override async Task DownloadUsersAsync(IEnumerable guilds) { if (ConnectionState == ConnectionState.Connected) @@ -316,6 +326,7 @@ namespace Discord.WebSocket } } + /// public override async Task SetStatusAsync(UserStatus status) { Status = status; @@ -325,6 +336,7 @@ namespace Discord.WebSocket _statusSince = null; await SendStatusAsync().ConfigureAwait(false); } + /// public override async Task SetGameAsync(string name, string streamUrl = null, ActivityType type = ActivityType.Playing) { if (!string.IsNullOrEmpty(streamUrl)) @@ -335,6 +347,7 @@ namespace Discord.WebSocket Activity = null; await SendStatusAsync().ConfigureAwait(false); } + /// public override async Task SetActivityAsync(IActivity activity) { Activity = activity; @@ -351,8 +364,8 @@ namespace Discord.WebSocket var gameModel = new GameModel(); // Discord only accepts rich presence over RPC, don't even bother building a payload - if (Activity is RichGame game) - throw new NotSupportedException("Outgoing Rich Presences are not supported"); + if (Activity is RichGame) + throw new NotSupportedException("Outgoing Rich Presences are not supported via WebSocket."); if (Activity != null) { @@ -479,7 +492,7 @@ namespace Discord.WebSocket await TimedInvokeAsync(_readyEvent, nameof(Ready)).ConfigureAwait(false); await _gatewayLogger.InfoAsync("Ready").ConfigureAwait(false); }); - var _ = _connection.CompleteAsync(); + _ = _connection.CompleteAsync(); } break; case "RESUMED": @@ -1173,7 +1186,7 @@ namespace Discord.WebSocket var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); bool isCached = msg != null; - var cacheable = new Cacheable(msg, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id)); + var cacheable = new Cacheable(msg, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id).ConfigureAwait(false)); await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheable, channel).ConfigureAwait(false); } @@ -1609,6 +1622,7 @@ namespace Discord.WebSocket return guild; } + /// Unexpected channel type is created. internal ISocketPrivateChannel AddPrivateChannel(API.Channel model, ClientState state) { var channel = SocketChannel.CreatePrivate(this, state, model); @@ -1781,43 +1795,59 @@ namespace Discord.WebSocket internal int GetAudioId() => _nextAudioId++; //IDiscordClient + /// async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) => await GetApplicationInfoAsync().ConfigureAwait(false); + /// Task IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetChannel(id)); + /// Task> IDiscordClient.GetPrivateChannelsAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(PrivateChannels); + /// Task> IDiscordClient.GetDMChannelsAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(DMChannels); + /// Task> IDiscordClient.GetGroupChannelsAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(GroupChannels); + /// async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) => await GetConnectionsAsync().ConfigureAwait(false); + /// async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) => await GetInviteAsync(inviteId).ConfigureAwait(false); + /// Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetGuild(id)); + /// Task> IDiscordClient.GetGuildsAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(Guilds); + /// async Task IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) => await CreateGuildAsync(name, region, jpegIcon).ConfigureAwait(false); + /// Task IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetUser(id)); + /// Task IDiscordClient.GetUserAsync(string username, string discriminator, RequestOptions options) => Task.FromResult(GetUser(username, discriminator)); + /// Task> IDiscordClient.GetVoiceRegionsAsync(RequestOptions options) => Task.FromResult>(VoiceRegions); + /// Task IDiscordClient.GetVoiceRegionAsync(string id, RequestOptions options) => Task.FromResult(GetVoiceRegion(id)); + /// async Task IDiscordClient.StartAsync() => await StartAsync().ConfigureAwait(false); + /// async Task IDiscordClient.StopAsync() => await StopAsync().ConfigureAwait(false); } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs index ec842c8a3..e0fb93d6a 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannel.cs @@ -58,6 +58,7 @@ namespace Discord.WebSocket internal abstract SocketUser GetUserInternal(ulong id); internal abstract IReadOnlyCollection GetUsersInternal(); + private string DebuggerDisplay => $"Unknown ({Id}, Channel)"; internal SocketChannel Clone() => MemberwiseClone() as SocketChannel; //IChannel diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannelHelper.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannelHelper.cs index ca53315aa..e6339b6d9 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketChannelHelper.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketChannelHelper.cs @@ -1,4 +1,4 @@ -using Discord.Rest; +using Discord.Rest; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -57,7 +57,7 @@ namespace Discord.WebSocket else return ImmutableArray.Create(); } - + /// Unexpected type. public static void AddMessage(ISocketMessageChannel channel, DiscordSocketClient discord, SocketMessage msg) { @@ -66,9 +66,10 @@ namespace Discord.WebSocket case SocketDMChannel dmChannel: dmChannel.AddMessage(msg); break; case SocketGroupChannel groupChannel: groupChannel.AddMessage(msg); break; case SocketTextChannel textChannel: textChannel.AddMessage(msg); break; - default: throw new NotSupportedException("Unexpected ISocketMessageChannel type"); + default: throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type."); } } + /// Unexpected type. public static SocketMessage RemoveMessage(ISocketMessageChannel channel, DiscordSocketClient discord, ulong id) { @@ -77,7 +78,7 @@ namespace Discord.WebSocket case SocketDMChannel dmChannel: return dmChannel.RemoveMessage(id); case SocketGroupChannel groupChannel: return groupChannel.RemoveMessage(id); case SocketTextChannel textChannel: return textChannel.RemoveMessage(id); - default: throw new NotSupportedException("Unexpected ISocketMessageChannel type"); + default: throw new NotSupportedException($"Unexpected {nameof(ISocketMessageChannel)} type."); } } } diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index 5cc35cf14..ae8ab54da 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -111,7 +111,6 @@ namespace Discord.WebSocket /// public Task TriggerTypingAsync(RequestOptions options = null) => ChannelHelper.TriggerTypingAsync(this, Discord, options); - /// public IDisposable EnterTypingState(RequestOptions options = null) => ChannelHelper.EnterTypingState(this, Discord, options); diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index c4c223e64..1f027e321 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -357,9 +357,12 @@ namespace Discord.WebSocket => GuildHelper.DeleteAsync(this, Discord, options); /// + /// is . public Task ModifyAsync(Action func, RequestOptions options = null) => GuildHelper.ModifyAsync(this, Discord, func, options); + /// + /// is . public Task ModifyEmbedAsync(Action func, RequestOptions options = null) => GuildHelper.ModifyEmbedAsync(this, Discord, func, options); /// @@ -431,31 +434,37 @@ namespace Discord.WebSocket /// public SocketVoiceChannel GetVoiceChannel(ulong id) => GetChannel(id) as SocketVoiceChannel; + /// /// Creates a text channel with the provided name. /// /// The name of the new channel. /// The options to be used when sending the request. + /// is . /// /// The created text channel. /// public Task CreateTextChannelAsync(string name, RequestOptions options = null) => GuildHelper.CreateTextChannelAsync(this, Discord, name, options); + /// /// Creates a voice channel with the provided name. /// /// The name of the new channel. /// The options to be used when sending the request. + /// is . /// /// The created voice channel. /// public Task CreateVoiceChannelAsync(string name, RequestOptions options = null) => GuildHelper.CreateVoiceChannelAsync(this, Discord, name, options); + /// /// Creates a category channel with the provided name. /// /// The name of the new channel. /// The options to be used when sending the request. + /// is . /// /// The created category channel. /// @@ -507,6 +516,7 @@ namespace Discord.WebSocket return value; return null; } + /// /// Creates a role. /// @@ -517,6 +527,7 @@ namespace Discord.WebSocket /// The color of the role. Set to to use the default color. /// Used to determine if users of this role are separated in the user list. /// The options to be used when sending the request. + /// is . /// /// The created role. /// @@ -645,6 +656,7 @@ namespace Discord.WebSocket public Task CreateEmoteAsync(string name, Image image, Optional> roles = default(Optional>), RequestOptions options = null) => GuildHelper.CreateEmoteAsync(this, Discord, name, image, roles, options); /// + /// is . public Task ModifyEmoteAsync(GuildEmote emote, Action func, RequestOptions options = null) => GuildHelper.ModifyEmoteAsync(this, Discord, emote.Id, func, options); /// @@ -931,9 +943,9 @@ namespace Discord.WebSocket /// async Task IGuild.GetWebhookAsync(ulong id, RequestOptions options) - => await GetWebhookAsync(id, options); + => await GetWebhookAsync(id, options).ConfigureAwait(false); /// async Task> IGuild.GetWebhooksAsync(RequestOptions options) - => await GetWebhooksAsync(options); + => await GetWebhooksAsync(options).ConfigureAwait(false); } } diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs index 5442c888a..d339a20ed 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs @@ -1,4 +1,4 @@ -using Discord.Rest; +using Discord.Rest; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -8,27 +8,38 @@ using Model = Discord.API.Message; namespace Discord.WebSocket { + /// + /// Represents a WebSocket-based message. + /// public abstract class SocketMessage : SocketEntity, IMessage { private long _timestampTicks; public SocketUser Author { get; } public ISocketMessageChannel Channel { get; } + /// public MessageSource Source { get; } + /// public string Content { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + /// public virtual bool IsTTS => false; + /// public virtual bool IsPinned => false; + /// public virtual DateTimeOffset? EditedTimestamp => null; public virtual IReadOnlyCollection Attachments => ImmutableArray.Create(); public virtual IReadOnlyCollection Embeds => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedChannels => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedRoles => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedUsers => ImmutableArray.Create(); + /// public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); + /// public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks); internal SocketMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) @@ -54,6 +65,7 @@ namespace Discord.WebSocket Content = model.Content.Value; } + /// public Task DeleteAsync(RequestOptions options = null) => MessageHelper.DeleteAsync(this, Discord, options); @@ -61,13 +73,21 @@ namespace Discord.WebSocket internal SocketMessage Clone() => MemberwiseClone() as SocketMessage; //IMessage + /// IUser IMessage.Author => Author; + /// IMessageChannel IMessage.Channel => Channel; + /// MessageType IMessage.Type => MessageType.Default; + /// IReadOnlyCollection IMessage.Attachments => Attachments; + /// IReadOnlyCollection IMessage.Embeds => Embeds; + /// IReadOnlyCollection IMessage.MentionedChannelIds => MentionedChannels.Select(x => x.Id).ToImmutableArray(); + /// IReadOnlyCollection IMessage.MentionedRoleIds => MentionedRoles.Select(x => x.Id).ToImmutableArray(); + /// IReadOnlyCollection IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); } } diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs index e8fa17a35..bfd6aa042 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs @@ -1,4 +1,4 @@ -using Model = Discord.API.Gateway.Reaction; +using Model = Discord.API.Gateway.Reaction; namespace Discord.WebSocket { @@ -9,6 +9,7 @@ namespace Discord.WebSocket public ulong MessageId { get; } public Optional Message { get; } public ISocketMessageChannel Channel { get; } + /// public IEmote Emote { get; } internal SocketReaction(ISocketMessageChannel channel, ulong messageId, Optional message, ulong userId, Optional user, IEmote emoji) @@ -30,6 +31,7 @@ namespace Discord.WebSocket return new SocketReaction(channel, model.MessageId, message, model.UserId, user, emote); } + /// public override bool Equals(object other) { if (other == null) return false; @@ -41,6 +43,7 @@ namespace Discord.WebSocket return UserId == otherReaction.UserId && MessageId == otherReaction.MessageId && Emote.Equals(otherReaction.Emote); } + /// public override int GetHashCode() { unchecked diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs index e6c67159f..c37f04124 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Model = Discord.API.Message; namespace Discord.WebSocket @@ -6,6 +6,7 @@ namespace Discord.WebSocket [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class SocketSystemMessage : SocketMessage, ISystemMessage { + /// public MessageType Type { get; private set; } internal SocketSystemMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author) diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs index 5489ad2bb..58e87017c 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs @@ -17,24 +17,34 @@ namespace Discord.WebSocket private ImmutableArray _attachments; private ImmutableArray _embeds; private ImmutableArray _tags; - private List _reactions = new List(); - + private readonly List _reactions = new List(); + + /// public override bool IsTTS => _isTTS; + /// public override bool IsPinned => _isPinned; + /// public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks); + /// public override IReadOnlyCollection Attachments => _attachments; + /// public override IReadOnlyCollection Embeds => _embeds; + /// public override IReadOnlyCollection Tags => _tags; + /// public override IReadOnlyCollection MentionedChannels => MessageHelper.FilterTagsByValue(TagType.ChannelMention, _tags); + /// public override IReadOnlyCollection MentionedRoles => MessageHelper.FilterTagsByValue(TagType.RoleMention, _tags); + /// public override IReadOnlyCollection MentionedUsers => MessageHelper.FilterTagsByValue(TagType.UserMention, _tags); + /// public IReadOnlyDictionary Reactions => _reactions.GroupBy(r => r.Emote).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) }); internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) : base(discord, id, channel, author, source) { } - internal static new SocketUserMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model) + internal new static SocketUserMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model) { var entity = new SocketUserMessage(discord, model.Id, channel, author, MessageHelper.GetSource(model)); entity.Update(state, model); @@ -121,30 +131,40 @@ namespace Discord.WebSocket _reactions.Clear(); } + /// + /// Only the author of a message may modify the message. + /// Message content is too long, length must be less or equal to . public Task ModifyAsync(Action func, RequestOptions options = null) => MessageHelper.ModifyAsync(this, Discord, func, options); + /// public Task AddReactionAsync(IEmote emote, RequestOptions options = null) => MessageHelper.AddReactionAsync(this, emote, Discord, options); + /// public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null) => MessageHelper.RemoveReactionAsync(this, user, emote, Discord, options); + /// public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); + /// public Task> GetReactionUsersAsync(IEmote emote, int limit = 100, ulong? afterUserId = null, RequestOptions options = null) => MessageHelper.GetReactionUsersAsync(this, emote, x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create(); }, Discord, options); + /// public Task PinAsync(RequestOptions options = null) => MessageHelper.PinAsync(this, Discord, options); + /// public Task UnpinAsync(RequestOptions options = null) => MessageHelper.UnpinAsync(this, Discord, options); public string Resolve(int startIndex, TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) => MentionUtils.Resolve(this, startIndex, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); + /// public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); - + private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; internal new SocketUserMessage Clone() => MemberwiseClone() as SocketUserMessage; } diff --git a/src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs b/src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs index c366258cc..14af11e07 100644 --- a/src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs +++ b/src/Discord.Net.WebSocket/Entities/Roles/SocketRole.cs @@ -1,4 +1,4 @@ -using Discord.Rest; +using Discord.Rest; using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,16 +13,25 @@ namespace Discord.WebSocket { public SocketGuild Guild { get; } + /// public Color Color { get; private set; } + /// public bool IsHoisted { get; private set; } + /// public bool IsManaged { get; private set; } + /// public bool IsMentionable { get; private set; } + /// public string Name { get; private set; } + /// public GuildPermissions Permissions { get; private set; } + /// public int Position { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); public bool IsEveryone => Id == Guild.Id; + /// public string Mention => IsEveryone ? "@everyone" : MentionUtils.MentionRole(Id); public IEnumerable Members => Guild.Users.Where(x => x.Roles.Any(r => r.Id == Id)); @@ -49,8 +58,10 @@ namespace Discord.WebSocket Permissions = new GuildPermissions(model.Permissions); } + /// public Task ModifyAsync(Action func, RequestOptions options = null) => RoleHelper.ModifyAsync(this, Discord, func, options); + /// public Task DeleteAsync(RequestOptions options = null) => RoleHelper.DeleteAsync(this, Discord, options); @@ -58,9 +69,11 @@ namespace Discord.WebSocket private string DebuggerDisplay => $"{Name} ({Id})"; internal SocketRole Clone() => MemberwiseClone() as SocketRole; + /// public int CompareTo(IRole role) => RoleUtils.Compare(this, role); //IRole + /// IGuild IRole.Guild => Guild; } } diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs index 356ba63ac..73f5f0b8a 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs @@ -13,7 +13,7 @@ using PresenceModel = Discord.API.Presence; namespace Discord.WebSocket { /// - /// Represents a WebSocket guild user. + /// Represents a WebSocket-based guild user. /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class SocketGuildUser : SocketUser, IGuildUser diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs index 7d7ba16ce..8942bdf32 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketPresence.cs @@ -1,13 +1,14 @@ -using System.Diagnostics; +using System.Diagnostics; using Model = Discord.API.Presence; namespace Discord.WebSocket { - //TODO: C#7 Candidate for record type [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public struct SocketPresence : IPresence { + /// public UserStatus Status { get; } + /// public IActivity Activity { get; } internal SocketPresence(UserStatus status, IActivity activity) diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs index b7c02c2db..972ba6ea0 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs @@ -1,4 +1,4 @@ -using Discord.Rest; +using Discord.Rest; using System; using System.Diagnostics; using System.Threading.Tasks; @@ -9,17 +9,26 @@ namespace Discord.WebSocket [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class SocketSelfUser : SocketUser, ISelfUser { + /// public string Email { get; private set; } + /// public bool IsVerified { get; private set; } + /// public bool IsMfaEnabled { get; private set; } internal override SocketGlobalUser GlobalUser { get; } + /// public override bool IsBot { get { return GlobalUser.IsBot; } internal set { GlobalUser.IsBot = value; } } + /// public override string Username { get { return GlobalUser.Username; } internal set { GlobalUser.Username = value; } } + /// public override ushort DiscriminatorValue { get { return GlobalUser.DiscriminatorValue; } internal set { GlobalUser.DiscriminatorValue = value; } } + /// public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } } + /// internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } } + /// public override bool IsWebhook => false; internal SocketSelfUser(DiscordSocketClient discord, SocketGlobalUser globalUser) @@ -53,7 +62,8 @@ namespace Discord.WebSocket } return hasGlobalChanges; } - + + /// public Task ModifyAsync(Action func, RequestOptions options = null) => UserHelper.ModifyAsync(this, Discord, func, options); diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs index c7f6cb846..4cfaa686d 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using Model = Discord.API.User; @@ -15,7 +15,8 @@ namespace Discord.WebSocket public override bool IsWebhook => false; internal override SocketPresence Presence { get { return new SocketPresence(UserStatus.Offline, null); } set { } } - internal override SocketGlobalUser GlobalUser { get { throw new NotSupportedException(); } } + internal override SocketGlobalUser GlobalUser => + throw new NotSupportedException(); internal SocketUnknownUser(DiscordSocketClient discord, ulong id) : base(discord, id) diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs index 45cd5deec..9a101cddb 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs @@ -1,11 +1,15 @@ using Discord.Rest; using System; +using System.Diagnostics; using System.Threading.Tasks; using Model = Discord.API.User; namespace Discord.WebSocket { - /// The WebSocket variant of . Represents a Discord user. + /// + /// Represents a WebSocket-based user. + /// + [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public abstract class SocketUser : SocketEntity, IUser { /// @@ -68,7 +72,7 @@ namespace Discord.WebSocket /// public async Task GetOrCreateDMChannelAsync(RequestOptions options = null) - => GlobalUser.DMChannel ?? await UserHelper.CreateDMChannelAsync(this, Discord, options) as IDMChannel; + => GlobalUser.DMChannel ?? await UserHelper.CreateDMChannelAsync(this, Discord, options).ConfigureAwait(false) as IDMChannel; /// public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) @@ -78,6 +82,12 @@ namespace Discord.WebSocket public string GetDefaultAvatarUrl() => CDN.GetDefaultUserAvatarUrl(DiscriminatorValue); + /// + /// Gets the full name of the user (e.g. Example#0001). + /// + /// + /// The full name of the user. + /// public override string ToString() => $"{Username}#{Discriminator}"; private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})"; internal SocketUser Clone() => MemberwiseClone() as SocketUser; diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs index 480103326..428405431 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketVoiceState.cs @@ -1,10 +1,9 @@ -using System; +using System; using System.Diagnostics; using Model = Discord.API.VoiceState; namespace Discord.WebSocket { - //TODO: C#7 Candidate for record type [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public struct SocketVoiceState : IVoiceState { @@ -22,14 +21,23 @@ namespace Discord.WebSocket } private readonly Flags _voiceStates; - + + /// + /// Gets the voice channel that the user is currently in; or if none. + /// public SocketVoiceChannel VoiceChannel { get; } + /// public string VoiceSessionId { get; } + /// public bool IsMuted => (_voiceStates & Flags.Muted) != 0; + /// public bool IsDeafened => (_voiceStates & Flags.Deafened) != 0; + /// public bool IsSuppressed => (_voiceStates & Flags.Suppressed) != 0; + /// public bool IsSelfMuted => (_voiceStates & Flags.SelfMuted) != 0; + /// public bool IsSelfDeafened => (_voiceStates & Flags.SelfDeafened) != 0; internal SocketVoiceState(SocketVoiceChannel voiceChannel, string sessionId, bool isSelfMuted, bool isSelfDeafened, bool isMuted, bool isDeafened, bool isSuppressed) @@ -55,6 +63,12 @@ namespace Discord.WebSocket return new SocketVoiceState(voiceChannel, model.SessionId, model.SelfMute, model.SelfDeaf, model.Mute, model.Deaf, model.Suppress); } + /// + /// Gets the name of the voice channel. + /// + /// + /// The name of the voice channel. + /// public override string ToString() => VoiceChannel?.Name ?? "Unknown"; private string DebuggerDisplay => $"{VoiceChannel?.Name ?? "Unknown"} ({_voiceStates})"; internal SocketVoiceState Clone() => this; diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs index 9221ea03a..d75437c7b 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs @@ -63,26 +63,32 @@ namespace Discord.WebSocket /// ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => Permissions.ToChannelPerms(channel, GuildPermissions.Webhook.RawValue); /// + /// Webhook users cannot be kicked. Task IGuildUser.KickAsync(string reason, RequestOptions options) => throw new NotSupportedException("Webhook users cannot be kicked."); /// + /// Webhook users cannot be modified. Task IGuildUser.ModifyAsync(Action func, RequestOptions options) => throw new NotSupportedException("Webhook users cannot be modified."); /// + /// Roles are not supported on webhook users. Task IGuildUser.AddRoleAsync(IRole role, RequestOptions options) => throw new NotSupportedException("Roles are not supported on webhook users."); /// + /// Roles are not supported on webhook users. Task IGuildUser.AddRolesAsync(IEnumerable roles, RequestOptions options) => throw new NotSupportedException("Roles are not supported on webhook users."); /// + /// Roles are not supported on webhook users. Task IGuildUser.RemoveRoleAsync(IRole role, RequestOptions options) => throw new NotSupportedException("Roles are not supported on webhook users."); /// + /// Roles are not supported on webhook users. Task IGuildUser.RemoveRolesAsync(IEnumerable roles, RequestOptions options) => throw new NotSupportedException("Roles are not supported on webhook users."); diff --git a/src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs b/src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs index a250acec9..2301d3e45 100644 --- a/src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs +++ b/src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs @@ -1,4 +1,4 @@ -#if DEFAULTWEBSOCKET +#if DEFAULTWEBSOCKET using System; using System.Collections.Generic; using System.ComponentModel; @@ -248,4 +248,4 @@ namespace Discord.Net.WebSockets } } } -#endif \ No newline at end of file +#endif diff --git a/src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs b/src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs index 68bd67c5b..ca05d1c56 100644 --- a/src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs +++ b/src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs @@ -8,6 +8,7 @@ namespace Discord.Net.WebSockets #if DEFAULTWEBSOCKET public static readonly WebSocketProvider Instance = Create(); + /// The default WebSocketProvider is not supported on this platform. public static WebSocketProvider Create(IWebProxy proxy = null) { return () => @@ -30,4 +31,4 @@ namespace Discord.Net.WebSockets }; #endif } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Webhook/WebhookClientHelper.cs b/src/Discord.Net.Webhook/WebhookClientHelper.cs index 992ae03ab..07148f34a 100644 --- a/src/Discord.Net.Webhook/WebhookClientHelper.cs +++ b/src/Discord.Net.Webhook/WebhookClientHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -12,11 +12,12 @@ namespace Discord.Webhook { internal static class WebhookClientHelper { + /// Could not find a webhook with the supplied credentials. public static async Task GetWebhookAsync(DiscordWebhookClient client, ulong webhookId) { var model = await client.ApiClient.GetWebhookAsync(webhookId).ConfigureAwait(false); if (model == null) - throw new InvalidOperationException("Could not find a webhook for the supplied credentials."); + throw new InvalidOperationException("Could not find a webhook with the supplied credentials."); return RestInternalWebhook.Create(client, model); } public static async Task SendMessageAsync(DiscordWebhookClient client,