diff --git a/src/Discord.Net.Rest/BaseDiscordClient.cs b/src/Discord.Net.Rest/BaseDiscordClient.cs index ed12ff383..321f2482b 100644 --- a/src/Discord.Net.Rest/BaseDiscordClient.cs +++ b/src/Discord.Net.Rest/BaseDiscordClient.cs @@ -85,7 +85,8 @@ namespace Discord.Rest await _loggedInEvent.InvokeAsync().ConfigureAwait(false); } - internal virtual Task OnLoginAsync(TokenType tokenType, string token) { return Task.Delay(0); } + internal virtual Task OnLoginAsync(TokenType tokenType, string token) + => Task.Delay(0); /// public async Task LogoutAsync() @@ -110,7 +111,8 @@ namespace Discord.Rest await _loggedOutEvent.InvokeAsync().ConfigureAwait(false); } - internal virtual Task OnLogoutAsync() { return Task.Delay(0); } + internal virtual Task OnLogoutAsync() + => Task.Delay(0); internal virtual void Dispose(bool disposing) { @@ -127,7 +129,8 @@ namespace Discord.Rest ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected; ISelfUser IDiscordClient.CurrentUser => CurrentUser; - Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) { throw new NotSupportedException(); } + Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) + => throw new NotSupportedException(); Task IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(null); @@ -148,7 +151,8 @@ namespace Discord.Rest => Task.FromResult(null); Task> IDiscordClient.GetGuildsAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(ImmutableArray.Create()); - Task IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) { throw new NotSupportedException(); } + Task IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) + => throw new NotSupportedException(); Task IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(null); diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.cs b/src/Discord.Net.Rpc/DiscordRpcClient.cs index 9c77fc919..31d91faac 100644 --- a/src/Discord.Net.Rpc/DiscordRpcClient.cs +++ b/src/Discord.Net.Rpc/DiscordRpcClient.cs @@ -67,6 +67,7 @@ namespace Discord.Rpc public Task StartAsync() => _connection.StartAsync(); public Task StopAsync() => _connection.StopAsync(); + private async Task OnConnectingAsync() { diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs new file mode 100644 index 000000000..82bcc31e4 --- /dev/null +++ b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs @@ -0,0 +1,250 @@ +using System; +using System.Threading.Tasks; + +namespace Discord.WebSocket +{ + public partial class BaseSocketClient + { + /// + /// Fired when a channel is created. + /// + public event Func ChannelCreated + { + add { _channelCreatedEvent.Add(value); } + remove { _channelCreatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _channelCreatedEvent = new AsyncEvent>(); + /// + /// Fired when a channel is destroyed. + /// + public event Func ChannelDestroyed { + add { _channelDestroyedEvent.Add(value); } + remove { _channelDestroyedEvent.Remove(value); } + } + internal readonly AsyncEvent> _channelDestroyedEvent = new AsyncEvent>(); + /// + /// Fired when a channel is updated. + /// + public event Func ChannelUpdated { + add { _channelUpdatedEvent.Add(value); } + remove { _channelUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _channelUpdatedEvent = new AsyncEvent>(); + + //Messages + /// + /// Fired when a message is received. + /// + public event Func MessageReceived { + add { _messageReceivedEvent.Add(value); } + remove { _messageReceivedEvent.Remove(value); } + } + internal readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); + /// + /// Fired when a message is deleted. + /// + public event Func, ISocketMessageChannel, Task> MessageDeleted { + add { _messageDeletedEvent.Add(value); } + remove { _messageDeletedEvent.Remove(value); } + } + internal readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + /// + /// Fired when a message is updated. + /// + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { + add { _messageUpdatedEvent.Add(value); } + remove { _messageUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + /// + /// Fired when a reaction is added to a message. + /// + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { + add { _reactionAddedEvent.Add(value); } + remove { _reactionAddedEvent.Remove(value); } + } + internal readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + /// + /// Fired when a reaction is removed from a message. + /// + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { + add { _reactionRemovedEvent.Add(value); } + remove { _reactionRemovedEvent.Remove(value); } + } + internal readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + /// + /// Fired when all reactions to a message are cleared. + /// + public event Func, ISocketMessageChannel, Task> ReactionsCleared { + add { _reactionsClearedEvent.Add(value); } + remove { _reactionsClearedEvent.Remove(value); } + } + internal readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + + //Roles + /// + /// Fired when a role is created. + /// + public event Func RoleCreated { + add { _roleCreatedEvent.Add(value); } + remove { _roleCreatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _roleCreatedEvent = new AsyncEvent>(); + /// + /// Fired when a role is deleted. + /// + public event Func RoleDeleted { + add { _roleDeletedEvent.Add(value); } + remove { _roleDeletedEvent.Remove(value); } + } + internal readonly AsyncEvent> _roleDeletedEvent = new AsyncEvent>(); + /// + /// Fired when a role is updated. + /// + public event Func RoleUpdated { + add { _roleUpdatedEvent.Add(value); } + remove { _roleUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _roleUpdatedEvent = new AsyncEvent>(); + + //Guilds + /// + /// Fired when the connected account joins a guild. + /// + public event Func JoinedGuild { + add { _joinedGuildEvent.Add(value); } + remove { _joinedGuildEvent.Remove(value); } + } + internal readonly AsyncEvent> _joinedGuildEvent = new AsyncEvent>(); + /// + /// Fired when the connected account leaves a guild. + /// + public event Func LeftGuild { + add { _leftGuildEvent.Add(value); } + remove { _leftGuildEvent.Remove(value); } + } + internal readonly AsyncEvent> _leftGuildEvent = new AsyncEvent>(); + /// + /// Fired when a guild becomes available. + /// + public event Func GuildAvailable { + add { _guildAvailableEvent.Add(value); } + remove { _guildAvailableEvent.Remove(value); } + } + internal readonly AsyncEvent> _guildAvailableEvent = new AsyncEvent>(); + /// + /// Fired when a guild becomes unavailable. + /// + public event Func GuildUnavailable { + add { _guildUnavailableEvent.Add(value); } + remove { _guildUnavailableEvent.Remove(value); } + } + internal readonly AsyncEvent> _guildUnavailableEvent = new AsyncEvent>(); + /// + /// Fired when offline guild members are downloaded. + /// + public event Func GuildMembersDownloaded { + add { _guildMembersDownloadedEvent.Add(value); } + remove { _guildMembersDownloadedEvent.Remove(value); } + } + internal readonly AsyncEvent> _guildMembersDownloadedEvent = new AsyncEvent>(); + /// + /// Fired when a guild is updated. + /// + public event Func GuildUpdated { + add { _guildUpdatedEvent.Add(value); } + remove { _guildUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _guildUpdatedEvent = new AsyncEvent>(); + + //Users + /// + /// Fired when a user joins a guild. + /// + public event Func UserJoined { + add { _userJoinedEvent.Add(value); } + remove { _userJoinedEvent.Remove(value); } + } + internal readonly AsyncEvent> _userJoinedEvent = new AsyncEvent>(); + /// + /// Fired when a user leaves a guild. + /// + public event Func UserLeft { + add { _userLeftEvent.Add(value); } + remove { _userLeftEvent.Remove(value); } + } + internal readonly AsyncEvent> _userLeftEvent = new AsyncEvent>(); + /// + /// Fired when a user is banned from a guild. + /// + public event Func UserBanned { + add { _userBannedEvent.Add(value); } + remove { _userBannedEvent.Remove(value); } + } + internal readonly AsyncEvent> _userBannedEvent = new AsyncEvent>(); + /// + /// Fired when a user is unbanned from a guild. + /// + public event Func UserUnbanned { + add { _userUnbannedEvent.Add(value); } + remove { _userUnbannedEvent.Remove(value); } + } + internal readonly AsyncEvent> _userUnbannedEvent = new AsyncEvent>(); + /// + /// Fired when a user is updated. + /// + public event Func UserUpdated { + add { _userUpdatedEvent.Add(value); } + remove { _userUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _userUpdatedEvent = new AsyncEvent>(); + /// + /// Fired when a guild member is updated, or a member presence is updated. + /// + public event Func GuildMemberUpdated { + add { _guildMemberUpdatedEvent.Add(value); } + remove { _guildMemberUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _guildMemberUpdatedEvent = new AsyncEvent>(); + /// + /// Fired when a user joins, leaves, or moves voice channels. + /// + public event Func UserVoiceStateUpdated { + add { _userVoiceStateUpdatedEvent.Add(value); } + remove { _userVoiceStateUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _userVoiceStateUpdatedEvent = new AsyncEvent>(); + /// + /// Fired when the connected account is updated. + /// + public event Func CurrentUserUpdated { + add { _selfUpdatedEvent.Add(value); } + remove { _selfUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _selfUpdatedEvent = new AsyncEvent>(); + /// + /// Fired when a user starts typing. + /// + public event Func UserIsTyping { + add { _userIsTypingEvent.Add(value); } + remove { _userIsTypingEvent.Remove(value); } + } + internal readonly AsyncEvent> _userIsTypingEvent = new AsyncEvent>(); + /// + /// Fired when a user joins a group channel. + /// + public event Func RecipientAdded { + add { _recipientAddedEvent.Add(value); } + remove { _recipientAddedEvent.Remove(value); } + } + internal readonly AsyncEvent> _recipientAddedEvent = new AsyncEvent>(); + /// + /// Fired when a user is removed from a group channel. + /// + public event Func RecipientRemoved { + add { _recipientRemovedEvent.Add(value); } + remove { _recipientRemovedEvent.Remove(value); } + } + internal readonly AsyncEvent> _recipientRemovedEvent = new AsyncEvent>(); + } +} diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.cs b/src/Discord.Net.WebSocket/BaseSocketClient.cs new file mode 100644 index 000000000..bfcc0ea9a --- /dev/null +++ b/src/Discord.Net.WebSocket/BaseSocketClient.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Discord.API; +using Discord.Rest; + +namespace Discord.WebSocket +{ + public abstract partial class BaseSocketClient : BaseDiscordClient, IDiscordClient + { + protected readonly DiscordSocketConfig _baseconfig; + + /// Gets the estimated round-trip latency, in milliseconds, to the gateway server. + public abstract int Latency { get; protected set; } + public abstract UserStatus Status { get; protected set; } + public abstract Game? Game { get; protected set; } + + internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; + + public new SocketSelfUser CurrentUser { get => base.CurrentUser as SocketSelfUser; protected set => base.CurrentUser = value; } + public abstract IReadOnlyCollection Guilds { get; } + public abstract IReadOnlyCollection PrivateChannels { get; } + public abstract IReadOnlyCollection VoiceRegions { get; } + + internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client) + : base(config, client) => _baseconfig = config; + private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) + => new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent); + + /// + public abstract Task GetApplicationInfoAsync(RequestOptions options = null); + /// + public abstract SocketUser GetUser(ulong id); + /// + public abstract SocketUser GetUser(string username, string discriminator); + /// + public abstract SocketChannel GetChannel(ulong id); + /// + public abstract SocketGuild GetGuild(ulong id); + /// + public abstract RestVoiceRegion GetVoiceRegion(string id); + /// + public abstract Task StartAsync(); + /// + public abstract Task StopAsync(); + public abstract Task SetStatusAsync(UserStatus status); + public abstract Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming); + // TODO: DownloadUsersAsync? + + /// + public Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null) + => ClientHelper.CreateGuildAsync(this, name, region, jpegIcon, options ?? RequestOptions.Default); + /// + public Task> GetConnectionsAsync(RequestOptions options = null) + => ClientHelper.GetConnectionsAsync(this, options ?? RequestOptions.Default); + /// + public Task GetInviteAsync(string inviteId, RequestOptions options = null) + => ClientHelper.GetInviteAsync(this, inviteId, options ?? RequestOptions.Default); + + // IDiscordClient + async Task IDiscordClient.GetApplicationInfoAsync(RequestOptions options) + => await GetApplicationInfoAsync(options).ConfigureAwait(false); + + Task IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) + => Task.FromResult(GetChannel(id)); + Task> IDiscordClient.GetPrivateChannelsAsync(CacheMode mode, RequestOptions options) + => Task.FromResult>(PrivateChannels); + + async Task> IDiscordClient.GetConnectionsAsync(RequestOptions options) + => await GetConnectionsAsync(options).ConfigureAwait(false); + + async Task IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options) + => await GetInviteAsync(inviteId, options).ConfigureAwait(false); + + Task IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) + => Task.FromResult(GetGuild(id)); + Task> IDiscordClient.GetGuildsAsync(CacheMode mode, RequestOptions options) + => Task.FromResult>(Guilds); + + async Task IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon, RequestOptions options) + => await CreateGuildAsync(name, region, jpegIcon, options).ConfigureAwait(false); + + Task IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) + => Task.FromResult(GetUser(id)); + Task IDiscordClient.GetUserAsync(string username, string discriminator, RequestOptions options) + => Task.FromResult(GetUser(username, discriminator)); + + Task IDiscordClient.GetVoiceRegionAsync(string id, RequestOptions options) + => Task.FromResult(GetVoiceRegion(id)); + Task> IDiscordClient.GetVoiceRegionsAsync(RequestOptions options) + => Task.FromResult>(VoiceRegions); + } +} diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs index c52675e70..87fb85ccd 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs @@ -6,194 +6,21 @@ namespace Discord.WebSocket //TODO: Add event docstrings public partial class DiscordShardedClient { - //Channels - public event Func ChannelCreated - { - add { _channelCreatedEvent.Add(value); } - remove { _channelCreatedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelCreatedEvent = new AsyncEvent>(); - public event Func ChannelDestroyed - { - add { _channelDestroyedEvent.Add(value); } - remove { _channelDestroyedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelDestroyedEvent = new AsyncEvent>(); - public event Func ChannelUpdated - { - add { _channelUpdatedEvent.Add(value); } - remove { _channelUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelUpdatedEvent = new AsyncEvent>(); - - //Messages - public event Func MessageReceived - { - add { _messageReceivedEvent.Add(value); } - remove { _messageReceivedEvent.Remove(value); } - } - private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, ISocketMessageChannel, Task> MessageDeleted - { - add { _messageDeletedEvent.Add(value); } - remove { _messageDeletedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated - { - add { _messageUpdatedEvent.Add(value); } - remove { _messageUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded - { - add { _reactionAddedEvent.Add(value); } - remove { _reactionAddedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved - { - add { _reactionRemovedEvent.Add(value); } - remove { _reactionRemovedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, Task> ReactionsCleared - { - add { _reactionsClearedEvent.Add(value); } - remove { _reactionsClearedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - - //Roles - public event Func RoleCreated - { - add { _roleCreatedEvent.Add(value); } - remove { _roleCreatedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleCreatedEvent = new AsyncEvent>(); - public event Func RoleDeleted - { - add { _roleDeletedEvent.Add(value); } - remove { _roleDeletedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleDeletedEvent = new AsyncEvent>(); - public event Func RoleUpdated - { - add { _roleUpdatedEvent.Add(value); } - remove { _roleUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleUpdatedEvent = new AsyncEvent>(); - - //Guilds - public event Func JoinedGuild - { - add { _joinedGuildEvent.Add(value); } - remove { _joinedGuildEvent.Remove(value); } - } - private AsyncEvent> _joinedGuildEvent = new AsyncEvent>(); - public event Func LeftGuild - { - add { _leftGuildEvent.Add(value); } - remove { _leftGuildEvent.Remove(value); } - } - private AsyncEvent> _leftGuildEvent = new AsyncEvent>(); - public event Func GuildAvailable - { - add { _guildAvailableEvent.Add(value); } - remove { _guildAvailableEvent.Remove(value); } - } - private AsyncEvent> _guildAvailableEvent = new AsyncEvent>(); - public event Func GuildUnavailable - { - add { _guildUnavailableEvent.Add(value); } - remove { _guildUnavailableEvent.Remove(value); } - } - private AsyncEvent> _guildUnavailableEvent = new AsyncEvent>(); - public event Func GuildMembersDownloaded - { - add { _guildMembersDownloadedEvent.Add(value); } - remove { _guildMembersDownloadedEvent.Remove(value); } - } - private AsyncEvent> _guildMembersDownloadedEvent = new AsyncEvent>(); - public event Func GuildUpdated - { - add { _guildUpdatedEvent.Add(value); } - remove { _guildUpdatedEvent.Remove(value); } - } - private AsyncEvent> _guildUpdatedEvent = new AsyncEvent>(); - - //Users - public event Func UserJoined - { - add { _userJoinedEvent.Add(value); } - remove { _userJoinedEvent.Remove(value); } - } - private readonly AsyncEvent> _userJoinedEvent = new AsyncEvent>(); - public event Func UserLeft - { - add { _userLeftEvent.Add(value); } - remove { _userLeftEvent.Remove(value); } - } - private readonly AsyncEvent> _userLeftEvent = new AsyncEvent>(); - public event Func UserBanned - { - add { _userBannedEvent.Add(value); } - remove { _userBannedEvent.Remove(value); } - } - private readonly AsyncEvent> _userBannedEvent = new AsyncEvent>(); - public event Func UserUnbanned - { - add { _userUnbannedEvent.Add(value); } - remove { _userUnbannedEvent.Remove(value); } - } - private readonly AsyncEvent> _userUnbannedEvent = new AsyncEvent>(); - public event Func UserUpdated - { - add { _userUpdatedEvent.Add(value); } - remove { _userUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _userUpdatedEvent = new AsyncEvent>(); - public event Func GuildMemberUpdated - { - add { _guildMemberUpdatedEvent.Add(value); } - remove { _guildMemberUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _guildMemberUpdatedEvent = new AsyncEvent>(); - public event Func, SocketUser, SocketPresence, SocketPresence, Task> UserPresenceUpdated - { - add { _userPresenceUpdatedEvent.Add(value); } - remove { _userPresenceUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent, SocketUser, SocketPresence, SocketPresence, Task>> _userPresenceUpdatedEvent = new AsyncEvent, SocketUser, SocketPresence, SocketPresence, Task>>(); - public event Func UserVoiceStateUpdated - { - add { _userVoiceStateUpdatedEvent.Add(value); } - remove { _userVoiceStateUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _userVoiceStateUpdatedEvent = new AsyncEvent>(); - public event Func CurrentUserUpdated - { - add { _selfUpdatedEvent.Add(value); } - remove { _selfUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _selfUpdatedEvent = new AsyncEvent>(); - public event Func UserIsTyping - { - add { _userIsTypingEvent.Add(value); } - remove { _userIsTypingEvent.Remove(value); } - } - private readonly AsyncEvent> _userIsTypingEvent = new AsyncEvent>(); - public event Func RecipientAdded - { - add { _recipientAddedEvent.Add(value); } - remove { _recipientAddedEvent.Remove(value); } - } - private readonly AsyncEvent> _recipientAddedEvent = new AsyncEvent>(); - public event Func RecipientRemoved - { - add { _recipientRemovedEvent.Add(value); } - remove { _recipientRemovedEvent.Remove(value); } - } - private readonly AsyncEvent> _recipientRemovedEvent = new AsyncEvent>(); + /// + /// Fired when a shard is connected to the Discord gateway. + /// + public event Func ShardConnected { + add { _shardConnectedEvent.Add(value); } + remove { _shardConnectedEvent.Remove(value); } + } + private readonly AsyncEvent> _shardConnectedEvent = new AsyncEvent>(); + /// + /// Fired when a shard is disconnected from the Discord gateway. + /// + public event Func ShardDisconnected { + add { _shardDisconnectedEvent.Add(value); } + remove { _shardDisconnectedEvent.Remove(value); } + } + private readonly AsyncEvent> _shardDisconnectedEvent = new AsyncEvent>(); } } diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index ab2cb9266..b9c41410c 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -9,7 +9,7 @@ using System.Threading; namespace Discord.WebSocket { - public partial class DiscordShardedClient : BaseDiscordClient, IDiscordClient + public partial class DiscordShardedClient : BaseSocketClient, IDiscordClient { private readonly DiscordSocketConfig _baseConfig; private readonly SemaphoreSlim _connectionGroupLock; @@ -20,16 +20,15 @@ namespace Discord.WebSocket private bool _automaticShards; /// Gets the estimated round-trip latency, in milliseconds, to the gateway server. - public int Latency => GetLatency(); - public UserStatus Status => _shards[0].Status; - public Game? Game => _shards[0].Game; + public override int Latency { get => GetLatency(); protected set { } } + public override UserStatus Status { get => _shards[0].Status; protected set { } } + public override Game? Game { get => _shards[0].Game; protected set { } } internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; - public new SocketSelfUser CurrentUser { get { return base.CurrentUser as SocketSelfUser; } private set { base.CurrentUser = value; } } - public IReadOnlyCollection Guilds => GetGuilds().ToReadOnlyCollection(() => GetGuildCount()); - public IReadOnlyCollection PrivateChannels => GetPrivateChannels().ToReadOnlyCollection(() => GetPrivateChannelCount()); + public override IReadOnlyCollection Guilds => GetGuilds().ToReadOnlyCollection(() => GetGuildCount()); + public override IReadOnlyCollection PrivateChannels => GetPrivateChannels().ToReadOnlyCollection(() => GetPrivateChannelCount()); public IReadOnlyCollection Shards => _shards; - public IReadOnlyCollection VoiceRegions => _shards[0].VoiceRegions; + public override IReadOnlyCollection VoiceRegions => _shards[0].VoiceRegions; /// Creates a new REST/WebSocket discord client. public DiscordShardedClient() : this(null, new DiscordSocketConfig()) { } @@ -115,15 +114,11 @@ namespace Discord.WebSocket } /// - public async Task StartAsync() - { - await Task.WhenAll(_shards.Select(x => x.StartAsync())).ConfigureAwait(false); - } + public override async Task StartAsync() + => await Task.WhenAll(_shards.Select(x => x.StartAsync())).ConfigureAwait(false); /// - public async Task StopAsync() - { + public override async Task StopAsync() => await Task.WhenAll(_shards.Select(x => x.StopAsync())).ConfigureAwait(false); - } public DiscordSocketClient GetShard(int id) { @@ -141,17 +136,15 @@ namespace Discord.WebSocket => GetShardFor(guild.Id); /// - public async Task GetApplicationInfoAsync() - => await _shards[0].GetApplicationInfoAsync().ConfigureAwait(false); + public override async Task GetApplicationInfoAsync(RequestOptions options = null) + => await _shards[0].GetApplicationInfoAsync(options).ConfigureAwait(false); /// - public SocketGuild GetGuild(ulong id) => GetShardFor(id).GetGuild(id); - /// - public Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null) - => ClientHelper.CreateGuildAsync(this, name, region, jpegIcon, new RequestOptions()); + public override SocketGuild GetGuild(ulong id) + => GetShardFor(id).GetGuild(id); /// - public SocketChannel GetChannel(ulong id) + public override SocketChannel GetChannel(ulong id) { for (int i = 0; i < _shards.Length; i++) { @@ -202,7 +195,7 @@ namespace Discord.WebSocket => ClientHelper.GetInviteAsync(this, inviteId, new RequestOptions()); /// - public SocketUser GetUser(ulong id) + public override SocketUser GetUser(ulong id) { for (int i = 0; i < _shards.Length; i++) { @@ -213,7 +206,7 @@ namespace Discord.WebSocket return null; } /// - public SocketUser GetUser(string username, string discriminator) + public override SocketUser GetUser(string username, string discriminator) { for (int i = 0; i < _shards.Length; i++) { @@ -225,7 +218,7 @@ namespace Discord.WebSocket } /// - public RestVoiceRegion GetVoiceRegion(string id) + public override RestVoiceRegion GetVoiceRegion(string id) => _shards[0].GetVoiceRegion(id); /// Downloads the users list for the provided guilds, if they don't have a complete list. @@ -248,12 +241,12 @@ namespace Discord.WebSocket return (int)Math.Round(total / (double)_shards.Length); } - public async Task SetStatusAsync(UserStatus status) + public override async Task SetStatusAsync(UserStatus status) { for (int i = 0; i < _shards.Length; i++) await _shards[i].SetStatusAsync(status).ConfigureAwait(false); } - public async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) + public override async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) { for (int i = 0; i < _shards.Length; i++) await _shards[i].SetGameAsync(name, streamUrl, streamType).ConfigureAwait(false); @@ -281,6 +274,9 @@ namespace Discord.WebSocket }; } + client.Connected += () => _shardConnectedEvent.InvokeAsync(client); + client.Disconnected += (exception) => _shardDisconnectedEvent.InvokeAsync(client, exception); + client.ChannelCreated += (channel) => _channelCreatedEvent.InvokeAsync(channel); client.ChannelDestroyed += (channel) => _channelDestroyedEvent.InvokeAsync(channel); client.ChannelUpdated += (oldChannel, newChannel) => _channelUpdatedEvent.InvokeAsync(oldChannel, newChannel); diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index fb155e535..3ccfa621b 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -7,213 +7,41 @@ namespace Discord.WebSocket public partial class DiscordSocketClient { //General + /// + /// Fired when connected to the Discord gateway. + /// public event Func Connected { add { _connectedEvent.Add(value); } remove { _connectedEvent.Remove(value); } } private readonly AsyncEvent> _connectedEvent = new AsyncEvent>(); + /// + /// Fired when disconnected to the Discord gateway. + /// public event Func Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } } private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>(); + /// + /// Fired when guild data has finished downloading. + /// public event Func Ready { add { _readyEvent.Add(value); } remove { _readyEvent.Remove(value); } } private readonly AsyncEvent> _readyEvent = new AsyncEvent>(); + /// + /// Fired when a heartbeat is received from the Discord gateway. + /// public event Func LatencyUpdated { add { _latencyUpdatedEvent.Add(value); } remove { _latencyUpdatedEvent.Remove(value); } } private readonly AsyncEvent> _latencyUpdatedEvent = new AsyncEvent>(); - - //Channels - public event Func ChannelCreated - { - add { _channelCreatedEvent.Add(value); } - remove { _channelCreatedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelCreatedEvent = new AsyncEvent>(); - public event Func ChannelDestroyed - { - add { _channelDestroyedEvent.Add(value); } - remove { _channelDestroyedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelDestroyedEvent = new AsyncEvent>(); - public event Func ChannelUpdated - { - add { _channelUpdatedEvent.Add(value); } - remove { _channelUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _channelUpdatedEvent = new AsyncEvent>(); - - //Messages - public event Func MessageReceived - { - add { _messageReceivedEvent.Add(value); } - remove { _messageReceivedEvent.Remove(value); } - } - private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, ISocketMessageChannel, Task> MessageDeleted - { - add { _messageDeletedEvent.Add(value); } - remove { _messageDeletedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated - { - add { _messageUpdatedEvent.Add(value); } - remove { _messageUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded - { - add { _reactionAddedEvent.Add(value); } - remove { _reactionAddedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved - { - add { _reactionRemovedEvent.Add(value); } - remove { _reactionRemovedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, Task> ReactionsCleared - { - add { _reactionsClearedEvent.Add(value); } - remove { _reactionsClearedEvent.Remove(value); } - } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - - //Roles - public event Func RoleCreated - { - add { _roleCreatedEvent.Add(value); } - remove { _roleCreatedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleCreatedEvent = new AsyncEvent>(); - public event Func RoleDeleted - { - add { _roleDeletedEvent.Add(value); } - remove { _roleDeletedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleDeletedEvent = new AsyncEvent>(); - public event Func RoleUpdated - { - add { _roleUpdatedEvent.Add(value); } - remove { _roleUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _roleUpdatedEvent = new AsyncEvent>(); - - //Guilds - public event Func JoinedGuild - { - add { _joinedGuildEvent.Add(value); } - remove { _joinedGuildEvent.Remove(value); } - } - private readonly AsyncEvent> _joinedGuildEvent = new AsyncEvent>(); - public event Func LeftGuild - { - add { _leftGuildEvent.Add(value); } - remove { _leftGuildEvent.Remove(value); } - } - private readonly AsyncEvent> _leftGuildEvent = new AsyncEvent>(); - public event Func GuildAvailable - { - add { _guildAvailableEvent.Add(value); } - remove { _guildAvailableEvent.Remove(value); } - } - private readonly AsyncEvent> _guildAvailableEvent = new AsyncEvent>(); - public event Func GuildUnavailable - { - add { _guildUnavailableEvent.Add(value); } - remove { _guildUnavailableEvent.Remove(value); } - } - private readonly AsyncEvent> _guildUnavailableEvent = new AsyncEvent>(); - public event Func GuildMembersDownloaded - { - add { _guildMembersDownloadedEvent.Add(value); } - remove { _guildMembersDownloadedEvent.Remove(value); } - } - private readonly AsyncEvent> _guildMembersDownloadedEvent = new AsyncEvent>(); - public event Func GuildUpdated - { - add { _guildUpdatedEvent.Add(value); } - remove { _guildUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _guildUpdatedEvent = new AsyncEvent>(); - - //Users - public event Func UserJoined - { - add { _userJoinedEvent.Add(value); } - remove { _userJoinedEvent.Remove(value); } - } - private readonly AsyncEvent> _userJoinedEvent = new AsyncEvent>(); - public event Func UserLeft - { - add { _userLeftEvent.Add(value); } - remove { _userLeftEvent.Remove(value); } - } - private readonly AsyncEvent> _userLeftEvent = new AsyncEvent>(); - public event Func UserBanned - { - add { _userBannedEvent.Add(value); } - remove { _userBannedEvent.Remove(value); } - } - private readonly AsyncEvent> _userBannedEvent = new AsyncEvent>(); - public event Func UserUnbanned - { - add { _userUnbannedEvent.Add(value); } - remove { _userUnbannedEvent.Remove(value); } - } - private readonly AsyncEvent> _userUnbannedEvent = new AsyncEvent>(); - public event Func UserUpdated - { - add { _userUpdatedEvent.Add(value); } - remove { _userUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _userUpdatedEvent = new AsyncEvent>(); - public event Func GuildMemberUpdated - { - add { _guildMemberUpdatedEvent.Add(value); } - remove { _guildMemberUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _guildMemberUpdatedEvent = new AsyncEvent>(); - public event Func UserVoiceStateUpdated - { - add { _userVoiceStateUpdatedEvent.Add(value); } - remove { _userVoiceStateUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _userVoiceStateUpdatedEvent = new AsyncEvent>(); - public event Func CurrentUserUpdated - { - add { _selfUpdatedEvent.Add(value); } - remove { _selfUpdatedEvent.Remove(value); } - } - private readonly AsyncEvent> _selfUpdatedEvent = new AsyncEvent>(); - public event Func UserIsTyping - { - add { _userIsTypingEvent.Add(value); } - remove { _userIsTypingEvent.Remove(value); } - } - private readonly AsyncEvent> _userIsTypingEvent = new AsyncEvent>(); - public event Func RecipientAdded - { - add { _recipientAddedEvent.Add(value); } - remove { _recipientAddedEvent.Remove(value); } - } - private readonly AsyncEvent> _recipientAddedEvent = new AsyncEvent>(); - public event Func RecipientRemoved - { - add { _recipientRemovedEvent.Add(value); } - remove { _recipientRemovedEvent.Remove(value); } - } - private readonly AsyncEvent> _recipientRemovedEvent = new AsyncEvent>(); } } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index b13ceca1d..f3c05d385 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -19,7 +19,7 @@ using GameModel = Discord.API.Game; namespace Discord.WebSocket { - public partial class DiscordSocketClient : BaseDiscordClient, IDiscordClient + public partial class DiscordSocketClient : BaseSocketClient, IDiscordClient { private readonly ConcurrentQueue _largeGuilds; private readonly JsonSerializer _serializer; @@ -44,10 +44,10 @@ namespace Discord.WebSocket public int ShardId { get; } /// Gets the current connection state of this client. public ConnectionState ConnectionState => _connection.State; - /// Gets the estimated round-trip latency, in milliseconds, to the gateway server. - public int Latency { get; private set; } - internal UserStatus Status { get; private set; } = UserStatus.Online; - internal Game? Game { get; private set; } + /// + public override int Latency { get; protected set; } + public override UserStatus Status { get; protected set; } = UserStatus.Online; + public override Game? Game { get; protected set; } //From DiscordSocketConfig internal int TotalShards { get; private set; } @@ -60,14 +60,13 @@ namespace Discord.WebSocket internal int? HandlerTimeout { get; private set; } internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; - public new SocketSelfUser CurrentUser { get => base.CurrentUser as SocketSelfUser; private set => base.CurrentUser = value; } - public IReadOnlyCollection Guilds => State.Guilds; - public IReadOnlyCollection PrivateChannels => State.PrivateChannels; + public override IReadOnlyCollection Guilds => State.Guilds; + public override IReadOnlyCollection PrivateChannels => State.PrivateChannels; public IReadOnlyCollection DMChannels => State.PrivateChannels.Select(x => x as SocketDMChannel).Where(x => x != null).ToImmutableArray(); public IReadOnlyCollection GroupChannels => State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray(); - public IReadOnlyCollection VoiceRegions => _voiceRegions.ToReadOnlyCollection(); + public override IReadOnlyCollection VoiceRegions => _voiceRegions.ToReadOnlyCollection(); /// Creates a new REST/WebSocket discord client. public DiscordSocketClient() : this(new DiscordSocketConfig()) { } @@ -155,9 +154,9 @@ namespace Discord.WebSocket _voiceRegions = ImmutableDictionary.Create(); } - public async Task StartAsync() + public override async Task StartAsync() => await _connection.StartAsync().ConfigureAwait(false); - public async Task StopAsync() + public override async Task StopAsync() => await _connection.StopAsync().ConfigureAwait(false); private async Task OnConnectingAsync() @@ -231,25 +230,16 @@ namespace Discord.WebSocket } /// - public async Task GetApplicationInfoAsync() - { - return _applicationInfo ?? (_applicationInfo = await ClientHelper.GetApplicationInfoAsync(this, new RequestOptions())); - } + public override async Task GetApplicationInfoAsync(RequestOptions options = null) + => _applicationInfo ?? (_applicationInfo = await ClientHelper.GetApplicationInfoAsync(this, options ?? RequestOptions.Default)); /// - public SocketGuild GetGuild(ulong id) - { - return State.GetGuild(id); - } - /// - public Task CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null) - => ClientHelper.CreateGuildAsync(this, name, region, jpegIcon, new RequestOptions()); + public override SocketGuild GetGuild(ulong id) + => State.GetGuild(id); /// - public SocketChannel GetChannel(ulong id) - { - return State.GetChannel(id); - } + public override SocketChannel GetChannel(ulong id) + => State.GetChannel(id); /// public Task> GetConnectionsAsync() @@ -260,15 +250,11 @@ namespace Discord.WebSocket => ClientHelper.GetInviteAsync(this, inviteId, new RequestOptions()); /// - public SocketUser GetUser(ulong id) - { - return State.GetUser(id); - } + public override SocketUser GetUser(ulong id) + => State.GetUser(id); /// - public SocketUser GetUser(string username, string discriminator) - { - return State.Users.FirstOrDefault(x => x.Discriminator == discriminator && x.Username == username); - } + public override SocketUser GetUser(string username, string discriminator) + => State.Users.FirstOrDefault(x => x.Discriminator == discriminator && x.Username == username); internal SocketGlobalUser GetOrCreateUser(ClientState state, Discord.API.User model) { return state.GetOrAddUser(model.Id, x => @@ -288,13 +274,11 @@ namespace Discord.WebSocket return user; }); } - internal void RemoveUser(ulong id) - { - State.RemoveUser(id); - } + internal void RemoveUser(ulong id) + => State.RemoveUser(id); /// - public RestVoiceRegion GetVoiceRegion(string id) + public override RestVoiceRegion GetVoiceRegion(string id) { if (_voiceRegions.TryGetValue(id, out RestVoiceRegion region)) return region; @@ -340,7 +324,7 @@ namespace Discord.WebSocket } } - public async Task SetStatusAsync(UserStatus status) + public override async Task SetStatusAsync(UserStatus status) { Status = status; if (status == UserStatus.AFK) @@ -349,7 +333,7 @@ namespace Discord.WebSocket _statusSince = null; await SendStatusAsync().ConfigureAwait(false); } - public async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) + public override async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) { if (name != null) Game = new Game(name, streamUrl, streamType);