@@ -6,7 +6,7 @@ namespace Discord.WebSocket | |||
{ | |||
public partial class BaseSocketClient | |||
{ | |||
//Channels | |||
#region Channels | |||
/// <summary> Fired when a channel is created. </summary> | |||
/// <remarks> | |||
/// <para> | |||
@@ -74,8 +74,9 @@ namespace Discord.WebSocket | |||
remove { _channelUpdatedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketChannel, SocketChannel, Task>> _channelUpdatedEvent = new AsyncEvent<Func<SocketChannel, SocketChannel, Task>>(); | |||
#endregion | |||
//Messages | |||
#region Messages | |||
/// <summary> Fired when a message is received. </summary> | |||
/// <remarks> | |||
/// <para> | |||
@@ -128,7 +129,8 @@ namespace Discord.WebSocket | |||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs" /> | |||
/// </example> | |||
public event Func<Cacheable<IMessage, ulong>, Cacheable<IMessageChannel, ulong>, Task> MessageDeleted { | |||
public event Func<Cacheable<IMessage, ulong>, Cacheable<IMessageChannel, ulong>, Task> MessageDeleted | |||
{ | |||
add { _messageDeletedEvent.Add(value); } | |||
remove { _messageDeletedEvent.Remove(value); } | |||
} | |||
@@ -222,19 +224,22 @@ namespace Discord.WebSocket | |||
/// <code language="cs" region="ReactionAdded" | |||
/// source="..\Discord.Net.Examples\WebSocket\BaseSocketClient.Events.Examples.cs"/> | |||
/// </example> | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task> ReactionAdded { | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task> ReactionAdded | |||
{ | |||
add { _reactionAddedEvent.Add(value); } | |||
remove { _reactionAddedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task>>(); | |||
/// <summary> Fired when a reaction is removed from a message. </summary> | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task> ReactionRemoved { | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task> ReactionRemoved | |||
{ | |||
add { _reactionRemovedEvent.Add(value); } | |||
remove { _reactionRemovedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, SocketReaction, Task>>(); | |||
/// <summary> Fired when all reactions to a message are cleared. </summary> | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, Task> ReactionsCleared { | |||
public event Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, Task> ReactionsCleared | |||
{ | |||
add { _reactionsClearedEvent.Add(value); } | |||
remove { _reactionsClearedEvent.Remove(value); } | |||
} | |||
@@ -261,8 +266,9 @@ namespace Discord.WebSocket | |||
remove { _reactionsRemovedForEmoteEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, IEmote, Task>> _reactionsRemovedForEmoteEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, Cacheable<IMessageChannel, ulong>, IEmote, Task>>(); | |||
#endregion | |||
//Roles | |||
#region Roles | |||
/// <summary> Fired when a role is created. </summary> | |||
public event Func<SocketRole, Task> RoleCreated | |||
{ | |||
@@ -284,8 +290,9 @@ namespace Discord.WebSocket | |||
remove { _roleUpdatedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketRole, SocketRole, Task>> _roleUpdatedEvent = new AsyncEvent<Func<SocketRole, SocketRole, Task>>(); | |||
#endregion | |||
//Guilds | |||
#region Guilds | |||
/// <summary> Fired when the connected account joins a guild. </summary> | |||
public event Func<SocketGuild, Task> JoinedGuild | |||
{ | |||
@@ -328,8 +335,9 @@ namespace Discord.WebSocket | |||
remove { _guildUpdatedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketGuild, SocketGuild, Task>> _guildUpdatedEvent = new AsyncEvent<Func<SocketGuild, SocketGuild, Task>>(); | |||
#endregion | |||
//Users | |||
#region Users | |||
/// <summary> Fired when a user joins a guild. </summary> | |||
public event Func<SocketGuildUser, Task> UserJoined | |||
{ | |||
@@ -366,11 +374,12 @@ namespace Discord.WebSocket | |||
} | |||
internal readonly AsyncEvent<Func<SocketUser, SocketUser, Task>> _userUpdatedEvent = new AsyncEvent<Func<SocketUser, SocketUser, Task>>(); | |||
/// <summary> Fired when a guild member is updated, or a member presence is updated. </summary> | |||
public event Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task> GuildMemberUpdated { | |||
public event Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task> GuildMemberUpdated | |||
{ | |||
add { _guildMemberUpdatedEvent.Add(value); } | |||
remove { _guildMemberUpdatedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task>> _guildMemberUpdatedEvent = new AsyncEvent<Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task>>(); | |||
internal readonly AsyncEvent<Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task>> _guildMemberUpdatedEvent = new AsyncEvent<Func<Cacheable<SocketGuildUser, ulong>, SocketGuildUser, Task>>(); | |||
/// <summary> Fired when a user joins, leaves, or moves voice channels. </summary> | |||
public event Func<SocketUser, SocketVoiceState, SocketVoiceState, Task> UserVoiceStateUpdated | |||
{ | |||
@@ -393,7 +402,8 @@ namespace Discord.WebSocket | |||
} | |||
internal readonly AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>> _selfUpdatedEvent = new AsyncEvent<Func<SocketSelfUser, SocketSelfUser, Task>>(); | |||
/// <summary> Fired when a user starts typing. </summary> | |||
public event Func<Cacheable<IUser, ulong>, Cacheable<IMessageChannel, ulong>, Task> UserIsTyping { | |||
public event Func<Cacheable<IUser, ulong>, Cacheable<IMessageChannel, ulong>, Task> UserIsTyping | |||
{ | |||
add { _userIsTypingEvent.Add(value); } | |||
remove { _userIsTypingEvent.Remove(value); } | |||
} | |||
@@ -412,8 +422,9 @@ namespace Discord.WebSocket | |||
remove { _recipientRemovedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<SocketGroupUser, Task>>(); | |||
#endregion | |||
//Invites | |||
#region Invites | |||
/// <summary> | |||
/// Fired when an invite is created. | |||
/// </summary> | |||
@@ -454,8 +465,9 @@ namespace Discord.WebSocket | |||
remove { _inviteDeletedEvent.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketGuildChannel, string, Task>> _inviteDeletedEvent = new AsyncEvent<Func<SocketGuildChannel, string, Task>>(); | |||
#endregion | |||
//Interactions | |||
#region Interactions | |||
/// <summary> | |||
/// Fired when an Interaction is created. This event covers all types of interactions including but not limited to: buttons, select menus, slash commands. | |||
/// </summary> | |||
@@ -730,5 +742,6 @@ namespace Discord.WebSocket | |||
remove { _guildStickerDeleted.Remove(value); } | |||
} | |||
internal readonly AsyncEvent<Func<SocketCustomSticker, Task>> _guildStickerDeleted = new AsyncEvent<Func<SocketCustomSticker, Task>>(); | |||
#endregion | |||
} | |||
} |
@@ -12,6 +12,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public abstract partial class BaseSocketClient : BaseDiscordClient, IDiscordClient | |||
{ | |||
#region BaseSocketClient | |||
protected readonly DiscordSocketConfig BaseConfig; | |||
/// <summary> | |||
@@ -79,7 +80,7 @@ namespace Discord.WebSocket | |||
: base(config, client) => BaseConfig = config; | |||
private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) | |||
=> new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, | |||
useSystemClock: config.UseSystemClock); | |||
useSystemClock: config.UseSystemClock); | |||
/// <summary> | |||
/// Gets a Discord application information for the logged-in user. | |||
@@ -282,8 +283,9 @@ namespace Discord.WebSocket | |||
/// A <see cref="SocketSticker"/> if found, otherwise <see langword="null"/>. | |||
/// </returns> | |||
public abstract Task<SocketSticker> GetStickerAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | |||
// IDiscordClient | |||
#endregion | |||
#region IDiscordClient | |||
/// <inheritdoc /> | |||
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync(RequestOptions options) | |||
=> await GetApplicationInfoAsync(options).ConfigureAwait(false); | |||
@@ -331,5 +333,6 @@ namespace Discord.WebSocket | |||
{ | |||
return await GetVoiceRegionsAsync().ConfigureAwait(false); | |||
} | |||
#endregion | |||
} | |||
} |
@@ -5,6 +5,7 @@ namespace Discord.Commands | |||
/// <summary> The sharded variant of <see cref="ICommandContext"/>, which may contain the client, user, guild, channel, and message. </summary> | |||
public class ShardedCommandContext : SocketCommandContext, ICommandContext | |||
{ | |||
#region ShardedCommandContext | |||
/// <summary> Gets the <see cref="DiscordShardedClient"/> that the command is executed with. </summary> | |||
public new DiscordShardedClient Client { get; } | |||
@@ -17,9 +18,11 @@ namespace Discord.Commands | |||
/// <summary> Gets the shard ID of the command context. </summary> | |||
private static int GetShardId(DiscordShardedClient client, IGuild guild) | |||
=> guild == null ? 0 : client.GetShardIdFor(guild); | |||
#endregion | |||
//ICommandContext | |||
#region ICommandContext | |||
/// <inheritdoc /> | |||
IDiscordClient ICommandContext.Client => Client; | |||
#endregion | |||
} | |||
} |
@@ -7,6 +7,7 @@ namespace Discord.Commands | |||
/// </summary> | |||
public class SocketCommandContext : ICommandContext | |||
{ | |||
#region SocketCommandContext | |||
/// <summary> | |||
/// Gets the <see cref="DiscordSocketClient" /> that the command is executed with. | |||
/// </summary> | |||
@@ -46,8 +47,9 @@ namespace Discord.Commands | |||
User = msg.Author; | |||
Message = msg; | |||
} | |||
#endregion | |||
//ICommandContext | |||
#region ICommandContext | |||
/// <inheritdoc/> | |||
IDiscordClient ICommandContext.Client => Client; | |||
/// <inheritdoc/> | |||
@@ -58,5 +60,6 @@ namespace Discord.Commands | |||
IUser ICommandContext.User => User; | |||
/// <inheritdoc/> | |||
IUserMessage ICommandContext.Message => Message; | |||
#endregion | |||
} | |||
} |
@@ -5,7 +5,7 @@ namespace Discord.WebSocket | |||
{ | |||
public partial class DiscordShardedClient | |||
{ | |||
//General | |||
#region General | |||
/// <summary> Fired when a shard is connected to the Discord gateway. </summary> | |||
public event Func<DiscordSocketClient, Task> ShardConnected | |||
{ | |||
@@ -34,5 +34,6 @@ namespace Discord.WebSocket | |||
remove { _shardLatencyUpdatedEvent.Remove(value); } | |||
} | |||
private readonly AsyncEvent<Func<int, int, DiscordSocketClient, Task>> _shardLatencyUpdatedEvent = new AsyncEvent<Func<int, int, DiscordSocketClient, Task>>(); | |||
#endregion | |||
} | |||
} |
@@ -12,6 +12,7 @@ namespace Discord.WebSocket | |||
{ | |||
public partial class DiscordShardedClient : BaseSocketClient, IDiscordClient | |||
{ | |||
#region DiscordShardedClient | |||
private readonly DiscordSocketConfig _baseConfig; | |||
private readonly Dictionary<int, int> _shardIdsToIndex; | |||
private readonly bool _automaticShards; | |||
@@ -484,8 +485,9 @@ namespace Discord.WebSocket | |||
client.GuildStickerDeleted += (sticker) => _guildStickerDeleted.InvokeAsync(sticker); | |||
client.GuildStickerUpdated += (before, after) => _guildStickerUpdated.InvokeAsync(before, after); | |||
} | |||
#endregion | |||
//IDiscordClient | |||
#region IDiscordClient | |||
/// <inheritdoc /> | |||
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync(RequestOptions options) | |||
=> await GetApplicationInfoAsync().ConfigureAwait(false); | |||
@@ -532,7 +534,9 @@ namespace Discord.WebSocket | |||
{ | |||
return await GetVoiceRegionAsync(id).ConfigureAwait(false); | |||
} | |||
#endregion | |||
#region Dispose | |||
internal override void Dispose(bool disposing) | |||
{ | |||
if (!_isDisposed) | |||
@@ -551,5 +555,6 @@ namespace Discord.WebSocket | |||
base.Dispose(disposing); | |||
} | |||
#endregion | |||
} | |||
} |
@@ -217,7 +217,7 @@ namespace Discord.API | |||
ConnectionState = ConnectionState.Disconnected; | |||
} | |||
//Core | |||
#region Core | |||
public Task SendGatewayAsync(GatewayOpCode opCode, object payload, RequestOptions options = null) | |||
=> SendGatewayInternalAsync(opCode, payload, options); | |||
private async Task SendGatewayInternalAsync(GatewayOpCode opCode, object payload, RequestOptions options) | |||
@@ -327,5 +327,6 @@ namespace Discord.API | |||
options = RequestOptions.CreateOrClone(options); | |||
await SendGatewayAsync(GatewayOpCode.GuildSync, guildIds, options: options).ConfigureAwait(false); | |||
} | |||
#endregion | |||
} | |||
} |
@@ -6,7 +6,7 @@ namespace Discord.WebSocket | |||
{ | |||
public partial class DiscordSocketClient | |||
{ | |||
//General | |||
#region General | |||
/// <summary> Fired when connected to the Discord gateway. </summary> | |||
public event Func<Task> Connected | |||
{ | |||
@@ -45,5 +45,6 @@ namespace Discord.WebSocket | |||
internal DiscordSocketClient(DiscordSocketConfig config, DiscordRestApiClient client) : base(config, client) | |||
{ | |||
} | |||
#endregion | |||
} | |||
} |
@@ -2815,7 +2815,7 @@ namespace Discord.WebSocket | |||
internal int GetAudioId() => _nextAudioId++; | |||
//IDiscordClient | |||
#region IDiscordClient | |||
/// <inheritdoc /> | |||
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync(RequestOptions options) | |||
=> await GetApplicationInfoAsync().ConfigureAwait(false); | |||
@@ -2878,5 +2878,6 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
async Task IDiscordClient.StopAsync() | |||
=> await StopAsync().ConfigureAwait(false); | |||
#endregion | |||
} | |||
} |
@@ -18,6 +18,7 @@ namespace Discord.Audio | |||
{ | |||
internal class DiscordVoiceAPIClient : IDisposable | |||
{ | |||
#region DiscordVoiceAPIClient | |||
public const int MaxBitrate = 128 * 1024; | |||
public const string Mode = "xsalsa20_poly1305"; | |||
@@ -126,8 +127,9 @@ namespace Discord.Audio | |||
await _udp.SendAsync(data, offset, bytes).ConfigureAwait(false); | |||
await _sentDataEvent.InvokeAsync(bytes).ConfigureAwait(false); | |||
} | |||
#endregion | |||
//WebSocket | |||
#region WebSocket | |||
public async Task SendHeartbeatAsync(RequestOptions options = null) | |||
{ | |||
await SendAsync(VoiceOpCode.Heartbeat, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), options: options).ConfigureAwait(false); | |||
@@ -208,10 +210,12 @@ namespace Discord.Audio | |||
} | |||
private async Task DisconnectInternalAsync() | |||
{ | |||
if (ConnectionState == ConnectionState.Disconnected) return; | |||
if (ConnectionState == ConnectionState.Disconnected) | |||
return; | |||
ConnectionState = ConnectionState.Disconnecting; | |||
try { _connectCancelToken?.Cancel(false); } | |||
try | |||
{ _connectCancelToken?.Cancel(false); } | |||
catch { } | |||
//Wait for tasks to complete | |||
@@ -220,8 +224,9 @@ namespace Discord.Audio | |||
ConnectionState = ConnectionState.Disconnected; | |||
} | |||
#endregion | |||
//Udp | |||
#region Udp | |||
public async Task SendDiscoveryAsync(uint ssrc) | |||
{ | |||
var packet = new byte[70]; | |||
@@ -252,8 +257,9 @@ namespace Discord.Audio | |||
{ | |||
_udp.SetDestination(ip, port); | |||
} | |||
#endregion | |||
//Helpers | |||
#region Helpers | |||
private static double ToMilliseconds(Stopwatch stopwatch) => Math.Round((double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2); | |||
private string SerializeJson(object value) | |||
{ | |||
@@ -269,5 +275,6 @@ namespace Discord.Audio | |||
using (JsonReader reader = new JsonTextReader(text)) | |||
return _serializer.Deserialize<T>(reader); | |||
} | |||
#endregion | |||
} | |||
} |
@@ -14,6 +14,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketCategoryChannel : SocketGuildChannel, ICategoryChannel | |||
{ | |||
#region SocketCategoryChannel | |||
/// <inheritdoc /> | |||
public override IReadOnlyCollection<SocketGuildUser> Users | |||
=> Guild.Users.Where(x => Permissions.GetValue( | |||
@@ -41,8 +42,9 @@ namespace Discord.WebSocket | |||
entity.Update(state, model); | |||
return entity; | |||
} | |||
#endregion | |||
//Users | |||
#region Users | |||
/// <inheritdoc /> | |||
public override SocketGuildUser GetUser(ulong id) | |||
{ | |||
@@ -59,21 +61,24 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Name} ({Id}, Category)"; | |||
internal new SocketCategoryChannel Clone() => MemberwiseClone() as SocketCategoryChannel; | |||
#endregion | |||
// IGuildChannel | |||
#region IGuildChannel | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | |||
/// <inheritdoc /> | |||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IGuildUser>(GetUser(id)); | |||
#endregion | |||
//IChannel | |||
#region IChannel | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); | |||
/// <inheritdoc /> | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IUser>(GetUser(id)); | |||
#endregion | |||
} | |||
} |
@@ -13,6 +13,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public abstract class SocketChannel : SocketEntity<ulong>, IChannel | |||
{ | |||
#region SocketChannel | |||
/// <summary> | |||
/// Gets when the channel is created. | |||
/// </summary> | |||
@@ -41,8 +42,9 @@ namespace Discord.WebSocket | |||
} | |||
} | |||
internal abstract void Update(ClientState state, Model model); | |||
#endregion | |||
//User | |||
#region User | |||
/// <summary> | |||
/// Gets a generic user from this channel. | |||
/// </summary> | |||
@@ -56,8 +58,9 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"Unknown ({Id}, Channel)"; | |||
internal SocketChannel Clone() => MemberwiseClone() as SocketChannel; | |||
#endregion | |||
//IChannel | |||
#region IChannel | |||
/// <inheritdoc /> | |||
string IChannel.Name => null; | |||
@@ -67,5 +70,6 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> AsyncEnumerable.Empty<IReadOnlyCollection<IUser>>(); //Overridden | |||
#endregion | |||
} | |||
} |
@@ -16,6 +16,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketDMChannel : SocketChannel, IDMChannel, ISocketPrivateChannel, ISocketMessageChannel | |||
{ | |||
#region SocketDMChannel | |||
/// <summary> | |||
/// Gets the recipient of the channel. | |||
/// </summary> | |||
@@ -58,8 +59,9 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
public Task CloseAsync(RequestOptions options = null) | |||
=> ChannelHelper.DeleteAsync(this, Discord, options); | |||
#endregion | |||
//Messages | |||
#region Messages | |||
/// <inheritdoc /> | |||
public SocketMessage GetCachedMessage(ulong id) | |||
=> null; | |||
@@ -172,8 +174,9 @@ namespace Discord.WebSocket | |||
{ | |||
return null; | |||
} | |||
#endregion | |||
//Users | |||
#region Users | |||
/// <summary> | |||
/// Gets a user in this channel from the provided <paramref name="id"/>. | |||
/// </summary> | |||
@@ -197,26 +200,31 @@ namespace Discord.WebSocket | |||
public override string ToString() => $"@{Recipient}"; | |||
private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)"; | |||
internal new SocketDMChannel Clone() => MemberwiseClone() as SocketDMChannel; | |||
#endregion | |||
//SocketChannel | |||
#region SocketChannel | |||
/// <inheritdoc /> | |||
internal override IReadOnlyCollection<SocketUser> GetUsersInternal() => Users; | |||
/// <inheritdoc /> | |||
internal override SocketUser GetUserInternal(ulong id) => GetUser(id); | |||
#endregion | |||
//IDMChannel | |||
#region IDMChannel | |||
/// <inheritdoc /> | |||
IUser IDMChannel.Recipient => Recipient; | |||
#endregion | |||
//ISocketPrivateChannel | |||
#region ISocketPrivateChannel | |||
/// <inheritdoc /> | |||
IReadOnlyCollection<SocketUser> ISocketPrivateChannel.Recipients => ImmutableArray.Create(Recipient); | |||
#endregion | |||
//IPrivateChannel | |||
#region IPrivateChannel | |||
/// <inheritdoc /> | |||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => ImmutableArray.Create<IUser>(Recipient); | |||
#endregion | |||
//IMessageChannel | |||
#region IMessageChannel | |||
/// <inheritdoc /> | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
@@ -246,8 +254,9 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, ISticker[] stickers) | |||
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false); | |||
#endregion | |||
//IChannel | |||
#region IChannel | |||
/// <inheritdoc /> | |||
string IChannel.Name => $"@{Recipient}"; | |||
@@ -257,5 +266,6 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); | |||
#endregion | |||
} | |||
} |
@@ -20,6 +20,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketGroupChannel : SocketChannel, IGroupChannel, ISocketPrivateChannel, ISocketMessageChannel, ISocketAudioChannel | |||
{ | |||
#region SocketGroupChannel | |||
private readonly MessageCache _messages; | |||
private readonly ConcurrentDictionary<ulong, SocketVoiceState> _voiceStates; | |||
@@ -84,8 +85,9 @@ namespace Discord.WebSocket | |||
{ | |||
throw new NotSupportedException("Voice is not yet supported for group channels."); | |||
} | |||
#endregion | |||
//Messages | |||
#region Messages | |||
/// <inheritdoc /> | |||
public SocketMessage GetCachedMessage(ulong id) | |||
=> _messages?.Get(id); | |||
@@ -204,8 +206,9 @@ namespace Discord.WebSocket | |||
=> _messages?.Add(msg); | |||
internal SocketMessage RemoveMessage(ulong id) | |||
=> _messages?.Remove(id); | |||
#endregion | |||
//Users | |||
#region Users | |||
/// <summary> | |||
/// Gets a user from this group. | |||
/// </summary> | |||
@@ -240,8 +243,9 @@ namespace Discord.WebSocket | |||
} | |||
return null; | |||
} | |||
#endregion | |||
//Voice States | |||
#region Voice States | |||
internal SocketVoiceState AddOrUpdateVoiceState(ClientState state, VoiceStateModel model) | |||
{ | |||
var voiceChannel = state.GetChannel(model.ChannelId.Value) as SocketVoiceChannel; | |||
@@ -268,22 +272,26 @@ namespace Discord.WebSocket | |||
public override string ToString() => Name; | |||
private string DebuggerDisplay => $"{Name} ({Id}, Group)"; | |||
internal new SocketGroupChannel Clone() => MemberwiseClone() as SocketGroupChannel; | |||
#endregion | |||
//SocketChannel | |||
#region SocketChannel | |||
/// <inheritdoc /> | |||
internal override IReadOnlyCollection<SocketUser> GetUsersInternal() => Users; | |||
/// <inheritdoc /> | |||
internal override SocketUser GetUserInternal(ulong id) => GetUser(id); | |||
#endregion | |||
//ISocketPrivateChannel | |||
#region ISocketPrivateChannel | |||
/// <inheritdoc /> | |||
IReadOnlyCollection<SocketUser> ISocketPrivateChannel.Recipients => Recipients; | |||
#endregion | |||
//IPrivateChannel | |||
#region IPrivateChannel | |||
/// <inheritdoc /> | |||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => Recipients; | |||
#endregion | |||
//IMessageChannel | |||
#region IMessageChannel | |||
/// <inheritdoc /> | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
@@ -314,19 +322,22 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, ISticker[] stickers) | |||
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false); | |||
#endregion | |||
//IAudioChannel | |||
#region IAudioChannel | |||
/// <inheritdoc /> | |||
/// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception> | |||
Task<IAudioClient> IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } | |||
Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } | |||
#endregion | |||
//IChannel | |||
#region IChannel | |||
/// <inheritdoc /> | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IUser>(GetUser(id)); | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); | |||
#endregion | |||
} | |||
} |
@@ -15,6 +15,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketGuildChannel : SocketChannel, IGuildChannel | |||
{ | |||
#region SocketGuildChannel | |||
private ImmutableArray<Overwrite> _overwrites; | |||
/// <summary> | |||
@@ -27,7 +28,7 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
public string Name { get; private set; } | |||
/// <inheritdoc /> | |||
public int Position { get; private set; } | |||
public int Position { get; private set; } | |||
/// <inheritdoc /> | |||
public virtual IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites; | |||
@@ -69,7 +70,7 @@ namespace Discord.WebSocket | |||
{ | |||
Name = model.Name.Value; | |||
Position = model.Position.GetValueOrDefault(0); | |||
var overwrites = model.PermissionOverwrites.GetValueOrDefault(new API.Overwrite[0]); | |||
var newOverwrites = ImmutableArray.CreateBuilder<Overwrite>(overwrites.Length); | |||
for (int i = 0; i < overwrites.Length; i++) | |||
@@ -180,14 +181,16 @@ namespace Discord.WebSocket | |||
public override string ToString() => Name; | |||
private string DebuggerDisplay => $"{Name} ({Id}, Guild)"; | |||
internal new SocketGuildChannel Clone() => MemberwiseClone() as SocketGuildChannel; | |||
#endregion | |||
//SocketChannel | |||
#region SocketChannel | |||
/// <inheritdoc /> | |||
internal override IReadOnlyCollection<SocketUser> GetUsersInternal() => Users; | |||
/// <inheritdoc /> | |||
internal override SocketUser GetUserInternal(ulong id) => GetUser(id); | |||
#endregion | |||
//IGuildChannel | |||
#region IGuildChannel | |||
/// <inheritdoc /> | |||
IGuild IGuildChannel.Guild => Guild; | |||
/// <inheritdoc /> | |||
@@ -218,13 +221,15 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IGuildUser>(GetUser(id)); | |||
#endregion | |||
//IChannel | |||
#region IChannel | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); //Overridden in Text/Voice | |||
/// <inheritdoc /> | |||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IUser>(GetUser(id)); //Overridden in Text/Voice | |||
#endregion | |||
} | |||
} |
@@ -16,6 +16,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketTextChannel : SocketGuildChannel, ITextChannel, ISocketMessageChannel | |||
{ | |||
#region SocketTextChannel | |||
private readonly MessageCache _messages; | |||
/// <inheritdoc /> | |||
@@ -122,8 +123,9 @@ namespace Discord.WebSocket | |||
return thread; | |||
} | |||
#endregion | |||
//Messages | |||
#region Messages | |||
/// <inheritdoc /> | |||
public SocketMessage GetCachedMessage(ulong id) | |||
=> _messages?.Get(id); | |||
@@ -250,8 +252,9 @@ namespace Discord.WebSocket | |||
=> _messages?.Add(msg); | |||
internal SocketMessage RemoveMessage(ulong id) | |||
=> _messages?.Remove(id); | |||
#endregion | |||
//Users | |||
#region Users | |||
/// <inheritdoc /> | |||
public override SocketGuildUser GetUser(ulong id) | |||
{ | |||
@@ -265,8 +268,9 @@ namespace Discord.WebSocket | |||
} | |||
return null; | |||
} | |||
#endregion | |||
//Webhooks | |||
#region Webhooks | |||
/// <summary> | |||
/// Creates a webhook in this text channel. | |||
/// </summary> | |||
@@ -300,8 +304,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public virtual Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||
=> ChannelHelper.GetWebhooksAsync(this, Discord, options); | |||
#endregion | |||
//Invites | |||
#region Invites | |||
/// <inheritdoc /> | |||
public virtual async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | |||
@@ -317,8 +322,9 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Name} ({Id}, Text)"; | |||
internal new SocketTextChannel Clone() => MemberwiseClone() as SocketTextChannel; | |||
#endregion | |||
//ITextChannel | |||
#region ITextChannel | |||
/// <inheritdoc /> | |||
async Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options) | |||
=> await CreateWebhookAsync(name, avatar, options).ConfigureAwait(false); | |||
@@ -331,16 +337,18 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
async Task<IThreadChannel> ITextChannel.CreateThreadAsync(string name, ThreadType type, ThreadArchiveDuration autoArchiveDuration, IMessage message, RequestOptions options) | |||
=> await CreateThreadAsync(name, type, autoArchiveDuration, message, options); | |||
#endregion | |||
//IGuildChannel | |||
#region IGuildChannel | |||
/// <inheritdoc /> | |||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IGuildUser>(GetUser(id)); | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | |||
#endregion | |||
//IMessageChannel | |||
#region IMessageChannel | |||
/// <inheritdoc /> | |||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) | |||
{ | |||
@@ -371,10 +379,12 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, ISticker[] stickers) | |||
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false); | |||
#endregion | |||
// INestedChannel | |||
#region INestedChannel | |||
/// <inheritdoc /> | |||
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) | |||
=> Task.FromResult(Category); | |||
#endregion | |||
} | |||
} |
@@ -16,6 +16,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketVoiceChannel : SocketGuildChannel, IVoiceChannel, ISocketAudioChannel | |||
{ | |||
#region SocketVoiceChannel | |||
/// <inheritdoc /> | |||
public int Bitrate { get; private set; } | |||
/// <inheritdoc /> | |||
@@ -84,8 +85,9 @@ namespace Discord.WebSocket | |||
return user; | |||
return null; | |||
} | |||
#endregion | |||
//Invites | |||
#region Invites | |||
/// <inheritdoc /> | |||
public async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) | |||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false); | |||
@@ -101,18 +103,21 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; | |||
internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel; | |||
#endregion | |||
//IGuildChannel | |||
#region IGuildChannel | |||
/// <inheritdoc /> | |||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||
=> Task.FromResult<IGuildUser>(GetUser(id)); | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | |||
#endregion | |||
// INestedChannel | |||
#region INestedChannel | |||
/// <inheritdoc /> | |||
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options) | |||
=> Task.FromResult(Category); | |||
#endregion | |||
} | |||
} |
@@ -30,6 +30,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketGuild : SocketEntity<ulong>, IGuild, IDisposable | |||
{ | |||
#region SocketGuild | |||
#pragma warning disable IDISP002, IDISP006 | |||
private readonly SemaphoreSlim _audioLock; | |||
private TaskCompletionSource<bool> _syncPromise, _downloaderPromise; | |||
@@ -571,6 +572,7 @@ namespace Discord.WebSocket | |||
emotes.Add(model.Emojis[i].ToEntity()); | |||
_emotes = emotes.ToImmutable(); | |||
} | |||
#endregion | |||
#region General | |||
/// <inheritdoc /> | |||
@@ -960,8 +962,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public Task<RestInviteMetadata> GetVanityInviteAsync(RequestOptions options = null) | |||
=> GuildHelper.GetVanityInviteAsync(this, Discord, options); | |||
#endregion | |||
//Roles | |||
#region Roles | |||
/// <summary> | |||
/// Gets a role in this guild. | |||
/// </summary> | |||
@@ -1189,8 +1192,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public Task<IReadOnlyCollection<RestGuildUser>> SearchUsersAsync(string query, int limit = DiscordConfig.MaxUsersPerBatch, RequestOptions options = null) | |||
=> GuildHelper.SearchUsersAsync(this, Discord, query, limit, options); | |||
#endregion | |||
//Audit logs | |||
#region Audit logs | |||
/// <summary> | |||
/// Gets the specified number of audit log entries for this guild. | |||
/// </summary> | |||
@@ -1205,8 +1209,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null) | |||
=> GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType); | |||
#endregion | |||
//Webhooks | |||
#region Webhooks | |||
/// <summary> | |||
/// Gets a webhook found within this guild. | |||
/// </summary> | |||
@@ -1228,8 +1233,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) | |||
=> GuildHelper.GetWebhooksAsync(this, Discord, options); | |||
#endregion | |||
//Emotes | |||
#region Emotes | |||
/// <inheritdoc /> | |||
public Task<IReadOnlyCollection<GuildEmote>> GetEmotesAsync(RequestOptions options = null) | |||
=> GuildHelper.GetEmotesAsync(this, Discord, options); | |||
@@ -10,6 +10,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public class SocketSlashCommandDataOption : IApplicationCommandInteractionDataOption | |||
{ | |||
#region SocketSlashCommandDataOption | |||
/// <inheritdoc/> | |||
public string Name { get; private set; } | |||
@@ -116,17 +117,20 @@ namespace Discord.WebSocket | |||
? model.Options.Value.Select(x => new SocketSlashCommandDataOption(data, x)).ToImmutableArray() | |||
: null; | |||
} | |||
#endregion | |||
// Converters | |||
#region Converters | |||
public static explicit operator bool(SocketSlashCommandDataOption option) | |||
=> (bool)option.Value; | |||
public static explicit operator int(SocketSlashCommandDataOption option) | |||
=> (int)option.Value; | |||
public static explicit operator string(SocketSlashCommandDataOption option) | |||
=> option.Value.ToString(); | |||
#endregion | |||
// IApplicationCommandInteractionDataOption | |||
#region IApplicationCommandInteractionDataOption | |||
IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options | |||
=> this.Options; | |||
#endregion | |||
} | |||
} |
@@ -15,6 +15,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public class SocketApplicationCommand : SocketEntity<ulong>, IApplicationCommand | |||
{ | |||
#region SocketApplicationCommand | |||
/// <summary> | |||
/// <see langword="true"/> if this command is a global command, otherwise <see langword="false"/>. | |||
/// </summary> | |||
@@ -113,8 +114,10 @@ namespace Discord.WebSocket | |||
this.Update(command); | |||
} | |||
#endregion | |||
// IApplicationCommand | |||
#region IApplicationCommand | |||
IReadOnlyCollection<IApplicationCommandOption> IApplicationCommand.Options => Options; | |||
#endregion | |||
} | |||
} |
@@ -12,6 +12,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public abstract class SocketInteraction : SocketEntity<ulong>, IDiscordInteraction | |||
{ | |||
#region SocketInteraction | |||
/// <summary> | |||
/// The <see cref="ISocketMessageChannel"/> this interaction was used in. | |||
/// </summary> | |||
@@ -219,9 +220,9 @@ namespace Discord.WebSocket | |||
// Tokens last for 15 minutes according to https://discord.com/developers/docs/interactions/slash-commands#responding-to-an-interaction | |||
return (DateTime.UtcNow - this.CreatedAt.UtcDateTime).TotalMinutes <= 15d; | |||
} | |||
#endregion | |||
// IDiscordInteraction | |||
#region IDiscordInteraction | |||
/// <inheritdoc/> | |||
async Task<IUserMessage> IDiscordInteraction.FollowupAsync (string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, | |||
RequestOptions options, MessageComponent component, Embed embed) | |||
@@ -234,5 +235,6 @@ namespace Discord.WebSocket | |||
/// <inheritdoc/> | |||
async Task<IUserMessage> IDiscordInteraction.ModifyOriginalResponseAsync (Action<MessageProperties> func, RequestOptions options) | |||
=> await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false); | |||
#endregion | |||
} | |||
} |
@@ -14,6 +14,7 @@ namespace Discord.WebSocket | |||
/// </summary> | |||
public abstract class SocketMessage : SocketEntity<ulong>, IMessage | |||
{ | |||
#region SocketMessage | |||
private long _timestampTicks; | |||
private readonly List<SocketReaction> _reactions = new List<SocketReaction>(); | |||
@@ -240,8 +241,9 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public override string ToString() => Content; | |||
internal SocketMessage Clone() => MemberwiseClone() as SocketMessage; | |||
#endregion | |||
//IMessage | |||
#region IMessage | |||
/// <inheritdoc /> | |||
IUser IMessage.Author => Author; | |||
/// <inheritdoc /> | |||
@@ -299,5 +301,6 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null) | |||
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options); | |||
#endregion | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
using Discord.Rest; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
@@ -14,6 +14,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketRole : SocketEntity<ulong>, IRole | |||
{ | |||
#region SocketRole | |||
/// <summary> | |||
/// Gets the guild that owns this role. | |||
/// </summary> | |||
@@ -54,7 +55,7 @@ namespace Discord.WebSocket | |||
/// <summary> | |||
/// Returns an IEnumerable containing all <see cref="SocketGuildUser"/> that have this role. | |||
/// </summary> | |||
public IEnumerable<SocketGuildUser> Members | |||
public IEnumerable<SocketGuildUser> Members | |||
=> Guild.Users.Where(x => x.Roles.Any(r => r.Id == Id)); | |||
internal SocketRole(SocketGuild guild, ulong id) | |||
@@ -100,9 +101,11 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
public int CompareTo(IRole role) => RoleUtils.Compare(this, role); | |||
#endregion | |||
//IRole | |||
#region IRole | |||
/// <inheritdoc /> | |||
IGuild IRole.Guild => Guild; | |||
#endregion | |||
} | |||
} |
@@ -16,6 +16,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketCustomSticker : SocketSticker, ICustomSticker | |||
{ | |||
#region SocketCustomSticker | |||
/// <summary> | |||
/// Gets the user that uploaded the guild sticker. | |||
/// </summary> | |||
@@ -71,12 +72,14 @@ namespace Discord.WebSocket | |||
internal SocketCustomSticker Clone() => MemberwiseClone() as SocketCustomSticker; | |||
private new string DebuggerDisplay => Guild == null ? base.DebuggerDisplay : $"{Name} in {Guild.Name} ({Id})"; | |||
#endregion | |||
// ICustomSticker | |||
#region ICustomSticker | |||
ulong? ICustomSticker.AuthorId | |||
=> this.AuthorId; | |||
IGuild ICustomSticker.Guild | |||
=> this.Guild; | |||
#endregion | |||
} | |||
} |
@@ -10,6 +10,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay("{DebuggerDisplay,nq}")] | |||
public class SocketGroupUser : SocketUser, IGroupUser | |||
{ | |||
#region SocketGroupUser | |||
/// <summary> | |||
/// Gets the group channel of the user. | |||
/// </summary> | |||
@@ -53,8 +54,9 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Group)"; | |||
internal new SocketGroupUser Clone() => MemberwiseClone() as SocketGroupUser; | |||
#endregion | |||
//IVoiceState | |||
#region IVoiceState | |||
/// <inheritdoc /> | |||
bool IVoiceState.IsDeafened => false; | |||
/// <inheritdoc /> | |||
@@ -73,5 +75,6 @@ namespace Discord.WebSocket | |||
bool IVoiceState.IsStreaming => false; | |||
/// <inheritdoc /> | |||
DateTimeOffset? IVoiceState.RequestToSpeakTimestamp => null; | |||
#endregion | |||
} | |||
} |
@@ -18,6 +18,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketGuildUser : SocketUser, IGuildUser | |||
{ | |||
#region SocketGuildUser | |||
private long? _premiumSinceTicks; | |||
private long? _joinedAtTicks; | |||
private ImmutableArray<ulong> _roleIds; | |||
@@ -65,7 +66,7 @@ namespace Discord.WebSocket | |||
public DateTimeOffset? RequestToSpeakTimestamp => VoiceState?.RequestToSpeakTimestamp ?? null; | |||
/// <inheritdoc /> | |||
public bool? IsPending { get; private set; } | |||
/// <inheritdoc /> | |||
public DateTimeOffset? JoinedAt => DateTimeUtils.FromTicks(_joinedAtTicks); | |||
@@ -220,8 +221,9 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Guild)"; | |||
internal new SocketGuildUser Clone() => MemberwiseClone() as SocketGuildUser; | |||
#endregion | |||
//IGuildUser | |||
#region IGuildUser | |||
/// <inheritdoc /> | |||
IGuild IGuildUser.Guild => Guild; | |||
/// <inheritdoc /> | |||
@@ -232,5 +234,6 @@ namespace Discord.WebSocket | |||
//IVoiceState | |||
/// <inheritdoc /> | |||
IVoiceChannel IVoiceState.VoiceChannel => VoiceChannel; | |||
#endregion | |||
} | |||
} |
@@ -13,6 +13,7 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketWebhookUser : SocketUser, IWebhookUser | |||
{ | |||
#region SocketWebhookUser | |||
/// <summary> Gets the guild of this webhook. </summary> | |||
public SocketGuild Guild { get; } | |||
/// <inheritdoc /> | |||
@@ -66,9 +67,9 @@ namespace Discord.WebSocket | |||
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Webhook)"; | |||
internal new SocketWebhookUser Clone() => MemberwiseClone() as SocketWebhookUser; | |||
#endregion | |||
//IGuildUser | |||
#region IGuildUser | |||
/// <inheritdoc /> | |||
IGuild IGuildUser.Guild => Guild; | |||
/// <inheritdoc /> | |||
@@ -139,8 +140,9 @@ namespace Discord.WebSocket | |||
/// <exception cref="NotSupportedException">Roles are not supported on webhook users.</exception> | |||
Task IGuildUser.RemoveRolesAsync(IEnumerable<IRole> roles, RequestOptions options) => | |||
throw new NotSupportedException("Roles are not supported on webhook users."); | |||
#endregion | |||
//IVoiceState | |||
#region IVoiceState | |||
/// <inheritdoc /> | |||
bool IVoiceState.IsDeafened => false; | |||
/// <inheritdoc /> | |||
@@ -159,5 +161,6 @@ namespace Discord.WebSocket | |||
bool IVoiceState.IsStreaming => false; | |||
/// <inheritdoc /> | |||
DateTimeOffset? IVoiceState.RequestToSpeakTimestamp => null; | |||
#endregion | |||
} | |||
} |