diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj index e2d76b727..4bbf8e44a 100644 --- a/src/Discord.Net.Net45/Discord.Net.csproj +++ b/src/Discord.Net.Net45/Discord.Net.csproj @@ -201,6 +201,9 @@ Net\WebSockets\VoiceWebSocket.cs + + Net\WebSockets\VoiceWebSocket.Events.cs + Net\WebSockets\WebSocket.BuiltIn.cs diff --git a/src/Discord.Net/DiscordClient.API.cs b/src/Discord.Net/DiscordClient.API.cs index d9ba4f385..b9539d48f 100644 --- a/src/Discord.Net/DiscordClient.API.cs +++ b/src/Discord.Net/DiscordClient.API.cs @@ -279,7 +279,7 @@ namespace Discord var model = await _api.SendMessage(channelId, blockText, mentions, nonce).ConfigureAwait(false); var msg = _messages.GetOrAdd(model.Id, channelId, model.Author.Id); msg.Update(model); - RaiseEvent(nameof(MessageSent), () => RaiseMessageSent(msg)); + RaiseMessageSent(msg); } await Task.Delay(1000).ConfigureAwait(false); } diff --git a/src/Discord.Net/DiscordClient.Events.cs b/src/Discord.Net/DiscordClient.Events.cs index f8b1da5eb..064ddebb0 100644 --- a/src/Discord.Net/DiscordClient.Events.cs +++ b/src/Discord.Net/DiscordClient.Events.cs @@ -122,6 +122,23 @@ namespace Discord Channel = channel; } } + public sealed class UserIsSpeakingEventArgs : EventArgs + { + public Channel Channel => Member.VoiceChannel; + public string ChannelId => Member.VoiceChannelId; + public Server Server => Member.Server; + public string ServerId => Member.ServerId; + public User User => Member.User; + public string UserId => Member.UserId; + public Member Member { get; } + public bool IsSpeaking { get; } + + internal UserIsSpeakingEventArgs(Member member, bool isSpeaking) + { + Member = member; + IsSpeaking = isSpeaking; + } + } /*public sealed class VoiceServerUpdatedEventArgs : EventArgs { public Server Server { get; } @@ -141,19 +158,19 @@ namespace Discord private void RaiseConnected() { if (Connected != null) - Connected(this, EventArgs.Empty); + RaiseEvent(nameof(Connected), () => Connected(this, EventArgs.Empty)); } public event EventHandler Disconnected; private void RaiseDisconnected(DisconnectedEventArgs e) { if (Disconnected != null) - Disconnected(this, e); + RaiseEvent(nameof(Disconnected), () => Disconnected(this, e)); } public event EventHandler LogMessage; internal void RaiseOnLog(LogMessageSeverity severity, LogMessageSource source, string message) { if (LogMessage != null) - LogMessage(this, new LogMessageEventArgs(severity, source, message)); + RaiseEvent(nameof(LogMessage), () => LogMessage(this, new LogMessageEventArgs(severity, source, message))); } //Server @@ -161,27 +178,19 @@ namespace Discord private void RaiseServerCreated(Server server) { if (ServerCreated != null) - ServerCreated(this, new ServerEventArgs(server)); + RaiseEvent(nameof(ServerCreated), () => ServerCreated(this, new ServerEventArgs(server))); } public event EventHandler ServerDestroyed; private void RaiseServerDestroyed(Server server) { if (ServerDestroyed != null) - ServerDestroyed(this, new ServerEventArgs(server)); + RaiseEvent(nameof(ServerDestroyed), () => ServerDestroyed(this, new ServerEventArgs(server))); } public event EventHandler ServerUpdated; private void RaiseServerUpdated(Server server) { if (ServerUpdated != null) - ServerUpdated(this, new ServerEventArgs(server)); - } - - //User - public event EventHandler UserUpdated; - private void RaiseUserUpdated(User user) - { - if (UserUpdated != null) - UserUpdated(this, new UserEventArgs(user)); + RaiseEvent(nameof(ServerUpdated), () => ServerUpdated(this, new ServerEventArgs(server))); } //Channel @@ -189,19 +198,19 @@ namespace Discord private void RaiseChannelCreated(Channel channel) { if (ChannelCreated != null) - ChannelCreated(this, new ChannelEventArgs(channel)); + RaiseEvent(nameof(ChannelCreated), () => ChannelCreated(this, new ChannelEventArgs(channel))); } public event EventHandler ChannelDestroyed; private void RaiseChannelDestroyed(Channel channel) { if (ChannelDestroyed != null) - ChannelDestroyed(this, new ChannelEventArgs(channel)); + RaiseEvent(nameof(ChannelDestroyed), () => ChannelDestroyed(this, new ChannelEventArgs(channel))); } public event EventHandler ChannelUpdated; private void RaiseChannelUpdated(Channel channel) { if (ChannelUpdated != null) - ChannelUpdated(this, new ChannelEventArgs(channel)); + RaiseEvent(nameof(ChannelUpdated), () => ChannelUpdated(this, new ChannelEventArgs(channel))); } //Message @@ -209,31 +218,31 @@ namespace Discord private void RaiseMessageCreated(Message msg) { if (MessageCreated != null) - MessageCreated(this, new MessageEventArgs(msg)); + RaiseEvent(nameof(MessageCreated), () => MessageCreated(this, new MessageEventArgs(msg))); } public event EventHandler MessageDeleted; private void RaiseMessageDeleted(Message msg) { if (MessageDeleted != null) - MessageDeleted(this, new MessageEventArgs(msg)); + RaiseEvent(nameof(MessageDeleted), () => MessageDeleted(this, new MessageEventArgs(msg))); } public event EventHandler MessageUpdated; private void RaiseMessageUpdated(Message msg) { if (MessageUpdated != null) - MessageUpdated(this, new MessageEventArgs(msg)); + RaiseEvent(nameof(MessageUpdated), () => MessageUpdated(this, new MessageEventArgs(msg))); } public event EventHandler MessageReadRemotely; private void RaiseMessageReadRemotely(Message msg) { if (MessageReadRemotely != null) - MessageReadRemotely(this, new MessageEventArgs(msg)); + RaiseEvent(nameof(MessageReadRemotely), () => MessageReadRemotely(this, new MessageEventArgs(msg))); } public event EventHandler MessageSent; private void RaiseMessageSent(Message msg) { if (MessageSent != null) - MessageSent(this, new MessageEventArgs(msg)); + RaiseEvent(nameof(MessageSent), () => MessageSent(this, new MessageEventArgs(msg))); } //Role @@ -241,19 +250,19 @@ namespace Discord private void RaiseRoleCreated(Role role) { if (RoleCreated != null) - RoleCreated(this, new RoleEventArgs(role)); + RaiseEvent(nameof(RoleCreated), () => RoleCreated(this, new RoleEventArgs(role))); } public event EventHandler RoleUpdated; private void RaiseRoleDeleted(Role role) { if (RoleDeleted != null) - RoleDeleted(this, new RoleEventArgs(role)); + RaiseEvent(nameof(RoleDeleted), () => RoleDeleted(this, new RoleEventArgs(role))); } public event EventHandler RoleDeleted; private void RaiseRoleUpdated(Role role) { if (RoleUpdated != null) - RoleUpdated(this, new RoleEventArgs(role)); + RaiseEvent(nameof(RoleUpdated), () => RoleUpdated(this, new RoleEventArgs(role))); } //Ban @@ -261,71 +270,77 @@ namespace Discord private void RaiseBanAdded(string userId, Server server) { if (BanAdded != null) - BanAdded(this, new BanEventArgs(_users[userId], userId, server)); + RaiseEvent(nameof(BanAdded), () => BanAdded(this, new BanEventArgs(_users[userId], userId, server))); } public event EventHandler BanRemoved; private void RaiseBanRemoved(string userId, Server server) { if (BanRemoved != null) - BanRemoved(this, new BanEventArgs(_users[userId], userId, server)); + RaiseEvent(nameof(BanRemoved), () => BanRemoved(this, new BanEventArgs(_users[userId], userId, server))); } - //Member - public event EventHandler MemberAdded; - private void RaiseMemberAdded(Member member) + //User + public event EventHandler UserAdded; + private void RaiseUserAdded(Member member) { - if (MemberAdded != null) - MemberAdded(this, new MemberEventArgs(member)); + if (UserAdded != null) + RaiseEvent(nameof(UserAdded), () => UserAdded(this, new MemberEventArgs(member))); } - public event EventHandler MemberRemoved; - private void RaiseMemberRemoved(Member member) + public event EventHandler UserRemoved; + private void RaiseUserRemoved(Member member) { - if (MemberRemoved != null) - MemberRemoved(this, new MemberEventArgs(member)); + if (UserRemoved != null) + RaiseEvent(nameof(UserRemoved), () => UserRemoved(this, new MemberEventArgs(member))); + } + public event EventHandler UserUpdated; + private void RaiseUserUpdated(User user) + { + if (UserUpdated != null) + RaiseEvent(nameof(UserUpdated), () => UserUpdated(this, new UserEventArgs(user))); } public event EventHandler MemberUpdated; private void RaiseMemberUpdated(Member member) { if (MemberUpdated != null) - MemberUpdated(this, new MemberEventArgs(member)); + RaiseEvent(nameof(MemberUpdated), () => MemberUpdated(this, new MemberEventArgs(member))); } - public event EventHandler MemberPresenceUpdated; - private void RaiseMemberPresenceUpdated(Member member) + public event EventHandler UserPresenceUpdated; + private void RaiseUserPresenceUpdated(Member member) { - if (MemberPresenceUpdated != null) - MemberPresenceUpdated(this, new MemberEventArgs(member)); + if (UserPresenceUpdated != null) + RaiseEvent(nameof(UserPresenceUpdated), () => UserPresenceUpdated(this, new MemberEventArgs(member))); } - public event EventHandler MemberVoiceStateUpdated; - private void RaiseMemberVoiceStateUpdated(Member member) + public event EventHandler UserVoiceStateUpdated; + private void RaiseUserVoiceStateUpdated(Member member) { - if (MemberVoiceStateUpdated != null) - MemberVoiceStateUpdated(this, new MemberEventArgs(member)); + if (UserVoiceStateUpdated != null) + RaiseEvent(nameof(UserVoiceStateUpdated), () => UserVoiceStateUpdated(this, new MemberEventArgs(member))); } public event EventHandler UserIsTyping; private void RaiseUserIsTyping(User user, Channel channel) { if (UserIsTyping != null) - UserIsTyping(this, new UserTypingEventArgs(user, channel)); - } + RaiseEvent(nameof(UserIsTyping), () => UserIsTyping(this, new UserTypingEventArgs(user, channel))); + } + public event EventHandler UserIsSpeaking; + private void RaiseUserIsSpeaking(Member member, bool isSpeaking) + { + if (UserIsSpeaking != null) + RaiseEvent(nameof(UserIsSpeaking), () => UserIsSpeaking(this, new UserIsSpeakingEventArgs(member, isSpeaking))); + } //Voice public event EventHandler VoiceConnected; private void RaiseVoiceConnected() { if (VoiceConnected != null) - VoiceConnected(this, EventArgs.Empty); + RaiseEvent(nameof(UserIsSpeaking), () => VoiceConnected(this, EventArgs.Empty)); } public event EventHandler VoiceDisconnected; private void RaiseVoiceDisconnected(DisconnectedEventArgs e) { if (VoiceDisconnected != null) - VoiceDisconnected(this, e); + RaiseEvent(nameof(UserIsSpeaking), () => VoiceDisconnected(this, e)); } - /*public event EventHandler VoiceServerChanged; - private void RaiseVoiceServerUpdated(Server server, string endpoint) - { - if (VoiceServerChanged != null) - VoiceServerChanged(this, new VoiceServerUpdatedEventArgs(server, endpoint)); - }*/ } } diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 53d3341eb..93fef55ac 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -32,8 +32,8 @@ namespace Discord private readonly ManualResetEvent _disconnectedEvent; private readonly ManualResetEventSlim _connectedEvent; private readonly JsonSerializer _serializer; - private Task _runTask; protected ExceptionDispatchInfo _disconnectReason; + private Task _runTask; private bool _wasDisconnectUnexpected; private string _token; @@ -100,7 +100,32 @@ namespace Discord { _voiceSocket = new VoiceWebSocket(this); _voiceSocket.Connected += (s, e) => RaiseVoiceConnected(); - _voiceSocket.Disconnected += async (s, e) => { RaiseVoiceDisconnected(e); if (e.WasUnexpected) await _voiceSocket.Reconnect(_cancelToken); }; + _voiceSocket.Disconnected += async (s, e) => + { + foreach (var member in _members) + { + if (member.IsSpeaking) + { + member.IsSpeaking = false; + RaiseUserIsSpeaking(member, false); + } + } + RaiseVoiceDisconnected(e); + if (e.WasUnexpected) + await _voiceSocket.Reconnect(_cancelToken); + }; + _voiceSocket.IsSpeaking += (s, e) => + { + if (_voiceSocket.CurrentVoiceServerId != null) + { + var member = _members[e.UserId, _voiceSocket.CurrentVoiceServerId]; + if (!member.IsSpeaking) + { + member.IsSpeaking = true; + RaiseUserIsSpeaking(member, true); + } + } + }; } _channels = new Channels(this); @@ -136,9 +161,6 @@ namespace Discord ServerUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Updated Server: {e.Server?.Name}" + (isDebug ? $" ({e.ServerId})" : "")); - UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, - $"Updated User: {e.User.Name}" + - (isDebug ? $" ({e.UserId})" : "")); UserIsTyping += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Updated User (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel.Name}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.ChannelId}/{e.UserId})" : "")); @@ -181,19 +203,22 @@ namespace Discord BanRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? "Unknown"}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); - MemberAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Added Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); - MemberRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Removed Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); - MemberUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + $"Updated User: {e.User.Name}" + + (isDebug ? $" ({e.UserId})." : "")); + MemberUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Updated Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); - MemberPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + UserPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Updated Member (Presence): {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})" : "")); - MemberVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, + UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Updated Member (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + (isDebug ? $" ({e.ServerId ?? "0"}/{e.UserId})" : "")); @@ -267,7 +292,7 @@ namespace Discord var model = e.Payload.ToObject(_serializer); var server = _servers.GetOrAdd(model.Id); server.Update(model); - RaiseEvent(nameof(ServerCreated), () => RaiseServerCreated(server)); + RaiseServerCreated(server); } break; case "GUILD_UPDATE": @@ -277,7 +302,7 @@ namespace Discord if (server != null) { server.Update(model); - RaiseEvent(nameof(ServerUpdated), () => RaiseServerUpdated(server)); + RaiseServerUpdated(server); } } break; @@ -286,7 +311,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var server = _servers.TryRemove(data.Id); if (server != null) - RaiseEvent(nameof(ServerDestroyed), () => RaiseServerDestroyed(server)); + RaiseServerDestroyed(server); } break; @@ -296,7 +321,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var channel = _channels.GetOrAdd(data.Id, data.GuildId, data.Recipient?.Id); channel.Update(data); - RaiseEvent(nameof(ChannelCreated), () => RaiseChannelCreated(channel)); + RaiseChannelCreated(channel); } break; case "CHANNEL_UPDATE": @@ -306,7 +331,7 @@ namespace Discord if (channel != null) { channel.Update(data); - RaiseEvent(nameof(ChannelUpdated), () => RaiseChannelUpdated(channel)); + RaiseChannelUpdated(channel); } } break; @@ -315,7 +340,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var channel = _channels.TryRemove(data.Id); if (channel != null) - RaiseEvent(nameof(ChannelDestroyed), () => RaiseChannelDestroyed(channel)); + RaiseChannelDestroyed(channel); } break; @@ -329,7 +354,7 @@ namespace Discord user.UpdateActivity(DateTime.UtcNow); var member = _members.GetOrAdd(data.User.Id, data.GuildId); member.Update(data); - RaiseEvent(nameof(MemberAdded), () => RaiseMemberAdded(member)); + RaiseUserAdded(member); } break; case "GUILD_MEMBER_UPDATE": @@ -339,7 +364,7 @@ namespace Discord if (member != null) { member.Update(data); - RaiseEvent(nameof(MemberUpdated), () => RaiseMemberUpdated(member)); + RaiseMemberUpdated(member); } } break; @@ -348,7 +373,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var member = _members.TryRemove(data.UserId, data.GuildId); if (member != null) - RaiseEvent(nameof(MemberRemoved), () => RaiseMemberRemoved(member)); + RaiseUserRemoved(member); } break; @@ -358,7 +383,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var role = _roles.GetOrAdd(data.Data.Id, data.GuildId); role.Update(data.Data); - RaiseEvent(nameof(RoleUpdated), () => RaiseRoleUpdated(role)); + RaiseRoleUpdated(role); } break; case "GUILD_ROLE_UPDATE": @@ -367,7 +392,7 @@ namespace Discord var role = _roles[data.Data.Id]; if (role != null) role.Update(data.Data); - RaiseEvent(nameof(RoleUpdated), () => RaiseRoleUpdated(role)); + RaiseRoleUpdated(role); } break; case "GUILD_ROLE_DELETE": @@ -375,7 +400,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var role = _roles.TryRemove(data.RoleId); if (role != null) - RaiseEvent(nameof(RoleDeleted), () => RaiseRoleDeleted(role)); + RaiseRoleDeleted(role); } break; @@ -387,7 +412,7 @@ namespace Discord if (server != null) { server.AddBan(data.UserId); - RaiseEvent(nameof(BanAdded), () => RaiseBanAdded(data.UserId, server)); + RaiseBanAdded(data.UserId, server); } } break; @@ -396,7 +421,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var server = _servers[data.GuildId]; if (server != null && server.RemoveBan(data.UserId)) - RaiseEvent(nameof(BanRemoved), () => RaiseBanRemoved(data.UserId, server)); + RaiseBanRemoved(data.UserId, server); } break; @@ -423,8 +448,8 @@ namespace Discord if (_config.TrackActivity) msg.User.UpdateActivity(data.Timestamp); if (wasLocal) - RaiseEvent(nameof(MessageSent), () => RaiseMessageSent(msg)); - RaiseEvent(nameof(MessageCreated), () => RaiseMessageCreated(msg)); + RaiseMessageSent(msg); + RaiseMessageCreated(msg); } break; case "MESSAGE_UPDATE": @@ -434,7 +459,7 @@ namespace Discord if (msg != null) { msg.Update(data); - RaiseEvent(nameof(MessageUpdated), () => RaiseMessageUpdated(msg)); + RaiseMessageUpdated(msg); } } break; @@ -443,7 +468,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var msg = _messages.TryRemove(data.Id); if (msg != null) - RaiseEvent(nameof(MessageDeleted), () => RaiseMessageDeleted(msg)); + RaiseMessageDeleted(msg); } break; case "MESSAGE_ACK": @@ -451,7 +476,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var msg = GetMessage(data.MessageId); if (msg != null) - RaiseEvent(nameof(MessageReadRemotely), () => RaiseMessageReadRemotely(msg)); + RaiseMessageReadRemotely(msg); } break; @@ -469,7 +494,7 @@ namespace Discord if (member != null) { member.Update(data); - RaiseEvent(nameof(MemberPresenceUpdated), () => RaiseMemberPresenceUpdated(member)); + RaiseUserPresenceUpdated(member); } } break; @@ -486,7 +511,12 @@ namespace Discord if (member != null) { member.Update(data); - RaiseEvent(nameof(MemberVoiceStateUpdated), () => RaiseMemberVoiceStateUpdated(member)); + if (member.IsSpeaking) + { + member.IsSpeaking = false; + RaiseUserIsSpeaking(member, false); + } + RaiseUserVoiceStateUpdated(member); } } break; @@ -495,12 +525,13 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var channel = _channels[data.ChannelId]; var user = _users[data.UserId]; + if (user != null) { if (_config.TrackActivity) user.UpdateActivity(DateTime.UtcNow); if (channel != null) - RaiseEvent(nameof(UserIsTyping), () => RaiseUserIsTyping(user, channel)); + RaiseUserIsTyping(user, channel); } } break; @@ -526,7 +557,7 @@ namespace Discord if (user != null) { user.Update(data); - RaiseEvent(nameof(UserUpdated), () => RaiseUserUpdated(user)); + RaiseUserUpdated(user); } } break; @@ -773,7 +804,7 @@ namespace Discord } msg.IsQueued = false; msg.HasFailed = hasFailed; - RaiseEvent(nameof(MessageSent), () => RaiseMessageSent(msg)); + RaiseMessageSent(msg); } await Task.Delay(interval).ConfigureAwait(false); } diff --git a/src/Discord.Net/Models/Member.cs b/src/Discord.Net/Models/Member.cs index f5555b2c1..3ea8684e8 100644 --- a/src/Discord.Net/Models/Member.cs +++ b/src/Discord.Net/Models/Member.cs @@ -16,6 +16,7 @@ namespace Discord public bool IsSelfMuted { get; internal set; } public bool IsSelfDeafened { get; internal set; } public bool IsSuppressed { get; internal set; } + public bool IsSpeaking { get; internal set; } public string SessionId { get; internal set; } public string Token { get; internal set; } diff --git a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.Events.cs b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.Events.cs new file mode 100644 index 000000000..c97d3937d --- /dev/null +++ b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.Events.cs @@ -0,0 +1,25 @@ +using System; + +namespace Discord.Net.WebSockets +{ + public sealed class IsTalkingEventArgs : EventArgs + { + public readonly string UserId; + public readonly bool IsSpeaking; + internal IsTalkingEventArgs(string userId, bool isTalking) + { + UserId = userId; + IsSpeaking = isTalking; + } + } + + internal partial class VoiceWebSocket + { + public event EventHandler IsSpeaking; + private void RaiseIsSpeaking(string userId, bool isSpeaking) + { + if (IsSpeaking != null) + IsSpeaking(this, new IsTalkingEventArgs(userId, isSpeaking)); + } + } +} diff --git a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs index 86c7e80ce..56bbcd83f 100644 --- a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs @@ -323,6 +323,12 @@ namespace Discord.Net.WebSockets _connectWaitOnLogin.Set(); } break; + case 5: + { + var payload = (msg.Payload as JToken).ToObject(); + RaiseIsSpeaking(payload.UserId, payload.IsSpeaking); + } + break; default: if (_logLevel >= LogMessageSeverity.Warning) RaiseOnLog(LogMessageSeverity.Warning, $"Unknown Opcode: {msg.Operation}");