diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj
index 1f001d361..3dbcfef5c 100644
--- a/src/Discord.Net.Net45/Discord.Net.csproj
+++ b/src/Discord.Net.Net45/Discord.Net.csproj
@@ -94,9 +94,6 @@
API\Enums\PermissionTarget.cs
-
- API\Enums\Region.cs
-
API\Enums\StringEnum.cs
@@ -259,6 +256,9 @@
Models\Permissions.cs
+
+ Models\Region.cs
+
Models\Role.cs
diff --git a/src/Discord.Net/API/Converters/StringEnumConverter.cs b/src/Discord.Net/API/Converters/StringEnumConverter.cs
new file mode 100644
index 000000000..251c5ff05
--- /dev/null
+++ b/src/Discord.Net/API/Converters/StringEnumConverter.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Discord.API.Converters
+{
+ public class StringEnumConverter
+ {
+ }
+}
diff --git a/src/Discord.Net/DiscordAPIClientConfig.cs b/src/Discord.Net/DiscordAPIClientConfig.cs
index 0fde36c2c..9fb036f7d 100644
--- a/src/Discord.Net/DiscordAPIClientConfig.cs
+++ b/src/Discord.Net/DiscordAPIClientConfig.cs
@@ -6,6 +6,8 @@ namespace Discord
{
public class DiscordAPIClientConfig
{
+ internal static readonly string UserAgent = $"Discord.Net/{DiscordClient.Version} (https://github.com/RogueException/Discord.Net)";
+
/// Specifies the minimum log level severity that will be sent to the LogMessage event. Warning: setting this to debug will really hurt performance but should help investigate any internal issues.
public LogMessageSeverity LogLevel { get { return _logLevel; } set { SetValue(ref _logLevel, value); } }
private LogMessageSeverity _logLevel = LogMessageSeverity.Info;
@@ -21,15 +23,6 @@ namespace Discord
public NetworkCredential ProxyCredentials { get { return _proxyCredentials; } set { SetValue(ref _proxyCredentials, value); } }
private NetworkCredential _proxyCredentials = null;
- internal string UserAgent
- {
- get
- {
- string version = typeof(DiscordClientConfig).GetTypeInfo().Assembly.GetName().Version.ToString(2);
- return $"Discord.Net/{version} (https://github.com/RogueException/Discord.Net)";
- }
- }
-
//Lock
protected bool _isLocked;
internal void Lock() { _isLocked = true; }
diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs
index 19bbdef18..f8fa09eb8 100644
--- a/src/Discord.Net/DiscordClient.Messages.cs
+++ b/src/Discord.Net/DiscordClient.Messages.cs
@@ -261,7 +261,7 @@ namespace Discord
}
/// Deserializes messages from JSON format and imports them into the message cache.
- public IEnumerable ImportMessages(string json)
+ public IEnumerable ImportMessages(Channel channel, string json)
{
if (json == null) throw new ArgumentNullException(nameof(json));
@@ -269,8 +269,8 @@ namespace Discord
.Select(x =>
{
var msg = new Message(this,
- x["Id"].Value(),
- x["ChannelId"].Value(),
+ x["Id"].Value(),
+ channel.Id,
x["UserId"].Value());
var reader = x.CreateReader();
diff --git a/src/Discord.Net/DiscordClient.Servers.cs b/src/Discord.Net/DiscordClient.Servers.cs
index 889c5879e..b52901fa0 100644
--- a/src/Discord.Net/DiscordClient.Servers.cs
+++ b/src/Discord.Net/DiscordClient.Servers.cs
@@ -86,19 +86,19 @@ namespace Discord
if (region == null) throw new ArgumentNullException(nameof(region));
CheckReady();
- var response = await _api.CreateServer(name, region.Value).ConfigureAwait(false);
+ var response = await _api.CreateServer(name, region.Id).ConfigureAwait(false);
var server = _servers.GetOrAdd(response.Id);
server.Update(response);
return server;
}
/// Edits the provided server, changing only non-null attributes.
- public async Task EditServer(Server server, string name = null, Region region = null, ImageType iconType = ImageType.Png, byte[] icon = null)
+ public async Task EditServer(Server server, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null)
{
if (server == null) throw new ArgumentNullException(nameof(server));
CheckReady();
- var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region.Value, iconType: iconType, icon: icon).ConfigureAwait(false);
+ var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region, iconType: iconType, icon: icon).ConfigureAwait(false);
server.Update(response);
}
@@ -112,5 +112,12 @@ namespace Discord
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { }
//return _servers.TryRemove(server.Id);
}
+
+ public async Task> GetVoiceRegions()
+ {
+ CheckReady();
+
+ return (await _api.GetVoiceRegions()).Select(x => new Region { Id = x.Id, Name = x.Name, Hostname = x.Hostname, Port = x.Port });
+ }
}
}
\ No newline at end of file
diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs
index c9ef3366b..12e246ea6 100644
--- a/src/Discord.Net/DiscordClient.cs
+++ b/src/Discord.Net/DiscordClient.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
using System.Threading.Tasks;
namespace Discord
@@ -12,12 +13,14 @@ namespace Discord
/// Provides a connection to the DiscordApp service.
public sealed partial class DiscordClient : DiscordWSClient
{
+ public static readonly string Version = typeof(DiscordClientConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3);
+
private readonly DiscordAPIClient _api;
private readonly Random _rand;
- private readonly JsonSerializer _socketSerializer, _messageImporter;
+ private readonly JsonSerializer _messageImporter;
private readonly ConcurrentQueue _pendingMessages;
private readonly ConcurrentDictionary _voiceClients;
- private readonly Dictionary _services;
+ private readonly Dictionary _singletons;
private bool _sentInitialLog;
private uint _nextVoiceClientId;
private UserStatus _status;
@@ -47,7 +50,7 @@ namespace Discord
_roles = new Roles(this, cacheLock);
_servers = new Servers(this, cacheLock);
_globalUsers = new GlobalUsers(this, cacheLock);
- _services = new Dictionary();
+ _singletons = new Dictionary();
_status = UserStatus.Online;
@@ -162,16 +165,9 @@ namespace Discord
if (Config.UseMessageQueue)
_pendingMessages = new ConcurrentQueue();
-
- _socketSerializer = new JsonSerializer();
- _socketSerializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
-#if TEST_RESPONSES
- _serializer.CheckAdditionalContent = true;
- _serializer.MissingMemberHandling = MissingMemberHandling.Error;
-#endif
-
+
_messageImporter = new JsonSerializer();
- _messageImporter.ContractResolver = new MessageImporterResolver();
+ _messageImporter.ContractResolver = new Message.ImportResolver();
}
internal override VoiceWebSocket CreateVoiceSocket()
{
@@ -276,25 +272,34 @@ namespace Discord
_privateUser = null;
}
+ public T AddSingleton(T obj)
+ where T : class
+ {
+ _singletons.Add(typeof(T), obj);
+ return obj;
+ }
+ public T GetSingleton(bool required = true)
+ where T : class
+ {
+ object singleton;
+ T singletonT = null;
+ if (_singletons.TryGetValue(typeof(T), out singleton))
+ singletonT = singleton as T;
+
+ if (singletonT == null && required)
+ throw new InvalidOperationException($"This operation requires {nameof(T)} to be added to {nameof(DiscordClient)}.");
+ return singletonT;
+ }
public T AddService(T obj)
where T : class, IService
{
- _services.Add(typeof(T), obj);
+ AddSingleton(obj);
obj.Install(this);
return obj;
}
public T GetService(bool required = true)
where T : class, IService
- {
- IService service;
- T serviceT = null;
- if (_services.TryGetValue(typeof(T), out service))
- serviceT = service as T;
-
- if (serviceT == null && required)
- throw new InvalidOperationException($"This operation requires {nameof(T)} to be added to {nameof(DiscordClient)}.");
- return serviceT;
- }
+ => GetSingleton(required);
protected override IEnumerable GetTasks()
{
@@ -314,7 +319,7 @@ namespace Discord
case "READY": //Resync
{
base.OnReceivedEvent(e).Wait(); //This cannot be an await, or we'll get later messages before we're ready
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
_privateUser = _users.GetOrAdd(data.User.Id, null);
_privateUser.Update(data.User);
_privateUser.Global.Update(data.User);
@@ -339,7 +344,7 @@ namespace Discord
//Servers
case "GUILD_CREATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
if (data.Unavailable != true)
{
var server = _servers.GetOrAdd(data.Id);
@@ -353,7 +358,7 @@ namespace Discord
break;
case "GUILD_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var server = _servers[data.Id];
if (server != null)
{
@@ -364,7 +369,7 @@ namespace Discord
break;
case "GUILD_DELETE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var server = _servers.TryRemove(data.Id);
if (server != null)
{
@@ -379,7 +384,7 @@ namespace Discord
//Channels
case "CHANNEL_CREATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
Channel channel;
if (data.IsPrivate)
{
@@ -395,7 +400,7 @@ namespace Discord
break;
case "CHANNEL_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var channel = _channels[data.Id];
if (channel != null)
{
@@ -406,7 +411,7 @@ namespace Discord
break;
case "CHANNEL_DELETE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var channel = _channels.TryRemove(data.Id);
if (channel != null)
RaiseChannelDestroyed(channel);
@@ -416,7 +421,7 @@ namespace Discord
//Members
case "GUILD_MEMBER_ADD":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _users.GetOrAdd(data.User.Id, data.GuildId);
user.Update(data);
if (Config.TrackActivity)
@@ -426,7 +431,7 @@ namespace Discord
break;
case "GUILD_MEMBER_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _users[data.User.Id, data.GuildId];
if (user != null)
{
@@ -437,7 +442,7 @@ namespace Discord
break;
case "GUILD_MEMBER_REMOVE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _users.TryRemove(data.UserId, data.GuildId);
if (user != null)
RaiseUserLeft(user);
@@ -445,7 +450,7 @@ namespace Discord
break;
case "GUILD_MEMBERS_CHUNK":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
foreach (var memberData in data.Members)
{
var user = _users.GetOrAdd(memberData.User.Id, memberData.GuildId);
@@ -458,7 +463,7 @@ namespace Discord
//Roles
case "GUILD_ROLE_CREATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var role = _roles.GetOrAdd(data.Data.Id, data.GuildId);
role.Update(data.Data);
var server = _servers[data.GuildId];
@@ -469,7 +474,7 @@ namespace Discord
break;
case "GUILD_ROLE_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var role = _roles[data.Data.Id];
if (role != null)
{
@@ -480,7 +485,7 @@ namespace Discord
break;
case "GUILD_ROLE_DELETE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var role = _roles.TryRemove(data.RoleId);
if (role != null)
{
@@ -495,7 +500,7 @@ namespace Discord
//Bans
case "GUILD_BAN_ADD":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var server = _servers[data.GuildId];
if (server != null)
{
@@ -507,7 +512,7 @@ namespace Discord
break;
case "GUILD_BAN_REMOVE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var server = _servers[data.GuildId];
if (server != null)
{
@@ -521,7 +526,7 @@ namespace Discord
//Messages
case "MESSAGE_CREATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
Message msg = null;
bool isAuthor = data.Author.Id == _userId;
@@ -548,7 +553,7 @@ namespace Discord
break;
case "MESSAGE_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var msg = _messages[data.Id];
if (msg != null)
{
@@ -559,7 +564,7 @@ namespace Discord
break;
case "MESSAGE_DELETE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var msg = _messages.TryRemove(data.Id);
if (msg != null)
RaiseMessageDeleted(msg);
@@ -567,7 +572,7 @@ namespace Discord
break;
case "MESSAGE_ACK":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var msg = GetMessage(data.MessageId);
if (msg != null)
RaiseMessageReadRemotely(msg);
@@ -577,7 +582,7 @@ namespace Discord
//Statuses
case "PRESENCE_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _users.GetOrAdd(data.User.Id, data.GuildId);
if (user != null)
{
@@ -588,7 +593,7 @@ namespace Discord
break;
case "TYPING_START":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var channel = _channels[data.ChannelId];
if (channel != null)
{
@@ -614,7 +619,7 @@ namespace Discord
//Voice
case "VOICE_STATE_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _users[data.UserId, data.GuildId];
if (user != null)
{
@@ -633,7 +638,7 @@ namespace Discord
//Settings
case "USER_UPDATE":
{
- var data = e.Payload.ToObject(_socketSerializer);
+ var data = e.Payload.ToObject(_dataSocketSerializer);
var user = _globalUsers[data.Id];
if (user != null)
{
diff --git a/src/Discord.Net/DiscordWSClient.cs b/src/Discord.Net/DiscordWSClient.cs
index d79cdf7a5..14f020fda 100644
--- a/src/Discord.Net/DiscordWSClient.cs
+++ b/src/Discord.Net/DiscordWSClient.cs
@@ -1,5 +1,6 @@
using Discord.Net;
using Discord.Net.WebSockets;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -23,9 +24,9 @@ namespace Discord
protected readonly DiscordWSClientConfig _config;
protected readonly ManualResetEvent _disconnectedEvent;
protected readonly ManualResetEventSlim _connectedEvent;
+ protected ExceptionDispatchInfo _disconnectReason;
internal readonly DataWebSocket _dataSocket;
internal readonly VoiceWebSocket _voiceSocket;
- protected ExceptionDispatchInfo _disconnectReason;
protected string _gateway, _token;
protected long? _userId, _voiceServerId;
private Task _runTask;
@@ -44,6 +45,10 @@ namespace Discord
private CancellationTokenSource _cancelTokenSource;
protected CancellationToken _cancelToken;
+ internal JsonSerializer DataSocketSerializer => _dataSocketSerializer;
+ internal JsonSerializer VoiceSocketSerializer => _voiceSocketSerializer;
+ protected readonly JsonSerializer _dataSocketSerializer, _voiceSocketSerializer;
+
/// Initializes a new instance of the DiscordClient class.
public DiscordWSClient(DiscordWSClientConfig config = null)
{
@@ -55,6 +60,32 @@ namespace Discord
_disconnectedEvent = new ManualResetEvent(true);
_connectedEvent = new ManualResetEventSlim(false);
+ _dataSocketSerializer = new JsonSerializer();
+ _dataSocketSerializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
+#if TEST_RESPONSES
+ _dataSocketSerializer.CheckAdditionalContent = true;
+ _dataSocketSerializer.MissingMemberHandling = MissingMemberHandling.Error;
+#else
+ _dataSocketSerializer.Error += (s, e) =>
+ {
+ e.ErrorContext.Handled = true;
+ RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.DataWebSocket, "Serialization Failed", e.ErrorContext.Error);
+ };
+#endif
+
+ _voiceSocketSerializer = new JsonSerializer();
+ _voiceSocketSerializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
+#if TEST_RESPONSES
+ _voiceSocketSerializer.CheckAdditionalContent = true;
+ _voiceSocketSerializer.MissingMemberHandling = MissingMemberHandling.Error;
+#else
+ _voiceSocketSerializer.Error += (s, e) =>
+ {
+ e.ErrorContext.Handled = true;
+ RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.VoiceWebSocket, "Serialization Failed", e.ErrorContext.Error);
+ };
+#endif
+
_dataSocket = CreateDataSocket();
if (_config.EnableVoice)
_voiceSocket = CreateVoiceSocket();
diff --git a/src/Discord.Net/Helpers/AsyncCollection.cs b/src/Discord.Net/Helpers/AsyncCollection.cs
index 1035a45d2..f173eaefb 100644
--- a/src/Discord.Net/Helpers/AsyncCollection.cs
+++ b/src/Discord.Net/Helpers/AsyncCollection.cs
@@ -84,15 +84,21 @@ namespace Discord
lock (_writerLock)
{
- TValue newItem = createFunc();
- result = _dictionary.GetOrAdd(key, newItem);
- if (result == newItem)
+ if (!_dictionary.ContainsKey(key))
{
- result.Cache();
- RaiseItemCreated(result);
+ result = createFunc();
+ if (result.Cache())
+ {
+ _dictionary.TryAdd(key, result);
+ RaiseItemCreated(result);
+ }
+ else
+ result.Uncache();
+ return result;
}
+ else
+ return _dictionary[key];
}
- return result;
}
protected void Import(IEnumerable> items)
{
@@ -101,9 +107,13 @@ namespace Discord
foreach (var pair in items)
{
var value = pair.Value;
- _dictionary.TryAdd(pair.Key, value);
- value.Cache();
- RaiseItemCreated(value);
+ if (value.Cache())
+ {
+ _dictionary.TryAdd(pair.Key, value);
+ RaiseItemCreated(value);
+ }
+ else
+ value.Uncache();
}
}
}
diff --git a/src/Discord.Net/Helpers/CachedObject.cs b/src/Discord.Net/Helpers/CachedObject.cs
index d0232b91a..dcd3b3c4a 100644
--- a/src/Discord.Net/Helpers/CachedObject.cs
+++ b/src/Discord.Net/Helpers/CachedObject.cs
@@ -31,10 +31,14 @@ namespace Discord
_client = client;
}
- internal void Cache()
+ internal bool Cache()
{
- LoadReferences();
- _isCached = true;
+ if (LoadReferences())
+ {
+ _isCached = true;
+ return true;
+ }
+ return false;
}
internal void Uncache()
{
@@ -44,7 +48,7 @@ namespace Discord
_isCached = false;
}
}
- internal abstract void LoadReferences();
+ internal abstract bool LoadReferences();
internal abstract void UnloadReferences();
}
}
diff --git a/src/Discord.Net/Helpers/Reference.cs b/src/Discord.Net/Helpers/Reference.cs
index ff9aa79ae..3ea7705e8 100644
--- a/src/Discord.Net/Helpers/Reference.cs
+++ b/src/Discord.Net/Helpers/Reference.cs
@@ -41,9 +41,9 @@ namespace Discord
}
}
- public T Load()
+ public bool Load()
{
- return Value; //Used for precaching
+ return Value != null; //Used for precaching
}
public void Unload()
diff --git a/src/Discord.Net/Models/Channel.cs b/src/Discord.Net/Models/Channel.cs
index ce9db815b..b2233aa20 100644
--- a/src/Discord.Net/Models/Channel.cs
+++ b/src/Discord.Net/Models/Channel.cs
@@ -124,12 +124,12 @@ namespace Discord
if (client.Config.MessageCacheLength > 0)
_messages = new ConcurrentDictionary();
}
- internal override void LoadReferences()
+ internal override bool LoadReferences()
{
if (IsPrivate)
- _recipient.Load();
+ return _recipient.Load();
else
- _server.Load();
+ return _server.Load();
}
internal override void UnloadReferences()
{
diff --git a/src/Discord.Net/Models/GlobalUser.cs b/src/Discord.Net/Models/GlobalUser.cs
index f43fef90b..016f522e0 100644
--- a/src/Discord.Net/Models/GlobalUser.cs
+++ b/src/Discord.Net/Models/GlobalUser.cs
@@ -44,7 +44,7 @@ namespace Discord
{
_users = new ConcurrentDictionary();
}
- internal override void LoadReferences() { }
+ internal override bool LoadReferences() { return true; }
internal override void UnloadReferences()
{
//Don't need to clean _users - they're considered owned by server
diff --git a/src/Discord.Net/Models/Invite.cs b/src/Discord.Net/Models/Invite.cs
index 4601dadf5..a89da9abc 100644
--- a/src/Discord.Net/Models/Invite.cs
+++ b/src/Discord.Net/Models/Invite.cs
@@ -82,7 +82,7 @@ namespace Discord
{
XkcdCode = xkcdPass;
}
- internal override void LoadReferences() { }
+ internal override bool LoadReferences() { return true; }
internal override void UnloadReferences() { }
internal void Update(InviteReference model)
diff --git a/src/Discord.Net/Models/Message.cs b/src/Discord.Net/Models/Message.cs
index 0fd2fd057..2c1c0731c 100644
--- a/src/Discord.Net/Models/Message.cs
+++ b/src/Discord.Net/Models/Message.cs
@@ -15,24 +15,25 @@ namespace Discord
Queued,
Failed
}
- internal class MessageImporterResolver : DefaultContractResolver
+
+ public sealed class Message : CachedObject
{
- protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+ internal class ImportResolver : DefaultContractResolver
{
- var property = base.CreateProperty(member, memberSerialization);
- if (member is PropertyInfo)
+ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
- if (!(member as PropertyInfo).CanWrite)
- return null;
+ var property = base.CreateProperty(member, memberSerialization);
+ if (member is PropertyInfo)
+ {
+ if (member.Name == nameof(ChannelId) || !(member as PropertyInfo).CanWrite)
+ return null;
- property.Writable = true; //Handles private setters
+ property.Writable = true; //Handles private setters
+ }
+ return property;
}
- return property;
}
- }
- public sealed class Message : CachedObject
- {
public sealed class Attachment : File
{
/// Unique identifier for this file.
@@ -173,6 +174,8 @@ namespace Discord
x =>
{
var channel = Channel;
+ if (channel == null) return null;
+
if (!channel.IsPrivate)
return _client.Users[x, channel.Server.Id];
else
@@ -181,10 +184,9 @@ namespace Discord
Attachments = _initialAttachments;
Embeds = _initialEmbeds;
}
- internal override void LoadReferences()
+ internal override bool LoadReferences()
{
- _channel.Load();
- _user.Load();
+ return _channel.Load() && _user.Load();
}
internal override void UnloadReferences()
{
diff --git a/src/Discord.Net/Models/Region.cs b/src/Discord.Net/Models/Region.cs
new file mode 100644
index 000000000..f37d6949e
--- /dev/null
+++ b/src/Discord.Net/Models/Region.cs
@@ -0,0 +1,10 @@
+namespace Discord
+{
+ public sealed class Region
+ {
+ public string Hostname;
+ public int Port;
+ public string Id;
+ public string Name;
+ }
+}
diff --git a/src/Discord.Net/Models/Role.cs b/src/Discord.Net/Models/Role.cs
index 420edec27..285cc59f3 100644
--- a/src/Discord.Net/Models/Role.cs
+++ b/src/Discord.Net/Models/Role.cs
@@ -47,9 +47,9 @@ namespace Discord
Color = new Color(0);
Color.Lock();
}
- internal override void LoadReferences()
+ internal override bool LoadReferences()
{
- _server.Load();
+ return _server.Load();
}
internal override void UnloadReferences()
{
diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs
index a403e2cc5..50236161a 100644
--- a/src/Discord.Net/Models/Server.cs
+++ b/src/Discord.Net/Models/Server.cs
@@ -103,9 +103,10 @@ namespace Discord
//Local Cache
_bans = new ConcurrentDictionary();
}
- internal override void LoadReferences()
+ internal override bool LoadReferences()
{
_afkChannel.Load();
+ return true;
}
internal override void UnloadReferences()
{
diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs
index c0c02a835..2fe2e95c7 100644
--- a/src/Discord.Net/Models/User.cs
+++ b/src/Discord.Net/Models/User.cs
@@ -148,10 +148,10 @@ namespace Discord
if (serverId == null)
UpdateRoles(null);
}
- internal override void LoadReferences()
+ internal override bool LoadReferences()
{
- _globalUser.Load();
- _server.Load();
+ return _globalUser.Load() &&
+ (IsPrivate || _server.Load());
}
internal override void UnloadReferences()
{
diff --git a/src/Discord.Net/Net/Rest/SharpRestEngine.cs b/src/Discord.Net/Net/Rest/SharpRestEngine.cs
index 64382eaca..2dfc0780d 100644
--- a/src/Discord.Net/Net/Rest/SharpRestEngine.cs
+++ b/src/Discord.Net/Net/Rest/SharpRestEngine.cs
@@ -20,7 +20,7 @@ namespace Discord.Net.Rest
{
PreAuthenticate = false,
ReadWriteTimeout = _config.APITimeout,
- UserAgent = _config.UserAgent
+ UserAgent = DiscordAPIClientConfig.UserAgent
};
if (_config.ProxyUrl != null)
_client.Proxy = new WebProxy(_config.ProxyUrl, true, new string[0], _config.ProxyCredentials);
diff --git a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs
index d8bcce68a..659cb26a0 100644
--- a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs
+++ b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs
@@ -82,13 +82,13 @@ namespace Discord.Net.WebSockets
JToken token = msg.Payload as JToken;
if (msg.Type == "READY")
{
- var payload = token.ToObject();
+ var payload = token.ToObject(_client.DataSocketSerializer);
_sessionId = payload.SessionId;
_heartbeatInterval = payload.HeartbeatInterval;
}
else if (msg.Type == "RESUMED")
{
- var payload = token.ToObject();
+ var payload = token.ToObject(_client.DataSocketSerializer);
_heartbeatInterval = payload.HeartbeatInterval;
}
RaiseReceivedEvent(msg.Type, token);
@@ -98,7 +98,7 @@ namespace Discord.Net.WebSockets
break;
case 7: //Redirect
{
- var payload = (msg.Payload as JToken).ToObject();
+ var payload = (msg.Payload as JToken).ToObject(_client.DataSocketSerializer);
if (payload.Url != null)
{
Host = payload.Url;
diff --git a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
index a060f78d1..37da540b8 100644
--- a/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
+++ b/src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs
@@ -443,7 +443,7 @@ namespace Discord.Net.WebSockets
{
if (_state != (int)WebSocketState.Connected)
{
- var payload = (msg.Payload as JToken).ToObject();
+ var payload = (msg.Payload as JToken).ToObject(_client.VoiceSocketSerializer);
_heartbeatInterval = payload.HeartbeatInterval;
_ssrc = payload.SSRC;
_endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(), payload.Port);
@@ -486,7 +486,7 @@ namespace Discord.Net.WebSockets
break;
case 4: //SESSION_DESCRIPTION
{
- var payload = (msg.Payload as JToken).ToObject();
+ var payload = (msg.Payload as JToken).ToObject(_client.VoiceSocketSerializer);
_secretKey = payload.SecretKey;
SendIsTalking(true);
EndConnect();
@@ -494,7 +494,7 @@ namespace Discord.Net.WebSockets
break;
case 5:
{
- var payload = (msg.Payload as JToken).ToObject();
+ var payload = (msg.Payload as JToken).ToObject(_client.VoiceSocketSerializer);
RaiseIsSpeaking(payload.UserId, payload.IsSpeaking);
}
break;