From 89eba9acb4525e9142b32a9484d85c259c3cb64e Mon Sep 17 00:00:00 2001 From: RogueException Date: Wed, 23 Dec 2015 04:35:14 -0400 Subject: [PATCH] I shan't, it's Christmas! --- src/Discord.Net.Commands/CommandService.cs | 2 +- src/Discord.Net/API/Client/Common/Channel.cs | 3 +- .../API/Client/Common/ChannelReference.cs | 4 +- .../API/Client/Common/MemberReference.cs | 2 +- src/Discord.Net/DiscordClient.cs | 63 ++++++++------- src/Discord.Net/Extensions.cs | 11 ++- src/Discord.Net/Models/Channel.cs | 25 +++++- src/Discord.Net/Models/Color.cs | 1 - src/Discord.Net/Models/GlobalUser.cs | 79 ------------------- src/Discord.Net/Models/Message.cs | 4 + src/Discord.Net/Models/Profile.cs | 7 +- src/Discord.Net/Models/Role.cs | 1 + src/Discord.Net/Models/Server.cs | 9 ++- src/Discord.Net/Models/User.cs | 3 +- 14 files changed, 88 insertions(+), 126 deletions(-) delete mode 100644 src/Discord.Net/Models/GlobalUser.cs diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 8cf52e498..c21bd2356 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -68,7 +68,7 @@ namespace Discord.Commands client.MessageReceived += async (s, e) => { 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; if (msg.Length == 0) return; diff --git a/src/Discord.Net/API/Client/Common/Channel.cs b/src/Discord.Net/API/Client/Common/Channel.cs index fd879c680..f54c11e5c 100644 --- a/src/Discord.Net/API/Client/Common/Channel.cs +++ b/src/Discord.Net/API/Client/Common/Channel.cs @@ -9,8 +9,7 @@ namespace Discord.API.Client { [JsonProperty("type")] public string Type { get; set; } - [JsonProperty("id")] - [JsonConverter(typeof(LongStringConverter))] + [JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] public ulong Id { get; set; } [JsonProperty("deny")] public uint Deny { get; set; } diff --git a/src/Discord.Net/API/Client/Common/ChannelReference.cs b/src/Discord.Net/API/Client/Common/ChannelReference.cs index 5ac70d202..a243e0f49 100644 --- a/src/Discord.Net/API/Client/Common/ChannelReference.cs +++ b/src/Discord.Net/API/Client/Common/ChannelReference.cs @@ -7,8 +7,8 @@ namespace Discord.API.Client { [JsonProperty("id"), JsonConverter(typeof(LongStringConverter))] public ulong Id { get; set; } - [JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] - public ulong GuildId { get; set; } + [JsonProperty("guild_id"), JsonConverter(typeof(NullableLongStringConverter))] + public ulong? GuildId { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("type")] diff --git a/src/Discord.Net/API/Client/Common/MemberReference.cs b/src/Discord.Net/API/Client/Common/MemberReference.cs index 2db5c30a2..ba6f37762 100644 --- a/src/Discord.Net/API/Client/Common/MemberReference.cs +++ b/src/Discord.Net/API/Client/Common/MemberReference.cs @@ -5,7 +5,7 @@ namespace Discord.API.Client { public class MemberReference { - [JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] + [JsonProperty("guild_id"), JsonConverter(typeof(NullableLongStringConverter))] public ulong? GuildId { get; set; } [JsonProperty("user")] public UserReference User { get; set; } diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 3edd6a11b..ba509c790 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -171,10 +171,7 @@ namespace Discord State = ConnectionState.Connecting; _disconnectedEvent.Reset(); - await Login(email, password, token).ConfigureAwait(false); - - ClientAPI.Token = token; - GatewaySocket.Token = token; + await Login(email, password, token).ConfigureAwait(false); await GatewaySocket.Connect().ConfigureAwait(false); List tasks = new List(); @@ -233,6 +230,9 @@ namespace Discord } } + ClientAPI.Token = token; + GatewaySocket.Token = token; + //Get gateway and check token try { @@ -309,22 +309,10 @@ namespace Discord } #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; - return channel; - } + } private Channel RemoveChannel(ulong id) { Channel channel; @@ -337,20 +325,26 @@ namespace Discord } return channel; } - - internal Channel GetChannel(ulong id) + public Channel GetChannel(ulong id) { Channel channel; _channels.TryGetValue(id, out 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) { Channel channel; _privateChannels.TryGetValue(recipientId, out channel); return channel; } - internal async Task CreatePrivateChannel(User user) { var channel = GetPrivateChannel(user.Id); @@ -358,8 +352,8 @@ namespace Discord var request = new CreatePrivateChannelRequest() { RecipientId = user.Id }; 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); return channel; } @@ -453,6 +447,7 @@ namespace Discord SessionId = data.SessionId; PrivateUser = new User(this, data.User.Id, null); PrivateUser.Update(data.User); + CurrentUser = new Profile(this, data.User.Id); CurrentUser.Update(data.User); foreach (var model in data.Guilds) { @@ -464,7 +459,7 @@ namespace Discord } 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); } } @@ -523,10 +518,22 @@ namespace Discord case "CHANNEL_CREATE": { var data = e.Payload.ToObject(_serializer); - Channel channel = AddChannel(data.Id, data.GuildId, data.Recipient.Id); - channel.Update(data); - Logger.Info($"Channel Created: {channel.Server?.Name ?? "[Private]"}/{channel.Name}"); - OnChannelCreated(channel); + + 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); + Logger.Info($"Channel Created: {channel.Server?.Name ?? "[Private]"}/{channel.Name}"); + OnChannelCreated(channel); + } } break; case "CHANNEL_UPDATE": diff --git a/src/Discord.Net/Extensions.cs b/src/Discord.Net/Extensions.cs index 30acf0e0b..2d843cef9 100644 --- a/src/Discord.Net/Extensions.cs +++ b/src/Discord.Net/Extensions.cs @@ -27,15 +27,22 @@ namespace Discord [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasBit(this uint value, byte bit) => ((value >> bit) & 1U) == 1; - public static bool TryGetAdd(this ConcurrentDictionary d, + public static bool TryGetOrAdd(this ConcurrentDictionary d, TKey key, Func factory, out TValue result) + where TValue : class { + TValue newValue = null; while (true) { if (d.TryGetValue(key, out result)) return false; - if (d.TryAdd(key, factory(key))) + if (newValue == null) + newValue = factory(key); + if (d.TryAdd(key, newValue)) + { + result = newValue; return true; + } } } diff --git a/src/Discord.Net/Models/Channel.cs b/src/Discord.Net/Models/Channel.cs index 552c146c9..f739fc0f1 100644 --- a/src/Discord.Net/Models/Channel.cs +++ b/src/Discord.Net/Models/Channel.cs @@ -112,7 +112,6 @@ namespace Discord : this(client, id) { Recipient = recipient; - Name = $"@{recipient}"; AddUser(client.PrivateUser); AddUser(recipient); } @@ -143,7 +142,10 @@ namespace Discord if (model.Topic != null) Topic = model.Topic; if (model.Recipient != null) + { Recipient.Update(model.Recipient); + Name = $"@{Recipient}"; + } if (model.PermissionOverwrites != null) { @@ -263,9 +265,13 @@ namespace Discord public Message GetMessage(ulong id) { - Message result; - _messages.TryGetValue(id, out result); - return result; + if (Client.Config.MessageCacheSize > 0) + { + Message result; + _messages.TryGetValue(id, out result); + return result; + } + return null; } public async Task DownloadMessages(int limit = 100, ulong? relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before, bool useCache = true) @@ -556,6 +562,17 @@ namespace Discord } 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; _users.TryGetValue(id, out result); return result.User; diff --git a/src/Discord.Net/Models/Color.cs b/src/Discord.Net/Models/Color.cs index 190c5157e..faea44507 100644 --- a/src/Discord.Net/Models/Color.cs +++ b/src/Discord.Net/Models/Color.cs @@ -28,7 +28,6 @@ namespace Discord public static readonly Color LightGrey = PresetColor(0x979C9F); public static readonly Color DarkerGrey = PresetColor(0x546E7A); - private static Color PresetColor(uint packedValue) { Color color = new Color(packedValue); diff --git a/src/Discord.Net/Models/GlobalUser.cs b/src/Discord.Net/Models/GlobalUser.cs deleted file mode 100644 index 819f4396d..000000000 --- a/src/Discord.Net/Models/GlobalUser.cs +++ /dev/null @@ -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 - { - /// Returns the email for this user. Note: this field is only ever populated for the current logged in user. - [JsonIgnore] - public string Email { get; private set; } - /// Returns if the email for this user has been verified. Note: this field is only ever populated for the current logged in user. - [JsonIgnore] - public bool? IsVerified { get; private set; } - - /// Returns the private messaging channel with this user, if one exists. - [JsonIgnore] - public Channel PrivateChannel - { - get { return _privateChannel; } - set - { - _privateChannel = value; - if (value == null) - CheckUser(); - } - } - [JsonProperty] - private ulong? PrivateChannelId => _privateChannel?.Id; - private Channel _privateChannel; - - /// Returns a collection of all server-specific data for every server this user is a member of. - [JsonIgnore] - public IEnumerable Memberships => _users.Select(x => x.Value); - [JsonProperty] - private IEnumerable ServerIds => _users.Select(x => x.Key); - private readonly ConcurrentDictionary _users; - - /// Returns the string used to mention this user. - public string Mention => $"<@{Id}>"; - - internal GlobalUser(DiscordClient client, ulong id) - : base(client, id) - { - _users = new ConcurrentDictionary(); - } - 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); - }*/ -} diff --git a/src/Discord.Net/Models/Message.cs b/src/Discord.Net/Models/Message.cs index 78adb0170..43052fed9 100644 --- a/src/Discord.Net/Models/Message.cs +++ b/src/Discord.Net/Models/Message.cs @@ -201,6 +201,10 @@ namespace Discord internal Message(ulong id, Channel channel, ulong userId) { + Id = id; + Channel = channel; + _userId = userId; + Attachments = _initialAttachments; Embeds = _initialEmbeds; } diff --git a/src/Discord.Net/Models/Profile.cs b/src/Discord.Net/Models/Profile.cs index 65f73cfe1..33bd6f059 100644 --- a/src/Discord.Net/Models/Profile.cs +++ b/src/Discord.Net/Models/Profile.cs @@ -11,20 +11,21 @@ namespace Discord internal DiscordClient Client { get; } /// Gets the unique identifier for this user. - public ulong Id { get; private set; } + public ulong Id { get; } + /// Gets the email for this user. public string Email { get; private set; } /// Gets if the email for this user has been verified. public bool? IsVerified { get; private set; } - internal Profile(DiscordClient client) + internal Profile(DiscordClient client, ulong id) { Client = client; + Id = id; } internal void Update(APIUser model) { - Id = model.Id; Email = model.Email; IsVerified = model.IsVerified; } diff --git a/src/Discord.Net/Models/Role.cs b/src/Discord.Net/Models/Role.cs index 44aae34cc..1db60eba7 100644 --- a/src/Discord.Net/Models/Role.cs +++ b/src/Discord.Net/Models/Role.cs @@ -52,6 +52,7 @@ namespace Discord { Id = id; Server = server; + Permissions = new ServerPermissions(0); Permissions.Lock(); Color = new Color(0); diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs index 71f6ecab6..181e3011b 100644 --- a/src/Discord.Net/Models/Server.cs +++ b/src/Discord.Net/Models/Server.cs @@ -78,6 +78,7 @@ namespace Discord { Client = client; Id = id; + _channels = new ConcurrentDictionary(); _roles = new ConcurrentDictionary(); _users = new ConcurrentDictionary(); @@ -97,7 +98,7 @@ namespace Discord if (model.AFKTimeout != null) AFKTimeout = model.AFKTimeout.Value; - _afkChannelId = model.AFKChannelId.Value; //Can be null + _afkChannelId = model.AFKChannelId; //Can be null if (model.JoinedAt != null) JoinedAt = model.JoinedAt.Value; if (model.OwnerId != null) @@ -196,7 +197,11 @@ namespace Discord #region Channels 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) { Channel channel; diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs index 6a2948dab..454cca733 100644 --- a/src/Discord.Net/Models/User.cs +++ b/src/Discord.Net/Models/User.cs @@ -136,9 +136,10 @@ namespace Discord internal User(DiscordClient client, ulong id, Server server) { Client = client; + Id = id; Server = server; - _roles = new Dictionary(); + _roles = new Dictionary(); Status = UserStatus.Offline; if (server == null)