I shan't, it's Christmas!
This commit is contained in:
@@ -68,7 +68,7 @@ namespace Discord.Commands
|
|||||||
client.MessageReceived += async (s, e) =>
|
client.MessageReceived += async (s, e) =>
|
||||||
{
|
{
|
||||||
if (_allCommands.Count == 0) return;
|
if (_allCommands.Count == 0) return;
|
||||||
if (e.Message.User.Id == _client.CurrentUser.Id) return;
|
if (e.Message.User == null || e.Message.User.Id == _client.CurrentUser.Id) return;
|
||||||
|
|
||||||
string msg = e.Message.RawText;
|
string msg = e.Message.RawText;
|
||||||
if (msg.Length == 0) return;
|
if (msg.Length == 0) return;
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ namespace Discord.API.Client
|
|||||||
{
|
{
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))]
|
||||||
[JsonConverter(typeof(LongStringConverter))]
|
|
||||||
public ulong Id { get; set; }
|
public ulong Id { get; set; }
|
||||||
[JsonProperty("deny")]
|
[JsonProperty("deny")]
|
||||||
public uint Deny { get; set; }
|
public uint Deny { get; set; }
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ namespace Discord.API.Client
|
|||||||
{
|
{
|
||||||
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))]
|
[JsonProperty("id"), JsonConverter(typeof(LongStringConverter))]
|
||||||
public ulong Id { get; set; }
|
public ulong Id { get; set; }
|
||||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))]
|
[JsonProperty("guild_id"), JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
public ulong GuildId { get; set; }
|
public ulong? GuildId { get; set; }
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Discord.API.Client
|
|||||||
{
|
{
|
||||||
public class MemberReference
|
public class MemberReference
|
||||||
{
|
{
|
||||||
[JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))]
|
[JsonProperty("guild_id"), JsonConverter(typeof(NullableLongStringConverter))]
|
||||||
public ulong? GuildId { get; set; }
|
public ulong? GuildId { get; set; }
|
||||||
[JsonProperty("user")]
|
[JsonProperty("user")]
|
||||||
public UserReference User { get; set; }
|
public UserReference User { get; set; }
|
||||||
|
|||||||
@@ -172,9 +172,6 @@ namespace Discord
|
|||||||
_disconnectedEvent.Reset();
|
_disconnectedEvent.Reset();
|
||||||
|
|
||||||
await Login(email, password, token).ConfigureAwait(false);
|
await Login(email, password, token).ConfigureAwait(false);
|
||||||
|
|
||||||
ClientAPI.Token = token;
|
|
||||||
GatewaySocket.Token = token;
|
|
||||||
await GatewaySocket.Connect().ConfigureAwait(false);
|
await GatewaySocket.Connect().ConfigureAwait(false);
|
||||||
|
|
||||||
List<Task> tasks = new List<Task>();
|
List<Task> tasks = new List<Task>();
|
||||||
@@ -233,6 +230,9 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientAPI.Token = token;
|
||||||
|
GatewaySocket.Token = token;
|
||||||
|
|
||||||
//Get gateway and check token
|
//Get gateway and check token
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -309,21 +309,9 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Channels
|
#region Channels
|
||||||
private Channel AddChannel(ulong id, ulong? guildId, ulong? recipientId)
|
internal void AddChannel(Channel channel)
|
||||||
{
|
{
|
||||||
Channel channel;
|
|
||||||
if (recipientId != null)
|
|
||||||
{
|
|
||||||
channel = _privateChannels.GetOrAdd(recipientId.Value,
|
|
||||||
x => new Channel(this, x, new User(this, recipientId.Value, null)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var server = GetServer(guildId.Value);
|
|
||||||
channel = server.AddChannel(id);
|
|
||||||
}
|
|
||||||
_channels[channel.Id] = channel;
|
_channels[channel.Id] = channel;
|
||||||
return channel;
|
|
||||||
}
|
}
|
||||||
private Channel RemoveChannel(ulong id)
|
private Channel RemoveChannel(ulong id)
|
||||||
{
|
{
|
||||||
@@ -337,20 +325,26 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
public Channel GetChannel(ulong id)
|
||||||
internal Channel GetChannel(ulong id)
|
|
||||||
{
|
{
|
||||||
Channel channel;
|
Channel channel;
|
||||||
_channels.TryGetValue(id, out channel);
|
_channels.TryGetValue(id, out channel);
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Channel AddPrivateChannel(ulong id, ulong recipientId)
|
||||||
|
{
|
||||||
|
Channel channel;
|
||||||
|
if (_privateChannels.TryGetOrAdd(recipientId, x => new Channel(this, id, new User(this, x, null)), out channel))
|
||||||
|
AddChannel(channel);
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
internal Channel GetPrivateChannel(ulong recipientId)
|
internal Channel GetPrivateChannel(ulong recipientId)
|
||||||
{
|
{
|
||||||
Channel channel;
|
Channel channel;
|
||||||
_privateChannels.TryGetValue(recipientId, out channel);
|
_privateChannels.TryGetValue(recipientId, out channel);
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<Channel> CreatePrivateChannel(User user)
|
internal async Task<Channel> CreatePrivateChannel(User user)
|
||||||
{
|
{
|
||||||
var channel = GetPrivateChannel(user.Id);
|
var channel = GetPrivateChannel(user.Id);
|
||||||
@@ -359,7 +353,7 @@ namespace Discord
|
|||||||
var request = new CreatePrivateChannelRequest() { RecipientId = user.Id };
|
var request = new CreatePrivateChannelRequest() { RecipientId = user.Id };
|
||||||
var response = await ClientAPI.Send(request).ConfigureAwait(false);
|
var response = await ClientAPI.Send(request).ConfigureAwait(false);
|
||||||
|
|
||||||
channel = AddChannel(response.Id, null, response.Recipient.Id);
|
channel = AddPrivateChannel(response.Id, user.Id);
|
||||||
channel.Update(response);
|
channel.Update(response);
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
@@ -453,6 +447,7 @@ namespace Discord
|
|||||||
SessionId = data.SessionId;
|
SessionId = data.SessionId;
|
||||||
PrivateUser = new User(this, data.User.Id, null);
|
PrivateUser = new User(this, data.User.Id, null);
|
||||||
PrivateUser.Update(data.User);
|
PrivateUser.Update(data.User);
|
||||||
|
CurrentUser = new Profile(this, data.User.Id);
|
||||||
CurrentUser.Update(data.User);
|
CurrentUser.Update(data.User);
|
||||||
foreach (var model in data.Guilds)
|
foreach (var model in data.Guilds)
|
||||||
{
|
{
|
||||||
@@ -464,7 +459,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
foreach (var model in data.PrivateChannels)
|
foreach (var model in data.PrivateChannels)
|
||||||
{
|
{
|
||||||
var channel = AddChannel(model.Id, null, model.Recipient.Id);
|
var channel = AddPrivateChannel(model.Id, model.Recipient.Id);
|
||||||
channel.Update(model);
|
channel.Update(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,11 +518,23 @@ namespace Discord
|
|||||||
case "CHANNEL_CREATE":
|
case "CHANNEL_CREATE":
|
||||||
{
|
{
|
||||||
var data = e.Payload.ToObject<ChannelCreateEvent>(_serializer);
|
var data = e.Payload.ToObject<ChannelCreateEvent>(_serializer);
|
||||||
Channel channel = AddChannel(data.Id, data.GuildId, data.Recipient.Id);
|
|
||||||
|
Channel channel = null;
|
||||||
|
if (data.GuildId != null)
|
||||||
|
{
|
||||||
|
var server = GetServer(data.GuildId.Value);
|
||||||
|
if (server != null)
|
||||||
|
channel = server.AddChannel(data.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
channel = AddPrivateChannel(data.Id, data.Recipient.Id);
|
||||||
|
if (channel != null)
|
||||||
|
{
|
||||||
channel.Update(data);
|
channel.Update(data);
|
||||||
Logger.Info($"Channel Created: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
|
Logger.Info($"Channel Created: {channel.Server?.Name ?? "[Private]"}/{channel.Name}");
|
||||||
OnChannelCreated(channel);
|
OnChannelCreated(channel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "CHANNEL_UPDATE":
|
case "CHANNEL_UPDATE":
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,17 +27,24 @@ namespace Discord
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool HasBit(this uint value, byte bit) => ((value >> bit) & 1U) == 1;
|
public static bool HasBit(this uint value, byte bit) => ((value >> bit) & 1U) == 1;
|
||||||
|
|
||||||
public static bool TryGetAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> d,
|
public static bool TryGetOrAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> d,
|
||||||
TKey key, Func<TKey, TValue> factory, out TValue result)
|
TKey key, Func<TKey, TValue> factory, out TValue result)
|
||||||
|
where TValue : class
|
||||||
{
|
{
|
||||||
|
TValue newValue = null;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (d.TryGetValue(key, out result))
|
if (d.TryGetValue(key, out result))
|
||||||
return false;
|
return false;
|
||||||
if (d.TryAdd(key, factory(key)))
|
if (newValue == null)
|
||||||
|
newValue = factory(key);
|
||||||
|
if (d.TryAdd(key, newValue))
|
||||||
|
{
|
||||||
|
result = newValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<Channel> Find(this IEnumerable<Channel> channels, string name, ChannelType type = null, bool exactMatch = false)
|
public static IEnumerable<Channel> Find(this IEnumerable<Channel> channels, string name, ChannelType type = null, bool exactMatch = false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ namespace Discord
|
|||||||
: this(client, id)
|
: this(client, id)
|
||||||
{
|
{
|
||||||
Recipient = recipient;
|
Recipient = recipient;
|
||||||
Name = $"@{recipient}";
|
|
||||||
AddUser(client.PrivateUser);
|
AddUser(client.PrivateUser);
|
||||||
AddUser(recipient);
|
AddUser(recipient);
|
||||||
}
|
}
|
||||||
@@ -143,7 +142,10 @@ namespace Discord
|
|||||||
if (model.Topic != null)
|
if (model.Topic != null)
|
||||||
Topic = model.Topic;
|
Topic = model.Topic;
|
||||||
if (model.Recipient != null)
|
if (model.Recipient != null)
|
||||||
|
{
|
||||||
Recipient.Update(model.Recipient);
|
Recipient.Update(model.Recipient);
|
||||||
|
Name = $"@{Recipient}";
|
||||||
|
}
|
||||||
|
|
||||||
if (model.PermissionOverwrites != null)
|
if (model.PermissionOverwrites != null)
|
||||||
{
|
{
|
||||||
@@ -262,11 +264,15 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Message GetMessage(ulong id)
|
public Message GetMessage(ulong id)
|
||||||
|
{
|
||||||
|
if (Client.Config.MessageCacheSize > 0)
|
||||||
{
|
{
|
||||||
Message result;
|
Message result;
|
||||||
_messages.TryGetValue(id, out result);
|
_messages.TryGetValue(id, out result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public async Task<Message[]> DownloadMessages(int limit = 100, ulong? relativeMessageId = null,
|
public async Task<Message[]> DownloadMessages(int limit = 100, ulong? relativeMessageId = null,
|
||||||
RelativeDirection relativeDir = RelativeDirection.Before, bool useCache = true)
|
RelativeDirection relativeDir = RelativeDirection.Before, bool useCache = true)
|
||||||
{
|
{
|
||||||
@@ -556,6 +562,17 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
public User GetUser(ulong id)
|
public User GetUser(ulong id)
|
||||||
{
|
{
|
||||||
|
if (!Client.Config.UsePermissionsCache)
|
||||||
|
{
|
||||||
|
var user = Server.GetUser(id);
|
||||||
|
ChannelPermissions perms = new ChannelPermissions();
|
||||||
|
UpdatePermissions(user, perms);
|
||||||
|
if (perms.ReadMessages)
|
||||||
|
return user;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Member result;
|
Member result;
|
||||||
_users.TryGetValue(id, out result);
|
_users.TryGetValue(id, out result);
|
||||||
return result.User;
|
return result.User;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ namespace Discord
|
|||||||
public static readonly Color LightGrey = PresetColor(0x979C9F);
|
public static readonly Color LightGrey = PresetColor(0x979C9F);
|
||||||
public static readonly Color DarkerGrey = PresetColor(0x546E7A);
|
public static readonly Color DarkerGrey = PresetColor(0x546E7A);
|
||||||
|
|
||||||
|
|
||||||
private static Color PresetColor(uint packedValue)
|
private static Color PresetColor(uint packedValue)
|
||||||
{
|
{
|
||||||
Color color = new Color(packedValue);
|
Color color = new Color(packedValue);
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using APIUser = Discord.API.Client.User;
|
|
||||||
|
|
||||||
namespace Discord
|
|
||||||
{
|
|
||||||
/*public sealed class GlobalUser : CachedObject<ulong>
|
|
||||||
{
|
|
||||||
/// <summary> Returns the email for this user. Note: this field is only ever populated for the current logged in user. </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public string Email { get; private set; }
|
|
||||||
/// <summary> Returns if the email for this user has been verified. Note: this field is only ever populated for the current logged in user. </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool? IsVerified { get; private set; }
|
|
||||||
|
|
||||||
/// <summary> Returns the private messaging channel with this user, if one exists. </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public Channel PrivateChannel
|
|
||||||
{
|
|
||||||
get { return _privateChannel; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_privateChannel = value;
|
|
||||||
if (value == null)
|
|
||||||
CheckUser();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[JsonProperty]
|
|
||||||
private ulong? PrivateChannelId => _privateChannel?.Id;
|
|
||||||
private Channel _privateChannel;
|
|
||||||
|
|
||||||
/// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public IEnumerable<User> Memberships => _users.Select(x => x.Value);
|
|
||||||
[JsonProperty]
|
|
||||||
private IEnumerable<ulong> ServerIds => _users.Select(x => x.Key);
|
|
||||||
private readonly ConcurrentDictionary<ulong, User> _users;
|
|
||||||
|
|
||||||
/// <summary> Returns the string used to mention this user. </summary>
|
|
||||||
public string Mention => $"<@{Id}>";
|
|
||||||
|
|
||||||
internal GlobalUser(DiscordClient client, ulong id)
|
|
||||||
: base(client, id)
|
|
||||||
{
|
|
||||||
_users = new ConcurrentDictionary<ulong, User>();
|
|
||||||
}
|
|
||||||
internal override bool LoadReferences() { return true; }
|
|
||||||
internal override void UnloadReferences()
|
|
||||||
{
|
|
||||||
//Don't need to clean _users - they're considered owned by server
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Update(APIUser model)
|
|
||||||
{
|
|
||||||
if (model.Email != null)
|
|
||||||
Email = model.Email;
|
|
||||||
if (model.IsVerified != null)
|
|
||||||
IsVerified = model.IsVerified;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddUser(User user) => _users.TryAdd(user.Server?.Id ?? 0, user);
|
|
||||||
internal void RemoveUser(User user)
|
|
||||||
{
|
|
||||||
if (_users.TryRemove(user.Server?.Id ?? 0, out user))
|
|
||||||
CheckUser();
|
|
||||||
}
|
|
||||||
internal void CheckUser()
|
|
||||||
{
|
|
||||||
if (_users.Count == 0 && PrivateChannel == null)
|
|
||||||
_client.GlobalUsers.TryRemove(Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj) => obj is GlobalUser && (obj as GlobalUser).Id == Id;
|
|
||||||
public override int GetHashCode() => unchecked(Id.GetHashCode() + 7891);
|
|
||||||
public override string ToString() => IdConvert.ToString(Id);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
@@ -201,6 +201,10 @@ namespace Discord
|
|||||||
|
|
||||||
internal Message(ulong id, Channel channel, ulong userId)
|
internal Message(ulong id, Channel channel, ulong userId)
|
||||||
{
|
{
|
||||||
|
Id = id;
|
||||||
|
Channel = channel;
|
||||||
|
_userId = userId;
|
||||||
|
|
||||||
Attachments = _initialAttachments;
|
Attachments = _initialAttachments;
|
||||||
Embeds = _initialEmbeds;
|
Embeds = _initialEmbeds;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,20 +11,21 @@ namespace Discord
|
|||||||
internal DiscordClient Client { get; }
|
internal DiscordClient Client { get; }
|
||||||
|
|
||||||
/// <summary> Gets the unique identifier for this user. </summary>
|
/// <summary> Gets the unique identifier for this user. </summary>
|
||||||
public ulong Id { get; private set; }
|
public ulong Id { get; }
|
||||||
|
|
||||||
/// <summary> Gets the email for this user. </summary>
|
/// <summary> Gets the email for this user. </summary>
|
||||||
public string Email { get; private set; }
|
public string Email { get; private set; }
|
||||||
/// <summary> Gets if the email for this user has been verified. </summary>
|
/// <summary> Gets if the email for this user has been verified. </summary>
|
||||||
public bool? IsVerified { get; private set; }
|
public bool? IsVerified { get; private set; }
|
||||||
|
|
||||||
internal Profile(DiscordClient client)
|
internal Profile(DiscordClient client, ulong id)
|
||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
|
Id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update(APIUser model)
|
internal void Update(APIUser model)
|
||||||
{
|
{
|
||||||
Id = model.Id;
|
|
||||||
Email = model.Email;
|
Email = model.Email;
|
||||||
IsVerified = model.IsVerified;
|
IsVerified = model.IsVerified;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Server = server;
|
Server = server;
|
||||||
|
|
||||||
Permissions = new ServerPermissions(0);
|
Permissions = new ServerPermissions(0);
|
||||||
Permissions.Lock();
|
Permissions.Lock();
|
||||||
Color = new Color(0);
|
Color = new Color(0);
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
Id = id;
|
Id = id;
|
||||||
|
|
||||||
_channels = new ConcurrentDictionary<ulong, Channel>();
|
_channels = new ConcurrentDictionary<ulong, Channel>();
|
||||||
_roles = new ConcurrentDictionary<ulong, Role>();
|
_roles = new ConcurrentDictionary<ulong, Role>();
|
||||||
_users = new ConcurrentDictionary<ulong, Member>();
|
_users = new ConcurrentDictionary<ulong, Member>();
|
||||||
@@ -97,7 +98,7 @@ namespace Discord
|
|||||||
|
|
||||||
if (model.AFKTimeout != null)
|
if (model.AFKTimeout != null)
|
||||||
AFKTimeout = model.AFKTimeout.Value;
|
AFKTimeout = model.AFKTimeout.Value;
|
||||||
_afkChannelId = model.AFKChannelId.Value; //Can be null
|
_afkChannelId = model.AFKChannelId; //Can be null
|
||||||
if (model.JoinedAt != null)
|
if (model.JoinedAt != null)
|
||||||
JoinedAt = model.JoinedAt.Value;
|
JoinedAt = model.JoinedAt.Value;
|
||||||
if (model.OwnerId != null)
|
if (model.OwnerId != null)
|
||||||
@@ -196,7 +197,11 @@ namespace Discord
|
|||||||
|
|
||||||
#region Channels
|
#region Channels
|
||||||
internal Channel AddChannel(ulong id)
|
internal Channel AddChannel(ulong id)
|
||||||
=> _channels.GetOrAdd(id, x => new Channel(Client, x, this));
|
{
|
||||||
|
var channel = _channels.GetOrAdd(id, x => new Channel(Client, x, this));
|
||||||
|
Client.AddChannel(channel);
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
internal Channel RemoveChannel(ulong id)
|
internal Channel RemoveChannel(ulong id)
|
||||||
{
|
{
|
||||||
Channel channel;
|
Channel channel;
|
||||||
|
|||||||
@@ -136,9 +136,10 @@ namespace Discord
|
|||||||
internal User(DiscordClient client, ulong id, Server server)
|
internal User(DiscordClient client, ulong id, Server server)
|
||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
|
Id = id;
|
||||||
Server = server;
|
Server = server;
|
||||||
_roles = new Dictionary<ulong, Role>();
|
|
||||||
|
|
||||||
|
_roles = new Dictionary<ulong, Role>();
|
||||||
Status = UserStatus.Offline;
|
Status = UserStatus.Offline;
|
||||||
|
|
||||||
if (server == null)
|
if (server == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user