Concrete class prototype

This commit is contained in:
RogueException
2016-09-22 21:15:37 -03:00
parent ab42129eb9
commit 6319933ed0
394 changed files with 3648 additions and 3224 deletions

View File

@@ -0,0 +1,9 @@
namespace Discord.WebSocket
{
internal interface ISocketUser : IUser, IEntity<ulong>
{
SocketGlobalUser User { get; }
ISocketUser Clone();
}
}

View File

@@ -0,0 +1,17 @@
namespace Discord.WebSocket
{
//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;
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Diagnostics;
using PresenceModel = Discord.API.Presence;
namespace Discord.WebSocket
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
internal class SocketDMUser : ISocketUser
{
internal bool IsAttached => true;
bool IEntity<ulong>.IsAttached => IsAttached;
public SocketGlobalUser User { get; }
public DiscordSocketClient Discord => User.Discord;
public Game Game => Presence.Game;
public UserStatus Status => Presence.Status;
public Presence Presence => User.Presence; //{ get; private set; }
public ulong Id => User.Id;
public string AvatarUrl => User.AvatarUrl;
public DateTimeOffset CreatedAt => User.CreatedAt;
public string Discriminator => User.Discriminator;
public ushort DiscriminatorValue => User.DiscriminatorValue;
public bool IsBot => User.IsBot;
public string Mention => MentionUtils.Mention(this);
public string Username => User.Username;
public SocketDMUser(SocketGlobalUser user)
{
User = user;
}
public void Update(PresenceModel model)
{
User.Update(model, source);
}
public SocketDMUser Clone() => MemberwiseClone() as SocketDMUser;
ISocketUser ISocketUser.Clone() => Clone();
public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id})";
}
}

View File

@@ -0,0 +1,60 @@
using Discord.Rest;
using System;
using Model = Discord.API.User;
using PresenceModel = Discord.API.Presence;
namespace Discord.WebSocket
{
internal class SocketGlobalUser : User, ISocketUser
{
internal override bool IsAttached => true;
private ushort _references;
public Presence Presence { get; private set; }
public new DiscordSocketClient Discord { get { throw new NotSupportedException(); } }
SocketGlobalUser ISocketUser.User => this;
public SocketGlobalUser(Model model)
: base(model)
{
}
public void AddRef()
{
checked
{
lock (this)
_references++;
}
}
public void RemoveRef(DiscordSocketClient discord)
{
lock (this)
{
if (--_references == 0)
discord.RemoveUser(Id);
}
}
public override void Update(Model model)
{
lock (this)
base.Update(model, source);
}
public void Update(PresenceModel model)
{
//Race conditions are okay here. Multiple shards racing already cant guarantee presence in order.
//lock (this)
//{
var game = model.Game != null ? new Game(model.Game) : null;
Presence = new Presence(game, model.Status);
//}
}
public SocketGlobalUser Clone() => MemberwiseClone() as SocketGlobalUser;
ISocketUser ISocketUser.Clone() => Clone();
}
}

View File

@@ -0,0 +1,36 @@
using Discord.Rest;
using System.Diagnostics;
namespace Discord.WebSocket
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
internal class SocketGroupUser : GroupUser, ISocketUser
{
internal override bool IsAttached => true;
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
public new SocketGroupChannel Channel => base.Channel as SocketGroupChannel;
public new SocketGlobalUser User => base.User as SocketGlobalUser;
public Presence Presence => User.Presence; //{ get; private set; }
public override Game Game => Presence.Game;
public override UserStatus Status => Presence.Status;
public VoiceState? VoiceState => Channel.GetVoiceState(Id);
public bool IsSelfDeafened => VoiceState?.IsSelfDeafened ?? false;
public bool IsSelfMuted => VoiceState?.IsSelfMuted ?? false;
public bool IsSuppressed => VoiceState?.IsSuppressed ?? false;
public SocketVoiceChannel VoiceChannel => VoiceState?.VoiceChannel;
public SocketGroupUser(SocketGroupChannel channel, SocketGlobalUser user)
: base(channel, user)
{
}
public SocketGroupUser Clone() => MemberwiseClone() as SocketGroupUser;
ISocketUser ISocketUser.Clone() => Clone();
public override string ToString() => $"{Username}#{Discriminator}";
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id})";
}
}

View File

@@ -0,0 +1,53 @@
using Discord.Rest;
using Model = Discord.API.GuildMember;
using PresenceModel = Discord.API.Presence;
namespace Discord.WebSocket
{
internal class SocketGuildUser : GuildUser, ISocketUser, IVoiceState
{
internal override bool IsAttached => true;
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
public new SocketGuild Guild => base.Guild as SocketGuild;
public new SocketGlobalUser User => base.User as SocketGlobalUser;
public Presence Presence => User.Presence; //{ get; private set; }
public override Game Game => Presence.Game;
public override UserStatus Status => Presence.Status;
public VoiceState? VoiceState => Guild.GetVoiceState(Id);
public bool IsSelfDeafened => VoiceState?.IsSelfDeafened ?? false;
public bool IsSelfMuted => VoiceState?.IsSelfMuted ?? false;
public bool IsSuppressed => VoiceState?.IsSuppressed ?? false;
public SocketVoiceChannel VoiceChannel => VoiceState?.VoiceChannel;
public bool IsDeafened => VoiceState?.IsDeafened ?? false;
public bool IsMuted => VoiceState?.IsMuted ?? false;
public string VoiceSessionId => VoiceState?.VoiceSessionId ?? "";
public SocketGuildUser(SocketGuild guild, SocketGlobalUser user, Model model)
: base(guild, user, model)
{
//Presence = new Presence(null, UserStatus.Offline);
}
public SocketGuildUser(SocketGuild guild, SocketGlobalUser user, PresenceModel model)
: base(guild, user, model)
{
}
public override void Update(PresenceModel model)
{
base.Update(model, source);
var game = model.Game != null ? new Game(model.Game) : null;
//Presence = new Presence(game, model.Status);
User.Update(model, source);
}
IVoiceChannel IVoiceState.VoiceChannel => VoiceState?.VoiceChannel;
public SocketGuildUser Clone() => MemberwiseClone() as SocketGuildUser;
ISocketUser ISocketUser.Clone() => Clone();
}
}

View File

@@ -0,0 +1,47 @@
using Discord.API.Rest;
using Discord.Rest;
using System;
using System.Threading.Tasks;
using Model = Discord.API.User;
namespace Discord.WebSocket
{
internal class SocketSelfUser : SelfUser, ISocketUser, ISelfUser
{
internal override bool IsAttached => true;
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
SocketGlobalUser ISocketUser.User { get { throw new NotSupportedException(); } }
public SocketSelfUser(DiscordSocketClient discord, Model model)
: base(discord, model)
{
}
public async Task ModifyStatusAsync(Action<ModifyPresenceParams> func)
{
if (func == null) throw new NullReferenceException(nameof(func));
var args = new ModifyPresenceParams();
func(args);
var game = args._game.GetValueOrDefault(_game);
var status = args._status.GetValueOrDefault(_status);
long idleSince = _idleSince;
if (status == UserStatus.Idle && _status != UserStatus.Idle)
idleSince = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var apiGame = game != null ? new API.Game { Name = game.Name, StreamType = game.StreamType, StreamUrl = game.StreamUrl } : null;
await Discord.ApiClient.SendStatusUpdateAsync(status == UserStatus.Idle ? _idleSince : (long?)null, apiGame).ConfigureAwait(false);
//Save values
_idleSince = idleSince;
_game = game;
_status = status;
}
public SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser;
ISocketUser ISocketUser.Clone() => Clone();
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Model = Discord.API.VoiceState;
namespace Discord.WebSocket
{
//TODO: C#7 Candidate for record type
internal struct VoiceState : IVoiceState
{
[Flags]
private enum Flags : byte
{
None = 0x00,
Suppressed = 0x01,
Muted = 0x02,
Deafened = 0x04,
SelfMuted = 0x08,
SelfDeafened = 0x10,
}
private readonly Flags _voiceStates;
public SocketVoiceChannel 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 VoiceState(SocketVoiceChannel voiceChannel, Model model)
: this(voiceChannel, model.SessionId, model.SelfMute, model.SelfDeaf, model.Suppress) { }
public VoiceState(SocketVoiceChannel voiceChannel, string sessionId, bool isSelfMuted, bool isSelfDeafened, bool isSuppressed)
{
VoiceChannel = voiceChannel;
VoiceSessionId = sessionId;
Flags voiceStates = Flags.None;
if (isSelfMuted)
voiceStates |= Flags.SelfMuted;
if (isSelfDeafened)
voiceStates |= Flags.SelfDeafened;
if (isSuppressed)
voiceStates |= Flags.Suppressed;
_voiceStates = voiceStates;
}
public VoiceState Clone() => this;
IVoiceChannel IVoiceState.VoiceChannel => VoiceChannel;
}
}