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