Started converting websocket and rpc classes

This commit is contained in:
RogueException
2016-09-28 04:12:17 -03:00
parent 0c4641ac68
commit dd86f03306
107 changed files with 1836 additions and 1882 deletions

View File

@@ -0,0 +1,6 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Discord.Net.Rpc")]
[assembly: InternalsVisibleTo("Discord.Net.WebSocket")]
[assembly: InternalsVisibleTo("Discord.Net.Commands")]
[assembly: InternalsVisibleTo("Discord.Net.Test")]

View File

@@ -0,0 +1,118 @@
using Discord.API.Rest;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Discord.Rest
{
internal static class ClientHelper
{
//Applications
public static async Task<RestApplication> GetApplicationInfoAsync(DiscordClient client)
{
var model = await client.ApiClient.GetMyApplicationAsync().ConfigureAwait(false);
return RestApplication.Create(client, model);
}
public static async Task<RestChannel> GetChannelAsync(DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetChannelAsync(id).ConfigureAwait(false);
if (model != null)
return RestChannel.Create(client, model);
return null;
}
public static async Task<IReadOnlyCollection<IPrivateChannel>> GetPrivateChannelsAsync(DiscordClient client)
{
var models = await client.ApiClient.GetMyPrivateChannelsAsync().ConfigureAwait(false);
return models.Select(x => RestDMChannel.Create(client, x)).ToImmutableArray();
}
public static async Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync(DiscordClient client)
{
var models = await client.ApiClient.GetMyConnectionsAsync().ConfigureAwait(false);
return models.Select(x => RestConnection.Create(x)).ToImmutableArray();
}
public static async Task<RestInvite> GetInviteAsync(DiscordClient client,
string inviteId)
{
var model = await client.ApiClient.GetInviteAsync(inviteId).ConfigureAwait(false);
if (model != null)
return RestInvite.Create(client, model);
return null;
}
public static async Task<RestGuild> GetGuildAsync(DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetGuildAsync(id).ConfigureAwait(false);
if (model != null)
return RestGuild.Create(client, model);
return null;
}
public static async Task<RestGuildEmbed?> GetGuildEmbedAsync(DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetGuildEmbedAsync(id).ConfigureAwait(false);
if (model != null)
return RestGuildEmbed.Create(model);
return null;
}
public static async Task<IReadOnlyCollection<RestUserGuild>> GetGuildSummariesAsync(DiscordClient client)
{
var models = await client.ApiClient.GetMyGuildsAsync().ConfigureAwait(false);
return models.Select(x => RestUserGuild.Create(client, x)).ToImmutableArray();
}
public static async Task<IReadOnlyCollection<RestGuild>> GetGuildsAsync(DiscordClient client)
{
var summaryModels = await client.ApiClient.GetMyGuildsAsync().ConfigureAwait(false);
var guilds = ImmutableArray.CreateBuilder<RestGuild>(summaryModels.Count);
foreach (var summaryModel in summaryModels)
{
var guildModel = await client.ApiClient.GetGuildAsync(summaryModel.Id).ConfigureAwait(false);
if (guildModel != null)
guilds.Add(RestGuild.Create(client, guildModel));
}
return guilds.ToImmutable();
}
public static async Task<RestGuild> CreateGuildAsync(DiscordClient client,
string name, IVoiceRegion region, Stream jpegIcon = null)
{
var args = new CreateGuildParams(name, region.Id);
var model = await client.ApiClient.CreateGuildAsync(args).ConfigureAwait(false);
return RestGuild.Create(client, model);
}
public static async Task<RestUser> GetUserAsync(DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetUserAsync(id).ConfigureAwait(false);
if (model != null)
return RestUser.Create(client, model);
return null;
}
public static async Task<RestUser> GetUserAsync(DiscordClient client,
string username, string discriminator)
{
var model = await client.ApiClient.GetUserAsync(username, discriminator).ConfigureAwait(false);
if (model != null)
return RestUser.Create(client, model);
return null;
}
public static async Task<IReadOnlyCollection<RestVoiceRegion>> GetVoiceRegionsAsync(DiscordClient client)
{
var models = await client.ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(client, x)).ToImmutableArray();
}
public static async Task<RestVoiceRegion> GetVoiceRegionAsync(DiscordClient client,
string id)
{
var models = await client.ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(client, x)).Where(x => x.Id == id).FirstOrDefault();
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Discord.Logging;
using System.Collections.Immutable;
namespace Discord.Rest
{
public abstract class DiscordClient : IDiscordClient
{
public event Func<LogMessage, Task> Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
private readonly AsyncEvent<Func<LogMessage, Task>> _logEvent = new AsyncEvent<Func<LogMessage, Task>>();
public event Func<Task> LoggedIn { add { _loggedInEvent.Add(value); } remove { _loggedInEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _loggedInEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> LoggedOut { add { _loggedOutEvent.Add(value); } remove { _loggedOutEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _loggedOutEvent = new AsyncEvent<Func<Task>>();
internal readonly Logger _restLogger, _queueLogger;
internal readonly SemaphoreSlim _connectionLock;
private bool _isFirstLogin;
private bool _isDisposed;
public API.DiscordRestApiClient ApiClient { get; }
internal LogManager LogManager { get; }
public LoginState LoginState { get; private set; }
public ISelfUser CurrentUser { get; protected set; }
/// <summary> Creates a new REST-only discord client. </summary>
internal DiscordClient(DiscordRestConfig config, API.DiscordRestApiClient client)
{
ApiClient = client;
LogManager = new LogManager(config.LogLevel);
LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
_connectionLock = new SemaphoreSlim(1, 1);
_restLogger = LogManager.CreateLogger("Rest");
_queueLogger = LogManager.CreateLogger("Queue");
_isFirstLogin = true;
ApiClient.RequestQueue.RateLimitTriggered += async (id, bucket, millis) =>
{
await _queueLogger.WarningAsync($"Rate limit triggered (id = \"{id ?? "null"}\")").ConfigureAwait(false);
if (bucket == null && id != null)
await _queueLogger.WarningAsync($"Unknown rate limit bucket \"{id ?? "null"}\"").ConfigureAwait(false);
};
ApiClient.SentRequest += async (method, endpoint, millis) => await _restLogger.VerboseAsync($"{method} {endpoint}: {millis} ms").ConfigureAwait(false);
}
/// <inheritdoc />
public async Task LoginAsync(TokenType tokenType, string token, bool validateToken = true)
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LoginInternalAsync(tokenType, token).ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
}
private async Task LoginInternalAsync(TokenType tokenType, string token)
{
if (_isFirstLogin)
{
_isFirstLogin = false;
await LogManager.WriteInitialLog().ConfigureAwait(false);
}
if (LoginState != LoginState.LoggedOut)
await LogoutInternalAsync().ConfigureAwait(false);
LoginState = LoginState.LoggingIn;
try
{
await OnLoginAsync(tokenType, token).ConfigureAwait(false);
LoginState = LoginState.LoggedIn;
}
catch (Exception)
{
await LogoutInternalAsync().ConfigureAwait(false);
throw;
}
await _loggedInEvent.InvokeAsync().ConfigureAwait(false);
}
protected virtual Task OnLoginAsync(TokenType tokenType, string token) { return Task.CompletedTask; }
/// <inheritdoc />
public async Task LogoutAsync()
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LogoutInternalAsync().ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
}
private async Task LogoutInternalAsync()
{
if (LoginState == LoginState.LoggedOut) return;
LoginState = LoginState.LoggingOut;
await ApiClient.LogoutAsync().ConfigureAwait(false);
await OnLogoutAsync().ConfigureAwait(false);
CurrentUser = null;
LoginState = LoginState.LoggedOut;
await _loggedOutEvent.InvokeAsync().ConfigureAwait(false);
}
protected virtual Task OnLogoutAsync() { return Task.CompletedTask; }
internal virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
ApiClient.Dispose();
_isDisposed = true;
}
}
/// <inheritdoc />
public void Dispose() => Dispose(true);
//IDiscordClient
ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected;
ISelfUser IDiscordClient.CurrentUser => CurrentUser;
Task<IApplication> IDiscordClient.GetApplicationInfoAsync() { throw new NotSupportedException(); }
Task<IChannel> IDiscordClient.GetChannelAsync(ulong id)
=> Task.FromResult<IChannel>(null);
Task<IReadOnlyCollection<IPrivateChannel>> IDiscordClient.GetPrivateChannelsAsync()
=> Task.FromResult<IReadOnlyCollection<IPrivateChannel>>(ImmutableArray.Create<IPrivateChannel>());
Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync()
=> Task.FromResult<IReadOnlyCollection<IConnection>>(ImmutableArray.Create<IConnection>());
Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId)
=> Task.FromResult<IInvite>(null);
Task<IGuild> IDiscordClient.GetGuildAsync(ulong id)
=> Task.FromResult<IGuild>(null);
Task<IReadOnlyCollection<IGuild>> IDiscordClient.GetGuildsAsync()
=> Task.FromResult<IReadOnlyCollection<IGuild>>(ImmutableArray.Create<IGuild>());
Task<IGuild> IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon) { throw new NotSupportedException(); }
Task<IUser> IDiscordClient.GetUserAsync(ulong id)
=> Task.FromResult<IUser>(null);
Task<IUser> IDiscordClient.GetUserAsync(string username, string discriminator)
=> Task.FromResult<IUser>(null);
Task<IReadOnlyCollection<IVoiceRegion>> IDiscordClient.GetVoiceRegionsAsync()
=> Task.FromResult<IReadOnlyCollection<IVoiceRegion>>(ImmutableArray.Create<IVoiceRegion>());
Task<IVoiceRegion> IDiscordClient.GetVoiceRegionAsync(string id)
=> Task.FromResult<IVoiceRegion>(null);
Task IDiscordClient.ConnectAsync() { throw new NotSupportedException(); }
Task IDiscordClient.DisconnectAsync() { throw new NotSupportedException(); }
}
}

View File

@@ -1,324 +1,105 @@
using Discord.API.Rest;
using Discord.Net;
using Discord.Net.Queue;
using System;
using Discord.Net.Queue;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Discord.Logging;
namespace Discord.Rest
{
public class DiscordRestClient : IDiscordClient
public class DiscordRestClient : DiscordClient, IDiscordClient
{
private readonly object _eventLock = new object();
public new RestSelfUser CurrentUser => base.CurrentUser as RestSelfUser;
public event Func<LogMessage, Task> Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
private readonly AsyncEvent<Func<LogMessage, Task>> _logEvent = new AsyncEvent<Func<LogMessage, Task>>();
public event Func<Task> LoggedIn { add { _loggedInEvent.Add(value); } remove { _loggedInEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _loggedInEvent = new AsyncEvent<Func<Task>>();
public event Func<Task> LoggedOut { add { _loggedOutEvent.Add(value); } remove { _loggedOutEvent.Remove(value); } }
private readonly AsyncEvent<Func<Task>> _loggedOutEvent = new AsyncEvent<Func<Task>>();
internal readonly Logger _clientLogger, _restLogger, _queueLogger;
internal readonly SemaphoreSlim _connectionLock;
private bool _isFirstLogSub;
internal bool _isDisposed;
public API.DiscordRestApiClient ApiClient { get; }
internal LogManager LogManager { get; }
public LoginState LoginState { get; private set; }
public RestSelfUser CurrentUser { get; private set; }
/// <summary> Creates a new REST-only discord client. </summary>
public DiscordRestClient() : this(new DiscordRestConfig()) { }
public DiscordRestClient(DiscordRestConfig config) : this(config, CreateApiClient(config)) { }
/// <summary> Creates a new REST-only discord client. </summary>
internal DiscordRestClient(DiscordRestConfig config, API.DiscordRestApiClient client)
{
ApiClient = client;
LogManager = new LogManager(config.LogLevel);
LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
_clientLogger = LogManager.CreateLogger("Client");
_restLogger = LogManager.CreateLogger("Rest");
_queueLogger = LogManager.CreateLogger("Queue");
_isFirstLogSub = true;
public DiscordRestClient(DiscordRestConfig config) : base(config, CreateApiClient(config)) { }
_connectionLock = new SemaphoreSlim(1, 1);
ApiClient.RequestQueue.RateLimitTriggered += async (id, bucket, millis) =>
{
await _queueLogger.WarningAsync($"Rate limit triggered (id = \"{id ?? "null"}\")").ConfigureAwait(false);
if (bucket == null && id != null)
await _queueLogger.WarningAsync($"Unknown rate limit bucket \"{id ?? "null"}\"").ConfigureAwait(false);
};
ApiClient.SentRequest += async (method, endpoint, millis) => await _restLogger.VerboseAsync($"{method} {endpoint}: {millis} ms").ConfigureAwait(false);
}
private static API.DiscordRestApiClient CreateApiClient(DiscordRestConfig config)
=> new API.DiscordRestApiClient(config.RestClientProvider, DiscordRestConfig.UserAgent, requestQueue: new RequestQueue());
/// <inheritdoc />
public async Task LoginAsync(TokenType tokenType, string token, bool validateToken = true)
protected override async Task OnLoginAsync(TokenType tokenType, string token)
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LoginInternalAsync(tokenType, token).ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
await ApiClient.LoginAsync(tokenType, token).ConfigureAwait(false);
base.CurrentUser = RestSelfUser.Create(this, ApiClient.CurrentUser);
}
private async Task LoginInternalAsync(TokenType tokenType, string token)
{
if (_isFirstLogSub)
{
_isFirstLogSub = false;
await WriteInitialLog().ConfigureAwait(false);
}
if (LoginState != LoginState.LoggedOut)
await LogoutInternalAsync().ConfigureAwait(false);
LoginState = LoginState.LoggingIn;
try
{
await ApiClient.LoginAsync(tokenType, token).ConfigureAwait(false);
CurrentUser = RestSelfUser.Create(this, ApiClient.CurrentUser);
await OnLoginAsync(tokenType, token).ConfigureAwait(false);
LoginState = LoginState.LoggedIn;
}
catch (Exception)
{
await LogoutInternalAsync().ConfigureAwait(false);
throw;
}
await _loggedInEvent.InvokeAsync().ConfigureAwait(false);
}
protected virtual Task OnLoginAsync(TokenType tokenType, string token) => Task.CompletedTask;
/// <inheritdoc />
public async Task LogoutAsync()
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LogoutInternalAsync().ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
}
private async Task LogoutInternalAsync()
{
if (LoginState == LoginState.LoggedOut) return;
LoginState = LoginState.LoggingOut;
await ApiClient.LogoutAsync().ConfigureAwait(false);
await OnLogoutAsync().ConfigureAwait(false);
CurrentUser = null;
LoginState = LoginState.LoggedOut;
await _loggedOutEvent.InvokeAsync().ConfigureAwait(false);
}
protected virtual Task OnLogoutAsync() => Task.CompletedTask;
/// <inheritdoc />
public async Task<IApplication> GetApplicationInfoAsync()
{
var model = await ApiClient.GetMyApplicationAsync().ConfigureAwait(false);
return RestApplication.Create(this, model);
}
public Task<RestApplication> GetApplicationInfoAsync()
=> ClientHelper.GetApplicationInfoAsync(this);
/// <inheritdoc />
public virtual async Task<IChannel> GetChannelAsync(ulong id)
{
var model = await ApiClient.GetChannelAsync(id).ConfigureAwait(false);
if (model != null)
{
switch (model.Type)
{
case ChannelType.Text:
return RestTextChannel.Create(this, model);
case ChannelType.Voice:
return RestVoiceChannel.Create(this, model);
case ChannelType.DM:
return RestDMChannel.Create(this, model);
case ChannelType.Group:
return RestGroupChannel.Create(this, model);
default:
throw new InvalidOperationException($"Unexpected channel type: {model.Type}");
}
}
return null;
}
public Task<RestChannel> GetChannelAsync(ulong id)
=> ClientHelper.GetChannelAsync(this, id);
/// <inheritdoc />
public virtual async Task<IReadOnlyCollection<IPrivateChannel>> GetPrivateChannelsAsync()
{
var models = await ApiClient.GetMyPrivateChannelsAsync().ConfigureAwait(false);
return models.Select(x => RestDMChannel.Create(this, x)).ToImmutableArray();
}
/// <inheritdoc />
public async Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync()
{
var models = await ApiClient.GetMyConnectionsAsync().ConfigureAwait(false);
return models.Select(x => RestConnection.Create(x)).ToImmutableArray();
}
public Task<IReadOnlyCollection<IPrivateChannel>> GetPrivateChannelsAsync()
=> ClientHelper.GetPrivateChannelsAsync(this);
/// <inheritdoc />
public virtual async Task<RestInvite> GetInviteAsync(string inviteId)
{
var model = await ApiClient.GetInviteAsync(inviteId).ConfigureAwait(false);
if (model != null)
return RestInvite.Create(this, model);
return null;
}
public Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync()
=> ClientHelper.GetConnectionsAsync(this);
/// <inheritdoc />
public virtual async Task<RestGuild> GetGuildAsync(ulong id)
{
var model = await ApiClient.GetGuildAsync(id).ConfigureAwait(false);
if (model != null)
return RestGuild.Create(this, model);
return null;
}
/// <inheritdoc />
public virtual async Task<RestGuildEmbed?> GetGuildEmbedAsync(ulong id)
{
var model = await ApiClient.GetGuildEmbedAsync(id).ConfigureAwait(false);
if (model != null)
return RestGuildEmbed.Create(model);
return null;
}
/// <inheritdoc />
public virtual async Task<IReadOnlyCollection<RestUserGuild>> GetGuildSummariesAsync()
{
var models = await ApiClient.GetMyGuildsAsync().ConfigureAwait(false);
return models.Select(x => RestUserGuild.Create(this, x)).ToImmutableArray();
}
/// <inheritdoc />
public virtual async Task<IReadOnlyCollection<RestGuild>> GetGuildsAsync()
{
var summaryModels = await ApiClient.GetMyGuildsAsync().ConfigureAwait(false);
var guilds = ImmutableArray.CreateBuilder<RestGuild>(summaryModels.Count);
foreach (var summaryModel in summaryModels)
{
var guildModel = await ApiClient.GetGuildAsync(summaryModel.Id).ConfigureAwait(false);
if (guildModel != null)
guilds.Add(RestGuild.Create(this, guildModel));
}
return guilds.ToImmutable();
}
/// <inheritdoc />
public virtual async Task<RestGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null)
{
var args = new CreateGuildParams(name, region.Id);
var model = await ApiClient.CreateGuildAsync(args).ConfigureAwait(false);
return RestGuild.Create(this, model);
}
public Task<RestInvite> GetInviteAsync(string inviteId)
=> ClientHelper.GetInviteAsync(this, inviteId);
/// <inheritdoc />
public virtual async Task<RestUser> GetUserAsync(ulong id)
{
var model = await ApiClient.GetUserAsync(id).ConfigureAwait(false);
if (model != null)
return RestUser.Create(this, model);
return null;
}
public Task<RestGuild> GetGuildAsync(ulong id)
=> ClientHelper.GetGuildAsync(this, id);
/// <inheritdoc />
public virtual async Task<RestUser> GetUserAsync(string username, string discriminator)
{
var model = await ApiClient.GetUserAsync(username, discriminator).ConfigureAwait(false);
if (model != null)
return RestUser.Create(this, model);
return null;
}
public Task<RestGuildEmbed?> GetGuildEmbedAsync(ulong id)
=> ClientHelper.GetGuildEmbedAsync(this, id);
/// <inheritdoc />
public Task<IReadOnlyCollection<RestUserGuild>> GetGuildSummariesAsync()
=> ClientHelper.GetGuildSummariesAsync(this);
/// <inheritdoc />
public Task<IReadOnlyCollection<RestGuild>> GetGuildsAsync()
=> ClientHelper.GetGuildsAsync(this);
/// <inheritdoc />
public Task<RestGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null)
=> ClientHelper.CreateGuildAsync(this, name, region, jpegIcon);
/// <inheritdoc />
public virtual async Task<IReadOnlyCollection<RestUser>> QueryUsersAsync(string query, int limit)
{
var models = await ApiClient.QueryUsersAsync(query, limit).ConfigureAwait(false);
return models.Select(x => RestUser.Create(this, x)).ToImmutableArray();
}
public Task<RestUser> GetUserAsync(ulong id)
=> ClientHelper.GetUserAsync(this, id);
/// <inheritdoc />
public Task<RestUser> GetUserAsync(string username, string discriminator)
=> ClientHelper.GetUserAsync(this, username, discriminator);
/// <inheritdoc />
public virtual async Task<IReadOnlyCollection<RestVoiceRegion>> GetVoiceRegionsAsync()
{
var models = await ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(this, x)).ToImmutableArray();
}
public Task<IReadOnlyCollection<RestVoiceRegion>> GetVoiceRegionsAsync()
=> ClientHelper.GetVoiceRegionsAsync(this);
/// <inheritdoc />
public virtual async Task<RestVoiceRegion> GetVoiceRegionAsync(string id)
{
var models = await ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
return models.Select(x => RestVoiceRegion.Create(this, x)).Where(x => x.Id == id).FirstOrDefault();
}
internal virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
ApiClient.Dispose();
_isDisposed = true;
}
}
/// <inheritdoc />
public void Dispose() => Dispose(true);
private async Task WriteInitialLog()
{
/*if (this is DiscordSocketClient)
await _clientLogger.InfoAsync($"DiscordSocketClient v{DiscordConfig.Version} (API v{DiscordConfig.APIVersion}, {DiscordSocketConfig.GatewayEncoding})").ConfigureAwait(false);
else if (this is DiscordRpcClient)
await _clientLogger.InfoAsync($"DiscordRpcClient v{DiscordConfig.Version} (API v{DiscordConfig.APIVersion}, RPC API v{DiscordRpcConfig.RpcAPIVersion})").ConfigureAwait(false);*/
await _clientLogger.InfoAsync($"Discord.Net v{DiscordConfig.Version} (API v{DiscordConfig.APIVersion})").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($"Processors: {Environment.ProcessorCount}").ConfigureAwait(false);
}
private static string ToArchString(Architecture arch)
{
switch (arch)
{
case Architecture.X64: return "x64";
case Architecture.X86: return "x86";
default: return arch.ToString();
}
}
public Task<RestVoiceRegion> GetVoiceRegionAsync(string id)
=> ClientHelper.GetVoiceRegionAsync(this, id);
//IDiscordClient
ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected;
ISelfUser IDiscordClient.CurrentUser => CurrentUser;
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync()
=> await GetApplicationInfoAsync().ConfigureAwait(false);
async Task<IChannel> IDiscordClient.GetChannelAsync(ulong id)
=> await GetChannelAsync(id);
async Task<IReadOnlyCollection<IPrivateChannel>> IDiscordClient.GetPrivateChannelsAsync()
=> await GetPrivateChannelsAsync();
async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync()
=> await GetConnectionsAsync().ConfigureAwait(false);
async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId)
=> await GetInviteAsync(inviteId).ConfigureAwait(false);
async Task<IGuild> IDiscordClient.GetGuildAsync(ulong id)
=> await GetGuildAsync(id).ConfigureAwait(false);
async Task<IReadOnlyCollection<IUserGuild>> IDiscordClient.GetGuildSummariesAsync()
=> await GetGuildSummariesAsync().ConfigureAwait(false);
async Task<IReadOnlyCollection<IGuild>> IDiscordClient.GetGuildsAsync()
=> await GetGuildsAsync().ConfigureAwait(false);
async Task<IGuild> IDiscordClient.CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon)
=> await CreateGuildAsync(name, region, jpegIcon).ConfigureAwait(false);
async Task<IUser> IDiscordClient.GetUserAsync(ulong id)
=> await GetUserAsync(id).ConfigureAwait(false);
async Task<IUser> IDiscordClient.GetUserAsync(string username, string discriminator)
=> await GetUserAsync(username, discriminator).ConfigureAwait(false);
async Task<IReadOnlyCollection<IUser>> IDiscordClient.QueryUsersAsync(string query, int limit)
=> await QueryUsersAsync(query, limit).ConfigureAwait(false);
async Task<IReadOnlyCollection<IVoiceRegion>> IDiscordClient.GetVoiceRegionsAsync()
=> await GetVoiceRegionsAsync().ConfigureAwait(false);
async Task<IVoiceRegion> IDiscordClient.GetVoiceRegionAsync(string id)
=> await GetVoiceRegionAsync(id).ConfigureAwait(false);
Task IDiscordClient.ConnectAsync() { throw new NotSupportedException(); }
Task IDiscordClient.DisconnectAsync() { throw new NotSupportedException(); }
}
}

View File

@@ -12,33 +12,33 @@ namespace Discord.Rest
internal static class ChannelHelper
{
//General
public static async Task<Model> GetAsync(IGuildChannel channel, DiscordRestClient client)
public static async Task<Model> GetAsync(IGuildChannel channel, DiscordClient client)
{
return await client.ApiClient.GetChannelAsync(channel.GuildId, channel.Id).ConfigureAwait(false);
}
public static async Task<Model> GetAsync(IPrivateChannel channel, DiscordRestClient client)
public static async Task<Model> GetAsync(IPrivateChannel channel, DiscordClient client)
{
return await client.ApiClient.GetChannelAsync(channel.Id).ConfigureAwait(false);
}
public static async Task DeleteAsync(IChannel channel, DiscordRestClient client)
public static async Task DeleteAsync(IChannel channel, DiscordClient client)
{
await client.ApiClient.DeleteChannelAsync(channel.Id).ConfigureAwait(false);
}
public static async Task ModifyAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task ModifyAsync(IGuildChannel channel, DiscordClient client,
Action<ModifyGuildChannelParams> func)
{
var args = new ModifyGuildChannelParams();
func(args);
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, args);
}
public static async Task ModifyAsync(ITextChannel channel, DiscordRestClient client,
public static async Task ModifyAsync(ITextChannel channel, DiscordClient client,
Action<ModifyTextChannelParams> func)
{
var args = new ModifyTextChannelParams();
func(args);
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, args);
}
public static async Task ModifyAsync(IVoiceChannel channel, DiscordRestClient client,
public static async Task ModifyAsync(IVoiceChannel channel, DiscordClient client,
Action<ModifyVoiceChannelParams> func)
{
var args = new ModifyVoiceChannelParams();
@@ -47,12 +47,12 @@ namespace Discord.Rest
}
//Invites
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IChannel channel, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IChannel channel, DiscordClient client)
{
var models = await client.ApiClient.GetChannelInvitesAsync(channel.Id);
return models.Select(x => RestInviteMetadata.Create(client, x)).ToImmutableArray();
}
public static async Task<RestInviteMetadata> CreateInviteAsync(IChannel channel, DiscordRestClient client,
public static async Task<RestInviteMetadata> CreateInviteAsync(IChannel channel, DiscordClient client,
int? maxAge, int? maxUses, bool isTemporary)
{
var args = new CreateChannelInviteParams { IsTemporary = isTemporary };
@@ -65,13 +65,13 @@ namespace Discord.Rest
}
//Messages
public static async Task<RestMessage> GetMessageAsync(IChannel channel, DiscordRestClient client,
public static async Task<RestMessage> GetMessageAsync(IChannel channel, DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetChannelMessageAsync(channel.Id, id).ConfigureAwait(false);
return RestMessage.Create(client, model);
}
public static PagedAsyncEnumerable<RestMessage> GetMessagesAsync(IChannel channel, DiscordRestClient client,
public static IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IChannel channel, DiscordClient client,
ulong? fromMessageId = null, Direction dir = Direction.Before, int limit = DiscordConfig.MaxMessagesPerBatch)
{
//TODO: Test this with Around direction
@@ -102,13 +102,13 @@ namespace Discord.Rest
count: (uint)limit
);
}
public static async Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(IChannel channel, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(IChannel channel, DiscordClient client)
{
var models = await client.ApiClient.GetPinsAsync(channel.Id).ConfigureAwait(false);
return models.Select(x => RestMessage.Create(client, x)).ToImmutableArray();
}
public static async Task<RestUserMessage> SendMessageAsync(IChannel channel, DiscordRestClient client,
public static async Task<RestUserMessage> SendMessageAsync(IChannel channel, DiscordClient client,
string text, bool isTTS)
{
var args = new CreateMessageParams(text) { IsTTS = isTTS };
@@ -116,14 +116,14 @@ namespace Discord.Rest
return RestUserMessage.Create(client, model);
}
public static Task<RestUserMessage> SendFileAsync(IChannel channel, DiscordRestClient client,
public static Task<RestUserMessage> SendFileAsync(IChannel channel, DiscordClient client,
string filePath, string text, bool isTTS)
{
string filename = Path.GetFileName(filePath);
using (var file = File.OpenRead(filePath))
return SendFileAsync(channel, client, file, filename, text, isTTS);
}
public static async Task<RestUserMessage> SendFileAsync(IChannel channel, DiscordRestClient client,
public static async Task<RestUserMessage> SendFileAsync(IChannel channel, DiscordClient client,
Stream stream, string filename, string text, bool isTTS)
{
var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS };
@@ -131,7 +131,7 @@ namespace Discord.Rest
return RestUserMessage.Create(client, model);
}
public static async Task DeleteMessagesAsync(IChannel channel, DiscordRestClient client,
public static async Task DeleteMessagesAsync(IChannel channel, DiscordClient client,
IEnumerable<IMessage> messages)
{
var args = new DeleteMessagesParams(messages.Select(x => x.Id).ToArray());
@@ -139,31 +139,31 @@ namespace Discord.Rest
}
//Permission Overwrites
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, DiscordClient client,
IUser user, OverwritePermissions perms)
{
var args = new ModifyChannelPermissionsParams("member", perms.AllowValue, perms.DenyValue);
await client.ApiClient.ModifyChannelPermissionsAsync(channel.Id, user.Id, args).ConfigureAwait(false);
}
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, DiscordClient client,
IRole role, OverwritePermissions perms)
{
var args = new ModifyChannelPermissionsParams("role", perms.AllowValue, perms.DenyValue);
await client.ApiClient.ModifyChannelPermissionsAsync(channel.Id, role.Id, args).ConfigureAwait(false);
}
public static async Task RemovePermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task RemovePermissionOverwriteAsync(IGuildChannel channel, DiscordClient client,
IUser user)
{
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, user.Id).ConfigureAwait(false);
}
public static async Task RemovePermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task RemovePermissionOverwriteAsync(IGuildChannel channel, DiscordClient client,
IRole role)
{
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, role.Id).ConfigureAwait(false);
}
//Users
public static async Task<RestGuildUser> GetUserAsync(IGuildChannel channel, DiscordRestClient client,
public static async Task<RestGuildUser> GetUserAsync(IGuildChannel channel, DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetGuildMemberAsync(channel.GuildId, id);
@@ -175,7 +175,7 @@ namespace Discord.Rest
return user;
}
public static IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuildChannel channel, DiscordRestClient client,
public static IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuildChannel channel, DiscordClient client,
ulong? froUserId = null, uint? limit = DiscordConfig.MaxUsersPerBatch)
{
return new PagedAsyncEnumerable<RestGuildUser>(
@@ -203,7 +203,7 @@ namespace Discord.Rest
}
//Typing
public static IDisposable EnterTypingState(IChannel channel, DiscordRestClient client)
public static IDisposable EnterTypingState(IChannel channel, DiscordClient client)
{
throw new NotImplementedException(); //TODO: Impl
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public abstract class RestChannel : RestEntity<ulong>, IChannel, IUpdateable
{
internal RestChannel(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestChannel Create(DiscordClient discord, Model model)
{
switch (model.Type)
{
case ChannelType.Text:
return RestTextChannel.Create(discord, model);
case ChannelType.Voice:
return RestVoiceChannel.Create(discord, model);
case ChannelType.DM:
return RestDMChannel.Create(discord, model);
case ChannelType.Group:
return RestGroupChannel.Create(discord, model);
default:
throw new InvalidOperationException($"Unexpected channel type: {model.Type}");
}
}
internal abstract void Update(Model model);
public abstract Task UpdateAsync();
//IChannel
IReadOnlyCollection<IUser> IChannel.CachedUsers => ImmutableArray.Create<IUser>();
IUser IChannel.GetCachedUser(ulong id)
=> null;
Task<IUser> IChannel.GetUserAsync(ulong id)
=> Task.FromResult<IUser>(null);
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync()
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>().ToAsyncEnumerable();
}
}

View File

@@ -10,28 +10,31 @@ using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestDMChannel : RestEntity<ulong>, IDMChannel, IUpdateable
public class RestDMChannel : RestChannel, IDMChannel, IUpdateable
{
public RestUser Recipient { get; }
public RestUser CurrentUser { get; private set; }
public RestUser Recipient { get; private set; }
public IReadOnlyCollection<RestUser> Users => ImmutableArray.Create(Discord.CurrentUser, Recipient);
public IReadOnlyCollection<RestUser> Users => ImmutableArray.Create(CurrentUser, Recipient);
internal RestDMChannel(DiscordRestClient discord, ulong id)
internal RestDMChannel(DiscordClient discord, ulong id, ulong recipientId)
: base(discord, id)
{
Recipient = new RestUser(Discord, recipientId);
CurrentUser = new RestUser(Discord, discord.CurrentUser.Id);
}
internal static RestDMChannel Create(DiscordRestClient discord, Model model)
internal new static RestDMChannel Create(DiscordClient discord, Model model)
{
var entity = new RestDMChannel(discord, model.Id);
var entity = new RestDMChannel(discord, model.Id, model.Recipients.Value[0].Id);
entity.Update(model);
return entity;
}
internal void Update(Model model)
internal override void Update(Model model)
{
Recipient.Update(model.Recipients.Value[0]);
}
public async Task UpdateAsync()
public override async Task UpdateAsync()
=> Update(await ChannelHelper.GetAsync(this, Discord));
public Task CloseAsync()
=> ChannelHelper.DeleteAsync(this, Discord);
@@ -41,7 +44,7 @@ namespace Discord.Rest
if (id == Recipient.Id)
return Recipient;
else if (id == Discord.CurrentUser.Id)
return Discord.CurrentUser;
return CurrentUser;
else
return null;
}

View File

@@ -10,7 +10,7 @@ using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupChannel : RestEntity<ulong>, IGroupChannel, IUpdateable
public class RestGroupChannel : RestChannel, IGroupChannel, IUpdateable
{
private string _iconId;
private ImmutableDictionary<ulong, RestGroupUser> _users;
@@ -21,17 +21,17 @@ namespace Discord.Rest
public IReadOnlyCollection<RestGroupUser> Recipients
=> _users.Select(x => x.Value).Where(x => x.Id != Discord.CurrentUser.Id).ToReadOnlyCollection(() => _users.Count - 1);
internal RestGroupChannel(DiscordRestClient discord, ulong id)
internal RestGroupChannel(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestGroupChannel Create(DiscordRestClient discord, Model model)
internal new static RestGroupChannel Create(DiscordClient discord, Model model)
{
var entity = new RestGroupChannel(discord, model.Id);
entity.Update(model);
return entity;
}
internal void Update(Model model)
internal override void Update(Model model)
{
if (model.Name.IsSpecified)
Name = model.Name.Value;
@@ -49,7 +49,7 @@ namespace Discord.Rest
_users = users.ToImmutable();
}
public async Task UpdateAsync()
public override async Task UpdateAsync()
=> Update(await ChannelHelper.GetAsync(this, Discord));
public Task LeaveAsync()
=> ChannelHelper.DeleteAsync(this, Discord);

View File

@@ -10,7 +10,7 @@ using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public abstract class RestGuildChannel : RestEntity<ulong>, IGuildChannel, IUpdateable
public abstract class RestGuildChannel : RestChannel, IGuildChannel, IUpdateable
{
private ImmutableArray<Overwrite> _overwrites;
@@ -21,12 +21,12 @@ namespace Discord.Rest
public string Name { get; private set; }
public int Position { get; private set; }
internal RestGuildChannel(DiscordRestClient discord, ulong id, ulong guildId)
internal RestGuildChannel(DiscordClient discord, ulong id, ulong guildId)
: base(discord, id)
{
GuildId = guildId;
}
internal static RestGuildChannel Create(DiscordRestClient discord, Model model)
internal new static RestGuildChannel Create(DiscordClient discord, Model model)
{
switch (model.Type)
{
@@ -38,7 +38,7 @@ namespace Discord.Rest
throw new InvalidOperationException("Unknown guild channel type");
}
}
internal virtual void Update(Model model)
internal override void Update(Model model)
{
Name = model.Name.Value;
Position = model.Position.Value;
@@ -50,7 +50,7 @@ namespace Discord.Rest
_overwrites = newOverwrites.ToImmutable();
}
public async Task UpdateAsync()
public override async Task UpdateAsync()
=> Update(await ChannelHelper.GetAsync(this, Discord));
public Task ModifyAsync(Action<ModifyGuildChannelParams> func)
=> ChannelHelper.ModifyAsync(this, Discord, func);

View File

@@ -16,11 +16,11 @@ namespace Discord.Rest
public string Mention => MentionUtils.MentionChannel(Id);
internal RestTextChannel(DiscordRestClient discord, ulong id, ulong guildId)
internal RestTextChannel(DiscordClient discord, ulong id, ulong guildId)
: base(discord, id, guildId)
{
}
internal new static RestTextChannel Create(DiscordRestClient discord, Model model)
internal new static RestTextChannel Create(DiscordClient discord, Model model)
{
var entity = new RestTextChannel(discord, model.Id, model.GuildId.Value);
entity.Update(model);

View File

@@ -16,11 +16,11 @@ namespace Discord.Rest
public int Bitrate { get; private set; }
public int UserLimit { get; private set; }
internal RestVoiceChannel(DiscordRestClient discord, ulong id, ulong guildId)
internal RestVoiceChannel(DiscordClient discord, ulong id, ulong guildId)
: base(discord, id, guildId)
{
}
internal new static RestVoiceChannel Create(DiscordRestClient discord, Model model)
internal new static RestVoiceChannel Create(DiscordClient discord, Model model)
{
var entity = new RestVoiceChannel(discord, model.Id, model.GuildId.Value);
entity.Update(model);

View File

@@ -13,7 +13,7 @@ namespace Discord.Rest
internal static class GuildHelper
{
//General
public static async Task<Model> ModifyAsync(IGuild guild, DiscordRestClient client,
public static async Task<Model> ModifyAsync(IGuild guild, DiscordClient client,
Action<ModifyGuildParams> func)
{
if (func == null) throw new NullReferenceException(nameof(func));
@@ -28,7 +28,7 @@ namespace Discord.Rest
return await client.ApiClient.ModifyGuildAsync(guild.Id, args).ConfigureAwait(false);
}
public static async Task<EmbedModel> ModifyEmbedAsync(IGuild guild, DiscordRestClient client,
public static async Task<EmbedModel> ModifyEmbedAsync(IGuild guild, DiscordClient client,
Action<ModifyGuildEmbedParams> func)
{
if (func == null) throw new NullReferenceException(nameof(func));
@@ -37,46 +37,46 @@ namespace Discord.Rest
func(args);
return await client.ApiClient.ModifyGuildEmbedAsync(guild.Id, args).ConfigureAwait(false);
}
public static async Task ModifyChannelsAsync(IGuild guild, DiscordRestClient client,
public static async Task ModifyChannelsAsync(IGuild guild, DiscordClient client,
IEnumerable<ModifyGuildChannelsParams> args)
{
await client.ApiClient.ModifyGuildChannelsAsync(guild.Id, args).ConfigureAwait(false);
}
public static async Task<IReadOnlyCollection<RoleModel>> ModifyRolesAsync(IGuild guild, DiscordRestClient client,
public static async Task<IReadOnlyCollection<RoleModel>> ModifyRolesAsync(IGuild guild, DiscordClient client,
IEnumerable<ModifyGuildRolesParams> args)
{
return await client.ApiClient.ModifyGuildRolesAsync(guild.Id, args).ConfigureAwait(false);
}
public static async Task LeaveAsync(IGuild guild, DiscordRestClient client)
public static async Task LeaveAsync(IGuild guild, DiscordClient client)
{
await client.ApiClient.LeaveGuildAsync(guild.Id).ConfigureAwait(false);
}
public static async Task DeleteAsync(IGuild guild, DiscordRestClient client)
public static async Task DeleteAsync(IGuild guild, DiscordClient client)
{
await client.ApiClient.DeleteGuildAsync(guild.Id).ConfigureAwait(false);
}
//Bans
public static async Task<IReadOnlyCollection<RestBan>> GetBansAsync(IGuild guild, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestBan>> GetBansAsync(IGuild guild, DiscordClient client)
{
var models = await client.ApiClient.GetGuildBansAsync(guild.Id);
return models.Select(x => RestBan.Create(client, x)).ToImmutableArray();
}
public static async Task AddBanAsync(IGuild guild, DiscordRestClient client,
public static async Task AddBanAsync(IGuild guild, DiscordClient client,
ulong userId, int pruneDays)
{
var args = new CreateGuildBanParams { DeleteMessageDays = pruneDays };
await client.ApiClient.CreateGuildBanAsync(guild.Id, userId, args);
}
public static async Task RemoveBanAsync(IGuild guild, DiscordRestClient client,
public static async Task RemoveBanAsync(IGuild guild, DiscordClient client,
ulong userId)
{
await client.ApiClient.RemoveGuildBanAsync(guild.Id, userId);
}
//Channels
public static async Task<RestGuildChannel> GetChannelAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestGuildChannel> GetChannelAsync(IGuild guild, DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetChannelAsync(guild.Id, id).ConfigureAwait(false);
@@ -84,12 +84,12 @@ namespace Discord.Rest
return RestGuildChannel.Create(client, model);
return null;
}
public static async Task<IReadOnlyCollection<RestGuildChannel>> GetChannelsAsync(IGuild guild, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestGuildChannel>> GetChannelsAsync(IGuild guild, DiscordClient client)
{
var models = await client.ApiClient.GetGuildChannelsAsync(guild.Id).ConfigureAwait(false);
return models.Select(x => RestGuildChannel.Create(client, x)).ToImmutableArray();
}
public static async Task<RestTextChannel> CreateTextChannelAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestTextChannel> CreateTextChannelAsync(IGuild guild, DiscordClient client,
string name)
{
if (name == null) throw new ArgumentNullException(nameof(name));
@@ -98,7 +98,7 @@ namespace Discord.Rest
var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args).ConfigureAwait(false);
return RestTextChannel.Create(client, model);
}
public static async Task<RestVoiceChannel> CreateVoiceChannelAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestVoiceChannel> CreateVoiceChannelAsync(IGuild guild, DiscordClient client,
string name)
{
if (name == null) throw new ArgumentNullException(nameof(name));
@@ -109,12 +109,12 @@ namespace Discord.Rest
}
//Integrations
public static async Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(IGuild guild, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(IGuild guild, DiscordClient client)
{
var models = await client.ApiClient.GetGuildIntegrationsAsync(guild.Id).ConfigureAwait(false);
return models.Select(x => RestGuildIntegration.Create(client, x)).ToImmutableArray();
}
public static async Task<RestGuildIntegration> CreateIntegrationAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestGuildIntegration> CreateIntegrationAsync(IGuild guild, DiscordClient client,
ulong id, string type)
{
var args = new CreateGuildIntegrationParams(id, type);
@@ -123,14 +123,14 @@ namespace Discord.Rest
}
//Invites
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, DiscordClient client)
{
var models = await client.ApiClient.GetGuildInvitesAsync(guild.Id).ConfigureAwait(false);
return models.Select(x => RestInviteMetadata.Create(client, x)).ToImmutableArray();
}
//Roles
public static async Task<RestRole> CreateRoleAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestRole> CreateRoleAsync(IGuild guild, DiscordClient client,
string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false)
{
if (name == null) throw new ArgumentNullException(nameof(name));
@@ -150,7 +150,7 @@ namespace Discord.Rest
}
//Users
public static async Task<RestGuildUser> GetUserAsync(IGuild guild, DiscordRestClient client,
public static async Task<RestGuildUser> GetUserAsync(IGuild guild, DiscordClient client,
ulong id)
{
var model = await client.ApiClient.GetGuildMemberAsync(guild.Id, id).ConfigureAwait(false);
@@ -158,17 +158,17 @@ namespace Discord.Rest
return RestGuildUser.Create(client, model);
return null;
}
public static async Task<RestGuildUser> GetCurrentUserAsync(IGuild guild, DiscordRestClient client)
public static async Task<RestGuildUser> GetCurrentUserAsync(IGuild guild, DiscordClient client)
{
return await GetUserAsync(guild, client, client.CurrentUser.Id).ConfigureAwait(false);
}
public static async Task<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuild guild, DiscordRestClient client)
public static async Task<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuild guild, DiscordClient client)
{
var args = new GetGuildMembersParams();
var models = await client.ApiClient.GetGuildMembersAsync(guild.Id, args).ConfigureAwait(false);
return models.Select(x => RestGuildUser.Create(client, x)).ToImmutableArray();
}
public static async Task<int> PruneUsersAsync(IGuild guild, DiscordRestClient client,
public static async Task<int> PruneUsersAsync(IGuild guild, DiscordClient client,
int days = 30, bool simulate = false)
{
var args = new GuildPruneParams(days);

View File

@@ -14,7 +14,7 @@ namespace Discord.Rest
User = user;
Reason = reason;
}
internal static RestBan Create(DiscordRestClient client, Model model)
internal static RestBan Create(DiscordClient client, Model model)
{
return new RestBan(RestUser.Create(client, model.User), model.Reason);
}

View File

@@ -39,11 +39,11 @@ namespace Discord.Rest
public IReadOnlyCollection<Emoji> Emojis => _emojis;
public IReadOnlyCollection<string> Features => _features;
internal RestGuild(DiscordRestClient client, ulong id)
internal RestGuild(DiscordClient client, ulong id)
: base(client, id)
{
}
internal static RestGuild Create(DiscordRestClient discord, Model model)
internal static RestGuild Create(DiscordClient discord, Model model)
{
var entity = new RestGuild(discord, model.Id);
entity.Update(model);

View File

@@ -25,11 +25,11 @@ namespace Discord.Rest
public DateTimeOffset SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks);
internal RestGuildIntegration(DiscordRestClient discord, ulong id)
internal RestGuildIntegration(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestGuildIntegration Create(DiscordRestClient discord, Model model)
internal static RestGuildIntegration Create(DiscordClient discord, Model model)
{
var entity = new RestGuildIntegration(discord, model.Id);
entity.Update(model);

View File

@@ -15,11 +15,11 @@ namespace Discord.Rest
public string IconUrl => API.CDN.GetGuildIconUrl(Id, _iconId);
internal RestUserGuild(DiscordRestClient discord, ulong id)
internal RestUserGuild(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestUserGuild Create(DiscordRestClient discord, Model model)
internal static RestUserGuild Create(DiscordClient discord, Model model)
{
var entity = new RestUserGuild(discord, model.Id);
entity.Update(model);

View File

@@ -13,11 +13,11 @@ namespace Discord
public string SampleHostname { get; private set; }
public int SamplePort { get; private set; }
internal RestVoiceRegion(DiscordRestClient client, string id)
internal RestVoiceRegion(DiscordClient client, string id)
: base(client, id)
{
}
internal static RestVoiceRegion Create(DiscordRestClient client, Model model)
internal static RestVoiceRegion Create(DiscordClient client, Model model)
{
var entity = new RestVoiceRegion(client, model.Id);
entity.Update(model);

View File

@@ -5,15 +5,15 @@ namespace Discord.Rest
{
internal static class InviteHelper
{
public static async Task<Model> GetAsync(IInvite invite, DiscordRestClient client)
public static async Task<Model> GetAsync(IInvite invite, DiscordClient client)
{
return await client.ApiClient.GetInviteAsync(invite.Code).ConfigureAwait(false);
}
public static async Task AcceptAsync(IInvite invite, DiscordRestClient client)
public static async Task AcceptAsync(IInvite invite, DiscordClient client)
{
await client.ApiClient.AcceptInviteAsync(invite.Code).ConfigureAwait(false);
}
public static async Task DeleteAsync(IInvite invite, DiscordRestClient client)
public static async Task DeleteAsync(IInvite invite, DiscordClient client)
{
await client.ApiClient.DeleteInviteAsync(invite.Code).ConfigureAwait(false);
}

View File

@@ -16,11 +16,11 @@ namespace Discord.Rest
public string Code => Id;
public string Url => $"{DiscordConfig.InviteUrl}/{Code}";
internal RestInvite(DiscordRestClient discord, string id)
internal RestInvite(DiscordClient discord, string id)
: base(discord, id)
{
}
internal static RestInvite Create(DiscordRestClient discord, Model model)
internal static RestInvite Create(DiscordClient discord, Model model)
{
var entity = new RestInvite(discord, model.Code);
entity.Update(model);

View File

@@ -18,11 +18,11 @@ namespace Discord.Rest
public DateTimeOffset CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);
internal RestInviteMetadata(DiscordRestClient discord, string id)
internal RestInviteMetadata(DiscordClient discord, string id)
: base(discord, id)
{
}
internal static RestInviteMetadata Create(DiscordRestClient discord, Model model)
internal static RestInviteMetadata Create(DiscordClient discord, Model model)
{
var entity = new RestInviteMetadata(discord, model.Code);
entity.Update(model);

View File

@@ -6,26 +6,26 @@ namespace Discord.Rest
{
internal static class MessageHelper
{
public static async Task GetAsync(IMessage msg, DiscordRestClient client)
public static async Task GetAsync(IMessage msg, DiscordClient client)
{
await client.ApiClient.GetChannelMessageAsync(msg.ChannelId, msg.Id);
}
public static async Task ModifyAsync(IMessage msg, DiscordRestClient client, Action<ModifyMessageParams> func)
public static async Task ModifyAsync(IMessage msg, DiscordClient client, Action<ModifyMessageParams> func)
{
var args = new ModifyMessageParams();
func(args);
await client.ApiClient.ModifyMessageAsync(msg.ChannelId, msg.Id, args);
}
public static async Task DeleteAsync(IMessage msg, DiscordRestClient client)
public static async Task DeleteAsync(IMessage msg, DiscordClient client)
{
await client.ApiClient.DeleteMessageAsync(msg.ChannelId, msg.Id);
}
public static async Task PinAsync(IMessage msg, DiscordRestClient client)
public static async Task PinAsync(IMessage msg, DiscordClient client)
{
await client.ApiClient.AddPinAsync(msg.ChannelId, msg.Id);
}
public static async Task UnpinAsync(IMessage msg, DiscordRestClient client)
public static async Task UnpinAsync(IMessage msg, DiscordClient client)
{
await client.ApiClient.RemovePinAsync(msg.ChannelId, msg.Id);
}

View File

@@ -2,6 +2,7 @@
namespace Discord
{
//TODO: Rename to Attachment?
public class RestAttachment : IAttachment
{
public ulong Id { get; }

View File

@@ -29,12 +29,12 @@ namespace Discord.Rest
public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks);
internal RestMessage(DiscordRestClient discord, ulong id, ulong channelId)
internal RestMessage(DiscordClient discord, ulong id, ulong channelId)
: base(discord, id)
{
ChannelId = channelId;
}
internal static RestMessage Create(DiscordRestClient discord, Model model)
internal static RestMessage Create(DiscordClient discord, Model model)
{
if (model.Type == MessageType.Default)
return RestUserMessage.Create(discord, model);

View File

@@ -8,11 +8,11 @@ namespace Discord.Rest
{
public MessageType Type { get; private set; }
internal RestSystemMessage(DiscordRestClient discord, ulong id, ulong channelId)
internal RestSystemMessage(DiscordClient discord, ulong id, ulong channelId)
: base(discord, id, channelId)
{
}
internal new static RestSystemMessage Create(DiscordRestClient discord, Model model)
internal new static RestSystemMessage Create(DiscordClient discord, Model model)
{
var entity = new RestSystemMessage(discord, model.Id, model.ChannelId);
entity.Update(model);

View File

@@ -30,11 +30,11 @@ namespace Discord.Rest
public override IReadOnlyCollection<IRole> MentionedRoles => _mentionedRoles;
public override IReadOnlyCollection<IUser> MentionedUsers => _mentionedUsers;
internal RestUserMessage(DiscordRestClient discord, ulong id, ulong channelId)
internal RestUserMessage(DiscordClient discord, ulong id, ulong channelId)
: base(discord, id, channelId)
{
}
internal new static RestUserMessage Create(DiscordRestClient discord, Model model)
internal new static RestUserMessage Create(DiscordClient discord, Model model)
{
var entity = new RestUserMessage(discord, model.Id, model.ChannelId);
entity.Update(model);

View File

@@ -17,11 +17,11 @@ namespace Discord.Rest
public string IconUrl => API.CDN.GetApplicationIconUrl(Id, _iconId);
internal RestApplication(DiscordRestClient discord, ulong id)
internal RestApplication(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestApplication Create(DiscordRestClient discord, Model model)
internal static RestApplication Create(DiscordClient discord, Model model)
{
var entity = new RestApplication(discord, model.Id);
entity.Update(model);

View File

@@ -5,10 +5,10 @@ namespace Discord.Rest
public abstract class RestEntity<T> : IEntity<T>
where T : IEquatable<T>
{
public DiscordClient Discord { get; }
public T Id { get; }
public DiscordRestClient Discord { get; }
public RestEntity(DiscordRestClient discord, T id)
internal RestEntity(DiscordClient discord, T id)
{
Discord = discord;
Id = id;

View File

@@ -21,11 +21,11 @@ namespace Discord.Rest
public bool IsEveryone => Id == Guild.Id;
public string Mention => MentionUtils.MentionRole(Id);
internal RestRole(DiscordRestClient discord, ulong id)
internal RestRole(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestRole Create(DiscordRestClient discord, Model model)
internal static RestRole Create(DiscordClient discord, Model model)
{
var entity = new RestRole(discord, model.Id);
entity.Update(model);

View File

@@ -7,11 +7,11 @@ namespace Discord.Rest
internal static class RoleHelper
{
//General
public static async Task DeleteAsync(IRole role, DiscordRestClient client)
public static async Task DeleteAsync(IRole role, DiscordClient client)
{
await client.ApiClient.DeleteGuildRoleAsync(role.Guild.Id, role.Id).ConfigureAwait(false);
}
public static async Task ModifyAsync(IRole role, DiscordRestClient client,
public static async Task ModifyAsync(IRole role, DiscordClient client,
Action<ModifyGuildRoleParams> func)
{
var args = new ModifyGuildRoleParams();

View File

@@ -6,11 +6,11 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupUser : RestUser, IGroupUser
{
internal RestGroupUser(DiscordRestClient discord, ulong id)
internal RestGroupUser(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal new static RestGroupUser Create(DiscordRestClient discord, Model model)
internal new static RestGroupUser Create(DiscordClient discord, Model model)
{
var entity = new RestGroupUser(discord, model.Id);
entity.Update(model);

View File

@@ -21,11 +21,11 @@ namespace Discord.Rest
public DateTimeOffset? JoinedAt => DateTimeUtils.FromTicks(_joinedAtTicks);
internal RestGuildUser(DiscordRestClient discord, ulong id)
internal RestGuildUser(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestGuildUser Create(DiscordRestClient discord, Model model)
internal static RestGuildUser Create(DiscordClient discord, Model model)
{
var entity = new RestGuildUser(discord, model.User.Id);
entity.Update(model);

View File

@@ -13,11 +13,11 @@ namespace Discord.Rest
public bool IsVerified { get; private set; }
public bool IsMfaEnabled { get; private set; }
internal RestSelfUser(DiscordRestClient discord, ulong id)
internal RestSelfUser(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal new static RestSelfUser Create(DiscordRestClient discord, Model model)
internal new static RestSelfUser Create(DiscordClient discord, Model model)
{
var entity = new RestSelfUser(discord, model.Id);
entity.Update(model);

View File

@@ -18,11 +18,11 @@ namespace Discord.Rest
public virtual Game? Game => null;
public virtual UserStatus Status => UserStatus.Unknown;
internal RestUser(DiscordRestClient discord, ulong id)
internal RestUser(DiscordClient discord, ulong id)
: base(discord, id)
{
}
internal static RestUser Create(DiscordRestClient discord, Model model)
internal static RestUser Create(DiscordClient discord, Model model)
{
var entity = new RestUser(discord, model.Id);
entity.Update(model);

View File

@@ -8,22 +8,22 @@ namespace Discord.Rest
{
internal static class UserHelper
{
public static async Task<Model> GetAsync(IUser user, DiscordRestClient client)
public static async Task<Model> GetAsync(IUser user, DiscordClient client)
{
return await client.ApiClient.GetUserAsync(user.Id);
}
public static async Task<Model> GetAsync(ISelfUser user, DiscordRestClient client)
public static async Task<Model> GetAsync(ISelfUser user, DiscordClient client)
{
var model = await client.ApiClient.GetMyUserAsync();
if (model.Id != user.Id)
throw new InvalidOperationException("Unable to update this object using a different token.");
return model;
}
public static async Task<MemberModel> GetAsync(IGuildUser user, DiscordRestClient client)
public static async Task<MemberModel> GetAsync(IGuildUser user, DiscordClient client)
{
return await client.ApiClient.GetGuildMemberAsync(user.GuildId, user.Id);
}
public static async Task ModifyAsync(ISelfUser user, DiscordRestClient client, Action<ModifyCurrentUserParams> func)
public static async Task ModifyAsync(ISelfUser user, DiscordClient client, Action<ModifyCurrentUserParams> func)
{
if (user.Id != client.CurrentUser.Id)
throw new InvalidOperationException("Unable to modify this object using a different token.");
@@ -32,19 +32,19 @@ namespace Discord.Rest
func(args);
await client.ApiClient.ModifySelfAsync(args);
}
public static async Task ModifyAsync(IGuildUser user, DiscordRestClient client, Action<ModifyGuildMemberParams> func)
public static async Task ModifyAsync(IGuildUser user, DiscordClient client, Action<ModifyGuildMemberParams> func)
{
var args = new ModifyGuildMemberParams();
func(args);
await client.ApiClient.ModifyGuildMemberAsync(user.GuildId, user.Id, args);
}
public static async Task KickAsync(IGuildUser user, DiscordRestClient client)
public static async Task KickAsync(IGuildUser user, DiscordClient client)
{
await client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id);
}
public static async Task<IDMChannel> CreateDMChannelAsync(IUser user, DiscordRestClient client)
public static async Task<IDMChannel> CreateDMChannelAsync(IUser user, DiscordClient client)
{
var args = new CreateDMChannelParams(user.Id);
return RestDMChannel.Create(client, await client.ApiClient.CreateDMChannelAsync(args));

View File

@@ -1,12 +1,6 @@
{
"version": "1.0.0-beta2-*",
"buildOptions": {
"compile": {
"include": [ "../Discord.Net.Utils/**.cs" ]
}
},
"configurations": {
"Release": {
"buildOptions": {