| @@ -9,6 +9,7 @@ using Model = Discord.API.Rpc.Channel; | |||
| namespace Discord.Rpc | |||
| { | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class RpcDMChannel : RpcChannel, IRpcMessageChannel, IRpcPrivateChannel, IDMChannel | |||
| { | |||
| public IReadOnlyCollection<RpcMessage> CachedMessages { get; private set; } | |||
| @@ -10,6 +10,7 @@ using Model = Discord.API.Rpc.Channel; | |||
| namespace Discord.Rpc | |||
| { | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class RpcGroupChannel : RpcChannel, IRpcMessageChannel, IRpcAudioChannel, IRpcPrivateChannel, IGroupChannel | |||
| { | |||
| public IReadOnlyCollection<RpcMessage> CachedMessages { get; private set; } | |||
| @@ -1,4 +1,4 @@ | |||
| using System; | |||
| using System; | |||
| using System.IO; | |||
| namespace Discord.Audio | |||
| @@ -7,8 +7,17 @@ namespace Discord.Audio | |||
| { | |||
| public override bool CanWrite => true; | |||
| public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } | |||
| public override void SetLength(long value) { throw new NotSupportedException(); } | |||
| public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Reading this stream is not supported.</exception> | |||
| public override int Read(byte[] buffer, int offset, int count) => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Setting the length to this stream is not supported.</exception> | |||
| public override void SetLength(long value) => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Seeking this stream is not supported..</exception> | |||
| public override long Seek(long offset, SeekOrigin origin) => | |||
| throw new NotSupportedException(); | |||
| } | |||
| } | |||
| @@ -28,17 +28,30 @@ namespace Discord.Audio | |||
| public virtual Task ClearAsync(CancellationToken cancellationToken) { return Task.Delay(0); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Reading stream length is not supported.</exception> | |||
| public override long Length => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Getting or setting this stream position is not supported.</exception> | |||
| public override long Position | |||
| { | |||
| get => throw new NotSupportedException(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } | |||
| public override void SetLength(long value) { throw new NotSupportedException(); } | |||
| public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Reading this stream is not supported.</exception> | |||
| public override int Read(byte[] buffer, int offset, int count) => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Setting the length to this stream is not supported.</exception> | |||
| public override void SetLength(long value) => | |||
| throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Seeking this stream is not supported..</exception> | |||
| public override long Seek(long offset, SeekOrigin origin) => | |||
| throw new NotSupportedException(); | |||
| } | |||
| } | |||
| @@ -41,7 +41,7 @@ namespace Discord | |||
| } | |||
| /// <summary> Gets or sets the title of an <see cref="Embed"/>. </summary> | |||
| /// <exception cref="ArgumentException" accessor="set">Title length exceeds the maximum allowed by Discord. | |||
| /// <exception cref="ArgumentException" accessor="set">Title length exceeds <see cref="MaxTitleLength"/>. | |||
| /// </exception> | |||
| /// <returns> The title of the embed.</returns> | |||
| public string Title | |||
| @@ -55,7 +55,7 @@ namespace Discord | |||
| } | |||
| /// <summary> Gets or sets the description of an <see cref="Embed"/>. </summary> | |||
| /// <exception cref="ArgumentException" accessor="set">Description length exceeds the maximum allowed by Discord.</exception> | |||
| /// <exception cref="ArgumentException" accessor="set">Description length exceeds <see cref="MaxDescriptionLength"/>.</exception> | |||
| /// <returns> The description of the embed.</returns> | |||
| public string Description | |||
| { | |||
| @@ -107,8 +107,8 @@ namespace Discord | |||
| /// <summary> Gets or sets the list of <see cref="EmbedFieldBuilder"/> of an <see cref="Embed"/>. </summary> | |||
| /// <exception cref="ArgumentNullException" accessor="set">An embed builder's fields collection is set to | |||
| /// <see langword="null"/>.</exception> | |||
| /// <exception cref="ArgumentException" accessor="set">Description length exceeds the maximum allowed by | |||
| /// Discord.</exception> | |||
| /// <exception cref="ArgumentException" accessor="set">Description length exceeds <see cref="MaxFieldCount"/>. | |||
| /// </exception> | |||
| /// <returns> The list of existing <see cref="EmbedFieldBuilder"/>.</returns> | |||
| public List<EmbedFieldBuilder> Fields | |||
| { | |||
| @@ -282,7 +282,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Sets the author field of an <see cref="Embed" /> with the provided properties. | |||
| /// </summary> | |||
| /// <param name="action">The <see langword="delegate"/> containing the author field properties.</param> | |||
| /// <param name="action">The delegate containing the author field properties.</param> | |||
| /// <returns> | |||
| /// The current builder. | |||
| /// </returns> | |||
| @@ -328,7 +328,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Sets the footer field of an <see cref="Embed" /> with the provided properties. | |||
| /// </summary> | |||
| /// <param name="action">The <see langword="delegate"/> containing the footer field properties.</param> | |||
| /// <param name="action">The delegate containing the footer field properties.</param> | |||
| /// <returns> | |||
| /// The current builder. | |||
| /// </returns> | |||
| @@ -382,7 +382,7 @@ namespace Discord | |||
| /// <see cref="Embed" />. | |||
| /// </summary> | |||
| /// <param name="field">The field builder class containing the field properties.</param> | |||
| /// <exception cref="ArgumentException">Field count exceeds the maximum allowed by Discord.</exception> | |||
| /// <exception cref="ArgumentException">Field count exceeds <see cref="MaxFieldCount"/>.</exception> | |||
| /// <returns> | |||
| /// The current builder. | |||
| /// </returns> | |||
| @@ -399,7 +399,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Adds an <see cref="Embed" /> field with the provided properties. | |||
| /// </summary> | |||
| /// <param name="action">The <see langword="delegate"/> containing the field properties.</param> | |||
| /// <param name="action">The delegate containing the field properties.</param> | |||
| /// <returns> | |||
| /// The current builder. | |||
| /// </returns> | |||
| @@ -417,7 +417,7 @@ namespace Discord | |||
| /// <returns> | |||
| /// The built embed object. | |||
| /// </returns> | |||
| /// <exception cref="InvalidOperationException">Total embed length exceeds the maximum allowed by Discord.</exception> | |||
| /// <exception cref="InvalidOperationException">Total embed length exceeds <see cref="MaxEmbedLength"/>.</exception> | |||
| public Embed Build() | |||
| { | |||
| if (Length > MaxEmbedLength) | |||
| @@ -542,7 +542,7 @@ namespace Discord | |||
| /// <exception cref="ArgumentException"> | |||
| /// <para><see cref="Name"/> or <see cref="Value"/> is <see langword="null" />, empty or entirely whitespace.</para> | |||
| /// <para><c>- or -</c></para> | |||
| /// <para><see cref="Name"/> or <see cref="Value"/> length exceeds the maximum allowed by Discord.</para> | |||
| /// <para><see cref="Name"/> or <see cref="Value"/> exceeds the maximum length allowed by Discord.</para> | |||
| /// </exception> | |||
| public EmbedField Build() | |||
| => new EmbedField(Name, Value.ToString(), IsInline); | |||
| @@ -26,8 +26,8 @@ namespace Discord | |||
| public Exception Exception { get; } | |||
| /// <summary> | |||
| /// Initializes a new <see cref="LogMessage" /> <see langword="struct"/> with the severity, source, | |||
| /// <paramref name="message"/> of the event, and optionally, an exception. | |||
| /// Initializes a new <see cref="LogMessage" /> struct with the severity, source, message of the event, and | |||
| /// optionally, an exception. | |||
| /// </summary> | |||
| /// <param name="severity">The severity of the event.</param> | |||
| /// <param name="source">The source of the event.</param> | |||
| @@ -11,10 +11,20 @@ namespace Discord.Net | |||
| /// <summary> | |||
| /// Gets the HTTP status code returned by Discord. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// An | |||
| /// <see href="https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#http">HTTP status code</see> | |||
| /// from Discord. | |||
| /// </returns> | |||
| public HttpStatusCode HttpCode { get; } | |||
| /// <summary> | |||
| /// Gets the JSON error code returned by Discord, or <see langword="null"/> if none. | |||
| /// Gets the JSON error code returned by Discord. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// A | |||
| /// <see href="https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#json">JSON error code</see> | |||
| /// from Discord, or <see langword="null"/> if none. | |||
| /// </returns> | |||
| public int? DiscordCode { get; } | |||
| /// <summary> | |||
| /// Gets the reason of the exception. | |||
| @@ -2,6 +2,9 @@ using System; | |||
| namespace Discord.Net | |||
| { | |||
| /// <summary> | |||
| /// Represents a generic request to be sent to Discord. | |||
| /// </summary> | |||
| public interface IRequest | |||
| { | |||
| DateTimeOffset? TimeoutAt { get; } | |||
| @@ -2,13 +2,18 @@ using System; | |||
| namespace Discord.Net | |||
| { | |||
| /// <summary> | |||
| /// Describes an exception that causes the WebSocket to close during a session. | |||
| /// Describes an exception that causes the WebSocket to close during a session. | |||
| /// </summary> | |||
| public class WebSocketClosedException : Exception | |||
| { | |||
| /// <summary> | |||
| /// Gets the close code sent by Discord. | |||
| /// </summary> | |||
| /// <returns> | |||
| /// A | |||
| /// <see href="https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-close-event-codes">close code</see> | |||
| /// from Discord. | |||
| /// </returns> | |||
| public int CloseCode { get; } | |||
| /// <summary> | |||
| /// Gets the reason of the interruption. | |||
| @@ -16,8 +21,8 @@ namespace Discord.Net | |||
| public string Reason { get; } | |||
| /// <summary> | |||
| /// Initializes a new instance of the <see cref="WebSocketClosedException" /> using the Discord close code | |||
| /// and the optional reason. | |||
| /// Initializes a new instance of the <see cref="WebSocketClosedException" /> using a Discord close code | |||
| /// and an optional reason. | |||
| /// </summary> | |||
| public WebSocketClosedException(int closeCode, string reason = null) | |||
| : base($"The server sent close {closeCode}{(reason != null ? $": \"{reason}\"" : "")}") | |||
| @@ -4,7 +4,7 @@ using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| /// <summary> | |||
| /// Represents a <see langword="struct"/> that contains an entity that may be cached. | |||
| /// Represents a cached entity. | |||
| /// </summary> | |||
| /// <typeparam name="TEntity">The type of entity that is cached.</typeparam> | |||
| /// <typeparam name="TId">The type of this entity's ID.</typeparam> | |||
| @@ -25,7 +25,7 @@ namespace Discord | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// This value is not guaranteed to be set; in cases where the entity cannot be pulled from cache, it is | |||
| /// null. | |||
| /// <see langword="null"/>. | |||
| /// </remarks> | |||
| public TEntity Value { get; } | |||
| private Func<Task<TEntity>> DownloadFunc { get; } | |||
| @@ -174,6 +174,7 @@ namespace Discord.Rest | |||
| Task<IReadOnlyCollection<IGuild>> IDiscordClient.GetGuildsAsync(CacheMode mode, RequestOptions options) | |||
| => Task.FromResult<IReadOnlyCollection<IGuild>>(ImmutableArray.Create<IGuild>()); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Creating a guild is not supported with the base client.</exception> | |||
| Task<IGuild> IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| @@ -26,18 +26,30 @@ namespace Discord.Rest | |||
| private string DebuggerDisplay => $"{Name} ({Id}, Category)"; | |||
| // IGuildChannel | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| //IChannel | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| } | |||
| @@ -154,7 +154,10 @@ namespace Discord.Rest | |||
| => EnterTypingState(options); | |||
| //IAudioChannel | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) { throw new NotSupportedException(); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception> | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) => | |||
| throw new NotSupportedException(); | |||
| //IChannel | |||
| Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| @@ -1,4 +1,4 @@ | |||
| using Discord.Audio; | |||
| using Discord.Audio; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics; | |||
| @@ -41,7 +41,9 @@ namespace Discord.Rest | |||
| private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; | |||
| //IAudioChannel | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) { throw new NotSupportedException(); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Connecting to a REST-based channel is not supported.</exception> | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) => throw new NotSupportedException(); | |||
| //IGuildChannel | |||
| Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| @@ -1,4 +1,4 @@ | |||
| using Discord.Audio; | |||
| using Discord.Audio; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| @@ -417,7 +417,10 @@ namespace Discord.Rest | |||
| else | |||
| return ImmutableArray.Create<IGuildUser>(); | |||
| } | |||
| Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); } | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">Downloading users is not supported with a REST-based guild.</exception> | |||
| Task IGuild.DownloadUsersAsync() => | |||
| throw new NotSupportedException(); | |||
| async Task<IWebhook> IGuild.GetWebhookAsync(ulong id, RequestOptions options) | |||
| => await GetWebhookAsync(id, options).ConfigureAwait(false); | |||
| @@ -8,7 +8,7 @@ namespace Discord.WebSocket | |||
| { | |||
| public abstract partial class BaseSocketClient : BaseDiscordClient, IDiscordClient | |||
| { | |||
| protected readonly DiscordSocketConfig _baseconfig; | |||
| protected readonly DiscordSocketConfig BaseConfig; | |||
| /// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary> | |||
| public abstract int Latency { get; protected set; } | |||
| @@ -23,7 +23,7 @@ namespace Discord.WebSocket | |||
| public abstract IReadOnlyCollection<RestVoiceRegion> VoiceRegions { get; } | |||
| internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client) | |||
| : base(config, client) => _baseconfig = config; | |||
| : base(config, client) => BaseConfig = config; | |||
| private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) | |||
| => new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent); | |||
| @@ -55,8 +55,12 @@ namespace Discord.WebSocket | |||
| => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | |||
| Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| => Task.FromResult<IGuildUser>(GetUser(id)); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> | |||
| Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) | |||
| => throw new NotSupportedException(); | |||
| @@ -251,7 +251,9 @@ namespace Discord.WebSocket | |||
| //IAudioChannel | |||
| /// <inheritdoc /> | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) { throw new NotSupportedException(); } | |||
| /// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception> | |||
| Task<IAudioClient> IAudioChannel.ConnectAsync(Action<IAudioClient> configAction) => | |||
| throw new NotSupportedException(); | |||
| //IChannel | |||
| /// <inheritdoc /> | |||
| @@ -1,4 +1,4 @@ | |||
| using System; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Diagnostics; | |||