Browse Source

Fixed race condition, better handled serialization errors, and added singleton store

tags/docs-0.9
RogueException 9 years ago
parent
commit
91b3c17fb3
21 changed files with 187 additions and 113 deletions
  1. +3
    -3
      src/Discord.Net.Net45/Discord.Net.csproj
  2. +11
    -0
      src/Discord.Net/API/Converters/StringEnumConverter.cs
  3. +2
    -9
      src/Discord.Net/DiscordAPIClientConfig.cs
  4. +3
    -3
      src/Discord.Net/DiscordClient.Messages.cs
  5. +10
    -3
      src/Discord.Net/DiscordClient.Servers.cs
  6. +52
    -47
      src/Discord.Net/DiscordClient.cs
  7. +32
    -1
      src/Discord.Net/DiscordWSClient.cs
  8. +19
    -9
      src/Discord.Net/Helpers/AsyncCollection.cs
  9. +8
    -4
      src/Discord.Net/Helpers/CachedObject.cs
  10. +2
    -2
      src/Discord.Net/Helpers/Reference.cs
  11. +3
    -3
      src/Discord.Net/Models/Channel.cs
  12. +1
    -1
      src/Discord.Net/Models/GlobalUser.cs
  13. +1
    -1
      src/Discord.Net/Models/Invite.cs
  14. +16
    -14
      src/Discord.Net/Models/Message.cs
  15. +10
    -0
      src/Discord.Net/Models/Region.cs
  16. +2
    -2
      src/Discord.Net/Models/Role.cs
  17. +2
    -1
      src/Discord.Net/Models/Server.cs
  18. +3
    -3
      src/Discord.Net/Models/User.cs
  19. +1
    -1
      src/Discord.Net/Net/Rest/SharpRestEngine.cs
  20. +3
    -3
      src/Discord.Net/Net/WebSockets/DataWebSocket.cs
  21. +3
    -3
      src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs

+ 3
- 3
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -94,9 +94,6 @@
<Compile Include="..\Discord.Net\API\Enums\PermissionTarget.cs">
<Link>API\Enums\PermissionTarget.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\API\Enums\Region.cs">
<Link>API\Enums\Region.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\API\Enums\StringEnum.cs">
<Link>API\Enums\StringEnum.cs</Link>
</Compile>
@@ -259,6 +256,9 @@
<Compile Include="..\Discord.Net\Models\Permissions.cs">
<Link>Models\Permissions.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Models\Region.cs">
<Link>Models\Region.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Models\Role.cs">
<Link>Models\Role.cs</Link>
</Compile>


+ 11
- 0
src/Discord.Net/API/Converters/StringEnumConverter.cs View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Discord.API.Converters
{
public class StringEnumConverter
{
}
}

+ 2
- 9
src/Discord.Net/DiscordAPIClientConfig.cs View File

@@ -6,6 +6,8 @@ namespace Discord
{
public class DiscordAPIClientConfig
{
internal static readonly string UserAgent = $"Discord.Net/{DiscordClient.Version} (https://github.com/RogueException/Discord.Net)";

/// <summary> 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. </summary>
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; }


+ 3
- 3
src/Discord.Net/DiscordClient.Messages.cs View File

@@ -261,7 +261,7 @@ namespace Discord
}
/// <summary> Deserializes messages from JSON format and imports them into the message cache.</summary>
public IEnumerable<Message> ImportMessages(string json)
public IEnumerable<Message> 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<long>(),
x["ChannelId"].Value<long>(),
x["Id"].Value<long>(),
channel.Id,
x["UserId"].Value<long>());

var reader = x.CreateReader();


+ 10
- 3
src/Discord.Net/DiscordClient.Servers.cs View File

@@ -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;
}
/// <summary> Edits the provided server, changing only non-null attributes. </summary>
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<IEnumerable<Region>> GetVoiceRegions()
{
CheckReady();

return (await _api.GetVoiceRegions()).Select(x => new Region { Id = x.Id, Name = x.Name, Hostname = x.Hostname, Port = x.Port });
}
}
}

+ 52
- 47
src/Discord.Net/DiscordClient.cs View File

@@ -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
/// <summary> Provides a connection to the DiscordApp service. </summary>
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<Message> _pendingMessages;
private readonly ConcurrentDictionary<long, DiscordWSClient> _voiceClients;
private readonly Dictionary<Type, IService> _services;
private readonly Dictionary<Type, object> _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<Type, IService>();
_singletons = new Dictionary<Type, object>();

_status = UserStatus.Online;

@@ -162,16 +165,9 @@ namespace Discord

if (Config.UseMessageQueue)
_pendingMessages = new ConcurrentQueue<Message>();

_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>(T obj)
where T : class
{
_singletons.Add(typeof(T), obj);
return obj;
}
public T GetSingleton<T>(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>(T obj)
where T : class, IService
{
_services.Add(typeof(T), obj);
AddSingleton(obj);
obj.Install(this);
return obj;
}
public T GetService<T>(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<T>(required);

protected override IEnumerable<Task> 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<ReadyEvent>(_socketSerializer);
var data = e.Payload.ToObject<ReadyEvent>(_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<GuildCreateEvent>(_socketSerializer);
var data = e.Payload.ToObject<GuildCreateEvent>(_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<GuildUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<GuildUpdateEvent>(_dataSocketSerializer);
var server = _servers[data.Id];
if (server != null)
{
@@ -364,7 +369,7 @@ namespace Discord
break;
case "GUILD_DELETE":
{
var data = e.Payload.ToObject<GuildDeleteEvent>(_socketSerializer);
var data = e.Payload.ToObject<GuildDeleteEvent>(_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<ChannelCreateEvent>(_socketSerializer);
var data = e.Payload.ToObject<ChannelCreateEvent>(_dataSocketSerializer);
Channel channel;
if (data.IsPrivate)
{
@@ -395,7 +400,7 @@ namespace Discord
break;
case "CHANNEL_UPDATE":
{
var data = e.Payload.ToObject<ChannelUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<ChannelUpdateEvent>(_dataSocketSerializer);
var channel = _channels[data.Id];
if (channel != null)
{
@@ -406,7 +411,7 @@ namespace Discord
break;
case "CHANNEL_DELETE":
{
var data = e.Payload.ToObject<ChannelDeleteEvent>(_socketSerializer);
var data = e.Payload.ToObject<ChannelDeleteEvent>(_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<MemberAddEvent>(_socketSerializer);
var data = e.Payload.ToObject<MemberAddEvent>(_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<MemberUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<MemberUpdateEvent>(_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<MemberRemoveEvent>(_socketSerializer);
var data = e.Payload.ToObject<MemberRemoveEvent>(_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<MembersChunkEvent>(_socketSerializer);
var data = e.Payload.ToObject<MembersChunkEvent>(_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<RoleCreateEvent>(_socketSerializer);
var data = e.Payload.ToObject<RoleCreateEvent>(_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<RoleUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<RoleUpdateEvent>(_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<RoleDeleteEvent>(_socketSerializer);
var data = e.Payload.ToObject<RoleDeleteEvent>(_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<BanAddEvent>(_socketSerializer);
var data = e.Payload.ToObject<BanAddEvent>(_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<BanRemoveEvent>(_socketSerializer);
var data = e.Payload.ToObject<BanRemoveEvent>(_dataSocketSerializer);
var server = _servers[data.GuildId];
if (server != null)
{
@@ -521,7 +526,7 @@ namespace Discord
//Messages
case "MESSAGE_CREATE":
{
var data = e.Payload.ToObject<MessageCreateEvent>(_socketSerializer);
var data = e.Payload.ToObject<MessageCreateEvent>(_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<MessageUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<MessageUpdateEvent>(_dataSocketSerializer);
var msg = _messages[data.Id];
if (msg != null)
{
@@ -559,7 +564,7 @@ namespace Discord
break;
case "MESSAGE_DELETE":
{
var data = e.Payload.ToObject<MessageDeleteEvent>(_socketSerializer);
var data = e.Payload.ToObject<MessageDeleteEvent>(_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<MessageAckEvent>(_socketSerializer);
var data = e.Payload.ToObject<MessageAckEvent>(_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<PresenceUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<PresenceUpdateEvent>(_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<TypingStartEvent>(_socketSerializer);
var data = e.Payload.ToObject<TypingStartEvent>(_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<MemberVoiceStateUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<MemberVoiceStateUpdateEvent>(_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<UserUpdateEvent>(_socketSerializer);
var data = e.Payload.ToObject<UserUpdateEvent>(_dataSocketSerializer);
var user = _globalUsers[data.Id];
if (user != null)
{


+ 32
- 1
src/Discord.Net/DiscordWSClient.cs View File

@@ -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;

/// <summary> Initializes a new instance of the DiscordClient class. </summary>
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();


+ 19
- 9
src/Discord.Net/Helpers/AsyncCollection.cs View File

@@ -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<KeyValuePair<TKey, TValue>> 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();
}
}
}


+ 8
- 4
src/Discord.Net/Helpers/CachedObject.cs View File

@@ -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();
}
}

+ 2
- 2
src/Discord.Net/Helpers/Reference.cs View File

@@ -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()


+ 3
- 3
src/Discord.Net/Models/Channel.cs View File

@@ -124,12 +124,12 @@ namespace Discord
if (client.Config.MessageCacheLength > 0)
_messages = new ConcurrentDictionary<long, Message>();
}
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()
{


+ 1
- 1
src/Discord.Net/Models/GlobalUser.cs View File

@@ -44,7 +44,7 @@ namespace Discord
{
_users = new ConcurrentDictionary<long, User>();
}
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


+ 1
- 1
src/Discord.Net/Models/Invite.cs View File

@@ -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)


+ 16
- 14
src/Discord.Net/Models/Message.cs View File

@@ -15,24 +15,25 @@ namespace Discord
Queued,
Failed
}
internal class MessageImporterResolver : DefaultContractResolver

public sealed class Message : CachedObject<long>
{
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<long>
{
public sealed class Attachment : File
{
/// <summary> Unique identifier for this file. </summary>
@@ -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()
{


+ 10
- 0
src/Discord.Net/Models/Region.cs View File

@@ -0,0 +1,10 @@
namespace Discord
{
public sealed class Region
{
public string Hostname;
public int Port;
public string Id;
public string Name;
}
}

+ 2
- 2
src/Discord.Net/Models/Role.cs View File

@@ -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()
{


+ 2
- 1
src/Discord.Net/Models/Server.cs View File

@@ -103,9 +103,10 @@ namespace Discord
//Local Cache
_bans = new ConcurrentDictionary<long, bool>();
}
internal override void LoadReferences()
internal override bool LoadReferences()
{
_afkChannel.Load();
return true;
}
internal override void UnloadReferences()
{


+ 3
- 3
src/Discord.Net/Models/User.cs View File

@@ -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()
{


+ 1
- 1
src/Discord.Net/Net/Rest/SharpRestEngine.cs View File

@@ -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);


+ 3
- 3
src/Discord.Net/Net/WebSockets/DataWebSocket.cs View File

@@ -82,13 +82,13 @@ namespace Discord.Net.WebSockets
JToken token = msg.Payload as JToken;
if (msg.Type == "READY")
{
var payload = token.ToObject<ReadyEvent>();
var payload = token.ToObject<ReadyEvent>(_client.DataSocketSerializer);
_sessionId = payload.SessionId;
_heartbeatInterval = payload.HeartbeatInterval;
}
else if (msg.Type == "RESUMED")
{
var payload = token.ToObject<ResumedEvent>();
var payload = token.ToObject<ResumedEvent>(_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<RedirectEvent>();
var payload = (msg.Payload as JToken).ToObject<RedirectEvent>(_client.DataSocketSerializer);
if (payload.Url != null)
{
Host = payload.Url;


+ 3
- 3
src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs View File

@@ -443,7 +443,7 @@ namespace Discord.Net.WebSockets
{
if (_state != (int)WebSocketState.Connected)
{
var payload = (msg.Payload as JToken).ToObject<VoiceReadyEvent>();
var payload = (msg.Payload as JToken).ToObject<VoiceReadyEvent>(_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<JoinServerEvent>();
var payload = (msg.Payload as JToken).ToObject<JoinServerEvent>(_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<IsTalkingEvent>();
var payload = (msg.Payload as JToken).ToObject<IsTalkingEvent>(_client.VoiceSocketSerializer);
RaiseIsSpeaking(payload.UserId, payload.IsSpeaking);
}
break;


Loading…
Cancel
Save