Browse Source

Added Proxy support, split DiscordWebSocketClientConfig into DiscordAPIClientConfig

tags/docs-0.9
RogueException 9 years ago
parent
commit
98bad63957
10 changed files with 90 additions and 58 deletions
  1. +3
    -0
      src/Discord.Net.Net45/Discord.Net.csproj
  2. +5
    -2
      src/Discord.Net/DiscordAPIClient.cs
  3. +50
    -0
      src/Discord.Net/DiscordAPIClientConfig.cs
  4. +1
    -2
      src/Discord.Net/DiscordClient.cs
  5. +1
    -1
      src/Discord.Net/DiscordClientConfig.cs
  6. +3
    -29
      src/Discord.Net/DiscordWebSocketClientConfig.cs
  7. +7
    -5
      src/Discord.Net/Net/RestClient.SharpRest.cs
  8. +11
    -11
      src/Discord.Net/Net/RestClient.cs
  9. +8
    -7
      src/Discord.Net/Net/WebSocket.WebSocketSharp.cs
  10. +1
    -1
      src/Discord.Net/Net/WebSocket.cs

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

@@ -151,6 +151,9 @@
<Compile Include="..\Discord.Net\DiscordAPIClient.cs"> <Compile Include="..\Discord.Net\DiscordAPIClient.cs">
<Link>DiscordAPIClient.cs</Link> <Link>DiscordAPIClient.cs</Link>
</Compile> </Compile>
<Compile Include="..\Discord.Net\DiscordAPIClientConfig.cs">
<Link>DiscordAPIClientConfig.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordClient.API.cs"> <Compile Include="..\Discord.Net\DiscordClient.API.cs">
<Link>DiscordClient.API.cs</Link> <Link>DiscordClient.API.cs</Link>
</Compile> </Compile>


+ 5
- 2
src/Discord.Net/DiscordAPIClient.cs View File

@@ -11,12 +11,15 @@ namespace Discord
/// <summary> A lightweight wrapper around the Discord API. </summary> /// <summary> A lightweight wrapper around the Discord API. </summary>
public class DiscordAPIClient public class DiscordAPIClient
{ {
private readonly DiscordAPIClientConfig _config;

internal RestClient RestClient => _rest; internal RestClient RestClient => _rest;
private readonly RestClient _rest; private readonly RestClient _rest;


public DiscordAPIClient(LogMessageSeverity logLevel, string userAgent, int timeout)
public DiscordAPIClient(DiscordAPIClientConfig config = null)
{ {
_rest = new RestClient(logLevel, userAgent, timeout);
_config = config ?? new DiscordAPIClientConfig();
_rest = new RestClient(_config);
} }


private string _token; private string _token;


+ 50
- 0
src/Discord.Net/DiscordAPIClientConfig.cs View File

@@ -0,0 +1,50 @@
using System;
using System.Net;
using System.Reflection;

namespace Discord
{
public class DiscordAPIClientConfig
{
/// <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;
/// <summary> Max time (in milliseconds) to wait for an API request to complete. </summary>
public int APITimeout { get { return _apiTimeout; } set { SetValue(ref _apiTimeout, value); } }
private int _apiTimeout = 10000;

/// <summary> The proxy to user for API and WebSocket connections. </summary>
public string ProxyUrl { get { return _proxyUrl; } set { SetValue(ref _proxyUrl, value); } }
private string _proxyUrl = null;
/// <summary> The credentials to use for this proxy. </summary>
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; }
protected void SetValue<T>(ref T storage, T value)
{
if (_isLocked)
throw new InvalidOperationException("Unable to modify a discord client's configuration after it has been created.");
storage = value;
}

public DiscordAPIClientConfig Clone()
{
var config = MemberwiseClone() as DiscordAPIClientConfig;
config._isLocked = false;
return config;
}
}
}

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

@@ -55,7 +55,7 @@ namespace Discord
: base(config ?? new DiscordClientConfig()) : base(config ?? new DiscordClientConfig())
{ {
_rand = new Random(); _rand = new Random();
_api = new DiscordAPIClient(_config.LogLevel, _config.UserAgent, _config.APITimeout);
_api = new DiscordAPIClient(_config);
if (Config.UseMessageQueue) if (Config.UseMessageQueue)
_pendingMessages = new ConcurrentQueue<Message>(); _pendingMessages = new ConcurrentQueue<Message>();
if (Config.EnableVoiceMultiserver) if (Config.EnableVoiceMultiserver)
@@ -765,7 +765,6 @@ namespace Discord
{ {
var config = _config.Clone(); var config = _config.Clone();
config.LogLevel = _config.LogLevel;// (LogMessageSeverity)Math.Min((int)_config.LogLevel, (int)LogMessageSeverity.Warning); config.LogLevel = _config.LogLevel;// (LogMessageSeverity)Math.Min((int)_config.LogLevel, (int)LogMessageSeverity.Warning);
config.EnableVoiceMultiserver = false;
config.VoiceOnly = true; config.VoiceOnly = true;
config.VoiceClientId = unchecked(++_nextVoiceClientId); config.VoiceClientId = unchecked(++_nextVoiceClientId);
return new DiscordWebSocketClient(config, serverId); return new DiscordWebSocketClient(config, serverId);


+ 1
- 1
src/Discord.Net/DiscordClientConfig.cs View File

@@ -25,7 +25,7 @@


public new DiscordClientConfig Clone() public new DiscordClientConfig Clone()
{ {
var config = this.MemberwiseClone() as DiscordClientConfig;
var config = MemberwiseClone() as DiscordClientConfig;
config._isLocked = false; config._isLocked = false;
return config; return config;
} }


+ 3
- 29
src/Discord.Net/DiscordWebSocketClientConfig.cs View File

@@ -12,12 +12,8 @@ namespace Discord
Both = Outgoing | Incoming Both = Outgoing | Incoming
} }


public class DiscordWebSocketClientConfig
public class DiscordWebSocketClientConfig : DiscordAPIClientConfig
{ {
/// <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;

/// <summary> Max time in milliseconds to wait for DiscordClient to connect and initialize. </summary> /// <summary> Max time in milliseconds to wait for DiscordClient to connect and initialize. </summary>
public int ConnectionTimeout { get { return _connectionTimeout; } set { SetValue(ref _connectionTimeout, value); } } public int ConnectionTimeout { get { return _connectionTimeout; } set { SetValue(ref _connectionTimeout, value); } }
private int _connectionTimeout = 30000; private int _connectionTimeout = 30000;
@@ -27,9 +23,6 @@ namespace Discord
/// <summary> Gets or sets the time (in milliseconds) to wait after an reconnect fails before retrying. </summary> /// <summary> Gets or sets the time (in milliseconds) to wait after an reconnect fails before retrying. </summary>
public int FailedReconnectDelay { get { return _failedReconnectDelay; } set { SetValue(ref _failedReconnectDelay, value); } } public int FailedReconnectDelay { get { return _failedReconnectDelay; } set { SetValue(ref _failedReconnectDelay, value); } }
private int _failedReconnectDelay = 10000; private int _failedReconnectDelay = 10000;
/// <summary> Max time (in milliseconds) to wait for an API request to complete. </summary>
public int APITimeout { get { return _apiTimeout; } set { SetValue(ref _apiTimeout, value); } }
private int _apiTimeout = 10000;


/// <summary> Gets or sets the time (in milliseconds) to wait when the websocket's message queue is empty before checking again. </summary> /// <summary> Gets or sets the time (in milliseconds) to wait when the websocket's message queue is empty before checking again. </summary>
public int WebSocketInterval { get { return _webSocketInterval; } set { SetValue(ref _webSocketInterval, value); } } public int WebSocketInterval { get { return _webSocketInterval; } set { SetValue(ref _webSocketInterval, value); } }
@@ -54,28 +47,9 @@ namespace Discord


internal virtual bool EnableVoice => _voiceMode != DiscordVoiceMode.Disabled; internal virtual bool EnableVoice => _voiceMode != DiscordVoiceMode.Disabled;


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; }
protected void SetValue<T>(ref T storage, T value)
{
if (_isLocked)
throw new InvalidOperationException("Unable to modify a discord client's configuration after it has been created.");
storage = value;
}

public DiscordClientConfig Clone()
public new DiscordWebSocketClientConfig Clone()
{ {
var config = this.MemberwiseClone() as DiscordClientConfig;
var config = MemberwiseClone() as DiscordWebSocketClientConfig;
config._isLocked = false; config._isLocked = false;
return config; return config;
} }


+ 7
- 5
src/Discord.Net/Net/RestClient.SharpRest.cs View File

@@ -1,6 +1,7 @@
using Discord.API; using Discord.API;
using RestSharp; using RestSharp;
using System; using System;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -11,18 +12,19 @@ namespace Discord.Net
{ {
private RestSharp.RestClient _client; private RestSharp.RestClient _client;


partial void Initialize(string userAgent, int timeout)
partial void Initialize()
{ {
_client = new RestSharp.RestClient(Endpoints.BaseApi) _client = new RestSharp.RestClient(Endpoints.BaseApi)
{ {
PreAuthenticate = false
PreAuthenticate = false,
Proxy = new WebProxy(_config.ProxyUrl, true, new string[0], _config.ProxyCredentials),
ReadWriteTimeout = _config.APITimeout,
UserAgent = _config.UserAgent
}; };
_client.RemoveDefaultParameter("Accept"); _client.RemoveDefaultParameter("Accept");
_client.AddDefaultHeader("accept", "*/*"); _client.AddDefaultHeader("accept", "*/*");
_client.AddDefaultHeader("accept-encoding", "gzip,deflate"); _client.AddDefaultHeader("accept-encoding", "gzip,deflate");
_client.UserAgent = userAgent;
_client.ReadWriteTimeout = timeout;
}
}


internal void SetToken(string token) internal void SetToken(string token)
{ {


+ 11
- 11
src/Discord.Net/Net/RestClient.cs View File

@@ -10,15 +10,15 @@ namespace Discord.Net
{ {
internal partial class RestClient internal partial class RestClient
{ {
private readonly LogMessageSeverity _logLevel;
private readonly DiscordAPIClientConfig _config;
private CancellationToken _cancelToken; private CancellationToken _cancelToken;


public RestClient(LogMessageSeverity logLevel, string userAgent, int timeout)
public RestClient(DiscordAPIClientConfig config)
{ {
_logLevel = logLevel;
Initialize(userAgent, timeout);
_config = config;
Initialize();
} }
partial void Initialize(string userAgent, int timeout);
partial void Initialize();


//DELETE //DELETE
private static readonly HttpMethod _delete = HttpMethod.Delete; private static readonly HttpMethod _delete = HttpMethod.Delete;
@@ -90,7 +90,7 @@ namespace Discord.Net
if (content != null) if (content != null)
requestJson = JsonConvert.SerializeObject(content); requestJson = JsonConvert.SerializeObject(content);


if (_logLevel >= LogMessageSeverity.Verbose)
if (_config.LogLevel >= LogMessageSeverity.Verbose)
stopwatch = Stopwatch.StartNew(); stopwatch = Stopwatch.StartNew();
string responseJson = await SendInternal(method, path, requestJson, _cancelToken).ConfigureAwait(false); string responseJson = await SendInternal(method, path, requestJson, _cancelToken).ConfigureAwait(false);
@@ -100,10 +100,10 @@ namespace Discord.Net
throw new Exception("API check failed: Response is not empty."); throw new Exception("API check failed: Response is not empty.");
#endif #endif


if (_logLevel >= LogMessageSeverity.Verbose)
if (_config.LogLevel >= LogMessageSeverity.Verbose)
{ {
stopwatch.Stop(); stopwatch.Stop();
if (content != null && _logLevel >= LogMessageSeverity.Debug)
if (content != null && _config.LogLevel >= LogMessageSeverity.Debug)
{ {
if (path.StartsWith(Endpoints.Auth)) if (path.StartsWith(Endpoints.Auth))
RaiseOnRequest(method, path, "[Hidden]", stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); RaiseOnRequest(method, path, "[Hidden]", stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond);
@@ -129,7 +129,7 @@ namespace Discord.Net
{ {
Stopwatch stopwatch = null; Stopwatch stopwatch = null;


if (_logLevel >= LogMessageSeverity.Verbose)
if (_config.LogLevel >= LogMessageSeverity.Verbose)
stopwatch = Stopwatch.StartNew(); stopwatch = Stopwatch.StartNew();
string responseJson = await SendFileInternal(method, path, filePath, _cancelToken).ConfigureAwait(false); string responseJson = await SendFileInternal(method, path, filePath, _cancelToken).ConfigureAwait(false);
@@ -139,10 +139,10 @@ namespace Discord.Net
throw new Exception("API check failed: Response is not empty."); throw new Exception("API check failed: Response is not empty.");
#endif #endif


if (_logLevel >= LogMessageSeverity.Verbose)
if (_config.LogLevel >= LogMessageSeverity.Verbose)
{ {
stopwatch.Stop(); stopwatch.Stop();
if (_logLevel >= LogMessageSeverity.Debug)
if (_config.LogLevel >= LogMessageSeverity.Debug)
RaiseOnRequest(method, path, filePath, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); RaiseOnRequest(method, path, filePath, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond);
else else
RaiseOnRequest(method, path, null, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); RaiseOnRequest(method, path, null, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond);


+ 8
- 7
src/Discord.Net/Net/WebSocket.WebSocketSharp.cs View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using WSSharpNWebSocket = WebSocketSharp.WebSocket; using WSSharpNWebSocket = WebSocketSharp.WebSocket;
@@ -9,9 +10,8 @@ namespace Discord.Net
{ {
internal class WSSharpWebSocketEngine : IWebSocketEngine internal class WSSharpWebSocketEngine : IWebSocketEngine
{ {
private readonly DiscordWebSocketClientConfig _config;
private readonly ConcurrentQueue<string> _sendQueue; private readonly ConcurrentQueue<string> _sendQueue;
private readonly int _sendInterval;
private readonly string _userAgent;
private readonly WebSocket _parent; private readonly WebSocket _parent;
private WSSharpNWebSocket _webSocket; private WSSharpNWebSocket _webSocket;


@@ -22,11 +22,10 @@ namespace Discord.Net
ProcessMessage(this, new WebSocketMessageEventArgs(msg)); ProcessMessage(this, new WebSocketMessageEventArgs(msg));
} }


internal WSSharpWebSocketEngine(WebSocket parent, string userAgent, int sendInterval)
internal WSSharpWebSocketEngine(WebSocket parent, DiscordWebSocketClientConfig config)
{ {
_parent = parent; _parent = parent;
_userAgent = userAgent;
_sendInterval = sendInterval;
_config = config;
_sendQueue = new ConcurrentQueue<string>(); _sendQueue = new ConcurrentQueue<string>();
} }


@@ -35,7 +34,8 @@ namespace Discord.Net
_webSocket = new WSSharpNWebSocket(host); _webSocket = new WSSharpNWebSocket(host);
_webSocket.EmitOnPing = false; _webSocket.EmitOnPing = false;
_webSocket.EnableRedirection = true; _webSocket.EnableRedirection = true;
_webSocket.Compression = WebSocketSharp.CompressionMethod.None;
_webSocket.Compression = WebSocketSharp.CompressionMethod.None;
_webSocket.SetProxy(_config.ProxyUrl, _config.ProxyCredentials.UserName, _config.ProxyCredentials.Password);
_webSocket.OnMessage += (s, e) => RaiseProcessMessage(e.Data); _webSocket.OnMessage += (s, e) => RaiseProcessMessage(e.Data);
_webSocket.OnError += async (s, e) => _webSocket.OnError += async (s, e) =>
{ {
@@ -77,6 +77,7 @@ namespace Discord.Net


private Task SendAsync(CancellationToken cancelToken) private Task SendAsync(CancellationToken cancelToken)
{ {
var sendInterval = _config.WebSocketInterval;
return Task.Run(async () => return Task.Run(async () =>
{ {
try try
@@ -86,7 +87,7 @@ namespace Discord.Net
string json; string json;
while (_sendQueue.TryDequeue(out json)) while (_sendQueue.TryDequeue(out json))
_webSocket.Send(json); _webSocket.Send(json);
await Task.Delay(_sendInterval, cancelToken).ConfigureAwait(false);
await Task.Delay(sendInterval, cancelToken).ConfigureAwait(false);
} }
} }
catch (OperationCanceledException) { } catch (OperationCanceledException) { }


+ 1
- 1
src/Discord.Net/Net/WebSocket.cs View File

@@ -65,7 +65,7 @@ namespace Discord.Net
_cancelToken = new CancellationToken(true); _cancelToken = new CancellationToken(true);
_connectedEvent = new ManualResetEventSlim(false); _connectedEvent = new ManualResetEventSlim(false);
_engine = new WSSharpWebSocketEngine(this, client.Config.UserAgent, client.Config.WebSocketInterval);
_engine = new WSSharpWebSocketEngine(this, client.Config);
_engine.ProcessMessage += async (s, e) => _engine.ProcessMessage += async (s, e) =>
{ {
if (_logLevel >= LogMessageSeverity.Debug) if (_logLevel >= LogMessageSeverity.Debug)


Loading…
Cancel
Save