Concrete class prototype
This commit is contained in:
19
src/Discord.Net.Rest/Discord.Net.Rest.xproj
Normal file
19
src/Discord.Net.Rest/Discord.Net.Rest.xproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>bfc6dc28-0351-4573-926a-d4124244c04f</ProjectGuid>
|
||||
<RootNamespace>Discord.Rest</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
324
src/Discord.Net.Rest/DiscordRestClient.cs
Normal file
324
src/Discord.Net.Rest/DiscordRestClient.cs
Normal file
@@ -0,0 +1,324 @@
|
||||
using Discord.API.Rest;
|
||||
using Discord.Net;
|
||||
using Discord.Net.Queue;
|
||||
using System;
|
||||
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
|
||||
{
|
||||
private readonly object _eventLock = new object();
|
||||
|
||||
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;
|
||||
|
||||
_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)
|
||||
{
|
||||
await _connectionLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await LoginInternalAsync(tokenType, token).ConfigureAwait(false);
|
||||
}
|
||||
finally { _connectionLock.Release(); }
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
/// <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();
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
/// <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;
|
||||
}
|
||||
|
||||
/// <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();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IReadOnlyCollection<RestVoiceRegion>> GetVoiceRegionsAsync()
|
||||
{
|
||||
var models = await ApiClient.GetVoiceRegionsAsync().ConfigureAwait(false);
|
||||
return models.Select(x => RestVoiceRegion.Create(this, x)).ToImmutableArray();
|
||||
}
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
|
||||
//IDiscordClient
|
||||
ConnectionState IDiscordClient.ConnectionState => ConnectionState.Disconnected;
|
||||
ISelfUser IDiscordClient.CurrentUser => CurrentUser;
|
||||
|
||||
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(); }
|
||||
}
|
||||
}
|
||||
16
src/Discord.Net.Rest/DiscordRestConfig.cs
Normal file
16
src/Discord.Net.Rest/DiscordRestConfig.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Discord.Net.Rest;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
public class DiscordRestConfig : DiscordConfig
|
||||
{
|
||||
public static string UserAgent { get; } = $"DiscordBot (https://github.com/RogueException/Discord.Net, v{Version})";
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
211
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
Normal file
211
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using Discord.API.Rest;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Immutable;
|
||||
using Model = Discord.API.Channel;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class ChannelHelper
|
||||
{
|
||||
//General
|
||||
public static async Task<Model> GetAsync(IGuildChannel channel, DiscordRestClient client)
|
||||
{
|
||||
return await client.ApiClient.GetChannelAsync(channel.GuildId, channel.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task<Model> GetAsync(IPrivateChannel channel, DiscordRestClient client)
|
||||
{
|
||||
return await client.ApiClient.GetChannelAsync(channel.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task DeleteAsync(IChannel channel, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.DeleteChannelAsync(channel.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task ModifyAsync(IGuildChannel channel, DiscordRestClient 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,
|
||||
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,
|
||||
Action<ModifyVoiceChannelParams> func)
|
||||
{
|
||||
var args = new ModifyVoiceChannelParams();
|
||||
func(args);
|
||||
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, args);
|
||||
}
|
||||
|
||||
//Invites
|
||||
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IChannel channel, DiscordRestClient 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,
|
||||
int? maxAge, int? maxUses, bool isTemporary)
|
||||
{
|
||||
var args = new CreateChannelInviteParams { IsTemporary = isTemporary };
|
||||
if (maxAge.HasValue)
|
||||
args.MaxAge = maxAge.Value;
|
||||
if (maxUses.HasValue)
|
||||
args.MaxUses = maxUses.Value;
|
||||
var model = await client.ApiClient.CreateChannelInviteAsync(channel.Id, args);
|
||||
return RestInviteMetadata.Create(client, model);
|
||||
}
|
||||
|
||||
//Messages
|
||||
public static async Task<RestMessage> GetMessageAsync(IChannel channel, DiscordRestClient 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,
|
||||
ulong? fromMessageId = null, Direction dir = Direction.Before, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
{
|
||||
//TODO: Test this with Around direction
|
||||
return new PagedAsyncEnumerable<RestMessage>(
|
||||
DiscordConfig.MaxMessagesPerBatch,
|
||||
async (info, ct) =>
|
||||
{
|
||||
var args = new GetChannelMessagesParams
|
||||
{
|
||||
RelativeDirection = dir,
|
||||
Limit = info.PageSize
|
||||
};
|
||||
if (info.Position != null)
|
||||
args.RelativeMessageId = info.Position.Value;
|
||||
var models = await client.ApiClient.GetChannelMessagesAsync(channel.Id, args);
|
||||
return models.Select(x => RestMessage.Create(client, x)).ToImmutableArray(); ;
|
||||
},
|
||||
nextPage: (info, lastPage) =>
|
||||
{
|
||||
if (dir == Direction.Before)
|
||||
info.Position = lastPage.Min(x => x.Id);
|
||||
else
|
||||
info.Position = lastPage.Max(x => x.Id);
|
||||
if (lastPage.Count != DiscordConfig.MaxMessagesPerBatch)
|
||||
info.Remaining = 0;
|
||||
},
|
||||
start: fromMessageId,
|
||||
count: (uint)limit
|
||||
);
|
||||
}
|
||||
public static async Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(IChannel channel, DiscordRestClient 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,
|
||||
string text, bool isTTS)
|
||||
{
|
||||
var args = new CreateMessageParams(text) { IsTTS = isTTS };
|
||||
var model = await client.ApiClient.CreateMessageAsync(channel.Id, args).ConfigureAwait(false);
|
||||
return RestUserMessage.Create(client, model);
|
||||
}
|
||||
|
||||
public static Task<RestUserMessage> SendFileAsync(IChannel channel, DiscordRestClient 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,
|
||||
Stream stream, string filename, string text, bool isTTS)
|
||||
{
|
||||
var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS };
|
||||
var model = await client.ApiClient.UploadFileAsync(channel.Id, args).ConfigureAwait(false);
|
||||
return RestUserMessage.Create(client, model);
|
||||
}
|
||||
|
||||
public static async Task DeleteMessagesAsync(IChannel channel, DiscordRestClient client,
|
||||
IEnumerable<IMessage> messages)
|
||||
{
|
||||
var args = new DeleteMessagesParams(messages.Select(x => x.Id).ToArray());
|
||||
await client.ApiClient.DeleteMessagesAsync(channel.Id, args).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//Permission Overwrites
|
||||
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient 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,
|
||||
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,
|
||||
IUser user)
|
||||
{
|
||||
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, user.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task RemovePermissionOverwriteAsync(IGuildChannel channel, DiscordRestClient client,
|
||||
IRole role)
|
||||
{
|
||||
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, role.Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//Users
|
||||
public static async Task<RestGuildUser> GetUserAsync(IGuildChannel channel, DiscordRestClient client,
|
||||
ulong id)
|
||||
{
|
||||
var model = await client.ApiClient.GetGuildMemberAsync(channel.GuildId, id);
|
||||
if (model == null)
|
||||
return null;
|
||||
var user = RestGuildUser.Create(client, model);
|
||||
if (!user.GetPermissions(channel).ReadMessages)
|
||||
return null;
|
||||
|
||||
return user;
|
||||
}
|
||||
public static IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuildChannel channel, DiscordRestClient client,
|
||||
ulong? froUserId = null, uint? limit = DiscordConfig.MaxUsersPerBatch)
|
||||
{
|
||||
return new PagedAsyncEnumerable<RestGuildUser>(
|
||||
DiscordConfig.MaxUsersPerBatch,
|
||||
async (info, ct) =>
|
||||
{
|
||||
var args = new GetGuildMembersParams
|
||||
{
|
||||
Limit = info.PageSize
|
||||
};
|
||||
if (info.Position != null)
|
||||
args.AfterUserId = info.Position.Value;
|
||||
var models = await client.ApiClient.GetGuildMembersAsync(channel.GuildId, args);
|
||||
return models.Select(x => RestGuildUser.Create(client, x)).ToImmutableArray(); ;
|
||||
},
|
||||
nextPage: (info, lastPage) =>
|
||||
{
|
||||
info.Position = lastPage.Max(x => x.Id);
|
||||
if (lastPage.Count != DiscordConfig.MaxMessagesPerBatch)
|
||||
info.Remaining = 0;
|
||||
},
|
||||
start: froUserId,
|
||||
count: limit
|
||||
);
|
||||
}
|
||||
|
||||
//Typing
|
||||
public static IDisposable EnterTypingState(IChannel channel, DiscordRestClient client)
|
||||
{
|
||||
throw new NotImplementedException(); //TODO: Impl
|
||||
}
|
||||
}
|
||||
}
|
||||
113
src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
Normal file
113
src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Channel;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestDMChannel : RestEntity<ulong>, IDMChannel, IUpdateable
|
||||
{
|
||||
public RestUser Recipient { get; }
|
||||
|
||||
public IReadOnlyCollection<RestUser> Users => ImmutableArray.Create(Discord.CurrentUser, Recipient);
|
||||
|
||||
internal RestDMChannel(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestDMChannel Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestDMChannel(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
Recipient.Update(model.Recipients.Value[0]);
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
=> Update(await ChannelHelper.GetAsync(this, Discord));
|
||||
public Task CloseAsync()
|
||||
=> ChannelHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public RestUser GetUser(ulong id)
|
||||
{
|
||||
if (id == Recipient.Id)
|
||||
return Recipient;
|
||||
else if (id == Discord.CurrentUser.Id)
|
||||
return Discord.CurrentUser;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<RestMessage> GetMessageAsync(ulong id)
|
||||
=> ChannelHelper.GetMessageAsync(this, Discord, id);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, limit: limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit);
|
||||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync()
|
||||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord);
|
||||
|
||||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS)
|
||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS);
|
||||
|
||||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages)
|
||||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages);
|
||||
|
||||
public IDisposable EnterTypingState()
|
||||
=> ChannelHelper.EnterTypingState(this, Discord);
|
||||
|
||||
public override string ToString() => $"@{Recipient}";
|
||||
private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)";
|
||||
|
||||
//IDMChannel
|
||||
IUser IDMChannel.Recipient => Recipient;
|
||||
|
||||
//IPrivateChannel
|
||||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => ImmutableArray.Create<IUser>(Recipient);
|
||||
|
||||
//IMessageChannel
|
||||
IReadOnlyCollection<IMessage> IMessageChannel.CachedMessages => ImmutableArray.Create<IMessage>();
|
||||
IMessage IMessageChannel.GetCachedMessage(ulong id) => null;
|
||||
|
||||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id)
|
||||
=> await GetMessageAsync(id);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit)
|
||||
=> GetMessagesAsync(limit);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit)
|
||||
=> GetMessagesAsync(fromMessageId, dir, limit);
|
||||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync()
|
||||
=> await GetPinnedMessagesAsync().ConfigureAwait(false);
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> await SendFileAsync(filePath, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> await SendFileAsync(stream, filename, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS)
|
||||
=> await SendMessageAsync(text, isTTS);
|
||||
IDisposable IMessageChannel.EnterTypingState()
|
||||
=> EnterTypingState();
|
||||
|
||||
//IChannel
|
||||
IReadOnlyCollection<IUser> IChannel.CachedUsers => Users;
|
||||
|
||||
IUser IChannel.GetCachedUser(ulong id)
|
||||
=> GetUser(id);
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id)
|
||||
=> Task.FromResult<IUser>(GetUser(id));
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync()
|
||||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>().ToAsyncEnumerable();
|
||||
}
|
||||
}
|
||||
125
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
Normal file
125
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Channel;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestGroupChannel : RestEntity<ulong>, IGroupChannel, IUpdateable
|
||||
{
|
||||
private string _iconId;
|
||||
private ImmutableDictionary<ulong, RestGroupUser> _users;
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<RestGroupUser> Users => _users.ToReadOnlyCollection();
|
||||
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)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestGroupChannel Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestGroupChannel(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
if (model.Name.IsSpecified)
|
||||
Name = model.Name.Value;
|
||||
if (model.Icon.IsSpecified)
|
||||
_iconId = model.Icon.Value;
|
||||
|
||||
if (model.Recipients.IsSpecified)
|
||||
UpdateUsers(model.Recipients.Value);
|
||||
}
|
||||
internal virtual void UpdateUsers(API.User[] models)
|
||||
{
|
||||
var users = ImmutableDictionary.CreateBuilder<ulong, RestGroupUser>();
|
||||
for (int i = 0; i < models.Length; i++)
|
||||
users[models[i].Id] = RestGroupUser.Create(Discord, models[i]);
|
||||
_users = users.ToImmutable();
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
=> Update(await ChannelHelper.GetAsync(this, Discord));
|
||||
public Task LeaveAsync()
|
||||
=> ChannelHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public IUser GetUser(ulong id)
|
||||
{
|
||||
RestGroupUser user;
|
||||
if (_users.TryGetValue(id, out user))
|
||||
return user;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<RestMessage> GetMessageAsync(ulong id)
|
||||
=> ChannelHelper.GetMessageAsync(this, Discord, id);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, limit: limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit);
|
||||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync()
|
||||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord);
|
||||
|
||||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS)
|
||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS);
|
||||
|
||||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages)
|
||||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages);
|
||||
|
||||
public IDisposable EnterTypingState()
|
||||
=> ChannelHelper.EnterTypingState(this, Discord);
|
||||
|
||||
//IPrivateChannel
|
||||
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => Recipients;
|
||||
|
||||
//IMessageChannel
|
||||
IReadOnlyCollection<IMessage> IMessageChannel.CachedMessages => ImmutableArray.Create<IMessage>();
|
||||
|
||||
IMessage IMessageChannel.GetCachedMessage(ulong id)
|
||||
=> null;
|
||||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id)
|
||||
=> await GetMessageAsync(id);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit)
|
||||
=> GetMessagesAsync(limit);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit)
|
||||
=> GetMessagesAsync(fromMessageId, dir, limit);
|
||||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync()
|
||||
=> await GetPinnedMessagesAsync();
|
||||
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> await SendFileAsync(filePath, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> await SendFileAsync(stream, filename, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS)
|
||||
=> await SendMessageAsync(text, isTTS);
|
||||
IDisposable IMessageChannel.EnterTypingState()
|
||||
=> EnterTypingState();
|
||||
|
||||
//IChannel
|
||||
IReadOnlyCollection<IUser> IChannel.CachedUsers => Users;
|
||||
|
||||
IUser IChannel.GetCachedUser(ulong id)
|
||||
=> GetUser(id);
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id)
|
||||
=> Task.FromResult(GetUser(id));
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync()
|
||||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable();
|
||||
}
|
||||
}
|
||||
158
src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
Normal file
158
src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using Discord.API.Rest;
|
||||
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 RestGuildChannel : RestEntity<ulong>, IGuildChannel, IUpdateable
|
||||
{
|
||||
private ImmutableArray<Overwrite> _overwrites;
|
||||
|
||||
public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites;
|
||||
|
||||
public ulong GuildId { get; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
public int Position { get; private set; }
|
||||
|
||||
internal RestGuildChannel(DiscordRestClient discord, ulong id, ulong guildId)
|
||||
: base(discord, id)
|
||||
{
|
||||
GuildId = guildId;
|
||||
}
|
||||
internal static RestGuildChannel Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
switch (model.Type)
|
||||
{
|
||||
case ChannelType.Text:
|
||||
return RestTextChannel.Create(discord, model);
|
||||
case ChannelType.Voice:
|
||||
return RestVoiceChannel.Create(discord, model);
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown guild channel type");
|
||||
}
|
||||
}
|
||||
internal virtual void Update(Model model)
|
||||
{
|
||||
Name = model.Name.Value;
|
||||
Position = model.Position.Value;
|
||||
|
||||
var overwrites = model.PermissionOverwrites.Value;
|
||||
var newOverwrites = ImmutableArray.CreateBuilder<Overwrite>(overwrites.Length);
|
||||
for (int i = 0; i < overwrites.Length; i++)
|
||||
newOverwrites.Add(new Overwrite(overwrites[i]));
|
||||
_overwrites = newOverwrites.ToImmutable();
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
=> Update(await ChannelHelper.GetAsync(this, Discord));
|
||||
public Task ModifyAsync(Action<ModifyGuildChannelParams> func)
|
||||
=> ChannelHelper.ModifyAsync(this, Discord, func);
|
||||
public Task DeleteAsync()
|
||||
=> ChannelHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IUser user)
|
||||
{
|
||||
for (int i = 0; i < _overwrites.Length; i++)
|
||||
{
|
||||
if (_overwrites[i].TargetId == user.Id)
|
||||
return _overwrites[i].Permissions;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public OverwritePermissions? GetPermissionOverwrite(IRole role)
|
||||
{
|
||||
for (int i = 0; i < _overwrites.Length; i++)
|
||||
{
|
||||
if (_overwrites[i].TargetId == role.Id)
|
||||
return _overwrites[i].Permissions;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public async Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions perms)
|
||||
{
|
||||
await ChannelHelper.AddPermissionOverwriteAsync(this, Discord, user, perms).ConfigureAwait(false);
|
||||
_overwrites = _overwrites.Add(new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = user.Id, TargetType = PermissionTarget.User }));
|
||||
}
|
||||
public async Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions perms)
|
||||
{
|
||||
await ChannelHelper.AddPermissionOverwriteAsync(this, Discord, role, perms).ConfigureAwait(false);
|
||||
_overwrites.Add(new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = role.Id, TargetType = PermissionTarget.Role }));
|
||||
}
|
||||
public async Task RemovePermissionOverwriteAsync(IUser user)
|
||||
{
|
||||
await ChannelHelper.RemovePermissionOverwriteAsync(this, Discord, user).ConfigureAwait(false);
|
||||
|
||||
for (int i = 0; i < _overwrites.Length; i++)
|
||||
{
|
||||
if (_overwrites[i].TargetId == user.Id)
|
||||
{
|
||||
_overwrites = _overwrites.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
public async Task RemovePermissionOverwriteAsync(IRole role)
|
||||
{
|
||||
await ChannelHelper.RemovePermissionOverwriteAsync(this, Discord, role).ConfigureAwait(false);
|
||||
|
||||
for (int i = 0; i < _overwrites.Length; i++)
|
||||
{
|
||||
if (_overwrites[i].TargetId == role.Id)
|
||||
{
|
||||
_overwrites = _overwrites.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync()
|
||||
=> await ChannelHelper.GetInvitesAsync(this, Discord);
|
||||
public async Task<RestInviteMetadata> CreateInviteAsync(int? maxAge = 3600, int? maxUses = null, bool isTemporary = true)
|
||||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary);
|
||||
|
||||
//IGuildChannel
|
||||
async Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync()
|
||||
=> await GetInvitesAsync();
|
||||
async Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary)
|
||||
=> await CreateInviteAsync(maxAge, maxUses, isTemporary);
|
||||
|
||||
OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IRole role)
|
||||
=> GetPermissionOverwrite(role);
|
||||
OverwritePermissions? IGuildChannel.GetPermissionOverwrite(IUser user)
|
||||
=> GetPermissionOverwrite(user);
|
||||
async Task IGuildChannel.AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions)
|
||||
=> await AddPermissionOverwriteAsync(role, permissions);
|
||||
async Task IGuildChannel.AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions)
|
||||
=> await AddPermissionOverwriteAsync(user, permissions);
|
||||
async Task IGuildChannel.RemovePermissionOverwriteAsync(IRole role)
|
||||
=> await RemovePermissionOverwriteAsync(role);
|
||||
async Task IGuildChannel.RemovePermissionOverwriteAsync(IUser user)
|
||||
=> await RemovePermissionOverwriteAsync(user);
|
||||
|
||||
IReadOnlyCollection<IGuildUser> IGuildChannel.CachedUsers
|
||||
=> ImmutableArray.Create<IGuildUser>();
|
||||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync()
|
||||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>().ToAsyncEnumerable(); //Overriden in Text/Voice //TODO: Does this actually override?
|
||||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id)
|
||||
=> Task.FromResult<IGuildUser>(null); //Overriden in Text/Voice //TODO: Does this actually override?
|
||||
IGuildUser IGuildChannel.GetCachedUser(ulong id)
|
||||
=> null;
|
||||
|
||||
//IChannel
|
||||
IReadOnlyCollection<IUser> IChannel.CachedUsers
|
||||
=> ImmutableArray.Create<IUser>();
|
||||
IUser IChannel.GetCachedUser(ulong id)
|
||||
=> null;
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync()
|
||||
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>().ToAsyncEnumerable(); //Overriden in Text/Voice //TODO: Does this actually override?
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id)
|
||||
=> Task.FromResult<IUser>(null); //Overriden in Text/Voice //TODO: Does this actually override?
|
||||
}
|
||||
}
|
||||
98
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
Normal file
98
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Channel;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestTextChannel : RestGuildChannel, ITextChannel
|
||||
{
|
||||
public string Topic { get; private set; }
|
||||
|
||||
public string Mention => MentionUtils.MentionChannel(Id);
|
||||
|
||||
internal RestTextChannel(DiscordRestClient discord, ulong id, ulong guildId)
|
||||
: base(discord, id, guildId)
|
||||
{
|
||||
}
|
||||
internal new static RestTextChannel Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestTextChannel(discord, model.Id, model.GuildId.Value);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal override void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
|
||||
Topic = model.Topic.Value;
|
||||
}
|
||||
|
||||
|
||||
public Task ModifyAsync(Action<ModifyTextChannelParams> func)
|
||||
=> ChannelHelper.ModifyAsync(this, Discord, func);
|
||||
|
||||
public Task<RestGuildUser> GetUserAsync(ulong id)
|
||||
=> ChannelHelper.GetUserAsync(this, Discord, id);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync()
|
||||
=> ChannelHelper.GetUsersAsync(this, Discord);
|
||||
|
||||
public Task<RestMessage> GetMessageAsync(ulong id)
|
||||
=> ChannelHelper.GetMessageAsync(this, Discord, id);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, limit: limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit);
|
||||
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
|
||||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit);
|
||||
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync()
|
||||
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord);
|
||||
|
||||
public Task<RestUserMessage> SendMessageAsync(string text, bool isTTS)
|
||||
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS);
|
||||
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS);
|
||||
|
||||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages)
|
||||
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages);
|
||||
|
||||
public IDisposable EnterTypingState()
|
||||
=> ChannelHelper.EnterTypingState(this, Discord);
|
||||
|
||||
//IGuildChannel
|
||||
async Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id)
|
||||
=> await GetUserAsync(id);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync()
|
||||
=> GetUsersAsync();
|
||||
|
||||
//IMessageChannel
|
||||
IReadOnlyCollection<IMessage> IMessageChannel.CachedMessages
|
||||
=> ImmutableArray.Create<IMessage>();
|
||||
IMessage IMessageChannel.GetCachedMessage(ulong id)
|
||||
=> null;
|
||||
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id)
|
||||
=> await GetMessageAsync(id);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit)
|
||||
=> GetMessagesAsync(limit);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit)
|
||||
=> GetMessagesAsync(fromMessageId, dir, limit);
|
||||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync()
|
||||
=> await GetPinnedMessagesAsync();
|
||||
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS)
|
||||
=> await SendFileAsync(filePath, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS)
|
||||
=> await SendFileAsync(stream, filename, text, isTTS);
|
||||
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS)
|
||||
=> await SendMessageAsync(text, isTTS);
|
||||
IDisposable IMessageChannel.EnterTypingState()
|
||||
=> EnterTypingState();
|
||||
}
|
||||
}
|
||||
49
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
Normal file
49
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Discord.API.Rest;
|
||||
using Discord.Audio;
|
||||
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 class RestVoiceChannel : RestGuildChannel, IVoiceChannel
|
||||
{
|
||||
public int Bitrate { get; private set; }
|
||||
public int UserLimit { get; private set; }
|
||||
|
||||
internal RestVoiceChannel(DiscordRestClient discord, ulong id, ulong guildId)
|
||||
: base(discord, id, guildId)
|
||||
{
|
||||
}
|
||||
internal new static RestVoiceChannel Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestVoiceChannel(discord, model.Id, model.GuildId.Value);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal override void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
|
||||
Bitrate = model.Bitrate.Value;
|
||||
UserLimit = model.UserLimit.Value;
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<ModifyVoiceChannelParams> func)
|
||||
=> ChannelHelper.ModifyAsync(this, Discord, func);
|
||||
|
||||
//IVoiceChannel
|
||||
Task<IAudioClient> IVoiceChannel.ConnectAsync() { throw new NotSupportedException(); }
|
||||
|
||||
//IGuildChannel
|
||||
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id)
|
||||
=> Task.FromResult<IGuildUser>(null);
|
||||
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync()
|
||||
=> ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>().ToAsyncEnumerable();
|
||||
}
|
||||
}
|
||||
183
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
Normal file
183
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Guild;
|
||||
using EmbedModel = Discord.API.GuildEmbed;
|
||||
using RoleModel = Discord.API.Role;
|
||||
using System.Linq;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class GuildHelper
|
||||
{
|
||||
//General
|
||||
public static async Task<Model> ModifyAsync(IGuild guild, DiscordRestClient client,
|
||||
Action<ModifyGuildParams> func)
|
||||
{
|
||||
if (func == null) throw new NullReferenceException(nameof(func));
|
||||
|
||||
var args = new ModifyGuildParams();
|
||||
func(args);
|
||||
|
||||
if (args.Splash.IsSpecified && guild.SplashId != null)
|
||||
args.Splash = new API.Image(guild.SplashId);
|
||||
if (args.Icon.IsSpecified && guild.IconId != null)
|
||||
args.Icon = new API.Image(guild.IconId);
|
||||
|
||||
return await client.ApiClient.ModifyGuildAsync(guild.Id, args).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task<EmbedModel> ModifyEmbedAsync(IGuild guild, DiscordRestClient client,
|
||||
Action<ModifyGuildEmbedParams> func)
|
||||
{
|
||||
if (func == null) throw new NullReferenceException(nameof(func));
|
||||
|
||||
var args = new ModifyGuildEmbedParams();
|
||||
func(args);
|
||||
return await client.ApiClient.ModifyGuildEmbedAsync(guild.Id, args).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task ModifyChannelsAsync(IGuild guild, DiscordRestClient client,
|
||||
IEnumerable<ModifyGuildChannelsParams> args)
|
||||
{
|
||||
await client.ApiClient.ModifyGuildChannelsAsync(guild.Id, args).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task<IReadOnlyCollection<RoleModel>> ModifyRolesAsync(IGuild guild, DiscordRestClient client,
|
||||
IEnumerable<ModifyGuildRolesParams> args)
|
||||
{
|
||||
return await client.ApiClient.ModifyGuildRolesAsync(guild.Id, args).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task LeaveAsync(IGuild guild, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.LeaveGuildAsync(guild.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task DeleteAsync(IGuild guild, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.DeleteGuildAsync(guild.Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//Bans
|
||||
public static async Task<IReadOnlyCollection<RestBan>> GetBansAsync(IGuild guild, DiscordRestClient 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,
|
||||
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,
|
||||
ulong userId)
|
||||
{
|
||||
await client.ApiClient.RemoveGuildBanAsync(guild.Id, userId);
|
||||
}
|
||||
|
||||
//Channels
|
||||
public static async Task<RestGuildChannel> GetChannelAsync(IGuild guild, DiscordRestClient client,
|
||||
ulong id)
|
||||
{
|
||||
var model = await client.ApiClient.GetChannelAsync(guild.Id, id).ConfigureAwait(false);
|
||||
if (model != null)
|
||||
return RestGuildChannel.Create(client, model);
|
||||
return null;
|
||||
}
|
||||
public static async Task<IReadOnlyCollection<RestGuildChannel>> GetChannelsAsync(IGuild guild, DiscordRestClient 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,
|
||||
string name)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
|
||||
var args = new CreateGuildChannelParams(name, ChannelType.Text);
|
||||
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,
|
||||
string name)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
|
||||
var args = new CreateGuildChannelParams(name, ChannelType.Voice);
|
||||
var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args).ConfigureAwait(false);
|
||||
return RestVoiceChannel.Create(client, model);
|
||||
}
|
||||
|
||||
//Integrations
|
||||
public static async Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync(IGuild guild, DiscordRestClient 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,
|
||||
ulong id, string type)
|
||||
{
|
||||
var args = new CreateGuildIntegrationParams(id, type);
|
||||
var model = await client.ApiClient.CreateGuildIntegrationAsync(guild.Id, args).ConfigureAwait(false);
|
||||
return RestGuildIntegration.Create(client, model);
|
||||
}
|
||||
|
||||
//Invites
|
||||
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuild guild, DiscordRestClient 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,
|
||||
string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
|
||||
var model = await client.ApiClient.CreateGuildRoleAsync(guild.Id).ConfigureAwait(false);
|
||||
var role = RestRole.Create(client, model);
|
||||
|
||||
await role.ModifyAsync(x =>
|
||||
{
|
||||
x.Name = name;
|
||||
x.Permissions = (permissions ?? role.Permissions).RawValue;
|
||||
x.Color = (color ?? Color.Default).RawValue;
|
||||
x.Hoist = isHoisted;
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
//Users
|
||||
public static async Task<RestGuildUser> GetUserAsync(IGuild guild, DiscordRestClient client,
|
||||
ulong id)
|
||||
{
|
||||
var model = await client.ApiClient.GetGuildMemberAsync(guild.Id, id).ConfigureAwait(false);
|
||||
if (model != null)
|
||||
return RestGuildUser.Create(client, model);
|
||||
return null;
|
||||
}
|
||||
public static async Task<RestGuildUser> GetCurrentUserAsync(IGuild guild, DiscordRestClient client)
|
||||
{
|
||||
return await GetUserAsync(guild, client, client.CurrentUser.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(IGuild guild, DiscordRestClient 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,
|
||||
int days = 30, bool simulate = false)
|
||||
{
|
||||
var args = new GuildPruneParams(days);
|
||||
GetGuildPruneCountResponse model;
|
||||
if (simulate)
|
||||
model = await client.ApiClient.GetGuildPruneCountAsync(guild.Id, args).ConfigureAwait(false);
|
||||
else
|
||||
model = await client.ApiClient.BeginGuildPruneAsync(guild.Id, args).ConfigureAwait(false);
|
||||
return model.Pruned;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/Discord.Net.Rest/Entities/Guilds/RestBan.cs
Normal file
27
src/Discord.Net.Rest/Entities/Guilds/RestBan.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.Ban;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestBan : IBan
|
||||
{
|
||||
public RestUser User { get; }
|
||||
public string Reason { get; }
|
||||
|
||||
internal RestBan(RestUser user, string reason)
|
||||
{
|
||||
User = user;
|
||||
Reason = reason;
|
||||
}
|
||||
internal static RestBan Create(DiscordRestClient client, Model model)
|
||||
{
|
||||
return new RestBan(RestUser.Create(client, model.User), model.Reason);
|
||||
}
|
||||
|
||||
public override string ToString() => User.ToString();
|
||||
private string DebuggerDisplay => $"{User}: {Reason}";
|
||||
|
||||
IUser IBan.User => User;
|
||||
}
|
||||
}
|
||||
212
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
Normal file
212
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Immutable;
|
||||
using Discord.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.API.Rest;
|
||||
using Model = Discord.API.Guild;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestGuild : RestEntity<ulong>, IGuild, IUpdateable
|
||||
{
|
||||
private ImmutableDictionary<ulong, RestRole> _roles;
|
||||
private ImmutableArray<Emoji> _emojis;
|
||||
private ImmutableArray<string> _features;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public int AFKTimeout { get; private set; }
|
||||
public bool IsEmbeddable { get; private set; }
|
||||
public VerificationLevel VerificationLevel { get; private set; }
|
||||
public MfaLevel MfaLevel { get; private set; }
|
||||
public DefaultMessageNotifications DefaultMessageNotifications { get; private set; }
|
||||
|
||||
public ulong? AFKChannelId { get; private set; }
|
||||
public ulong? EmbedChannelId { get; private set; }
|
||||
public ulong OwnerId { get; private set; }
|
||||
public string VoiceRegionId { get; private set; }
|
||||
public string IconId { get; private set; }
|
||||
public string SplashId { get; private set; }
|
||||
|
||||
public ulong DefaultChannelId => Id;
|
||||
public string IconUrl => API.CDN.GetGuildIconUrl(Id, IconId);
|
||||
public string SplashUrl => API.CDN.GetGuildSplashUrl(Id, SplashId);
|
||||
|
||||
public RestRole EveryoneRole => GetRole(Id);
|
||||
public IReadOnlyCollection<RestRole> Roles => _roles.ToReadOnlyCollection();
|
||||
public IReadOnlyCollection<Emoji> Emojis => _emojis;
|
||||
public IReadOnlyCollection<string> Features => _features;
|
||||
|
||||
internal RestGuild(DiscordRestClient client, ulong id)
|
||||
: base(client, id)
|
||||
{
|
||||
}
|
||||
internal static RestGuild Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestGuild(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
AFKChannelId = model.AFKChannelId;
|
||||
EmbedChannelId = model.EmbedChannelId;
|
||||
AFKTimeout = model.AFKTimeout;
|
||||
IsEmbeddable = model.EmbedEnabled;
|
||||
IconId = model.Icon;
|
||||
Name = model.Name;
|
||||
OwnerId = model.OwnerId;
|
||||
VoiceRegionId = model.Region;
|
||||
SplashId = model.Splash;
|
||||
VerificationLevel = model.VerificationLevel;
|
||||
MfaLevel = model.MfaLevel;
|
||||
DefaultMessageNotifications = model.DefaultMessageNotifications;
|
||||
|
||||
if (model.Emojis != null)
|
||||
{
|
||||
var emojis = ImmutableArray.CreateBuilder<Emoji>(model.Emojis.Length);
|
||||
for (int i = 0; i < model.Emojis.Length; i++)
|
||||
emojis.Add(Emoji.Create(model.Emojis[i]));
|
||||
_emojis = emojis.ToImmutableArray();
|
||||
}
|
||||
else
|
||||
_emojis = ImmutableArray.Create<Emoji>();
|
||||
|
||||
if (model.Features != null)
|
||||
_features = model.Features.ToImmutableArray();
|
||||
else
|
||||
_features = ImmutableArray.Create<string>();
|
||||
|
||||
var roles = ImmutableDictionary.CreateBuilder<ulong, RestRole>();
|
||||
if (model.Roles != null)
|
||||
{
|
||||
for (int i = 0; i < model.Roles.Length; i++)
|
||||
roles[model.Roles[i].Id] = RestRole.Create(Discord, model.Roles[i]);
|
||||
}
|
||||
_roles = roles.ToImmutable();
|
||||
}
|
||||
|
||||
//General
|
||||
public async Task UpdateAsync()
|
||||
=> Update(await Discord.ApiClient.GetGuildAsync(Id));
|
||||
public Task DeleteAsync()
|
||||
=> GuildHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public Task ModifyAsync(Action<ModifyGuildParams> func)
|
||||
=> GuildHelper.ModifyAsync(this, Discord, func);
|
||||
public Task ModifyEmbedAsync(Action<ModifyGuildEmbedParams> func)
|
||||
=> GuildHelper.ModifyEmbedAsync(this, Discord, func);
|
||||
public Task ModifyChannelsAsync(IEnumerable<ModifyGuildChannelsParams> args)
|
||||
=> GuildHelper.ModifyChannelsAsync(this, Discord, args);
|
||||
public Task ModifyRolesAsync(IEnumerable<ModifyGuildRolesParams> args)
|
||||
=> GuildHelper.ModifyRolesAsync(this, Discord, args);
|
||||
|
||||
public Task LeaveAsync()
|
||||
=> GuildHelper.LeaveAsync(this, Discord);
|
||||
|
||||
//Bans
|
||||
public Task<IReadOnlyCollection<RestBan>> GetBansAsync()
|
||||
=> GuildHelper.GetBansAsync(this, Discord);
|
||||
|
||||
public Task AddBanAsync(IUser user, int pruneDays = 0)
|
||||
=> GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays);
|
||||
public Task AddBanAsync(ulong userId, int pruneDays = 0)
|
||||
=> GuildHelper.AddBanAsync(this, Discord, userId, pruneDays);
|
||||
|
||||
public Task RemoveBanAsync(IUser user)
|
||||
=> GuildHelper.RemoveBanAsync(this, Discord, user.Id);
|
||||
public Task RemoveBanAsync(ulong userId)
|
||||
=> GuildHelper.RemoveBanAsync(this, Discord, userId);
|
||||
|
||||
//Channels
|
||||
public Task<IReadOnlyCollection<RestGuildChannel>> GetChannelsAsync()
|
||||
=> GuildHelper.GetChannelsAsync(this, Discord);
|
||||
public Task<RestGuildChannel> GetChannelAsync(ulong id)
|
||||
=> GuildHelper.GetChannelAsync(this, Discord, id);
|
||||
public Task<RestTextChannel> CreateTextChannelAsync(string name)
|
||||
=> GuildHelper.CreateTextChannelAsync(this, Discord, name);
|
||||
public Task<RestVoiceChannel> CreateVoiceChannelAsync(string name)
|
||||
=> GuildHelper.CreateVoiceChannelAsync(this, Discord, name);
|
||||
|
||||
//Integrations
|
||||
public Task<IReadOnlyCollection<RestGuildIntegration>> GetIntegrationsAsync()
|
||||
=> GuildHelper.GetIntegrationsAsync(this, Discord);
|
||||
public Task<RestGuildIntegration> CreateIntegrationAsync(ulong id, string type)
|
||||
=> GuildHelper.CreateIntegrationAsync(this, Discord, id, type);
|
||||
|
||||
//Invites
|
||||
public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync()
|
||||
=> GuildHelper.GetInvitesAsync(this, Discord);
|
||||
|
||||
//Roles
|
||||
public RestRole GetRole(ulong id)
|
||||
{
|
||||
RestRole value;
|
||||
if (_roles.TryGetValue(id, out value))
|
||||
return value;
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IRole> CreateRoleAsync(string name, GuildPermissions? permissions = default(GuildPermissions?), Color? color = default(Color?), bool isHoisted = false)
|
||||
{
|
||||
var role = await GuildHelper.CreateRoleAsync(this, Discord, name, permissions, color, isHoisted);
|
||||
_roles = _roles.Add(role.Id, role);
|
||||
return role;
|
||||
}
|
||||
|
||||
//Users
|
||||
public Task<IReadOnlyCollection<RestGuildUser>> GetUsersAsync()
|
||||
=> GuildHelper.GetUsersAsync(this, Discord);
|
||||
public Task<RestGuildUser> GetUserAsync(ulong id)
|
||||
=> GuildHelper.GetUserAsync(this, Discord, id);
|
||||
public Task<RestGuildUser> GetCurrentUserAsync()
|
||||
=> GuildHelper.GetUserAsync(this, Discord, Discord.CurrentUser.Id);
|
||||
|
||||
public Task<int> PruneUsersAsync(int days = 30, bool simulate = false)
|
||||
=> GuildHelper.PruneUsersAsync(this, Discord, days, simulate);
|
||||
|
||||
//IGuild
|
||||
bool IGuild.Available => true;
|
||||
IAudioClient IGuild.AudioClient => null;
|
||||
IReadOnlyCollection<IGuildUser> IGuild.CachedUsers => ImmutableArray.Create<IGuildUser>();
|
||||
IRole IGuild.EveryoneRole => EveryoneRole;
|
||||
IReadOnlyCollection<IRole> IGuild.Roles => Roles;
|
||||
|
||||
async Task<IReadOnlyCollection<IBan>> IGuild.GetBansAsync()
|
||||
=> await GetBansAsync();
|
||||
|
||||
async Task<IReadOnlyCollection<IGuildChannel>> IGuild.GetChannelsAsync()
|
||||
=> await GetChannelsAsync();
|
||||
async Task<IGuildChannel> IGuild.GetChannelAsync(ulong id)
|
||||
=> await GetChannelAsync(id);
|
||||
IGuildChannel IGuild.GetCachedChannel(ulong id)
|
||||
=> null;
|
||||
async Task<ITextChannel> IGuild.CreateTextChannelAsync(string name)
|
||||
=> await CreateTextChannelAsync(name);
|
||||
async Task<IVoiceChannel> IGuild.CreateVoiceChannelAsync(string name)
|
||||
=> await CreateVoiceChannelAsync(name);
|
||||
|
||||
async Task<IReadOnlyCollection<IGuildIntegration>> IGuild.GetIntegrationsAsync()
|
||||
=> await GetIntegrationsAsync();
|
||||
async Task<IGuildIntegration> IGuild.CreateIntegrationAsync(ulong id, string type)
|
||||
=> await CreateIntegrationAsync(id, type);
|
||||
|
||||
async Task<IReadOnlyCollection<IInviteMetadata>> IGuild.GetInvitesAsync()
|
||||
=> await GetInvitesAsync();
|
||||
|
||||
IRole IGuild.GetRole(ulong id)
|
||||
=> GetRole(id);
|
||||
|
||||
async Task<IReadOnlyCollection<IGuildUser>> IGuild.GetUsersAsync()
|
||||
=> await GetUsersAsync();
|
||||
async Task<IGuildUser> IGuild.GetUserAsync(ulong id)
|
||||
=> await GetUserAsync(id);
|
||||
IGuildUser IGuild.GetCachedUser(ulong id)
|
||||
=> null;
|
||||
async Task<IGuildUser> IGuild.GetCurrentUserAsync()
|
||||
=> await GetCurrentUserAsync();
|
||||
Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); }
|
||||
}
|
||||
}
|
||||
25
src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs
Normal file
25
src/Discord.Net.Rest/Entities/Guilds/RestGuildEmbed.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.GuildEmbed;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public struct RestGuildEmbed
|
||||
{
|
||||
public bool IsEnabled { get; private set; }
|
||||
public ulong? ChannelId { get; private set; }
|
||||
|
||||
internal RestGuildEmbed(bool isEnabled, ulong? channelId)
|
||||
{
|
||||
ChannelId = channelId;
|
||||
IsEnabled = isEnabled;
|
||||
}
|
||||
internal static RestGuildEmbed Create(Model model)
|
||||
{
|
||||
return new RestGuildEmbed(model.Enabled, model.ChannelId);
|
||||
}
|
||||
|
||||
public override string ToString() => ChannelId?.ToString();
|
||||
private string DebuggerDisplay => $"{ChannelId} ({(IsEnabled ? "Enabled" : "Disabled")})";
|
||||
}
|
||||
}
|
||||
77
src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs
Normal file
77
src/Discord.Net.Rest/Entities/Guilds/RestGuildIntegration.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Integration;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestGuildIntegration : RestEntity<ulong>, IGuildIntegration
|
||||
{
|
||||
private long _syncedAtTicks;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string Type { get; private set; }
|
||||
public bool IsEnabled { get; private set; }
|
||||
public bool IsSyncing { get; private set; }
|
||||
public ulong ExpireBehavior { get; private set; }
|
||||
public ulong ExpireGracePeriod { get; private set; }
|
||||
|
||||
public ulong GuildId { get; private set; }
|
||||
public ulong RoleId { get; private set; }
|
||||
public RestUser User { get; private set; }
|
||||
public IntegrationAccount Account { get; private set; }
|
||||
|
||||
public DateTimeOffset SyncedAt => DateTimeUtils.FromTicks(_syncedAtTicks);
|
||||
|
||||
internal RestGuildIntegration(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestGuildIntegration Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestGuildIntegration(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void Update(Model model)
|
||||
{
|
||||
Name = model.Name;
|
||||
Type = model.Type;
|
||||
IsEnabled = model.Enabled;
|
||||
IsSyncing = model.Syncing;
|
||||
ExpireBehavior = model.ExpireBehavior;
|
||||
ExpireGracePeriod = model.ExpireGracePeriod;
|
||||
_syncedAtTicks = model.SyncedAt.UtcTicks;
|
||||
|
||||
RoleId = model.RoleId;
|
||||
User = RestUser.Create(Discord, model.User);
|
||||
}
|
||||
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
await Discord.ApiClient.DeleteGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
|
||||
}
|
||||
public async Task ModifyAsync(Action<ModifyGuildIntegrationParams> func)
|
||||
{
|
||||
if (func == null) throw new NullReferenceException(nameof(func));
|
||||
|
||||
var args = new ModifyGuildIntegrationParams();
|
||||
func(args);
|
||||
var model = await Discord.ApiClient.ModifyGuildIntegrationAsync(GuildId, Id, args).ConfigureAwait(false);
|
||||
|
||||
Update(model);
|
||||
}
|
||||
public async Task SyncAsync()
|
||||
{
|
||||
await Discord.ApiClient.SyncGuildIntegrationAsync(GuildId, Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override string ToString() => Name;
|
||||
private string DebuggerDisplay => $"{Name} ({Id}{(IsEnabled ? ", Enabled" : "")})";
|
||||
|
||||
IUser IGuildIntegration.User => User;
|
||||
}
|
||||
}
|
||||
49
src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs
Normal file
49
src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.UserGuild;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestUserGuild : RestEntity<ulong>, ISnowflakeEntity, IUserGuild
|
||||
{
|
||||
private string _iconId;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public bool IsOwner { get; private set; }
|
||||
public GuildPermissions Permissions { get; private set; }
|
||||
|
||||
public string IconUrl => API.CDN.GetGuildIconUrl(Id, _iconId);
|
||||
|
||||
internal RestUserGuild(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestUserGuild Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestUserGuild(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void Update(Model model)
|
||||
{
|
||||
_iconId = model.Icon;
|
||||
IsOwner = model.Owner;
|
||||
Name = model.Name;
|
||||
Permissions = new GuildPermissions(model.Permissions);
|
||||
}
|
||||
|
||||
public async Task LeaveAsync()
|
||||
{
|
||||
await Discord.ApiClient.LeaveGuildAsync(Id).ConfigureAwait(false);
|
||||
}
|
||||
public async Task DeleteAsync()
|
||||
{
|
||||
await Discord.ApiClient.DeleteGuildAsync(Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override string ToString() => Name;
|
||||
private string DebuggerDisplay => $"{Name} ({Id}{(IsOwner ? ", Owned" : "")})";
|
||||
}
|
||||
}
|
||||
38
src/Discord.Net.Rest/Entities/Guilds/RestVoiceRegion.cs
Normal file
38
src/Discord.Net.Rest/Entities/Guilds/RestVoiceRegion.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Discord.Rest;
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.VoiceRegion;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
[DebuggerDisplay("{DebuggerDisplay,nq}")]
|
||||
public class RestVoiceRegion : RestEntity<string>, IVoiceRegion
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public bool IsVip { get; private set; }
|
||||
public bool IsOptimal { get; private set; }
|
||||
public string SampleHostname { get; private set; }
|
||||
public int SamplePort { get; private set; }
|
||||
|
||||
internal RestVoiceRegion(DiscordRestClient client, string id)
|
||||
: base(client, id)
|
||||
{
|
||||
}
|
||||
internal static RestVoiceRegion Create(DiscordRestClient client, Model model)
|
||||
{
|
||||
var entity = new RestVoiceRegion(client, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
Name = model.Name;
|
||||
IsVip = model.IsVip;
|
||||
IsOptimal = model.IsOptimal;
|
||||
SampleHostname = model.SampleHostname;
|
||||
SamplePort = model.SamplePort;
|
||||
}
|
||||
|
||||
public override string ToString() => Name;
|
||||
private string DebuggerDisplay => $"{Name} ({Id}{(IsVip ? ", VIP" : "")}{(IsOptimal ? ", Optimal" : "")})";
|
||||
}
|
||||
}
|
||||
21
src/Discord.Net.Rest/Entities/Invites/InviteHelper.cs
Normal file
21
src/Discord.Net.Rest/Entities/Invites/InviteHelper.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Invite;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class InviteHelper
|
||||
{
|
||||
public static async Task<Model> GetAsync(IInvite invite, DiscordRestClient client)
|
||||
{
|
||||
return await client.ApiClient.GetInviteAsync(invite.Code).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task AcceptAsync(IInvite invite, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.AcceptInviteAsync(invite.Code).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task DeleteAsync(IInvite invite, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.DeleteInviteAsync(invite.Code).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/Discord.Net.Rest/Entities/Invites/RestInvite.cs
Normal file
50
src/Discord.Net.Rest/Entities/Invites/RestInvite.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Invite;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestInvite : RestEntity<string>, IInvite, IUpdateable
|
||||
{
|
||||
public string ChannelName { get; private set; }
|
||||
public string GuildName { get; private set; }
|
||||
|
||||
public ulong ChannelId { get; private set; }
|
||||
public ulong GuildId { get; private set; }
|
||||
|
||||
public string Code => Id;
|
||||
public string Url => $"{DiscordConfig.InviteUrl}/{Code}";
|
||||
|
||||
internal RestInvite(DiscordRestClient discord, string id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestInvite Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestInvite(discord, model.Code);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
GuildId = model.Guild.Id;
|
||||
ChannelId = model.Channel.Id;
|
||||
GuildName = model.Guild.Name;
|
||||
ChannelName = model.Channel.Name;
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
=> Update(await InviteHelper.GetAsync(this, Discord).ConfigureAwait(false));
|
||||
public Task DeleteAsync()
|
||||
=> InviteHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public Task AcceptAsync()
|
||||
=> InviteHelper.AcceptAsync(this, Discord);
|
||||
|
||||
public override string ToString() => Url;
|
||||
private string DebuggerDisplay => $"{Url} ({GuildName} / {ChannelName})";
|
||||
|
||||
string IEntity<string>.Id => Code;
|
||||
}
|
||||
}
|
||||
45
src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs
Normal file
45
src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.InviteMetadata;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestInviteMetadata : RestInvite, IInviteMetadata
|
||||
{
|
||||
private long _createdAtTicks;
|
||||
|
||||
public bool IsRevoked { get; private set; }
|
||||
public bool IsTemporary { get; private set; }
|
||||
public int? MaxAge { get; private set; }
|
||||
public int? MaxUses { get; private set; }
|
||||
public int Uses { get; private set; }
|
||||
public RestUser Inviter { get; private set; }
|
||||
|
||||
public DateTimeOffset CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);
|
||||
|
||||
internal RestInviteMetadata(DiscordRestClient discord, string id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestInviteMetadata Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestInviteMetadata(discord, model.Code);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
Inviter = RestUser.Create(Discord, model.Inviter);
|
||||
IsRevoked = model.Revoked;
|
||||
IsTemporary = model.Temporary;
|
||||
MaxAge = model.MaxAge != 0 ? model.MaxAge : (int?)null;
|
||||
MaxUses = model.MaxUses;
|
||||
Uses = model.Uses;
|
||||
_createdAtTicks = model.CreatedAt.UtcTicks;
|
||||
}
|
||||
|
||||
IUser IInviteMetadata.Inviter => Inviter;
|
||||
}
|
||||
}
|
||||
33
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
Normal file
33
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class MessageHelper
|
||||
{
|
||||
public static async Task GetAsync(IMessage msg, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.GetChannelMessageAsync(msg.ChannelId, msg.Id);
|
||||
}
|
||||
public static async Task ModifyAsync(IMessage msg, DiscordRestClient 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)
|
||||
{
|
||||
await client.ApiClient.DeleteMessageAsync(msg.ChannelId, msg.Id);
|
||||
}
|
||||
|
||||
public static async Task PinAsync(IMessage msg, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.AddPinAsync(msg.ChannelId, msg.Id);
|
||||
}
|
||||
public static async Task UnpinAsync(IMessage msg, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.RemovePinAsync(msg.ChannelId, msg.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/Discord.Net.Rest/Entities/Messages/RestAttachment.cs
Normal file
32
src/Discord.Net.Rest/Entities/Messages/RestAttachment.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Model = Discord.API.Attachment;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class RestAttachment : IAttachment
|
||||
{
|
||||
public ulong Id { get; }
|
||||
public string Filename { get; }
|
||||
public string Url { get; }
|
||||
public string ProxyUrl { get; }
|
||||
public int Size { get; }
|
||||
public int? Height { get; }
|
||||
public int? Width { get; }
|
||||
|
||||
internal RestAttachment(ulong id, string filename, string url, string proxyUrl, int size, int? height, int? width)
|
||||
{
|
||||
Id = id;
|
||||
Filename = filename;
|
||||
Url = url;
|
||||
ProxyUrl = proxyUrl;
|
||||
Size = size;
|
||||
Height = height;
|
||||
Width = width;
|
||||
}
|
||||
internal static RestAttachment Create(Model model)
|
||||
{
|
||||
return new RestAttachment(model.Id, model.Filename, model.Url, model.ProxyUrl, model.Size,
|
||||
model.Height.IsSpecified ? model.Height.Value : (int?)null,
|
||||
model.Width.IsSpecified ? model.Width.Value : (int?)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/Discord.Net.Rest/Entities/Messages/RestEmbed.cs
Normal file
30
src/Discord.Net.Rest/Entities/Messages/RestEmbed.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Model = Discord.API.Embed;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class RestEmbed : IEmbed
|
||||
{
|
||||
public string Description { get; }
|
||||
public string Url { get; }
|
||||
public string Title { get; }
|
||||
public string Type { get; }
|
||||
public EmbedProvider? Provider { get; }
|
||||
public EmbedThumbnail? Thumbnail { get; }
|
||||
|
||||
internal RestEmbed(string type, string title, string description, string url, EmbedProvider? provider, EmbedThumbnail? thumbnail)
|
||||
{
|
||||
Type = type;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Url = url;
|
||||
Provider = provider;
|
||||
Thumbnail = thumbnail;
|
||||
}
|
||||
internal static RestEmbed Create(Model model)
|
||||
{
|
||||
return new RestEmbed(model.Type, model.Title, model.Description, model.Url,
|
||||
model.Provider.IsSpecified ? EmbedProvider.Create(model.Provider.Value) : (EmbedProvider?)null,
|
||||
model.Thumbnail.IsSpecified ? EmbedThumbnail.Create(model.Thumbnail.Value) : (EmbedThumbnail?)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/Discord.Net.Rest/Entities/Messages/RestMessage.cs
Normal file
61
src/Discord.Net.Rest/Entities/Messages/RestMessage.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Message;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public abstract class RestMessage : RestEntity<ulong>, IMessage, IUpdateable
|
||||
{
|
||||
private long _timestampTicks;
|
||||
|
||||
public ulong ChannelId { get; }
|
||||
public IUser Author { get; }
|
||||
|
||||
public string Content { get; private set; }
|
||||
|
||||
public virtual bool IsTTS => false;
|
||||
public virtual bool IsPinned => false;
|
||||
public virtual DateTimeOffset? EditedTimestamp => null;
|
||||
|
||||
public virtual IReadOnlyCollection<IAttachment> Attachments => ImmutableArray.Create<IAttachment>();
|
||||
public virtual IReadOnlyCollection<IEmbed> Embeds => ImmutableArray.Create<IEmbed>();
|
||||
public virtual IReadOnlyCollection<ulong> MentionedChannelIds => ImmutableArray.Create<ulong>();
|
||||
public virtual IReadOnlyCollection<IRole> MentionedRoles => ImmutableArray.Create<IRole>();
|
||||
public virtual IReadOnlyCollection<IUser> MentionedUsers => ImmutableArray.Create<IUser>();
|
||||
|
||||
public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks);
|
||||
|
||||
internal RestMessage(DiscordRestClient discord, ulong id, ulong channelId)
|
||||
: base(discord, id)
|
||||
{
|
||||
ChannelId = channelId;
|
||||
}
|
||||
internal static RestMessage Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
if (model.Type == MessageType.Default)
|
||||
return RestUserMessage.Create(discord, model);
|
||||
else
|
||||
return RestSystemMessage.Create(discord, model);
|
||||
}
|
||||
internal virtual void Update(Model model)
|
||||
{
|
||||
if (model.Timestamp.IsSpecified)
|
||||
_timestampTicks = model.Timestamp.Value.UtcTicks;
|
||||
|
||||
if (model.Content.IsSpecified)
|
||||
Content = model.Content.Value;
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
{
|
||||
var model = await Discord.ApiClient.GetChannelMessageAsync(ChannelId, Id).ConfigureAwait(false);
|
||||
Update(model);
|
||||
}
|
||||
|
||||
MessageType IMessage.Type => MessageType.Default;
|
||||
}
|
||||
}
|
||||
28
src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
Normal file
28
src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.Message;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestSystemMessage : RestMessage, ISystemMessage
|
||||
{
|
||||
public MessageType Type { get; private set; }
|
||||
|
||||
internal RestSystemMessage(DiscordRestClient discord, ulong id, ulong channelId)
|
||||
: base(discord, id, channelId)
|
||||
{
|
||||
}
|
||||
internal new static RestSystemMessage Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestSystemMessage(discord, model.Id, model.ChannelId);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal override void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
|
||||
Type = model.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
Normal file
135
src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Message;
|
||||
using Discord.API;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestUserMessage : RestMessage, IUserMessage
|
||||
{
|
||||
private bool _isMentioningEveryone, _isTTS, _isPinned;
|
||||
private long? _editedTimestampTicks;
|
||||
private ImmutableArray<RestAttachment> _attachments;
|
||||
private ImmutableArray<RestEmbed> _embeds;
|
||||
private ImmutableArray<ulong> _mentionedChannelIds;
|
||||
private ImmutableArray<RestRole> _mentionedRoles;
|
||||
private ImmutableArray<RestUser> _mentionedUsers;
|
||||
|
||||
public override bool IsTTS => _isTTS;
|
||||
public override bool IsPinned => _isPinned;
|
||||
public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks);
|
||||
|
||||
public override IReadOnlyCollection<IAttachment> Attachments => _attachments;
|
||||
public override IReadOnlyCollection<IEmbed> Embeds => _embeds;
|
||||
public override IReadOnlyCollection<ulong> MentionedChannelIds => _mentionedChannelIds;
|
||||
public override IReadOnlyCollection<IRole> MentionedRoles => _mentionedRoles;
|
||||
public override IReadOnlyCollection<IUser> MentionedUsers => _mentionedUsers;
|
||||
|
||||
internal RestUserMessage(DiscordRestClient discord, ulong id, ulong channelId)
|
||||
: base(discord, id, channelId)
|
||||
{
|
||||
}
|
||||
internal new static RestUserMessage Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestUserMessage(discord, model.Id, model.ChannelId);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
internal override void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
|
||||
if (model.IsTextToSpeech.IsSpecified)
|
||||
_isTTS = model.IsTextToSpeech.Value;
|
||||
if (model.Pinned.IsSpecified)
|
||||
_isPinned = model.Pinned.Value;
|
||||
if (model.EditedTimestamp.IsSpecified)
|
||||
_editedTimestampTicks = model.EditedTimestamp.Value?.UtcTicks;
|
||||
if (model.MentionEveryone.IsSpecified)
|
||||
_isMentioningEveryone = model.MentionEveryone.Value;
|
||||
|
||||
if (model.Attachments.IsSpecified)
|
||||
{
|
||||
var value = model.Attachments.Value;
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var attachments = ImmutableArray.CreateBuilder<RestAttachment>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
attachments.Add(RestAttachment.Create(value[i]));
|
||||
_attachments = attachments.ToImmutable();
|
||||
}
|
||||
else
|
||||
_attachments = ImmutableArray.Create<RestAttachment>();
|
||||
}
|
||||
|
||||
if (model.Embeds.IsSpecified)
|
||||
{
|
||||
var value = model.Embeds.Value;
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var embeds = ImmutableArray.CreateBuilder<RestEmbed>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
embeds.Add(RestEmbed.Create(value[i]));
|
||||
_embeds = embeds.ToImmutable();
|
||||
}
|
||||
else
|
||||
_embeds = ImmutableArray.Create<RestEmbed>();
|
||||
}
|
||||
|
||||
ImmutableArray<RestUser> mentions = ImmutableArray.Create<RestUser>();
|
||||
if (model.Mentions.IsSpecified)
|
||||
{
|
||||
var value = model.Mentions.Value;
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var newMentions = ImmutableArray.CreateBuilder<RestUser>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
newMentions.Add(RestUser.Create(Discord, value[i]));
|
||||
mentions = newMentions.ToImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
if (model.Content.IsSpecified)
|
||||
{
|
||||
var text = model.Content.Value;
|
||||
|
||||
_mentionedUsers = MentionsHelper.GetUserMentions(text, null, mentions);
|
||||
_mentionedChannelIds = MentionsHelper.GetChannelMentions(text, null);
|
||||
_mentionedRoles = MentionsHelper.GetRoleMentions<RestRole>(text, null);
|
||||
model.Content = text;
|
||||
}
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<ModifyMessageParams> func)
|
||||
=> MessageHelper.ModifyAsync(this, Discord, func);
|
||||
public Task DeleteAsync()
|
||||
=> MessageHelper.DeleteAsync(this, Discord);
|
||||
|
||||
public Task PinAsync()
|
||||
=> MessageHelper.PinAsync(this, Discord);
|
||||
public Task UnpinAsync()
|
||||
=> MessageHelper.UnpinAsync(this, Discord);
|
||||
|
||||
public string Resolve(UserMentionHandling userHandling = UserMentionHandling.Name, ChannelMentionHandling channelHandling = ChannelMentionHandling.Name,
|
||||
RoleMentionHandling roleHandling = RoleMentionHandling.Name, EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore)
|
||||
=> Resolve(Content, userHandling, channelHandling, roleHandling, everyoneHandling);
|
||||
public string Resolve(int startIndex, int length, UserMentionHandling userHandling = UserMentionHandling.Name, ChannelMentionHandling channelHandling = ChannelMentionHandling.Name,
|
||||
RoleMentionHandling roleHandling = RoleMentionHandling.Name, EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore)
|
||||
=> Resolve(Content.Substring(startIndex, length), userHandling, channelHandling, roleHandling, everyoneHandling);
|
||||
public string Resolve(string text, UserMentionHandling userHandling, ChannelMentionHandling channelHandling,
|
||||
RoleMentionHandling roleHandling, EveryoneMentionHandling everyoneHandling)
|
||||
{
|
||||
text = MentionsHelper.ResolveUserMentions(text, null, MentionedUsers, userHandling);
|
||||
text = MentionsHelper.ResolveChannelMentions(text, null, channelHandling);
|
||||
text = MentionsHelper.ResolveRoleMentions(text, MentionedRoles, roleHandling);
|
||||
text = MentionsHelper.ResolveEveryoneMentions(text, everyoneHandling);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/Discord.Net.Rest/Entities/RestApplication.cs
Normal file
49
src/Discord.Net.Rest/Entities/RestApplication.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Application;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
public class RestApplication : RestEntity<ulong>, IApplication
|
||||
{
|
||||
protected string _iconId;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string Description { get; private set; }
|
||||
public string[] RPCOrigins { get; private set; }
|
||||
public ulong Flags { get; private set; }
|
||||
|
||||
public IUser Owner { get; private set; }
|
||||
|
||||
public string IconUrl => API.CDN.GetApplicationIconUrl(Id, _iconId);
|
||||
|
||||
internal RestApplication(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestApplication Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestApplication(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
internal void Update(Model model)
|
||||
{
|
||||
Description = model.Description;
|
||||
RPCOrigins = model.RPCOrigins;
|
||||
Name = model.Name;
|
||||
Flags = model.Flags;
|
||||
Owner = RestUser.Create(Discord, model.Owner);
|
||||
_iconId = model.Icon;
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
{
|
||||
var response = await Discord.ApiClient.GetMyApplicationAsync().ConfigureAwait(false);
|
||||
if (response.Id != Id)
|
||||
throw new InvalidOperationException("Unable to update this object from a different application token.");
|
||||
Update(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Discord.Net.Rest/Entities/RestEntity.cs
Normal file
19
src/Discord.Net.Rest/Entities/RestEntity.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
public abstract class RestEntity<T> : IEntity<T>
|
||||
where T : IEquatable<T>
|
||||
{
|
||||
public T Id { get; }
|
||||
public DiscordRestClient Discord { get; }
|
||||
|
||||
public RestEntity(DiscordRestClient discord, T id)
|
||||
{
|
||||
Discord = discord;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
IDiscordClient IEntity<T>.Discord => Discord;
|
||||
}
|
||||
}
|
||||
52
src/Discord.Net.Rest/Entities/Roles/RestRole.cs
Normal file
52
src/Discord.Net.Rest/Entities/Roles/RestRole.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.Role;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestRole : RestEntity<ulong>, IRole
|
||||
{
|
||||
public RestGuild Guild { get; }
|
||||
|
||||
public Color Color { get; private set; }
|
||||
public bool IsHoisted { get; private set; }
|
||||
public bool IsManaged { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public GuildPermissions Permissions { get; private set; }
|
||||
public int Position { get; private set; }
|
||||
|
||||
public bool IsEveryone => Id == Guild.Id;
|
||||
public string Mention => MentionUtils.MentionRole(Id);
|
||||
|
||||
internal RestRole(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestRole Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestRole(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
Name = model.Name;
|
||||
IsHoisted = model.Hoist;
|
||||
IsManaged = model.Managed;
|
||||
Position = model.Position;
|
||||
Color = new Color(model.Color);
|
||||
Permissions = new GuildPermissions(model.Permissions);
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<ModifyGuildRoleParams> func)
|
||||
=> RoleHelper.ModifyAsync(this, Discord, func);
|
||||
public Task DeleteAsync()
|
||||
=> RoleHelper.DeleteAsync(this, Discord);
|
||||
|
||||
//IRole
|
||||
IGuild IRole.Guild => Guild;
|
||||
}
|
||||
}
|
||||
22
src/Discord.Net.Rest/Entities/Roles/RoleHelper.cs
Normal file
22
src/Discord.Net.Rest/Entities/Roles/RoleHelper.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class RoleHelper
|
||||
{
|
||||
//General
|
||||
public static async Task DeleteAsync(IRole role, DiscordRestClient client)
|
||||
{
|
||||
await client.ApiClient.DeleteGuildRoleAsync(role.Guild.Id, role.Id).ConfigureAwait(false);
|
||||
}
|
||||
public static async Task ModifyAsync(IRole role, DiscordRestClient client,
|
||||
Action<ModifyGuildRoleParams> func)
|
||||
{
|
||||
var args = new ModifyGuildRoleParams();
|
||||
func(args);
|
||||
await client.ApiClient.ModifyGuildRoleAsync(role.Guild.Id, role.Id, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Discord.Net.Rest/Entities/Users/RestConnection.cs
Normal file
35
src/Discord.Net.Rest/Entities/Users/RestConnection.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.Connection;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestConnection : IConnection
|
||||
{
|
||||
public string Id { get; }
|
||||
public string Type { get; }
|
||||
public string Name { get; }
|
||||
public bool IsRevoked { get; }
|
||||
|
||||
public IReadOnlyCollection<ulong> IntegrationIds { get; }
|
||||
|
||||
internal RestConnection(string id, string type, string name, bool isRevoked, IReadOnlyCollection<ulong> integrationIds)
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
Name = name;
|
||||
IsRevoked = isRevoked;
|
||||
|
||||
IntegrationIds = integrationIds;
|
||||
}
|
||||
internal static RestConnection Create(Model model)
|
||||
{
|
||||
return new RestConnection(model.Id, model.Type, model.Name, model.Revoked, model.Integrations.ToImmutableArray());
|
||||
}
|
||||
|
||||
public override string ToString() => Name;
|
||||
private string DebuggerDisplay => $"{Name} ({Id}, Type = {Type}{(IsRevoked ? ", Revoked" : "")})";
|
||||
}
|
||||
}
|
||||
29
src/Discord.Net.Rest/Entities/Users/RestGroupUser.cs
Normal file
29
src/Discord.Net.Rest/Entities/Users/RestGroupUser.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Diagnostics;
|
||||
using Model = Discord.API.User;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestGroupUser : RestUser, IGroupUser
|
||||
{
|
||||
internal RestGroupUser(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal new static RestGroupUser Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestGroupUser(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
//IVoiceState
|
||||
bool IVoiceState.IsDeafened => false;
|
||||
bool IVoiceState.IsMuted => false;
|
||||
bool IVoiceState.IsSelfDeafened => false;
|
||||
bool IVoiceState.IsSelfMuted => false;
|
||||
bool IVoiceState.IsSuppressed => false;
|
||||
IVoiceChannel IVoiceState.VoiceChannel => null;
|
||||
string IVoiceState.VoiceSessionId => null;
|
||||
}
|
||||
}
|
||||
74
src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
Normal file
74
src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.GuildMember;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestGuildUser : RestUser, IGuildUser, IUpdateable
|
||||
{
|
||||
private long? _joinedAtTicks;
|
||||
private ImmutableArray<ulong> _roleIds;
|
||||
|
||||
public string Nickname { get; private set; }
|
||||
public ulong GuildId { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<ulong> RoleIds => _roleIds;
|
||||
|
||||
public DateTimeOffset? JoinedAt => DateTimeUtils.FromTicks(_joinedAtTicks);
|
||||
|
||||
internal RestGuildUser(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestGuildUser Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestGuildUser(discord, model.User.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal void Update(Model model)
|
||||
{
|
||||
_joinedAtTicks = model.JoinedAt.UtcTicks;
|
||||
if (model.Nick.IsSpecified)
|
||||
Nickname = model.Nick.Value;
|
||||
UpdateRoles(model.Roles);
|
||||
}
|
||||
private void UpdateRoles(ulong[] roleIds)
|
||||
{
|
||||
var roles = ImmutableArray.CreateBuilder<ulong>(roleIds.Length + 1);
|
||||
roles.Add(GuildId);
|
||||
for (int i = 0; i < roleIds.Length; i++)
|
||||
roles.Add(roleIds[i]);
|
||||
_roleIds = roles.ToImmutable();
|
||||
}
|
||||
|
||||
public override async Task UpdateAsync()
|
||||
=> Update(await UserHelper.GetAsync(this, Discord));
|
||||
public Task ModifyAsync(Action<ModifyGuildMemberParams> func)
|
||||
=> UserHelper.ModifyAsync(this, Discord, func);
|
||||
public Task KickAsync()
|
||||
=> UserHelper.KickAsync(this, Discord);
|
||||
|
||||
public ChannelPermissions GetPermissions(IGuildChannel channel)
|
||||
{
|
||||
throw new NotImplementedException(); //TODO: Impl
|
||||
}
|
||||
|
||||
//IGuildUser
|
||||
IReadOnlyCollection<ulong> IGuildUser.RoleIds => RoleIds;
|
||||
|
||||
//IVoiceState
|
||||
bool IVoiceState.IsDeafened => false;
|
||||
bool IVoiceState.IsMuted => false;
|
||||
bool IVoiceState.IsSelfDeafened => false;
|
||||
bool IVoiceState.IsSelfMuted => false;
|
||||
bool IVoiceState.IsSuppressed => false;
|
||||
IVoiceChannel IVoiceState.VoiceChannel => null;
|
||||
string IVoiceState.VoiceSessionId => null;
|
||||
}
|
||||
}
|
||||
45
src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
Normal file
45
src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.User;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestSelfUser : RestUser, ISelfUser
|
||||
{
|
||||
public string Email { get; private set; }
|
||||
public bool IsVerified { get; private set; }
|
||||
public bool IsMfaEnabled { get; private set; }
|
||||
|
||||
internal RestSelfUser(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal new static RestSelfUser Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestSelfUser(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal override void Update(Model model)
|
||||
{
|
||||
base.Update(model);
|
||||
|
||||
if (model.Email.IsSpecified)
|
||||
Email = model.Email.Value;
|
||||
if (model.Verified.IsSpecified)
|
||||
IsVerified = model.Verified.Value;
|
||||
if (model.MfaEnabled.IsSpecified)
|
||||
IsMfaEnabled = model.MfaEnabled.Value;
|
||||
}
|
||||
|
||||
public override async Task UpdateAsync()
|
||||
=> Update(await UserHelper.GetAsync(this, Discord));
|
||||
public Task ModifyAsync(Action<ModifyCurrentUserParams> func)
|
||||
=> UserHelper.ModifyAsync(this, Discord, func);
|
||||
|
||||
Task ISelfUser.ModifyStatusAsync(Action<ModifyPresenceParams> func) { throw new NotSupportedException(); }
|
||||
}
|
||||
}
|
||||
51
src/Discord.Net.Rest/Entities/Users/RestUser.cs
Normal file
51
src/Discord.Net.Rest/Entities/Users/RestUser.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.User;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
public class RestUser : RestEntity<ulong>, IUser, IUpdateable
|
||||
{
|
||||
public bool IsBot { get; private set; }
|
||||
public string Username { get; private set; }
|
||||
public ushort DiscriminatorValue { get; private set; }
|
||||
public string AvatarId { get; private set; }
|
||||
|
||||
public string AvatarUrl => API.CDN.GetUserAvatarUrl(Id, AvatarId);
|
||||
public string Discriminator => DiscriminatorValue.ToString("D4");
|
||||
public string Mention => MentionUtils.MentionUser(Id);
|
||||
public virtual Game? Game => null;
|
||||
public virtual UserStatus Status => UserStatus.Unknown;
|
||||
|
||||
internal RestUser(DiscordRestClient discord, ulong id)
|
||||
: base(discord, id)
|
||||
{
|
||||
}
|
||||
internal static RestUser Create(DiscordRestClient discord, Model model)
|
||||
{
|
||||
var entity = new RestUser(discord, model.Id);
|
||||
entity.Update(model);
|
||||
return entity;
|
||||
}
|
||||
internal virtual void Update(Model model)
|
||||
{
|
||||
if (model.Avatar.IsSpecified)
|
||||
AvatarId = model.Avatar.Value;
|
||||
if (model.Discriminator.IsSpecified)
|
||||
DiscriminatorValue = ushort.Parse(model.Discriminator.Value);
|
||||
if (model.Bot.IsSpecified)
|
||||
IsBot = model.Bot.Value;
|
||||
if (model.Username.IsSpecified)
|
||||
Username = model.Username.Value;
|
||||
}
|
||||
|
||||
public virtual async Task UpdateAsync()
|
||||
=> Update(await UserHelper.GetAsync(this, Discord));
|
||||
|
||||
public Task<IDMChannel> CreateDMChannelAsync()
|
||||
=> UserHelper.CreateDMChannelAsync(this, Discord);
|
||||
|
||||
IDMChannel IUser.GetCachedDMChannel() => null;
|
||||
}
|
||||
}
|
||||
53
src/Discord.Net.Rest/Entities/Users/UserHelper.cs
Normal file
53
src/Discord.Net.Rest/Entities/Users/UserHelper.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Discord.API.Rest;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.User;
|
||||
using MemberModel = Discord.API.GuildMember;
|
||||
using System;
|
||||
|
||||
namespace Discord.Rest
|
||||
{
|
||||
internal static class UserHelper
|
||||
{
|
||||
public static async Task<Model> GetAsync(IUser user, DiscordRestClient client)
|
||||
{
|
||||
return await client.ApiClient.GetUserAsync(user.Id);
|
||||
}
|
||||
public static async Task<Model> GetAsync(ISelfUser user, DiscordRestClient 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)
|
||||
{
|
||||
return await client.ApiClient.GetGuildMemberAsync(user.GuildId, user.Id);
|
||||
}
|
||||
public static async Task ModifyAsync(ISelfUser user, DiscordRestClient client, Action<ModifyCurrentUserParams> func)
|
||||
{
|
||||
if (user.Id != client.CurrentUser.Id)
|
||||
throw new InvalidOperationException("Unable to modify this object using a different token.");
|
||||
|
||||
var args = new ModifyCurrentUserParams();
|
||||
func(args);
|
||||
await client.ApiClient.ModifySelfAsync(args);
|
||||
}
|
||||
public static async Task ModifyAsync(IGuildUser user, DiscordRestClient 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)
|
||||
{
|
||||
await client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id);
|
||||
}
|
||||
|
||||
public static async Task<IDMChannel> CreateDMChannelAsync(IUser user, DiscordRestClient client)
|
||||
{
|
||||
var args = new CreateDMChannelParams(user.Id);
|
||||
return RestDMChannel.Create(client, await client.ApiClient.CreateDMChannelAsync(args));
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Discord.Net.Rest/Properties/AssemblyInfo.cs
Normal file
19
src/Discord.Net.Rest/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Discord.Net.Rest")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bfc6dc28-0351-4573-926a-d4124244c04f")]
|
||||
39
src/Discord.Net.Rest/project.json
Normal file
39
src/Discord.Net.Rest/project.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"buildOptions": {
|
||||
"compile": {
|
||||
"include": [ "../Discord.Net.Utils/**.cs" ]
|
||||
},
|
||||
"define": [ "REST" ]
|
||||
},
|
||||
|
||||
"configurations": {
|
||||
"Release": {
|
||||
"buildOptions": {
|
||||
"define": [ "RELEASE" ],
|
||||
"nowarn": [ "CS1573", "CS1591" ],
|
||||
"optimize": true,
|
||||
"warningsAsErrors": true,
|
||||
"xmlDoc": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"Discord.Net.Core": {
|
||||
"target": "project"
|
||||
},
|
||||
"NETStandard.Library": "1.6.0"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandard1.3": {
|
||||
"imports": [
|
||||
"dotnet5.4",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user