I shan't, it's Christmas!
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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<Task> tasks = new List<Task>();
|
||||
@@ -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<Channel> 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<ChannelCreateEvent>(_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":
|
||||
|
||||
@@ -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<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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Message[]> 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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
Id = id;
|
||||
Channel = channel;
|
||||
_userId = userId;
|
||||
|
||||
Attachments = _initialAttachments;
|
||||
Embeds = _initialEmbeds;
|
||||
}
|
||||
|
||||
@@ -11,20 +11,21 @@ namespace Discord
|
||||
internal DiscordClient Client { get; }
|
||||
|
||||
/// <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>
|
||||
public string Email { get; private set; }
|
||||
/// <summary> Gets if the email for this user has been verified. </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Discord
|
||||
{
|
||||
Id = id;
|
||||
Server = server;
|
||||
|
||||
Permissions = new ServerPermissions(0);
|
||||
Permissions.Lock();
|
||||
Color = new Color(0);
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace Discord
|
||||
{
|
||||
Client = client;
|
||||
Id = id;
|
||||
|
||||
_channels = new ConcurrentDictionary<ulong, Channel>();
|
||||
_roles = new ConcurrentDictionary<ulong, Role>();
|
||||
_users = new ConcurrentDictionary<ulong, Member>();
|
||||
@@ -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;
|
||||
|
||||
@@ -136,9 +136,10 @@ namespace Discord
|
||||
internal User(DiscordClient client, ulong id, Server server)
|
||||
{
|
||||
Client = client;
|
||||
Id = id;
|
||||
Server = server;
|
||||
_roles = new Dictionary<ulong, Role>();
|
||||
|
||||
_roles = new Dictionary<ulong, Role>();
|
||||
Status = UserStatus.Offline;
|
||||
|
||||
if (server == null)
|
||||
|
||||
Reference in New Issue
Block a user