Cleaned up clients and configs. Renamed DiscordClient -> DiscordRestClient.

This commit is contained in:
RogueException
2016-07-26 17:38:23 -03:00
parent dc06a17cd3
commit e8b95519da
15 changed files with 63 additions and 73 deletions

View File

@@ -3,14 +3,14 @@
internal static class CDN internal static class CDN
{ {
public static string GetApplicationIconUrl(ulong appId, string iconId) public static string GetApplicationIconUrl(ulong appId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null; => iconId != null ? $"{DiscordRestConfig.CDNUrl}app-icons/{appId}/{iconId}.jpg" : null;
public static string GetUserAvatarUrl(ulong userId, string avatarId) public static string GetUserAvatarUrl(ulong userId, string avatarId)
=> avatarId != null ? $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.jpg" : null; => avatarId != null ? $"{DiscordRestConfig.CDNUrl}avatars/{userId}/{avatarId}.jpg" : null;
public static string GetGuildIconUrl(ulong guildId, string iconId) public static string GetGuildIconUrl(ulong guildId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}icons/{guildId}/{iconId}.jpg" : null; => iconId != null ? $"{DiscordRestConfig.CDNUrl}icons/{guildId}/{iconId}.jpg" : null;
public static string GetGuildSplashUrl(ulong guildId, string splashId) public static string GetGuildSplashUrl(ulong guildId, string splashId)
=> splashId != null ? $"{DiscordConfig.CDNUrl}splashes/{guildId}/{splashId}.jpg" : null; => splashId != null ? $"{DiscordRestConfig.CDNUrl}splashes/{guildId}/{splashId}.jpg" : null;
public static string GetChannelIconUrl(ulong channelId, string iconId) public static string GetChannelIconUrl(ulong channelId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null; => iconId != null ? $"{DiscordRestConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null;
} }
} }

View File

@@ -55,9 +55,9 @@ namespace Discord.API
_requestQueue = requestQueue ?? new RequestQueue(); _requestQueue = requestQueue ?? new RequestQueue();
_restClient = restClientProvider(DiscordConfig.ClientAPIUrl); _restClient = restClientProvider(DiscordRestConfig.ClientAPIUrl);
_restClient.SetHeader("accept", "*/*"); _restClient.SetHeader("accept", "*/*");
_restClient.SetHeader("user-agent", DiscordConfig.UserAgent); _restClient.SetHeader("user-agent", DiscordRestConfig.UserAgent);
if (webSocketProvider != null) if (webSocketProvider != null)
{ {
_gatewayClient = webSocketProvider(); _gatewayClient = webSocketProvider();
@@ -211,7 +211,7 @@ namespace Discord.API
if (_gatewayUrl == null) if (_gatewayUrl == null)
{ {
var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false); var gatewayResponse = await GetGatewayAsync().ConfigureAwait(false);
_gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordConfig.GatewayEncoding}"; _gatewayUrl = $"{gatewayResponse.Url}?v={DiscordConfig.APIVersion}&encoding={DiscordSocketConfig.GatewayEncoding}";
} }
await _gatewayClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false); await _gatewayClient.ConnectAsync(_gatewayUrl).ConfigureAwait(false);
@@ -791,13 +791,13 @@ namespace Discord.API
List<GuildMember[]> result; List<GuildMember[]> result;
if (args.Limit.IsSpecified) if (args.Limit.IsSpecified)
result = new List<GuildMember[]>((limit + DiscordConfig.MaxUsersPerBatch - 1) / DiscordConfig.MaxUsersPerBatch); result = new List<GuildMember[]>((limit + DiscordRestConfig.MaxUsersPerBatch - 1) / DiscordRestConfig.MaxUsersPerBatch);
else else
result = new List<GuildMember[]>(); result = new List<GuildMember[]>();
while (true) while (true)
{ {
int runLimit = (limit >= DiscordConfig.MaxUsersPerBatch) ? DiscordConfig.MaxUsersPerBatch : limit; int runLimit = (limit >= DiscordRestConfig.MaxUsersPerBatch) ? DiscordRestConfig.MaxUsersPerBatch : limit;
string endpoint = $"guilds/{guildId}/members?limit={runLimit}&after={afterUserId}"; string endpoint = $"guilds/{guildId}/members?limit={runLimit}&after={afterUserId}";
var models = await SendAsync<GuildMember[]>("GET", endpoint, options: options).ConfigureAwait(false); var models = await SendAsync<GuildMember[]>("GET", endpoint, options: options).ConfigureAwait(false);
@@ -806,11 +806,11 @@ namespace Discord.API
result.Add(models); result.Add(models);
limit -= DiscordConfig.MaxUsersPerBatch; limit -= DiscordRestConfig.MaxUsersPerBatch;
afterUserId = models[models.Length - 1].User.Id; afterUserId = models[models.Length - 1].User.Id;
//Was this an incomplete (the last) batch? //Was this an incomplete (the last) batch?
if (models.Length != DiscordConfig.MaxUsersPerBatch) break; if (models.Length != DiscordRestConfig.MaxUsersPerBatch) break;
} }
if (result.Count > 1) if (result.Count > 1)
@@ -920,14 +920,14 @@ namespace Discord.API
break; break;
} }
int runs = (limit + DiscordConfig.MaxMessagesPerBatch - 1) / DiscordConfig.MaxMessagesPerBatch; int runs = (limit + DiscordRestConfig.MaxMessagesPerBatch - 1) / DiscordRestConfig.MaxMessagesPerBatch;
int lastRunCount = limit - (runs - 1) * DiscordConfig.MaxMessagesPerBatch; int lastRunCount = limit - (runs - 1) * DiscordRestConfig.MaxMessagesPerBatch;
var result = new API.Message[runs][]; var result = new API.Message[runs][];
int i = 0; int i = 0;
for (; i < runs; i++) for (; i < runs; i++)
{ {
int runCount = i == (runs - 1) ? lastRunCount : DiscordConfig.MaxMessagesPerBatch; int runCount = i == (runs - 1) ? lastRunCount : DiscordRestConfig.MaxMessagesPerBatch;
string endpoint; string endpoint;
if (relativeId != null) if (relativeId != null)
endpoint = $"channels/{channelId}/messages?limit={runCount}&{relativeDir}={relativeId}"; endpoint = $"channels/{channelId}/messages?limit={runCount}&{relativeDir}={relativeId}";
@@ -966,7 +966,7 @@ namespace Discord.API
} }
//Was this an incomplete (the last) batch? //Was this an incomplete (the last) batch?
if (models.Length != DiscordConfig.MaxMessagesPerBatch) { i++; break; } if (models.Length != DiscordRestConfig.MaxMessagesPerBatch) { i++; break; }
} }
if (i > 1) if (i > 1)
@@ -1011,8 +1011,8 @@ namespace Discord.API
Preconditions.NotEqual(channelId, 0, nameof(channelId)); Preconditions.NotEqual(channelId, 0, nameof(channelId));
Preconditions.NotNull(args, nameof(args)); Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
if (args.Content.Length > DiscordConfig.MaxMessageSize) if (args.Content.Length > DiscordRestConfig.MaxMessageSize)
throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordRestConfig.MaxMessageSize}.", nameof(args.Content));
if (guildId != 0) if (guildId != 0)
return await SendAsync<Message>("POST", $"channels/{channelId}/messages", args, GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false); return await SendAsync<Message>("POST", $"channels/{channelId}/messages", args, GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false);
@@ -1040,8 +1040,8 @@ namespace Discord.API
{ {
if (args.Content.Value == null) if (args.Content.Value == null)
args.Content = ""; args.Content = "";
if (args.Content.Value?.Length > DiscordConfig.MaxMessageSize) if (args.Content.Value?.Length > DiscordRestConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordRestConfig.MaxMessageSize}.", nameof(args.Content));
} }
if (guildId != 0) if (guildId != 0)
@@ -1121,8 +1121,8 @@ namespace Discord.API
if (args.Content.IsSpecified) if (args.Content.IsSpecified)
{ {
Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content));
if (args.Content.Value.Length > DiscordConfig.MaxMessageSize) if (args.Content.Value.Length > DiscordRestConfig.MaxMessageSize)
throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordRestConfig.MaxMessageSize}.", nameof(args.Content));
} }
if (guildId != 0) if (guildId != 0)

View File

@@ -2,7 +2,7 @@
{ {
public class GetChannelMessagesParams public class GetChannelMessagesParams
{ {
public int Limit { get; set; } = DiscordConfig.MaxMessagesPerBatch; public int Limit { get; set; } = DiscordRestConfig.MaxMessagesPerBatch;
public Direction RelativeDirection { get; set; } = Direction.Before; public Direction RelativeDirection { get; set; } = Direction.Before;
public Optional<ulong> RelativeMessageId { get; set; } public Optional<ulong> RelativeMessageId { get; set; }

View File

@@ -1,33 +1,17 @@
using Discord.Net.Rest; using System.Reflection;
using System.Reflection;
namespace Discord namespace Discord
{ {
public class DiscordConfig public class DiscordConfig
{ {
public static string Version { get; } = typeof(DiscordConfig).GetTypeInfo().Assembly?.GetName().Version.ToString(3) ?? "Unknown"; public const int APIVersion = 6;
public static string FullVersion { get; } = typeof(DiscordConfig).GetTypeInfo().Assembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion ?? "Unknown"; public static string Version { get; } = typeof(DiscordRestConfig).GetTypeInfo().Assembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion ?? "Unknown";
public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})";
public const int APIVersion = 6;
public const string GatewayEncoding = "json";
public static readonly string ClientAPIUrl = $"https://discordapp.com/api/v{APIVersion}/"; public static readonly string ClientAPIUrl = $"https://discordapp.com/api/v{APIVersion}/";
public const string CDNUrl = "https://cdn.discordapp.com/"; public const string CDNUrl = "https://cdn.discordapp.com/";
public const string InviteUrl = "https://discord.gg/"; public const string InviteUrl = "https://discord.gg/";
public const int MaxMessageSize = 2000;
public const int MaxMessagesPerBatch = 100;
public const int MaxUsersPerBatch = 1000;
internal const int RestTimeout = 10000;
internal const int MessageQueueInterval = 100;
internal const int WebSocketQueueInterval = 100;
/// <summary> Gets or sets the minimum log level severity that will be sent to the LogMessage event. </summary> /// <summary> Gets or sets the minimum log level severity that will be sent to the LogMessage event. </summary>
public LogSeverity LogLevel { get; set; } = LogSeverity.Info; public LogSeverity LogLevel { get; set; } = LogSeverity.Info;
/// <summary> Gets or sets the provider used to generate new REST connections. </summary>
public RestClientProvider RestClientProvider { get; set; } = url => new DefaultRestClient(url);
} }
} }

View File

@@ -37,9 +37,9 @@ namespace Discord
public LoginState LoginState { get; private set; } public LoginState LoginState { get; private set; }
/// <summary> Creates a new REST-only discord client. </summary> /// <summary> Creates a new REST-only discord client. </summary>
public DiscordRestClient() : this(new DiscordConfig()) { } public DiscordRestClient() : this(new DiscordRestConfig()) { }
/// <summary> Creates a new REST-only discord client. </summary> /// <summary> Creates a new REST-only discord client. </summary>
public DiscordRestClient(DiscordConfig config) public DiscordRestClient(DiscordRestConfig config)
{ {
LogManager = new LogManager(config.LogLevel); LogManager = new LogManager(config.LogLevel);
LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false); LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
@@ -304,9 +304,10 @@ namespace Discord
private async Task WriteInitialLog() private async Task WriteInitialLog()
{ {
if (this is DiscordSocketClient) if (this is DiscordSocketClient)
await _clientLogger.InfoAsync($"DiscordSocketClient v{DiscordConfig.FullVersion} (API v{DiscordConfig.APIVersion}, {DiscordConfig.GatewayEncoding})").ConfigureAwait(false); await _clientLogger.InfoAsync($"DiscordSocketClient v{DiscordConfig.Version} (API v{DiscordConfig.APIVersion}, {DiscordSocketConfig.GatewayEncoding})").ConfigureAwait(false);
else else
await _clientLogger.InfoAsync($"DiscordClient v{DiscordConfig.FullVersion} (API v{DiscordConfig.APIVersion})").ConfigureAwait(false); await _clientLogger.InfoAsync($"DiscordRestClient v{DiscordConfig.Version} (API v{DiscordConfig.APIVersion})").ConfigureAwait(false);
await _clientLogger.VerboseAsync($"Runtime: {RuntimeInformation.FrameworkDescription.Trim()} ({ToArchString(RuntimeInformation.ProcessArchitecture)})").ConfigureAwait(false); await _clientLogger.VerboseAsync($"Runtime: {RuntimeInformation.FrameworkDescription.Trim()} ({ToArchString(RuntimeInformation.ProcessArchitecture)})").ConfigureAwait(false);
await _clientLogger.VerboseAsync($"OS: {RuntimeInformation.OSDescription.Trim()} ({ToArchString(RuntimeInformation.OSArchitecture)})").ConfigureAwait(false); await _clientLogger.VerboseAsync($"OS: {RuntimeInformation.OSDescription.Trim()} ({ToArchString(RuntimeInformation.OSArchitecture)})").ConfigureAwait(false);
await _clientLogger.VerboseAsync($"Processors: {Environment.ProcessorCount}").ConfigureAwait(false); await _clientLogger.VerboseAsync($"Processors: {Environment.ProcessorCount}").ConfigureAwait(false);

View File

@@ -0,0 +1,20 @@
using Discord.Net.Rest;
namespace Discord
{
public class DiscordRestConfig : DiscordConfig
{
public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})";
public const int MaxMessageSize = 2000;
public const int MaxMessagesPerBatch = 100;
public const int MaxUsersPerBatch = 1000;
internal const int RestTimeout = 10000;
internal const int MessageQueueInterval = 100;
internal const int WebSocketQueueInterval = 100;
/// <summary> Gets or sets the provider used to generate new REST connections. </summary>
public RestClientProvider RestClientProvider { get; set; } = url => new DefaultRestClient(url);
}
}

View File

@@ -46,9 +46,6 @@ namespace Discord
//From DiscordSocketConfig //From DiscordSocketConfig
internal int TotalShards { get; private set; } internal int TotalShards { get; private set; }
internal int ConnectionTimeout { get; private set; }
internal int ReconnectDelay { get; private set; }
internal int FailedReconnectDelay { get; private set; }
internal int MessageCacheSize { get; private set; } internal int MessageCacheSize { get; private set; }
internal int LargeThreshold { get; private set; } internal int LargeThreshold { get; private set; }
internal AudioMode AudioMode { get; private set; } internal AudioMode AudioMode { get; private set; }
@@ -67,9 +64,6 @@ namespace Discord
{ {
ShardId = config.ShardId; ShardId = config.ShardId;
TotalShards = config.TotalShards; TotalShards = config.TotalShards;
ConnectionTimeout = config.ConnectionTimeout;
ReconnectDelay = config.ReconnectDelay;
FailedReconnectDelay = config.FailedReconnectDelay;
MessageCacheSize = config.MessageCacheSize; MessageCacheSize = config.MessageCacheSize;
LargeThreshold = config.LargeThreshold; LargeThreshold = config.LargeThreshold;
AudioMode = config.AudioMode; AudioMode = config.AudioMode;

View File

@@ -3,20 +3,15 @@ using Discord.Net.WebSockets;
namespace Discord namespace Discord
{ {
public class DiscordSocketConfig : DiscordConfig public class DiscordSocketConfig : DiscordRestConfig
{ {
public const string GatewayEncoding = "json";
/// <summary> Gets or sets the id for this shard. Must be less than TotalShards. </summary> /// <summary> Gets or sets the id for this shard. Must be less than TotalShards. </summary>
public int ShardId { get; set; } = 0; public int ShardId { get; set; } = 0;
/// <summary> Gets or sets the total number of shards for this application. </summary> /// <summary> Gets or sets the total number of shards for this application. </summary>
public int TotalShards { get; set; } = 1; public int TotalShards { get; set; } = 1;
/// <summary> Gets or sets the time (in milliseconds) to wait for the websocket to connect and initialize. </summary>
public int ConnectionTimeout { get; set; } = 30000;
/// <summary> Gets or sets the time (in milliseconds) to wait after an unexpected disconnect before reconnecting. </summary>
public int ReconnectDelay { get; set; } = 1000;
/// <summary> Gets or sets the time (in milliseconds) to wait after an reconnect fails before retrying. </summary>
public int FailedReconnectDelay { get; set; } = 15000;
/// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary> /// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary>
public int MessageCacheSize { get; set; } = 0; public int MessageCacheSize { get; set; } = 0;
/*/// <summary> /*/// <summary>

View File

@@ -20,9 +20,9 @@ namespace Discord
/// <summary> Gets the message from this channel's cache with the given id, or null if not found. </summary> /// <summary> Gets the message from this channel's cache with the given id, or null if not found. </summary>
IMessage GetCachedMessage(ulong id); IMessage GetCachedMessage(ulong id);
/// <summary> Gets the last N messages from this message channel. </summary> /// <summary> Gets the last N messages from this message channel. </summary>
Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch); Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordRestConfig.MaxMessagesPerBatch);
/// <summary> Gets a collection of messages in this channel. </summary> /// <summary> Gets a collection of messages in this channel. </summary>
Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch); Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordRestConfig.MaxMessagesPerBatch);
/// <summary> Bulk deletes multiple messages. </summary> /// <summary> Bulk deletes multiple messages. </summary>
Task DeleteMessagesAsync(IEnumerable<IMessage> messages); Task DeleteMessagesAsync(IEnumerable<IMessage> messages);

View File

@@ -16,8 +16,8 @@ namespace Discord
public override DiscordRestClient Discord { get; } public override DiscordRestClient Discord { get; }
public string Code => Id; public string Code => Id;
public string Url => $"{DiscordConfig.InviteUrl}/{XkcdCode ?? Code}"; public string Url => $"{DiscordRestConfig.InviteUrl}/{XkcdCode ?? Code}";
public string XkcdUrl => XkcdCode != null ? $"{DiscordConfig.InviteUrl}/{XkcdCode}" : null; public string XkcdUrl => XkcdCode != null ? $"{DiscordRestConfig.InviteUrl}/{XkcdCode}" : null;
public Invite(DiscordRestClient discord, Model model) public Invite(DiscordRestClient discord, Model model)
: base(model.Code) : base(model.Code)

View File

@@ -24,7 +24,7 @@ namespace Discord
public virtual UserStatus Status => UserStatus.Unknown; public virtual UserStatus Status => UserStatus.Unknown;
public virtual Game Game => null; public virtual Game Game => null;
public DiscordClient Discord => Channel.Discord; public DiscordRestClient Discord => Channel.Discord;
public GroupUser(GroupChannel channel, User user) public GroupUser(GroupChannel channel, User user)
{ {

View File

@@ -51,7 +51,7 @@ namespace Discord
return result; return result;
return null; return null;
} }
public override IImmutableList<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) public override IImmutableList<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordRestConfig.MaxMessagesPerBatch)
{ {
if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit)); if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit));
if (limit == 0) return ImmutableArray<SocketMessage>.Empty; if (limit == 0) return ImmutableArray<SocketMessage>.Empty;

View File

@@ -25,7 +25,7 @@ namespace Discord
public virtual SocketMessage Remove(ulong id) => null; public virtual SocketMessage Remove(ulong id) => null;
public virtual SocketMessage Get(ulong id) => null; public virtual SocketMessage Get(ulong id) => null;
public virtual IImmutableList<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) public virtual IImmutableList<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordRestConfig.MaxMessagesPerBatch)
=> ImmutableArray.Create<SocketMessage>(); => ImmutableArray.Create<SocketMessage>();
public virtual async Task<SocketMessage> DownloadAsync(ulong id) public virtual async Task<SocketMessage> DownloadAsync(ulong id)

View File

@@ -48,11 +48,11 @@ namespace Discord
{ {
return await _messages.DownloadAsync(id).ConfigureAwait(false); return await _messages.DownloadAsync(id).ConfigureAwait(false);
} }
public override async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch) public override async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordRestConfig.MaxMessagesPerBatch)
{ {
return await _messages.DownloadAsync(null, Direction.Before, limit).ConfigureAwait(false); return await _messages.DownloadAsync(null, Direction.Before, limit).ConfigureAwait(false);
} }
public override async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) public override async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordRestConfig.MaxMessagesPerBatch)
{ {
return await _messages.DownloadAsync(fromMessageId, dir, limit).ConfigureAwait(false); return await _messages.DownloadAsync(fromMessageId, dir, limit).ConfigureAwait(false);
} }

View File

@@ -11,14 +11,10 @@ namespace Discord
//TODO: Docstrings should explain when REST requests are sent and how many //TODO: Docstrings should explain when REST requests are sent and how many
public interface IDiscordClient : IDisposable public interface IDiscordClient : IDisposable
{ {
LoginState LoginState { get; }
ConnectionState ConnectionState { get; } ConnectionState ConnectionState { get; }
DiscordApiClient ApiClient { get; } DiscordApiClient ApiClient { get; }
ILogManager LogManager { get; } ILogManager LogManager { get; }
Task LoginAsync(TokenType tokenType, string token, bool validateToken = true);
Task LogoutAsync();
Task ConnectAsync(); Task ConnectAsync();
Task DisconnectAsync(); Task DisconnectAsync();