Browse Source

Reworked Presence and VoiceState, added updated events

tags/1.0-rc
RogueException 9 years ago
parent
commit
31b0085ae3
8 changed files with 277 additions and 136 deletions
  1. +190
    -0
      src/Discord.Net/DiscordSocketClient.Events.cs
  2. +42
    -100
      src/Discord.Net/DiscordSocketClient.cs
  3. +4
    -19
      src/Discord.Net/Entities/Users/GuildUser.cs
  4. +0
    -4
      src/Discord.Net/Entities/Users/IGuildUser.cs
  5. +4
    -0
      src/Discord.Net/Entities/Users/IVoiceState.cs
  6. +1
    -1
      src/Discord.Net/Entities/WebSocket/CachedGuild.cs
  7. +20
    -6
      src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs
  8. +16
    -6
      src/Discord.Net/Entities/WebSocket/VoiceState.cs

+ 190
- 0
src/Discord.Net/DiscordSocketClient.Events.cs View File

@@ -0,0 +1,190 @@
using System;
using System.Threading.Tasks;

namespace Discord
{
public partial class DiscordSocketClient
{
//General
public event Func<Task> Connected
{
add { _connectedEvent.Add(value); }
remove { _connectedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<Task>> _connectedEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> Disconnected
{
add { _disconnectedEvent.Add(value); }
remove { _disconnectedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<Task>> _disconnectedEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> Ready
{
add { _readyEvent.Add(value); }
remove { _readyEvent.Remove(value); }
}
private readonly AsyncEvent<Func<Task>> _readyEvent = new AsyncEvent<Func<Task>>();
public event Func<int, int, Task> LatencyUpdated
{
add { _latencyUpdatedEvent.Add(value); }
remove { _latencyUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<int, int, Task>> _latencyUpdatedEvent = new AsyncEvent<Func<int, int, Task>>();

//Channels
public event Func<IChannel, Task> ChannelCreated
{
add { _channelCreatedEvent.Add(value); }
remove { _channelCreatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IChannel, Task>> _channelCreatedEvent = new AsyncEvent<Func<IChannel, Task>>();
public event Func<IChannel, Task> ChannelDestroyed
{
add { _channelDestroyedEvent.Add(value); }
remove { _channelDestroyedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IChannel, Task>> _channelDestroyedEvent = new AsyncEvent<Func<IChannel, Task>>();
public event Func<IChannel, IChannel, Task> ChannelUpdated
{
add { _channelUpdatedEvent.Add(value); }
remove { _channelUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IChannel, IChannel, Task>> _channelUpdatedEvent = new AsyncEvent<Func<IChannel, IChannel, Task>>();

//Messages
public event Func<IMessage, Task> MessageReceived
{
add { _messageReceivedEvent.Add(value); }
remove { _messageReceivedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<IMessage, Task>>();
public event Func<ulong, Optional<IMessage>, Task> MessageDeleted
{
add { _messageDeletedEvent.Add(value); }
remove { _messageDeletedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<ulong, Optional<IMessage>, Task>> _messageDeletedEvent = new AsyncEvent<Func<ulong, Optional<IMessage>, Task>>();
public event Func<Optional<IMessage>, IMessage, Task> MessageUpdated
{
add { _messageUpdatedEvent.Add(value); }
remove { _messageUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<Optional<IMessage>, IMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Optional<IMessage>, IMessage, Task>>();

//Roles
public event Func<IRole, Task> RoleCreated
{
add { _roleCreatedEvent.Add(value); }
remove { _roleCreatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IRole, Task>> _roleCreatedEvent = new AsyncEvent<Func<IRole, Task>>();
public event Func<IRole, Task> RoleDeleted
{
add { _roleDeletedEvent.Add(value); }
remove { _roleDeletedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IRole, Task>> _roleDeletedEvent = new AsyncEvent<Func<IRole, Task>>();
public event Func<IRole, IRole, Task> RoleUpdated
{
add { _roleUpdatedEvent.Add(value); }
remove { _roleUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IRole, IRole, Task>> _roleUpdatedEvent = new AsyncEvent<Func<IRole, IRole, Task>>();

//Guilds
public event Func<IGuild, Task> JoinedGuild
{
add { _joinedGuildEvent.Add(value); }
remove { _joinedGuildEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> LeftGuild
{
add { _leftGuildEvent.Add(value); }
remove { _leftGuildEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildAvailable
{
add { _guildAvailableEvent.Add(value); }
remove { _guildAvailableEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildUnavailable
{
add { _guildUnavailableEvent.Add(value); }
remove { _guildUnavailableEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildDownloadedMembers
{
add { _guildDownloadedMembersEvent.Add(value); }
remove { _guildDownloadedMembersEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, Task>> _guildDownloadedMembersEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, IGuild, Task> GuildUpdated
{
add { _guildUpdatedEvent.Add(value); }
remove { _guildUpdatedEvent.Remove(value); }
}
private AsyncEvent<Func<IGuild, IGuild, Task>> _guildUpdatedEvent = new AsyncEvent<Func<IGuild, IGuild, Task>>();

//Users
public event Func<IGuildUser, Task> UserJoined
{
add { _userJoinedEvent.Add(value); }
remove { _userJoinedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IGuildUser, Task>> _userJoinedEvent = new AsyncEvent<Func<IGuildUser, Task>>();
public event Func<IGuildUser, Task> UserLeft
{
add { _userLeftEvent.Add(value); }
remove { _userLeftEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IGuildUser, Task>> _userLeftEvent = new AsyncEvent<Func<IGuildUser, Task>>();
public event Func<IUser, IGuild, Task> UserBanned
{
add { _userBannedEvent.Add(value); }
remove { _userBannedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IUser, IGuild, Task>> _userBannedEvent = new AsyncEvent<Func<IUser, IGuild, Task>>();
public event Func<IUser, IGuild, Task> UserUnbanned
{
add { _userUnbannedEvent.Add(value); }
remove { _userUnbannedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IUser, IGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<IUser, IGuild, Task>>();
public event Func<IGuildUser, IGuildUser, Task> UserUpdated
{
add { _userUpdatedEvent.Add(value); }
remove { _userUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IGuildUser, IGuildUser, Task>> _userUpdatedEvent = new AsyncEvent<Func<IGuildUser, IGuildUser, Task>>();
public event Func<IGuildUser, IPresence, IPresence, Task> UserPresenceUpdated
{
add { _userPresenceUpdatedEvent.Add(value); }
remove { _userPresenceUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>> _userPresenceUpdatedEvent = new AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>>();
public event Func<IGuildUser, IVoiceState, IVoiceState, Task> UserVoiceStateUpdated
{
add { _userVoiceStateUpdatedEvent.Add(value); }
remove { _userVoiceStateUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IGuildUser, IVoiceState, IVoiceState, Task>> _userVoiceStateUpdatedEvent = new AsyncEvent<Func<IGuildUser, IVoiceState, IVoiceState, Task>>();
public event Func<ISelfUser, ISelfUser, Task> CurrentUserUpdated
{
add { _selfUpdatedEvent.Add(value); }
remove { _selfUpdatedEvent.Remove(value); }
}
private readonly AsyncEvent<Func<ISelfUser, ISelfUser, Task>> _selfUpdatedEvent = new AsyncEvent<Func<ISelfUser, ISelfUser, Task>>();
public event Func<IUser, IChannel, Task> UserIsTyping
{
add { _userIsTypingEvent.Add(value); }
remove { _userIsTypingEvent.Remove(value); }
}
private readonly AsyncEvent<Func<IUser, IChannel, Task>> _userIsTypingEvent = new AsyncEvent<Func<IUser, IChannel, Task>>();

//TODO: Add PresenceUpdated? VoiceStateUpdated?, VoiceConnected, VoiceDisconnected;
}
}

+ 42
- 100
src/Discord.Net/DiscordSocketClient.cs View File

@@ -19,77 +19,8 @@ namespace Discord
//TODO: Add event docstrings
//TODO: Add reconnect logic (+ensure the heartbeat task to shut down)
//TODO: Add resume logic
public class DiscordSocketClient : DiscordClient, IDiscordClient
public partial class DiscordSocketClient : DiscordClient, IDiscordClient
{
private object _eventLock = new object();

//General
public event Func<Task> Connected { add { _connectedEvent.Add(value); } remove { _connectedEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _connectedEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _disconnectedEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> Ready { add { _readyEvent.Add(value); } remove { _readyEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _readyEvent = new AsyncEvent<Func<Task>>();

public event Func<int, int, Task> LatencyUpdated { add { _latencyUpdatedEvent.Add(value); } remove { _latencyUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<int, int, Task>> _latencyUpdatedEvent = new AsyncEvent<Func<int, int, Task>>();

//Channels
public event Func<IChannel, Task> ChannelCreated { add { _channelCreatedEvent.Add(value); } remove { _channelCreatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IChannel, Task>> _channelCreatedEvent = new AsyncEvent<Func<IChannel, Task>>();
public event Func<IChannel, Task> ChannelDestroyed { add { _channelDestroyedEvent.Add(value); } remove { _channelDestroyedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IChannel, Task>> _channelDestroyedEvent = new AsyncEvent<Func<IChannel, Task>>();
public event Func<IChannel, IChannel, Task> ChannelUpdated { add { _channelUpdatedEvent.Add(value); } remove { _channelUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IChannel, IChannel, Task>> _channelUpdatedEvent = new AsyncEvent<Func<IChannel, IChannel, Task>>();

//Messages
public event Func<IMessage, Task> MessageReceived { add { _messageReceivedEvent.Add(value); } remove { _messageReceivedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<IMessage, Task>>();
public event Func<ulong, Optional<IMessage>, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } }
private readonly AsyncEvent<Func<ulong, Optional<IMessage>, Task>> _messageDeletedEvent = new AsyncEvent<Func<ulong, Optional<IMessage>, Task>>();
public event Func<Optional<IMessage>, IMessage, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<Optional<IMessage>, IMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Optional<IMessage>, IMessage, Task>>();

//Roles
public event Func<IRole, Task> RoleCreated { add { _roleCreatedEvent.Add(value); } remove { _roleCreatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IRole, Task>> _roleCreatedEvent = new AsyncEvent<Func<IRole, Task>>();
public event Func<IRole, Task> RoleDeleted { add { _roleDeletedEvent.Add(value); } remove { _roleDeletedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IRole, Task>> _roleDeletedEvent = new AsyncEvent<Func<IRole, Task>>();
public event Func<IRole, IRole, Task> RoleUpdated { add { _roleUpdatedEvent.Add(value); } remove { _roleUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IRole, IRole, Task>> _roleUpdatedEvent = new AsyncEvent<Func<IRole, IRole, Task>>();

//Guilds
public event Func<IGuild, Task> JoinedGuild { add { _joinedGuildEvent.Add(value); } remove { _joinedGuildEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> LeftGuild { add { _leftGuildEvent.Add(value); } remove { _leftGuildEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildAvailable { add { _guildAvailableEvent.Add(value); } remove { _guildAvailableEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildUnavailable { add { _guildUnavailableEvent.Add(value); } remove { _guildUnavailableEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, Task> GuildDownloadedMembers { add { _guildDownloadedMembersEvent.Add(value); } remove { _guildDownloadedMembersEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, Task>> _guildDownloadedMembersEvent = new AsyncEvent<Func<IGuild, Task>>();
public event Func<IGuild, IGuild, Task> GuildUpdated { add { _guildUpdatedEvent.Add(value); } remove { _guildUpdatedEvent.Remove(value); } }
private AsyncEvent<Func<IGuild, IGuild, Task>> _guildUpdatedEvent = new AsyncEvent<Func<IGuild, IGuild, Task>>();

//Users
public event Func<IGuildUser, Task> UserJoined { add { _userJoinedEvent.Add(value); } remove { _userJoinedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IGuildUser, Task>> _userJoinedEvent = new AsyncEvent<Func<IGuildUser, Task>>();
public event Func<IGuildUser, Task> UserLeft { add { _userLeftEvent.Add(value); } remove { _userLeftEvent.Remove(value); } }
private readonly AsyncEvent<Func<IGuildUser, Task>> _userLeftEvent = new AsyncEvent<Func<IGuildUser, Task>>();
public event Func<IUser, IGuild, Task> UserBanned { add { _userBannedEvent.Add(value); } remove { _userBannedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IUser, IGuild, Task>> _userBannedEvent = new AsyncEvent<Func<IUser, IGuild, Task>>();
public event Func<IUser, IGuild, Task> UserUnbanned { add { _userUnbannedEvent.Add(value); } remove { _userUnbannedEvent.Remove(value); } }
private readonly AsyncEvent<Func<IUser, IGuild, Task>> _userUnbannedEvent = new AsyncEvent<Func<IUser, IGuild, Task>>();
public event Func<Optional<IGuildUser>, IGuildUser, Task> UserUpdated { add { _userUpdatedEvent.Add(value); } remove { _userUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<Optional<IGuildUser>, IGuildUser, Task>> _userUpdatedEvent = new AsyncEvent<Func<Optional<IGuildUser>, IGuildUser, Task>>();
public event Func<ISelfUser, ISelfUser, Task> CurrentUserUpdated { add { _selfUpdatedEvent.Add(value); } remove { _selfUpdatedEvent.Remove(value); } }
private readonly AsyncEvent<Func<ISelfUser, ISelfUser, Task>> _selfUpdatedEvent = new AsyncEvent<Func<ISelfUser, ISelfUser, Task>>();
public event Func<IUser, IChannel, Task> UserIsTyping { add { _userIsTypingEvent.Add(value); } remove { _userIsTypingEvent.Remove(value); } }
private readonly AsyncEvent<Func<IUser, IChannel, Task>> _userIsTypingEvent = new AsyncEvent<Func<IUser, IChannel, Task>>();

//TODO: Add PresenceUpdated? VoiceStateUpdated?, VoiceConnected, VoiceDisconnected;

private readonly ConcurrentQueue<ulong> _largeGuilds;
private readonly Logger _gatewayLogger;
#if BENCHMARK
@@ -1066,19 +997,20 @@ namespace Discord
break;
}

IPresence before;
var user = guild.GetUser(data.User.Id);
if (user != null)
{
var before = user.Clone();
before = user.Presence.Clone();
user.Update(data, UpdateSource.WebSocket);
await _userUpdatedEvent.InvokeAsync(before, user).ConfigureAwait(false);
}
else
{
before = new Presence(null, UserStatus.Offline);
user = guild.AddOrUpdateUser(data, DataStore);
user.Update(data, UpdateSource.WebSocket);
await _userUpdatedEvent.InvokeAsync(Optional.Create<IGuildUser>(), user).ConfigureAwait(false);
}

await _userPresenceUpdatedEvent.InvokeAsync(user, before, user).ConfigureAwait(false);
}
else
{
@@ -1103,6 +1035,26 @@ namespace Discord
}
break;

//Users
case "USER_UPDATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (USER_UPDATE)").ConfigureAwait(false);

var data = (payload as JToken).ToObject<API.User>(_serializer);
if (data.Id == CurrentUser.Id)
{
var before = CurrentUser.Clone();
CurrentUser.Update(data, UpdateSource.WebSocket);
await _selfUpdatedEvent.InvokeAsync(before, CurrentUser).ConfigureAwait(false);
}
else
{
await _gatewayLogger.WarningAsync("Received USER_UPDATE for wrong user.").ConfigureAwait(false);
return;
}
}
break;

//Voice
case "VOICE_STATE_UPDATE":
{
@@ -1114,17 +1066,27 @@ namespace Discord
var guild = DataStore.GetGuild(data.GuildId.Value);
if (guild != null)
{
if (data.ChannelId == null)
guild.RemoveVoiceState(data.UserId);
VoiceState before, after;
if (data.ChannelId != null)
{
before = guild.GetVoiceState(data.UserId)?.Clone() ?? new VoiceState(null, null, false, false, false);
after = guild.AddOrUpdateVoiceState(data, DataStore);
}
else
guild.AddOrUpdateVoiceState(data, DataStore);
{
before = guild.RemoveVoiceState(data.UserId) ?? new VoiceState(null, null, false, false, false);
after = new VoiceState(null, data);
}

var user = guild.GetUser(data.UserId);
if (user != null)
{
var before = user.Clone();
user.Update(data, UpdateSource.WebSocket);
await _userUpdatedEvent.InvokeAsync(before, user).ConfigureAwait(false);
await _userVoiceStateUpdatedEvent.InvokeAsync(user, before, after).ConfigureAwait(false);
}
else
{
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown user.").ConfigureAwait(false);
return;
}
}
else
@@ -1136,26 +1098,6 @@ namespace Discord
}
break;

//Settings
case "USER_UPDATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (USER_UPDATE)").ConfigureAwait(false);

var data = (payload as JToken).ToObject<API.User>(_serializer);
if (data.Id == CurrentUser.Id)
{
var before = CurrentUser.Clone();
CurrentUser.Update(data, UpdateSource.WebSocket);
await _selfUpdatedEvent.InvokeAsync(before, CurrentUser).ConfigureAwait(false);
}
else
{
await _gatewayLogger.WarningAsync("Received USER_UPDATE for wrong user.").ConfigureAwait(false);
return;
}
}
break;

//Ignored
case "USER_SETTINGS_UPDATE":
await _gatewayLogger.DebugAsync("Ignored Dispatch (USER_SETTINGS_UPDATE)").ConfigureAwait(false);


+ 4
- 19
src/Discord.Net/Entities/Users/GuildUser.cs View File

@@ -15,9 +15,7 @@ namespace Discord
internal class GuildUser : IGuildUser, ISnowflakeEntity
{
private long? _joinedAtTicks;

public bool IsDeaf { get; private set; }
public bool IsMute { get; private set; }
public string Nickname { get; private set; }
public GuildPermissions GuildPermissions { get; private set; }

@@ -59,11 +57,7 @@ namespace Discord
public void Update(Model model, UpdateSource source)
{
if (source == UpdateSource.Rest && IsAttached) return;

//if (model.Deaf.IsSpecified)
IsDeaf = model.Deaf;
//if (model.Mute.IsSpecified)
IsMute = model.Mute;
//if (model.JoinedAt.IsSpecified)
_joinedAtTicks = model.JoinedAt.UtcTicks;
if (model.Nick.IsSpecified)
@@ -81,13 +75,6 @@ namespace Discord
if (model.Nick.IsSpecified)
Nickname = model.Nick.Value;
}
public void Update(VoiceStateModel model, UpdateSource source)
{
if (source == UpdateSource.Rest && IsAttached) return;

IsDeaf = model.Deaf;
IsMute = model.Mute;
}
private void UpdateRoles(ulong[] roleIds)
{
var roles = ImmutableArray.CreateBuilder<Role>(roleIds.Length + 1);
@@ -127,10 +114,6 @@ namespace Discord
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified)
{
await Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, Id, args).ConfigureAwait(false);
if (args.Deaf.IsSpecified)
IsDeaf = args.Deaf.Value;
if (args.Mute.IsSpecified)
IsMute = args.Mute.Value;
if (args.Nickname.IsSpecified)
Nickname = args.Nickname.Value ?? "";
if (args.RoleIds.IsSpecified)
@@ -161,6 +144,8 @@ namespace Discord

IGuild IGuildUser.Guild => Guild;
IReadOnlyCollection<IRole> IGuildUser.Roles => Roles;
bool IVoiceState.IsDeafened => false;
bool IVoiceState.IsMuted => false;
bool IVoiceState.IsSelfDeafened => false;
bool IVoiceState.IsSelfMuted => false;
bool IVoiceState.IsSuppressed => false;


+ 0
- 4
src/Discord.Net/Entities/Users/IGuildUser.cs View File

@@ -8,10 +8,6 @@ namespace Discord
/// <summary> A Guild-User pairing. </summary>
public interface IGuildUser : IUpdateable, IUser, IVoiceState
{
/// <summary> Returns true if the guild has deafened this user. </summary>
bool IsDeaf { get; }
/// <summary> Returns true if the guild has muted this user. </summary>
bool IsMute { get; }
/// <summary> Gets when this user joined this guild. </summary>
DateTimeOffset? JoinedAt { get; }
/// <summary> Gets the nickname for this user. </summary>


+ 4
- 0
src/Discord.Net/Entities/Users/IVoiceState.cs View File

@@ -2,6 +2,10 @@
{
public interface IVoiceState
{
/// <summary> Returns true if the guild has deafened this user. </summary>
bool IsDeafened { get; }
/// <summary> Returns true if the guild has muted this user. </summary>
bool IsMuted { get; }
/// <summary> Returns true if this user has marked themselves as deafened. </summary>
bool IsSelfDeafened { get; }
/// <summary> Returns true if this user has marked themselves as muted. </summary>


+ 1
- 1
src/Discord.Net/Entities/WebSocket/CachedGuild.cs View File

@@ -204,7 +204,7 @@ namespace Discord
public VoiceState AddOrUpdateVoiceState(VoiceStateModel model, DataStore dataStore, ConcurrentDictionary<ulong, VoiceState> voiceStates = null)
{
var voiceChannel = dataStore.GetChannel(model.ChannelId.Value) as CachedVoiceChannel;
var voiceState = new VoiceState(voiceChannel, model.SessionId, model.SelfMute, model.SelfDeaf, model.Suppress);
var voiceState = new VoiceState(voiceChannel, model);
(voiceStates ?? _voiceStates)[model.UserId] = voiceState;
return voiceState;
}


+ 20
- 6
src/Discord.Net/Entities/WebSocket/CachedGuildUser.cs View File

@@ -3,17 +3,31 @@ using PresenceModel = Discord.API.Presence;

namespace Discord
{
//TODO: C#7 Candidate for record type
internal struct Presence : IPresence
{
public Game Game { get; }
public UserStatus Status { get; }

public Presence(Game game, UserStatus status)
{
Game = game;
Status = status;
}

public Presence Clone() => this;
}

internal class CachedGuildUser : GuildUser, ICachedUser
{
private Game _game;
private UserStatus _status;
public Presence Presence { get; private set; }

public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
public new CachedGuild Guild => base.Guild as CachedGuild;
public new CachedGlobalUser User => base.User as CachedGlobalUser;

public override Game Game => _game;
public override UserStatus Status => _status;
public override Game Game => Presence.Game;
public override UserStatus Status => Presence.Status;

public VoiceState? VoiceState => Guild.GetVoiceState(Id);
public bool IsSelfDeafened => VoiceState?.IsSelfDeafened ?? false;
@@ -34,8 +48,8 @@ namespace Discord
{
base.Update(model, source);

_status = model.Status;
_game = model.Game != null ? new Game(model.Game) : (Game)null;
var game = model.Game != null ? new Game(model.Game) : null;
Presence = new Presence(game, model.Status);
}

public CachedGuildUser Clone() => MemberwiseClone() as CachedGuildUser;


+ 16
- 6
src/Discord.Net/Entities/WebSocket/VoiceState.cs View File

@@ -1,16 +1,20 @@
using System;
using Model = Discord.API.VoiceState;

namespace Discord
{
//TODO: C#7 Candidate for record type
internal struct VoiceState : IVoiceState
{
[Flags]
private enum Flags : byte
{
None = 0x0,
Suppressed = 0x1,
SelfMuted = 0x2,
SelfDeafened = 0x4,
None = 0x00,
Suppressed = 0x01,
Muted = 0x02,
Deafened = 0x04,
SelfMuted = 0x08,
SelfDeafened = 0x10,
}

private readonly Flags _voiceStates;
@@ -18,10 +22,14 @@ namespace Discord
public CachedVoiceChannel VoiceChannel { get; }
public string VoiceSessionId { get; }

public bool IsMuted => (_voiceStates & Flags.Muted) != 0;
public bool IsDeafened => (_voiceStates & Flags.Deafened) != 0;
public bool IsSuppressed => (_voiceStates & Flags.Suppressed) != 0;
public bool IsSelfMuted => (_voiceStates & Flags.SelfMuted) != 0;
public bool IsSelfDeafened => (_voiceStates & Flags.SelfDeafened) != 0;
public bool IsSuppressed => (_voiceStates & Flags.Suppressed) != 0;

public VoiceState(CachedVoiceChannel voiceChannel, Model model)
: this(voiceChannel, model.SessionId, model.SelfMute, model.SelfDeaf, model.Suppress) { }
public VoiceState(CachedVoiceChannel voiceChannel, string sessionId, bool isSelfMuted, bool isSelfDeafened, bool isSuppressed)
{
VoiceChannel = voiceChannel;
@@ -37,6 +45,8 @@ namespace Discord
_voiceStates = voiceStates;
}

public VoiceState Clone() => this;

IVoiceChannel IVoiceState.VoiceChannel => VoiceChannel;
}
}

Loading…
Cancel
Save