diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs index 304592442..c236b1045 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs @@ -165,6 +165,13 @@ namespace Discord.WebSocket remove { _userVoiceStateUpdatedEvent.Remove(value); } } internal readonly AsyncEvent> _userVoiceStateUpdatedEvent = new AsyncEvent>(); + /// Fired when the bot connects to a Discord voice server. + public event Func VoiceServerUpdated + { + add { _voiceServerUpdatedEvent.Add(value); } + remove { _voiceServerUpdatedEvent.Remove(value); } + } + internal readonly AsyncEvent> _voiceServerUpdatedEvent = new AsyncEvent>(); /// Fired when the connected account is updated. public event Func CurrentUserUpdated { add { _selfUpdatedEvent.Add(value); } diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index eef1b1c90..039ea2fe5 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -134,7 +134,7 @@ namespace Discord.WebSocket private int GetShardIdFor(ulong guildId) => (int)((guildId >> 22) % (uint)_totalShards); public int GetShardIdFor(IGuild guild) - => GetShardIdFor(guild.Id); + => GetShardIdFor(guild?.Id ?? 0); private DiscordSocketClient GetShardFor(ulong guildId) => GetShard(GetShardIdFor(guildId)); public DiscordSocketClient GetShardFor(IGuild guild) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index d43e8a1d4..9ea8cb16d 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1479,6 +1479,12 @@ namespace Discord.WebSocket var data = (payload as JToken).ToObject(_serializer); var guild = State.GetGuild(data.GuildId); + var cacheable = new Cacheable(guild, data.GuildId, guild != null, + async () => await ApiClient.GetGuildAsync(data.GuildId).ConfigureAwait(false) as IGuild); + + var voiceServer = new SocketVoiceServer(cacheable, data.GuildId, data.Endpoint, data.Token); + await TimedInvokeAsync(_voiceServerUpdatedEvent, nameof(UserVoiceStateUpdated), voiceServer).ConfigureAwait(false); + if (guild != null) { string endpoint = data.Endpoint.Substring(0, data.Endpoint.LastIndexOf(':')); @@ -1489,6 +1495,7 @@ namespace Discord.WebSocket await UnknownGuildAsync(type, data.GuildId).ConfigureAwait(false); return; } + } break; diff --git a/src/Discord.Net.WebSocket/SocketVoiceServer.cs b/src/Discord.Net.WebSocket/SocketVoiceServer.cs new file mode 100644 index 000000000..9ab6afd3f --- /dev/null +++ b/src/Discord.Net.WebSocket/SocketVoiceServer.cs @@ -0,0 +1,21 @@ +using System.Diagnostics; + +namespace Discord.WebSocket +{ + [DebuggerDisplay(@"{DebuggerDisplay,nq}")] + public class SocketVoiceServer + { + public Cacheable Guild { get; private set; } + public string Endpoint { get; private set; } + public string Token { get; private set; } + + internal SocketVoiceServer(Cacheable guild, ulong guildId, string endpoint, string token) + { + Guild = guild; + Endpoint = endpoint; + Token = token; + } + + private string DebuggerDisplay => $"SocketVoiceServer ({Guild.Id})"; + } +}