| @@ -117,7 +117,7 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | /// <returns> | ||||
| /// A collection of messages. | |||||
| /// An awaitable Task containing a collection of messages. | |||||
| /// </returns> | /// </returns> | ||||
| Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null); | Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null); | ||||
| @@ -31,14 +31,20 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the time this message was sent. | /// Gets the time this message was sent. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Time of when the message was sent. | |||||
| /// </returns> | |||||
| DateTimeOffset Timestamp { get; } | DateTimeOffset Timestamp { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets the time of this message's last edit, or <see langword="null" /> if none is set. | |||||
| /// Gets the time of this message's last edit. | |||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Time of when the message was last edited; <see langword="null"/> when the message is never edited. | |||||
| /// </returns> | |||||
| DateTimeOffset? EditedTimestamp { get; } | DateTimeOffset? EditedTimestamp { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets the channel this message was sent to. | |||||
| /// Gets the source channel of the message. | |||||
| /// </summary> | /// </summary> | ||||
| IMessageChannel Channel { get; } | IMessageChannel Channel { get; } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -49,10 +55,16 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Returns all attachments included in this message. | /// Returns all attachments included in this message. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of attachments. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<IAttachment> Attachments { get; } | IReadOnlyCollection<IAttachment> Attachments { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns all embeds included in this message. | /// Returns all embeds included in this message. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of embed objects. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<IEmbed> Embeds { get; } | IReadOnlyCollection<IEmbed> Embeds { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns all tags included in this message's content. | /// Returns all tags included in this message's content. | ||||
| @@ -61,14 +73,23 @@ namespace Discord | |||||
| /// <summary> | /// <summary> | ||||
| /// Returns the IDs of channels mentioned in this message. | /// Returns the IDs of channels mentioned in this message. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of channel IDs. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<ulong> MentionedChannelIds { get; } | IReadOnlyCollection<ulong> MentionedChannelIds { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the IDs of roles mentioned in this message. | /// Returns the IDs of roles mentioned in this message. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of role IDs. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<ulong> MentionedRoleIds { get; } | IReadOnlyCollection<ulong> MentionedRoleIds { get; } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the IDs of users mentioned in this message. | /// Returns the IDs of users mentioned in this message. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of user IDs. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<ulong> MentionedUserIds { get; } | IReadOnlyCollection<ulong> MentionedUserIds { get; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Represents a message sent by the system. | |||||
| /// Represents a generic message sent by the system. | |||||
| /// </summary> | /// </summary> | ||||
| public interface ISystemMessage : IMessage | public interface ISystemMessage : IMessage | ||||
| { | { | ||||
| @@ -5,7 +5,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Represents a Discord message object. | |||||
| /// Represents a generic message sent by a user. | |||||
| /// </summary> | /// </summary> | ||||
| public interface IUserMessage : IMessage | public interface IUserMessage : IMessage | ||||
| { | { | ||||
| @@ -12,37 +12,102 @@ namespace Discord.Rest | |||||
| /// <summary> | /// <summary> | ||||
| /// Sends a message to this message channel. | /// Sends a message to this message channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="text">The message to be sent.</param> | |||||
| /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> | |||||
| /// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| #if FILESYSTEM | #if FILESYSTEM | ||||
| /// <summary> | /// <summary> | ||||
| /// Sends a file to this message channel, with an optional caption. | /// Sends a file to this message channel, with an optional caption. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="filePath">The file path of the file.</param> | |||||
| /// <param name="text">The message to be sent.</param> | |||||
| /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> | |||||
| /// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <remarks> | |||||
| /// If you wish to upload an image and have it embedded in a <see cref="EmbedType.Rich"/> embed, you may | |||||
| /// upload the file and refer to the file with "attachment://filename.ext" in the | |||||
| /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | |||||
| /// </remarks> | |||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| #endif | #endif | ||||
| /// <summary> | /// <summary> | ||||
| /// Sends a file to this message channel, with an optional caption. | /// Sends a file to this message channel, with an optional caption. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="stream">The <see cref="Stream"/> of the file to be sent.</param> | |||||
| /// <param name="filename">The name of the attachment.</param> | |||||
| /// <param name="text">The message to be sent.</param> | |||||
| /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> | |||||
| /// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <remarks> | |||||
| /// If you wish to upload an image and have it embedded in a <see cref="EmbedType.Rich"/> embed, you may | |||||
| /// upload the file and refer to the file with "attachment://filename.ext" in the | |||||
| /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | |||||
| /// </remarks> | |||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a message from this message channel with the given ID, or <see langword="null"/> if not found. | |||||
| /// Gets a message from this message channel with the given id, or <see langword="null"/> if not found. | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="id">The ID of the message.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// The message gotten from either the cache or the download, or <see langword="null"/> if none is found. | |||||
| /// </returns> | |||||
| Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null); | Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets the last N messages from this message channel. | /// Gets the last N messages from this message channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="limit">The numbers of message to be gotten from.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// Paged collection of messages. Flattening the paginated response into a collection of messages with | |||||
| /// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the messages. | |||||
| /// </returns> | |||||
| IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of messages in this channel. | /// Gets a collection of messages in this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="fromMessageId">The ID of the starting message to get the messages from.</param> | |||||
| /// <param name="dir">The direction of the messages to be gotten from.</param> | |||||
| /// <param name="limit">The numbers of message to be gotten from.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// Paged collection of messages. Flattening the paginated response into a collection of messages with | |||||
| /// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the messages. | |||||
| /// </returns> | |||||
| IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of messages in this channel. | /// Gets a collection of messages in this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="fromMessage">The starting message to get the messages from.</param> | |||||
| /// <param name="dir">The direction of the messages to be gotten from.</param> | |||||
| /// <param name="limit">The numbers of message to be gotten from.</param> | |||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// Paged collection of messages. Flattening the paginated response into a collection of messages with | |||||
| /// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the messages. | |||||
| /// </returns> | |||||
| IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of pinned messages in this channel. | /// Gets a collection of pinned messages in this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | |||||
| /// <returns> | |||||
| /// An awaitable Task containing a collection of messages. | |||||
| /// </returns> | |||||
| new Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null); | new Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null); | ||||
| } | } | ||||
| } | } | ||||
| @@ -10,7 +10,12 @@ namespace Discord.WebSocket | |||||
| /// </summary> | /// </summary> | ||||
| public interface ISocketMessageChannel : IMessageChannel | public interface ISocketMessageChannel : IMessageChannel | ||||
| { | { | ||||
| /// <summary> Gets all messages in this channel's cache. </summary> | |||||
| /// <summary> | |||||
| /// Gets all messages in this channel's cache. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A collection of WebSocket-based messages. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<SocketMessage> CachedMessages { get; } | IReadOnlyCollection<SocketMessage> CachedMessages { get; } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -20,6 +25,9 @@ namespace Discord.WebSocket | |||||
| /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> | /// <param name="isTTS">Whether the message should be read aloud by Discord or not.</param> | ||||
| /// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param> | /// <param name="embed">The <see cref="EmbedType.Rich"/> <see cref="Embed"/> to be sent.</param> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| #if FILESYSTEM | #if FILESYSTEM | ||||
| /// <summary> | /// <summary> | ||||
| @@ -35,6 +43,9 @@ namespace Discord.WebSocket | |||||
| /// upload the file and refer to the file with "attachment://filename.ext" in the | /// upload the file and refer to the file with "attachment://filename.ext" in the | ||||
| /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | ||||
| /// </remarks> | /// </remarks> | ||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| #endif | #endif | ||||
| /// <summary> | /// <summary> | ||||
| @@ -51,14 +62,47 @@ namespace Discord.WebSocket | |||||
| /// upload the file and refer to the file with "attachment://filename.ext" in the | /// upload the file and refer to the file with "attachment://filename.ext" in the | ||||
| /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | /// <see cref="Discord.EmbedBuilder.ImageUrl"/>. | ||||
| /// </remarks> | /// </remarks> | ||||
| /// <returns> | |||||
| /// An awaitable Task containing the message sent to the channel. | |||||
| /// </returns> | |||||
| new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); | ||||
| /// <summary> | |||||
| /// Gets the cached message if one exists. | |||||
| /// </summary> | |||||
| /// <param name="id">The ID of the message.</param> | |||||
| /// <returns> | |||||
| /// Cached message object; <see langword="null"/> if it doesn't exist in the cache. | |||||
| /// </returns> | |||||
| SocketMessage GetCachedMessage(ulong id); | SocketMessage GetCachedMessage(ulong id); | ||||
| /// <summary> Gets the last N messages from this message channel. </summary> | |||||
| /// <summary> | |||||
| /// Gets the last N messages from this message channel. | |||||
| /// </summary> | |||||
| /// <param name="limit">The number of messages to get.</param> | |||||
| /// <returns> | |||||
| /// A collection of WebSocket-based messages. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch); | IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch); | ||||
| /// <summary> Gets a collection of messages in this channel. </summary> | |||||
| /// <summary> | |||||
| /// Gets a collection of messages in this channel. | |||||
| /// </summary> | |||||
| /// <param name="fromMessageId">The message ID to start the fetching from.</param> | |||||
| /// <param name="dir">The direction of which the message should be gotten from.</param> | |||||
| /// <param name="limit">The number of messages to get.</param> | |||||
| /// <returns> | |||||
| /// A collection of WebSocket-based messages. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch); | IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch); | ||||
| /// <summary> Gets a collection of messages in this channel. </summary> | |||||
| /// <summary> | |||||
| /// Gets a collection of messages in this channel. | |||||
| /// </summary> | |||||
| /// <param name="fromMessage">The message to start the fetching from.</param> | |||||
| /// <param name="dir">The direction of which the message should be gotten from.</param> | |||||
| /// <param name="limit">The number of messages to get.</param> | |||||
| /// <returns> | |||||
| /// A collection of WebSocket-based messages. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch); | IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of pinned messages in this channel. | /// Gets a collection of pinned messages in this channel. | ||||
| @@ -14,6 +14,7 @@ namespace Discord.WebSocket | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketCategoryChannel : SocketGuildChannel, ICategoryChannel | public class SocketCategoryChannel : SocketGuildChannel, ICategoryChannel | ||||
| { | { | ||||
| /// <inheritdoc /> | |||||
| public override IReadOnlyCollection<SocketGuildUser> Users | public override IReadOnlyCollection<SocketGuildUser> Users | ||||
| => Guild.Users.Where(x => Permissions.GetValue( | => Guild.Users.Where(x => Permissions.GetValue( | ||||
| Permissions.ResolveChannel(Guild, x, this, Permissions.ResolveGuild(Guild, x)), | Permissions.ResolveChannel(Guild, x, this, Permissions.ResolveGuild(Guild, x)), | ||||
| @@ -30,7 +30,7 @@ namespace Discord.WebSocket | |||||
| Recipient = recipient; | Recipient = recipient; | ||||
| recipient.GlobalUser.AddRef(); | recipient.GlobalUser.AddRef(); | ||||
| if (Discord.MessageCacheSize > 0) | if (Discord.MessageCacheSize > 0) | ||||
| _messages = new MessageCache(Discord, this); | |||||
| _messages = new MessageCache(Discord); | |||||
| } | } | ||||
| internal static SocketDMChannel Create(DiscordSocketClient discord, ClientState state, Model model) | internal static SocketDMChannel Create(DiscordSocketClient discord, ClientState state, Model model) | ||||
| { | { | ||||
| @@ -39,7 +39,7 @@ namespace Discord.WebSocket | |||||
| : base(discord, id) | : base(discord, id) | ||||
| { | { | ||||
| if (Discord.MessageCacheSize > 0) | if (Discord.MessageCacheSize > 0) | ||||
| _messages = new MessageCache(Discord, this); | |||||
| _messages = new MessageCache(Discord); | |||||
| _voiceStates = new ConcurrentDictionary<ulong, SocketVoiceState>(ConcurrentHashSet.DefaultConcurrencyLevel, 5); | _voiceStates = new ConcurrentDictionary<ulong, SocketVoiceState>(ConcurrentHashSet.DefaultConcurrencyLevel, 5); | ||||
| _users = new ConcurrentDictionary<ulong, SocketGroupUser>(ConcurrentHashSet.DefaultConcurrencyLevel, 5); | _users = new ConcurrentDictionary<ulong, SocketGroupUser>(ConcurrentHashSet.DefaultConcurrencyLevel, 5); | ||||
| } | } | ||||
| @@ -108,6 +108,7 @@ namespace Discord.WebSocket | |||||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||||
| public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) | public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) | ||||
| => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); | => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); | ||||
| #if FILESYSTEM | #if FILESYSTEM | ||||
| @@ -21,7 +21,7 @@ namespace Discord.WebSocket | |||||
| /// Gets the guild associated with this channel. | /// Gets the guild associated with this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | /// <returns> | ||||
| /// The guild that this channel belongs to. | |||||
| /// A guild that this channel belongs to. | |||||
| /// </returns> | /// </returns> | ||||
| public SocketGuild Guild { get; } | public SocketGuild Guild { get; } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -34,7 +34,7 @@ namespace Discord.WebSocket | |||||
| /// Gets the parent category of this channel. | /// Gets the parent category of this channel. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | /// <returns> | ||||
| /// The parent category ID associated with this channel, or <see langword="null"/> if none is set. | |||||
| /// A parent category ID associated with this channel, or <see langword="null"/> if none is set. | |||||
| /// </returns> | /// </returns> | ||||
| public ICategoryChannel Category | public ICategoryChannel Category | ||||
| => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; | => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; | ||||
| @@ -42,7 +42,7 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites; | public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites; | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns a collection of users that are able to view the channel. | |||||
| /// Gets a collection of users that are able to view the channel. | |||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | /// <returns> | ||||
| /// A collection of users that can access the channel (i.e. the users seen in the user list). | /// A collection of users that can access the channel (i.e. the users seen in the user list). | ||||
| @@ -39,7 +39,7 @@ namespace Discord.WebSocket | |||||
| : base(discord, id, guild) | : base(discord, id, guild) | ||||
| { | { | ||||
| if (Discord.MessageCacheSize > 0) | if (Discord.MessageCacheSize > 0) | ||||
| _messages = new MessageCache(Discord, this); | |||||
| _messages = new MessageCache(Discord); | |||||
| } | } | ||||
| internal new static SocketTextChannel Create(SocketGuild guild, ClientState state, Model model) | internal new static SocketTextChannel Create(SocketGuild guild, ClientState state, Model model) | ||||
| { | { | ||||
| @@ -91,11 +91,11 @@ namespace Discord.WebSocket | |||||
| public Task SyncPromise => _syncPromise.Task; | public Task SyncPromise => _syncPromise.Task; | ||||
| public Task DownloaderPromise => _downloaderPromise.Task; | public Task DownloaderPromise => _downloaderPromise.Task; | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the <see cref="IAudioClient" /> associated with this guild. | |||||
| /// Gets the <see cref="IAudioClient" /> associated with this guild. | |||||
| /// </summary> | /// </summary> | ||||
| public IAudioClient AudioClient => _audioClient; | public IAudioClient AudioClient => _audioClient; | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the first viewable text channel. | |||||
| /// Gets the first viewable text channel. | |||||
| /// </summary> | /// </summary> | ||||
| /// <remarks> | /// <remarks> | ||||
| /// This property does not guarantee the user can send message to it. | /// This property does not guarantee the user can send message to it. | ||||
| @@ -105,7 +105,7 @@ namespace Discord.WebSocket | |||||
| .OrderBy(c => c.Position) | .OrderBy(c => c.Position) | ||||
| .FirstOrDefault(); | .FirstOrDefault(); | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the AFK voice channel, or <see langword="null" /> if none is set. | |||||
| /// Gets the AFK voice channel, or <see langword="null" /> if none is set. | |||||
| /// </summary> | /// </summary> | ||||
| public SocketVoiceChannel AFKChannel | public SocketVoiceChannel AFKChannel | ||||
| { | { | ||||
| @@ -138,31 +138,34 @@ namespace Discord.WebSocket | |||||
| } | } | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns a collection of text channels present in this guild. | |||||
| /// Gets a collection of text channels present in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| public IReadOnlyCollection<SocketTextChannel> TextChannels | public IReadOnlyCollection<SocketTextChannel> TextChannels | ||||
| => Channels.Select(x => x as SocketTextChannel).Where(x => x != null).ToImmutableArray(); | => Channels.Select(x => x as SocketTextChannel).Where(x => x != null).ToImmutableArray(); | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns a collection of voice channels present in this guild. | |||||
| /// Gets a collection of voice channels present in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| public IReadOnlyCollection<SocketVoiceChannel> VoiceChannels | public IReadOnlyCollection<SocketVoiceChannel> VoiceChannels | ||||
| => Channels.Select(x => x as SocketVoiceChannel).Where(x => x != null).ToImmutableArray(); | => Channels.Select(x => x as SocketVoiceChannel).Where(x => x != null).ToImmutableArray(); | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns a collection of category channels present in this guild. | |||||
| /// Gets a collection of category channels present in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| public IReadOnlyCollection<SocketCategoryChannel> CategoryChannels | public IReadOnlyCollection<SocketCategoryChannel> CategoryChannels | ||||
| => Channels.Select(x => x as SocketCategoryChannel).Where(x => x != null).ToImmutableArray(); | => Channels.Select(x => x as SocketCategoryChannel).Where(x => x != null).ToImmutableArray(); | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the current logged-in user. | |||||
| /// Gets the current logged-in user. | |||||
| /// </summary> | /// </summary> | ||||
| public SocketGuildUser CurrentUser => _members.TryGetValue(Discord.CurrentUser.Id, out SocketGuildUser member) ? member : null; | public SocketGuildUser CurrentUser => _members.TryGetValue(Discord.CurrentUser.Id, out SocketGuildUser member) ? member : null; | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the @everyone role in this guild. | |||||
| /// Gets the @everyone role in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| public SocketRole EveryoneRole => GetRole(Id); | public SocketRole EveryoneRole => GetRole(Id); | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns a collection of channels present in this guild. | |||||
| /// Gets a collection of channels present in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of channels. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<SocketGuildChannel> Channels | public IReadOnlyCollection<SocketGuildChannel> Channels | ||||
| { | { | ||||
| get | get | ||||
| @@ -175,10 +178,16 @@ namespace Discord.WebSocket | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of emotes created in this guild. | /// Gets a collection of emotes created in this guild. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of emotes. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<GuildEmote> Emotes => _emotes; | public IReadOnlyCollection<GuildEmote> Emotes => _emotes; | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of features enabled in this guild. | /// Gets a collection of features enabled in this guild. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of features in string. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<string> Features => _features; | public IReadOnlyCollection<string> Features => _features; | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of users in this guild. | /// Gets a collection of users in this guild. | ||||
| @@ -188,10 +197,16 @@ namespace Discord.WebSocket | |||||
| /// You may need to enable <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/> to fetch the full user list | /// You may need to enable <see cref="DiscordSocketConfig.AlwaysDownloadUsers"/> to fetch the full user list | ||||
| /// upon startup, or use <see cref="DownloadUsersAsync"/> to manually download the users. | /// upon startup, or use <see cref="DownloadUsersAsync"/> to manually download the users. | ||||
| /// </remarks> | /// </remarks> | ||||
| /// <returns> | |||||
| /// Collection of users. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<SocketGuildUser> Users => _members.ToReadOnlyCollection(); | public IReadOnlyCollection<SocketGuildUser> Users => _members.ToReadOnlyCollection(); | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of roles in this guild. | /// Gets a collection of roles in this guild. | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns> | |||||
| /// Collection of roles. | |||||
| /// </returns> | |||||
| public IReadOnlyCollection<SocketRole> Roles => _roles.ToReadOnlyCollection(); | public IReadOnlyCollection<SocketRole> Roles => _roles.ToReadOnlyCollection(); | ||||
| internal SocketGuild(DiscordSocketClient client, ulong id) | internal SocketGuild(DiscordSocketClient client, ulong id) | ||||
| @@ -378,7 +393,7 @@ namespace Discord.WebSocket | |||||
| //Bans | //Bans | ||||
| /// <summary> | /// <summary> | ||||
| /// Gets a collection of the banned users in this guild. | |||||
| /// Returns a collection of the banned users in this guild. | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | /// <returns> | ||||
| @@ -634,7 +649,7 @@ namespace Discord.WebSocket | |||||
| /// <param name="id">The ID of the webhook.</param> | /// <param name="id">The ID of the webhook.</param> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | /// <returns> | ||||
| /// A webhook associated with the ID. | |||||
| /// An awaitable Task containing the webhook associated with the ID. | |||||
| /// </returns> | /// </returns> | ||||
| public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | public Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null) | ||||
| => GuildHelper.GetWebhookAsync(this, Discord, id, options); | => GuildHelper.GetWebhookAsync(this, Discord, id, options); | ||||
| @@ -643,7 +658,7 @@ namespace Discord.WebSocket | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="options">The options to be used when sending the request.</param> | /// <param name="options">The options to be used when sending the request.</param> | ||||
| /// <returns> | /// <returns> | ||||
| /// A collection of webhooks. | |||||
| /// An awaitable Task containing a collection of webhooks. | |||||
| /// </returns> | /// </returns> | ||||
| public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | ||||
| => GuildHelper.GetWebhooksAsync(this, Discord, options); | => GuildHelper.GetWebhooksAsync(this, Discord, options); | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| @@ -14,7 +14,7 @@ namespace Discord.WebSocket | |||||
| public IReadOnlyCollection<SocketMessage> Messages => _messages.ToReadOnlyCollection(); | public IReadOnlyCollection<SocketMessage> Messages => _messages.ToReadOnlyCollection(); | ||||
| public MessageCache(DiscordSocketClient discord, IChannel channel) | |||||
| public MessageCache(DiscordSocketClient discord) | |||||
| { | { | ||||
| _size = discord.MessageCacheSize; | _size = discord.MessageCacheSize; | ||||
| _messages = new ConcurrentDictionary<ulong, SocketMessage>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(_size * 1.05)); | _messages = new ConcurrentDictionary<ulong, SocketMessage>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(_size * 1.05)); | ||||
| @@ -28,7 +28,7 @@ namespace Discord.WebSocket | |||||
| _orderedMessages.Enqueue(message.Id); | _orderedMessages.Enqueue(message.Id); | ||||
| while (_orderedMessages.Count > _size && _orderedMessages.TryDequeue(out ulong msgId)) | while (_orderedMessages.Count > _size && _orderedMessages.TryDequeue(out ulong msgId)) | ||||
| _messages.TryRemove(msgId, out SocketMessage msg); | |||||
| _messages.TryRemove(msgId, out SocketMessage _); | |||||
| } | } | ||||
| } | } | ||||
| @@ -44,6 +44,8 @@ namespace Discord.WebSocket | |||||
| return result; | return result; | ||||
| return null; | return null; | ||||
| } | } | ||||
| /// <exception cref="ArgumentOutOfRangeException"><paramref name="limit"/> is less than 0.</exception> | |||||
| public IReadOnlyCollection<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | public IReadOnlyCollection<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | ||||
| { | { | ||||
| if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit)); | if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit)); | ||||
| @@ -14,8 +14,20 @@ namespace Discord.WebSocket | |||||
| public abstract class SocketMessage : SocketEntity<ulong>, IMessage | public abstract class SocketMessage : SocketEntity<ulong>, IMessage | ||||
| { | { | ||||
| private long _timestampTicks; | private long _timestampTicks; | ||||
| /// <summary> | |||||
| /// Gets the author of this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A WebSocket-based user object. | |||||
| /// </returns> | |||||
| public SocketUser Author { get; } | public SocketUser Author { get; } | ||||
| /// <summary> | |||||
| /// Gets the source channel of the message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A WebSocket-based message channel. | |||||
| /// </returns> | |||||
| public ISocketMessageChannel Channel { get; } | public ISocketMessageChannel Channel { get; } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public MessageSource Source { get; } | public MessageSource Source { get; } | ||||
| @@ -31,10 +43,40 @@ namespace Discord.WebSocket | |||||
| public virtual bool IsPinned => false; | public virtual bool IsPinned => false; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual DateTimeOffset? EditedTimestamp => null; | public virtual DateTimeOffset? EditedTimestamp => null; | ||||
| /// <summary> | |||||
| /// Returns all attachments included in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Collection of attachments. | |||||
| /// </returns> | |||||
| public virtual IReadOnlyCollection<Attachment> Attachments => ImmutableArray.Create<Attachment>(); | public virtual IReadOnlyCollection<Attachment> Attachments => ImmutableArray.Create<Attachment>(); | ||||
| /// <summary> | |||||
| /// Returns all embeds included in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Collection of embed objects. | |||||
| /// </returns> | |||||
| public virtual IReadOnlyCollection<Embed> Embeds => ImmutableArray.Create<Embed>(); | public virtual IReadOnlyCollection<Embed> Embeds => ImmutableArray.Create<Embed>(); | ||||
| /// <summary> | |||||
| /// Returns the channels mentioned in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Collection of WebSocket-based guild channels. | |||||
| /// </returns> | |||||
| public virtual IReadOnlyCollection<SocketGuildChannel> MentionedChannels => ImmutableArray.Create<SocketGuildChannel>(); | public virtual IReadOnlyCollection<SocketGuildChannel> MentionedChannels => ImmutableArray.Create<SocketGuildChannel>(); | ||||
| /// <summary> | |||||
| /// Returns the roles mentioned in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Collection of WebSocket-based roles. | |||||
| /// </returns> | |||||
| public virtual IReadOnlyCollection<SocketRole> MentionedRoles => ImmutableArray.Create<SocketRole>(); | public virtual IReadOnlyCollection<SocketRole> MentionedRoles => ImmutableArray.Create<SocketRole>(); | ||||
| /// <summary> | |||||
| /// Returns the users mentioned in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Collection of WebSocket-based users. | |||||
| /// </returns> | |||||
| public virtual IReadOnlyCollection<SocketUser> MentionedUsers => ImmutableArray.Create<SocketUser>(); | public virtual IReadOnlyCollection<SocketUser> MentionedUsers => ImmutableArray.Create<SocketUser>(); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | ||||
| @@ -69,6 +111,12 @@ namespace Discord.WebSocket | |||||
| public Task DeleteAsync(RequestOptions options = null) | public Task DeleteAsync(RequestOptions options = null) | ||||
| => MessageHelper.DeleteAsync(this, Discord, options); | => MessageHelper.DeleteAsync(this, Discord, options); | ||||
| /// <summary> | |||||
| /// Gets the content of the message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// Content of the message. | |||||
| /// </returns> | |||||
| public override string ToString() => Content; | public override string ToString() => Content; | ||||
| internal SocketMessage Clone() => MemberwiseClone() as SocketMessage; | internal SocketMessage Clone() => MemberwiseClone() as SocketMessage; | ||||
| @@ -2,12 +2,45 @@ using Model = Discord.API.Gateway.Reaction; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Represents a WebSocket-based reaction object. | |||||
| /// </summary> | |||||
| public class SocketReaction : IReaction | public class SocketReaction : IReaction | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Gets the ID of the user who added the reaction. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A user snowflake ID. | |||||
| /// </returns> | |||||
| public ulong UserId { get; } | public ulong UserId { get; } | ||||
| /// <summary> | |||||
| /// Gets the user who added the reaction if possible. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A user object where possible. This value is not always returned. | |||||
| /// </returns> | |||||
| public Optional<IUser> User { get; } | public Optional<IUser> User { get; } | ||||
| /// <summary> | |||||
| /// Gets the ID of the message that has been reacted to. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A message snowflake ID. | |||||
| /// </returns> | |||||
| public ulong MessageId { get; } | public ulong MessageId { get; } | ||||
| /// <summary> | |||||
| /// Gets the message that has been reacted to if possible. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A WebSocket-based message where possible. This value is not always returned. | |||||
| /// </returns> | |||||
| public Optional<SocketUserMessage> Message { get; } | public Optional<SocketUserMessage> Message { get; } | ||||
| /// <summary> | |||||
| /// Gets the channel where the reaction takes place in. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A WebSocket-based message channel. | |||||
| /// </returns> | |||||
| public ISocketMessageChannel Channel { get; } | public ISocketMessageChannel Channel { get; } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public IEmote Emote { get; } | public IEmote Emote { get; } | ||||
| @@ -3,6 +3,9 @@ using Model = Discord.API.Message; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Represents a WebSocket-based message sent by the system. | |||||
| /// </summary> | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketSystemMessage : SocketMessage, ISystemMessage | public class SocketSystemMessage : SocketMessage, ISystemMessage | ||||
| { | { | ||||
| @@ -9,6 +9,9 @@ using Model = Discord.API.Message; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Represents a WebSocket-based message sent by a user. | |||||
| /// </summary> | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketUserMessage : SocketMessage, IUserMessage | public class SocketUserMessage : SocketMessage, IUserMessage | ||||
| { | { | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System.Diagnostics; | |||||
| using System.Diagnostics; | |||||
| using System.Linq; | using System.Linq; | ||||
| using Model = Discord.API.User; | using Model = Discord.API.User; | ||||
| using PresenceModel = Discord.API.Presence; | using PresenceModel = Discord.API.Presence; | ||||
| @@ -54,7 +54,8 @@ namespace Discord.WebSocket | |||||
| Presence = SocketPresence.Create(model); | Presence = SocketPresence.Create(model); | ||||
| DMChannel = state.DMChannels.FirstOrDefault(x => x.Recipient.Id == Id); | DMChannel = state.DMChannels.FirstOrDefault(x => x.Recipient.Id == Id); | ||||
| } | } | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Global)"; | |||||
| internal new SocketGlobalUser Clone() => MemberwiseClone() as SocketGlobalUser; | internal new SocketGlobalUser Clone() => MemberwiseClone() as SocketGlobalUser; | ||||
| } | } | ||||
| } | } | ||||
| @@ -35,6 +35,7 @@ namespace Discord.WebSocket | |||||
| return entity; | return entity; | ||||
| } | } | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Group)"; | |||||
| internal new SocketGroupUser Clone() => MemberwiseClone() as SocketGroupUser; | internal new SocketGroupUser Clone() => MemberwiseClone() as SocketGroupUser; | ||||
| //IVoiceState | //IVoiceState | ||||
| @@ -173,6 +173,7 @@ namespace Discord.WebSocket | |||||
| public ChannelPermissions GetPermissions(IGuildChannel channel) | public ChannelPermissions GetPermissions(IGuildChannel channel) | ||||
| => new ChannelPermissions(Permissions.ResolveChannel(Guild, this, channel, GuildPermissions.RawValue)); | => new ChannelPermissions(Permissions.ResolveChannel(Guild, this, channel, GuildPermissions.RawValue)); | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Guild)"; | |||||
| internal new SocketGuildUser Clone() => MemberwiseClone() as SocketGuildUser; | internal new SocketGuildUser Clone() => MemberwiseClone() as SocketGuildUser; | ||||
| //IGuildUser | //IGuildUser | ||||
| @@ -67,6 +67,7 @@ namespace Discord.WebSocket | |||||
| public Task ModifyAsync(Action<SelfUserProperties> func, RequestOptions options = null) | public Task ModifyAsync(Action<SelfUserProperties> func, RequestOptions options = null) | ||||
| => UserHelper.ModifyAsync(this, Discord, func, options); | => UserHelper.ModifyAsync(this, Discord, func, options); | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Self)"; | |||||
| internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser; | internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser; | ||||
| } | } | ||||
| } | } | ||||
| @@ -29,6 +29,7 @@ namespace Discord.WebSocket | |||||
| return entity; | return entity; | ||||
| } | } | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Unknown)"; | |||||
| internal new SocketUnknownUser Clone() => MemberwiseClone() as SocketUnknownUser; | internal new SocketUnknownUser Clone() => MemberwiseClone() as SocketUnknownUser; | ||||
| } | } | ||||
| } | } | ||||
| @@ -44,6 +44,7 @@ namespace Discord.WebSocket | |||||
| return entity; | return entity; | ||||
| } | } | ||||
| private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Webhook)"; | |||||
| internal new SocketWebhookUser Clone() => MemberwiseClone() as SocketWebhookUser; | internal new SocketWebhookUser Clone() => MemberwiseClone() as SocketWebhookUser; | ||||
| @@ -2,12 +2,33 @@ using System.Diagnostics; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Represents a WebSocket-based voice server. | |||||
| /// </summary> | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketVoiceServer | public class SocketVoiceServer | ||||
| { | { | ||||
| public Cacheable<IGuild, ulong> Guild { get; private set; } | |||||
| public string Endpoint { get; private set; } | |||||
| public string Token { get; private set; } | |||||
| /// <summary> | |||||
| /// Gets the guild associated with the voice server. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A cached entity of the guild. | |||||
| /// </returns> | |||||
| public Cacheable<IGuild, ulong> Guild { get; } | |||||
| /// <summary> | |||||
| /// Gets the endpoint URL of the voice server host. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// An URL representing the voice server host. | |||||
| /// </returns> | |||||
| public string Endpoint { get; } | |||||
| /// <summary> | |||||
| /// Gets the voice connection token. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A voice connection token. | |||||
| /// </returns> | |||||
| public string Token { get; } | |||||
| internal SocketVoiceServer(Cacheable<IGuild, ulong> guild, string endpoint, string token) | internal SocketVoiceServer(Cacheable<IGuild, ulong> guild, string endpoint, string token) | ||||
| { | { | ||||