Added missing files
This commit is contained in:
@@ -1,15 +1,32 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord.API.Converters
|
||||
{
|
||||
public class LongStringEnumerableConverter : JsonConverter
|
||||
public class LongStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IEnumerable<ulong>);
|
||||
}
|
||||
public override bool CanConvert(Type objectType)
|
||||
=> objectType == typeof(ulong);
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
=> IdConvert.ToLong((string)reader.Value);
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
=> writer.WriteValue(IdConvert.ToString((ulong)value));
|
||||
}
|
||||
|
||||
public class NullableLongStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
=> objectType == typeof(ulong?);
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
=> IdConvert.ToNullableLong((string)reader.Value);
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
=> writer.WriteValue(IdConvert.ToString((ulong?)value));
|
||||
}
|
||||
|
||||
/*public class LongStringEnumerableConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(IEnumerable<ulong>);
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
List<ulong> result = new List<ulong>();
|
||||
@@ -36,14 +53,11 @@ namespace Discord.API.Converters
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
internal class LongStringArrayConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(IEnumerable<ulong[]>);
|
||||
}
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(IEnumerable<ulong[]>);
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var result = new List<ulong>();
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Converters
|
||||
{
|
||||
public class LongStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(ulong);
|
||||
}
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
return IdConvert.ToLong((string)reader.Value);
|
||||
}
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(IdConvert.ToString((ulong)value));
|
||||
}
|
||||
}
|
||||
|
||||
public class NullableLongStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(ulong?);
|
||||
}
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
return IdConvert.ToNullableLong((string)reader.Value);
|
||||
}
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(IdConvert.ToString((ulong?)value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
namespace Discord.API
|
||||
{
|
||||
public static class Endpoints
|
||||
{
|
||||
public const string BaseStatusApi = "https://status.discordapp.com/api/v2/";
|
||||
public const string BaseApi = "https://discordapp.com/api/";
|
||||
public const string BaseCdn = "https://cdn.discordapp.com/";
|
||||
|
||||
public const string Gateway = "gateway";
|
||||
|
||||
public const string Auth = "auth";
|
||||
public const string AuthLogin = "auth/login";
|
||||
public const string AuthLogout = "auth/logout";
|
||||
|
||||
public const string Channels = "channels";
|
||||
public static string Channel(ulong channelId) => $"channels/{channelId}";
|
||||
public static string ChannelInvites(ulong channelId) => $"channels/{channelId}/invites";
|
||||
public static string ChannelMessages(ulong channelId) => $"channels/{channelId}/messages";
|
||||
public static string ChannelMessages(ulong channelId, int limit) => $"channels/{channelId}/messages?limit={limit}";
|
||||
public static string ChannelMessages(ulong channelId, int limit, ulong relativeId, string relativeDir) => $"channels/{channelId}/messages?limit={limit}&{relativeDir}={relativeId}";
|
||||
public static string ChannelMessage(ulong channelId, ulong msgId) => $"channels/{channelId}/messages/{msgId}";
|
||||
public static string ChannelMessageAck(ulong channelId, ulong msgId) => $"channels/{channelId}/messages/{msgId}/ack";
|
||||
public static string ChannelPermission(ulong channelId, ulong userOrRoleId) => $"channels/{channelId}/permissions/{userOrRoleId}";
|
||||
public static string ChannelTyping(ulong channelId) => $"channels/{channelId}/typing";
|
||||
|
||||
public const string Servers = "guilds";
|
||||
public static string Server(ulong serverId) => $"guilds/{serverId}";
|
||||
public static string ServerBan(ulong serverId, ulong userId) => $"guilds/{serverId}/bans/{userId}";
|
||||
public static string ServerChannels(ulong serverId) => $"guilds/{serverId}/channels";
|
||||
public static string ServerInvites(ulong serverId) => $"guilds/{serverId}/invites";
|
||||
public static string ServerMember(ulong serverId, ulong userId) => $"guilds/{serverId}/members/{userId}";
|
||||
public static string ServerPrune(ulong serverId, int days) => $"guilds/{serverId}/prune?days={days}";
|
||||
public static string ServerRoles(ulong serverId) => $"guilds/{serverId}/roles";
|
||||
public static string ServerRole(ulong serverId, ulong roleId) => $"guilds/{serverId}/roles/{roleId}";
|
||||
public static string ServerIcon(ulong serverId, string iconId) => BaseCdn + $"icons/{serverId}/{iconId}.jpg";
|
||||
|
||||
public const string Invites = "invite";
|
||||
public static string Invite(ulong inviteId) => $"invite/{inviteId}";
|
||||
public static string Invite(string inviteIdOrXkcd) => $"invite/{inviteIdOrXkcd}";
|
||||
public static string InviteUrl(ulong inviteId) => $"https://discord.gg/{inviteId}";
|
||||
public static string InviteUrl(string inviteIdOrXkcd) => $"https://discord.gg/{inviteIdOrXkcd}";
|
||||
|
||||
public const string Users = "users";
|
||||
public static string UserMe => $"users/@me";
|
||||
public static string UserChannels(ulong userId) => $"users/{userId}/channels";
|
||||
public static string UserAvatar(ulong serverId, string avatarId) => BaseCdn + $"avatars/{serverId}/{avatarId}.jpg";
|
||||
|
||||
public const string Voice = "voice";
|
||||
public const string VoiceRegions = "voice/regions";
|
||||
|
||||
public const string StatusActiveMaintenance = "scheduled-maintenances/active.json";
|
||||
public const string StatusUpcomingMaintenance = "scheduled-maintenances/upcoming.json";
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
using Discord.API;
|
||||
using Discord.Net.Rest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public enum RelativeDirection { Before, After }
|
||||
|
||||
/// <summary> A lightweight wrapper around the Discord API. </summary>
|
||||
public class DiscordAPIClient
|
||||
{
|
||||
public static readonly string Version = DiscordClient.Version;
|
||||
|
||||
private readonly DiscordConfig _config;
|
||||
|
||||
internal RestClient RestClient => _rest;
|
||||
private readonly RestClient _rest;
|
||||
|
||||
public DiscordAPIClient(DiscordConfig config = null, Logger logger = null)
|
||||
{
|
||||
_config = config ?? new DiscordConfig();
|
||||
_rest = new RestClient(_config, logger);
|
||||
}
|
||||
|
||||
private string _token;
|
||||
public string Token
|
||||
{
|
||||
get { return _token; }
|
||||
set { _token = value; _rest.SetToken(value); }
|
||||
}
|
||||
private CancellationToken _cancelToken;
|
||||
public CancellationToken CancelToken
|
||||
{
|
||||
get { return _cancelToken; }
|
||||
set { _cancelToken = value; _rest.SetCancelToken(value); }
|
||||
}
|
||||
|
||||
//Auth
|
||||
public Task<GatewayResponse> Gateway()
|
||||
=> _rest.Get<GatewayResponse>(Endpoints.Gateway);
|
||||
public async Task<LoginResponse> Login(string email, string password)
|
||||
{
|
||||
if (email == null) throw new ArgumentNullException(nameof(email));
|
||||
if (password == null) throw new ArgumentNullException(nameof(password));
|
||||
|
||||
var request = new LoginRequest { Email = email, Password = password };
|
||||
return await _rest.Post<LoginResponse>(Endpoints.AuthLogin, request).ConfigureAwait(false);
|
||||
}
|
||||
public Task Logout()
|
||||
=> _rest.Post(Endpoints.AuthLogout);
|
||||
|
||||
//Channels
|
||||
public Task<CreateChannelResponse> CreateChannel(ulong serverId, string name, string channelType)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (channelType == null) throw new ArgumentNullException(nameof(channelType));
|
||||
|
||||
var request = new CreateChannelRequest { Name = name, Type = channelType };
|
||||
return _rest.Post<CreateChannelResponse>(Endpoints.ServerChannels(serverId), request);
|
||||
}
|
||||
public Task<CreateChannelResponse> CreatePMChannel(ulong myId, ulong recipientId)
|
||||
{
|
||||
var request = new CreatePMChannelRequest { RecipientId = recipientId };
|
||||
return _rest.Post<CreateChannelResponse>(Endpoints.UserChannels(myId), request);
|
||||
}
|
||||
public Task<DestroyChannelResponse> DestroyChannel(ulong channelId)
|
||||
{
|
||||
return _rest.Delete<DestroyChannelResponse>(Endpoints.Channel(channelId));
|
||||
}
|
||||
public Task<EditChannelResponse> EditChannel(ulong channelId, string name = null, string topic = null)
|
||||
{
|
||||
var request = new EditChannelRequest { Name = name, Topic = topic };
|
||||
return _rest.Patch<EditChannelResponse>(Endpoints.Channel(channelId), request);
|
||||
}
|
||||
public Task ReorderChannels(ulong serverId, IEnumerable<ulong> channelIds, int startPos = 0)
|
||||
{
|
||||
if (channelIds == null) throw new ArgumentNullException(nameof(channelIds));
|
||||
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
||||
|
||||
uint pos = (uint)startPos;
|
||||
var channels = channelIds.Select(x => new ReorderChannelsRequest.Channel { Id = x, Position = pos++ });
|
||||
var request = new ReorderChannelsRequest(channels);
|
||||
return _rest.Patch(Endpoints.ServerChannels(serverId), request);
|
||||
}
|
||||
public Task<GetMessagesResponse> GetMessages(ulong channelId, int count, ulong? relativeMessageId = null, RelativeDirection relativeDir = RelativeDirection.Before)
|
||||
{
|
||||
if (relativeMessageId != null)
|
||||
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count, relativeMessageId.Value, relativeDir == RelativeDirection.Before ? "before" : "after"));
|
||||
else
|
||||
return _rest.Get<GetMessagesResponse>(Endpoints.ChannelMessages(channelId, count));
|
||||
}
|
||||
|
||||
//Incidents
|
||||
public Task<GetIncidentsResponse> GetActiveIncidents()
|
||||
{
|
||||
return _rest.Get<GetIncidentsResponse>(Endpoints.StatusActiveMaintenance);
|
||||
}
|
||||
public Task<GetIncidentsResponse> GetUpcomingIncidents()
|
||||
{
|
||||
return _rest.Get<GetIncidentsResponse>(Endpoints.StatusUpcomingMaintenance);
|
||||
}
|
||||
|
||||
//Invites
|
||||
public Task<CreateInviteResponse> CreateInvite(ulong channelId, int maxAge, int maxUses, bool tempMembership, bool hasXkcd)
|
||||
{
|
||||
var request = new CreateInviteRequest { MaxAge = maxAge, MaxUses = maxUses, IsTemporary = tempMembership, WithXkcdPass = hasXkcd };
|
||||
return _rest.Post<CreateInviteResponse>(Endpoints.ChannelInvites(channelId), request);
|
||||
}
|
||||
public Task<GetInviteResponse> GetInvite(string inviteIdOrXkcd)
|
||||
{
|
||||
if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd));
|
||||
|
||||
return _rest.Get<GetInviteResponse>(Endpoints.Invite(inviteIdOrXkcd));
|
||||
}
|
||||
public Task<GetInvitesResponse> GetInvites(ulong serverId)
|
||||
{
|
||||
return _rest.Get<GetInvitesResponse>(Endpoints.ServerInvites(serverId));
|
||||
}
|
||||
public Task<AcceptInviteResponse> AcceptInvite(string inviteId)
|
||||
{
|
||||
if (inviteId == null) throw new ArgumentNullException(nameof(inviteId));
|
||||
|
||||
return _rest.Post<AcceptInviteResponse>(Endpoints.Invite(inviteId));
|
||||
}
|
||||
public Task DeleteInvite(string inviteId)
|
||||
{
|
||||
if (inviteId == null) throw new ArgumentNullException(nameof(inviteId));
|
||||
|
||||
return _rest.Delete(Endpoints.Invite(inviteId));
|
||||
}
|
||||
|
||||
//Users
|
||||
public Task EditUser(ulong serverId, ulong userId, bool? mute = null, bool? deaf = null, ulong? voiceChannelId = null, IEnumerable<ulong> roleIds = null)
|
||||
{
|
||||
var request = new EditMemberRequest { Mute = mute, Deaf = deaf, ChannelId = voiceChannelId, Roles = roleIds };
|
||||
return _rest.Patch(Endpoints.ServerMember(serverId, userId), request);
|
||||
}
|
||||
public Task KickUser(ulong serverId, ulong userId)
|
||||
{
|
||||
return _rest.Delete(Endpoints.ServerMember(serverId, userId));
|
||||
}
|
||||
public Task BanUser(ulong serverId, ulong userId)
|
||||
{
|
||||
return _rest.Put(Endpoints.ServerBan(serverId, userId));
|
||||
}
|
||||
public Task UnbanUser(ulong serverId, ulong userId)
|
||||
{
|
||||
return _rest.Delete(Endpoints.ServerBan(serverId, userId));
|
||||
}
|
||||
public Task<PruneUsersResponse> PruneUsers(ulong serverId, int days, bool simulate)
|
||||
{
|
||||
if (simulate)
|
||||
return _rest.Get<PruneUsersResponse>(Endpoints.ServerPrune(serverId, days));
|
||||
else
|
||||
return _rest.Post<PruneUsersResponse>(Endpoints.ServerPrune(serverId, days));
|
||||
}
|
||||
|
||||
//Messages
|
||||
public Task<SendMessageResponse> SendMessage(ulong channelId, string message, IEnumerable<ulong> mentionedUserIds = null, string nonce = null, bool isTTS = false)
|
||||
{
|
||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||
|
||||
var request = new SendMessageRequest { Content = message, Mentions = mentionedUserIds ?? new ulong[0], Nonce = nonce, IsTTS = isTTS ? true : false };
|
||||
return _rest.Post<SendMessageResponse>(Endpoints.ChannelMessages(channelId), request);
|
||||
}
|
||||
public Task<SendMessageResponse> SendFile(ulong channelId, string filename, Stream stream)
|
||||
{
|
||||
if (filename == null) throw new ArgumentNullException(nameof(filename));
|
||||
if (stream == null) throw new ArgumentNullException(nameof(stream));
|
||||
|
||||
return _rest.PostFile<SendMessageResponse>(Endpoints.ChannelMessages(channelId), filename, stream);
|
||||
}
|
||||
public Task DeleteMessage(ulong messageId, ulong channelId)
|
||||
{
|
||||
return _rest.Delete(Endpoints.ChannelMessage(channelId, messageId));
|
||||
}
|
||||
public Task<EditMessageResponse> EditMessage(ulong messageId, ulong channelId, string message = null, IEnumerable<ulong> mentionedUserIds = null)
|
||||
{
|
||||
var request = new EditMessageRequest { Content = message, Mentions = mentionedUserIds };
|
||||
return _rest.Patch<EditMessageResponse>(Endpoints.ChannelMessage(channelId, messageId), request);
|
||||
}
|
||||
public Task AckMessage(ulong messageId, ulong channelId)
|
||||
{
|
||||
return _rest.Post(Endpoints.ChannelMessageAck(channelId, messageId));
|
||||
}
|
||||
public Task SendIsTyping(ulong channelId)
|
||||
{
|
||||
return _rest.Post(Endpoints.ChannelTyping(channelId));
|
||||
}
|
||||
|
||||
//Permissions
|
||||
public Task SetChannelPermissions(ulong channelId, ulong userOrRoleId, string idType, uint allow = 0, uint deny = 0)
|
||||
{
|
||||
if (idType == null) throw new ArgumentNullException(nameof(idType));
|
||||
|
||||
var request = new SetChannelPermissionsRequest { Id = userOrRoleId, Type = idType, Allow = allow, Deny = deny };
|
||||
return _rest.Put(Endpoints.ChannelPermission(channelId, userOrRoleId), request);
|
||||
}
|
||||
public Task DeleteChannelPermissions(ulong channelId, ulong userOrRoleId)
|
||||
{
|
||||
return _rest.Delete(Endpoints.ChannelPermission(channelId, userOrRoleId), null);
|
||||
}
|
||||
|
||||
//Roles
|
||||
public Task<RoleInfo> CreateRole(ulong serverId)
|
||||
{
|
||||
return _rest.Post<RoleInfo>(Endpoints.ServerRoles(serverId));
|
||||
}
|
||||
public Task DeleteRole(ulong serverId, ulong roleId)
|
||||
{
|
||||
return _rest.Delete(Endpoints.ServerRole(serverId, roleId));
|
||||
}
|
||||
public Task<RoleInfo> EditRole(ulong serverId, ulong roleId, string name = null, uint? permissions = null, uint? color = null, bool? hoist = null)
|
||||
{
|
||||
var request = new EditRoleRequest { Name = name, Permissions = permissions, Hoist = hoist, Color = color };
|
||||
return _rest.Patch<RoleInfo>(Endpoints.ServerRole(serverId, roleId), request);
|
||||
}
|
||||
public Task ReorderRoles(ulong serverId, IEnumerable<ulong> roleIds, int startPos = 0)
|
||||
{
|
||||
if (roleIds == null) throw new ArgumentNullException(nameof(roleIds));
|
||||
if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer.");
|
||||
|
||||
uint pos = (uint)startPos;
|
||||
var roles = roleIds.Select(x => new ReorderRolesRequest.Role { Id = x, Position = pos++ });
|
||||
var request = new ReorderRolesRequest(roles);
|
||||
return _rest.Patch(Endpoints.ServerRoles(serverId), request);
|
||||
}
|
||||
|
||||
//Servers
|
||||
public Task<CreateServerResponse> CreateServer(string name, string region)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (region == null) throw new ArgumentNullException(nameof(region));
|
||||
|
||||
var request = new CreateServerRequest { Name = name, Region = region };
|
||||
return _rest.Post<CreateServerResponse>(Endpoints.Servers, request);
|
||||
}
|
||||
public Task LeaveServer(ulong serverId)
|
||||
{
|
||||
return _rest.Delete<DeleteServerResponse>(Endpoints.Server(serverId));
|
||||
}
|
||||
public Task<EditServerResponse> EditServer(ulong serverId, string name, string region,
|
||||
Stream icon, ImageType iconType, string existingIcon,
|
||||
ulong? afkChannelId, int afkTimeout)
|
||||
{
|
||||
var request = new EditServerRequest {
|
||||
Name = name,
|
||||
Region = region,
|
||||
Icon = Base64Picture(icon, iconType, existingIcon),
|
||||
AFKChannelId = afkChannelId,
|
||||
AFKTimeout = afkTimeout
|
||||
};
|
||||
return _rest.Patch<EditServerResponse>(Endpoints.Server(serverId), request);
|
||||
}
|
||||
|
||||
//User
|
||||
public Task<EditUserResponse> EditProfile(string currentPassword,
|
||||
string username, string email, string password,
|
||||
Stream avatar, ImageType avatarType, string existingAvatar)
|
||||
{
|
||||
if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword));
|
||||
|
||||
var request = new EditUserRequest { CurrentPassword = currentPassword, Username = username,
|
||||
Email = email, Password = password, Avatar = Base64Picture(avatar, avatarType, existingAvatar) };
|
||||
return _rest.Patch<EditUserResponse>(Endpoints.UserMe, request);
|
||||
}
|
||||
|
||||
//Voice
|
||||
public Task<GetRegionsResponse> GetVoiceRegions()
|
||||
=> _rest.Get<GetRegionsResponse>(Endpoints.VoiceRegions);
|
||||
|
||||
private string Base64Picture(Stream stream, ImageType type, string existingId)
|
||||
{
|
||||
if (type == ImageType.None)
|
||||
return null;
|
||||
else if (stream != null)
|
||||
{
|
||||
byte[] bytes = new byte[stream.Length - stream.Position];
|
||||
stream.Read(bytes, 0, bytes.Length);
|
||||
|
||||
string base64 = Convert.ToBase64String(bytes);
|
||||
string imageType = type == ImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64";
|
||||
return $"data:{imageType},{base64}";
|
||||
}
|
||||
return existingId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
using Discord.API;
|
||||
using Discord.API.Client.GatewaySocket;
|
||||
using Discord.API.Client.Rest;
|
||||
using Discord.Net;
|
||||
using Discord.Net.Rest;
|
||||
using Discord.Net.WebSockets;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -53,8 +53,6 @@ namespace Discord
|
||||
/// <summary> Provides a connection to the DiscordApp service. </summary>
|
||||
public partial class DiscordClient
|
||||
{
|
||||
public static readonly string Version = typeof(DiscordClient).GetTypeInfo().Assembly.GetName().Version.ToString(3);
|
||||
|
||||
private readonly LogService _log;
|
||||
private readonly Logger _logger, _restLogger, _cacheLogger;
|
||||
private readonly Dictionary<Type, object> _singletons;
|
||||
@@ -63,7 +61,6 @@ namespace Discord
|
||||
private readonly ManualResetEvent _disconnectedEvent;
|
||||
private readonly ManualResetEventSlim _connectedEvent;
|
||||
private readonly TaskManager _taskManager;
|
||||
private bool _sentInitialLog;
|
||||
private UserStatus _status;
|
||||
private int? _gameId;
|
||||
|
||||
@@ -76,8 +73,8 @@ namespace Discord
|
||||
private ConnectionState _state;
|
||||
|
||||
/// <summary> Gives direct access to the underlying DiscordAPIClient. This can be used to modify objects not in cache. </summary>
|
||||
public DiscordAPIClient APIClient => _api;
|
||||
private readonly DiscordAPIClient _api;
|
||||
public RestClient Rest => _rest;
|
||||
private readonly RestClient _rest;
|
||||
|
||||
/// <summary> Returns the internal websocket object. </summary>
|
||||
public GatewaySocket WebSocket => _webSocket;
|
||||
@@ -145,8 +142,11 @@ namespace Discord
|
||||
_cacheLogger = CreateCacheLogger();
|
||||
|
||||
//Networking
|
||||
_webSocket = new GatewaySocket(this, _log.CreateLogger("WebSocket"));
|
||||
var settings = new JsonSerializerSettings();
|
||||
_restLogger = CreateRestLogger();
|
||||
_rest = new RestClient(_config, _restLogger);
|
||||
|
||||
var webSocketLogger = _log.CreateLogger("WebSocket");
|
||||
_webSocket = new GatewaySocket(this, webSocketLogger);
|
||||
_webSocket.Connected += (s, e) =>
|
||||
{
|
||||
if (_state == ConnectionState.Connecting)
|
||||
@@ -156,18 +156,15 @@ namespace Discord
|
||||
{
|
||||
RaiseDisconnected(e);
|
||||
};
|
||||
|
||||
_webSocket.ReceivedDispatch += (s, e) => OnReceivedEvent(e);
|
||||
|
||||
_api = new DiscordAPIClient(_config);
|
||||
|
||||
if (Config.UseMessageQueue)
|
||||
_pendingMessages = new ConcurrentQueue<MessageQueueItem>();
|
||||
Connected += async (s, e) =>
|
||||
{
|
||||
_api.CancelToken = _cancelToken;
|
||||
_rest.SetCancelToken(_cancelToken);
|
||||
await SendStatus().ConfigureAwait(false);
|
||||
};
|
||||
_restLogger = CreateRestLogger();
|
||||
|
||||
//Import/Export
|
||||
_messageImporter = new JsonSerializer();
|
||||
@@ -216,7 +213,7 @@ namespace Discord
|
||||
if (_log.Level >= LogSeverity.Verbose)
|
||||
{
|
||||
logger = _log.CreateLogger("Rest");
|
||||
_api.RestClient.OnRequest += (s, e) =>
|
||||
_rest.OnRequest += (s, e) =>
|
||||
{
|
||||
if (e.Payload != null)
|
||||
logger.Verbose( $"{e.Method} {e.Path}: {Math.Round(e.ElapsedMilliseconds, 2)} ms ({e.Payload})");
|
||||
@@ -280,9 +277,6 @@ namespace Discord
|
||||
_lock.WaitOne();
|
||||
try
|
||||
{
|
||||
if (!_sentInitialLog)
|
||||
SendInitialLog();
|
||||
|
||||
if (State != ConnectionState.Disconnected)
|
||||
await Disconnect().ConfigureAwait(false);
|
||||
await _taskManager.Stop().ConfigureAwait(false);
|
||||
@@ -347,7 +341,8 @@ namespace Discord
|
||||
token = LoadToken(tokenPath, key);
|
||||
if (token == null)
|
||||
{
|
||||
var response = await _api.Login(email, password).ConfigureAwait(false);
|
||||
var request = new LoginRequest() { Email = email, Password = password };
|
||||
var response = await _rest.Send(request).ConfigureAwait(false);
|
||||
token = response.Token;
|
||||
SaveToken(tokenPath, key, token);
|
||||
useCache = false;
|
||||
@@ -355,17 +350,18 @@ namespace Discord
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = await _api.Login(email, password).ConfigureAwait(false);
|
||||
var request = new LoginRequest() { Email = email, Password = password };
|
||||
var response = await _rest.Send(request).ConfigureAwait(false);
|
||||
token = response.Token;
|
||||
}
|
||||
}
|
||||
_token = token;
|
||||
_api.Token = token;
|
||||
_rest.SetToken(token);
|
||||
|
||||
//Get gateway and check token
|
||||
try
|
||||
{
|
||||
var gatewayResponse = await _api.Gateway().ConfigureAwait(false);
|
||||
var gatewayResponse = await _rest.Send(new GatewayRequest()).ConfigureAwait(false);
|
||||
var gateway = gatewayResponse.Url;
|
||||
_gateway = gateway;
|
||||
if (_config.LogLevel >= LogSeverity.Verbose)
|
||||
@@ -399,7 +395,7 @@ namespace Discord
|
||||
while (_pendingMessages.TryDequeue(out ignored)) { }
|
||||
}
|
||||
|
||||
await _api.Logout().ConfigureAwait(false);
|
||||
await _rest.Send(new LogoutRequest()).ConfigureAwait(false);
|
||||
|
||||
_channels.Clear();
|
||||
_users.Clear();
|
||||
@@ -528,7 +524,7 @@ namespace Discord
|
||||
//Members
|
||||
case "GUILD_MEMBER_ADD":
|
||||
{
|
||||
var data = e.Payload.ToObject<MemberAddEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildMemberAddEvent>(_webSocket.Serializer);
|
||||
var user = _users.GetOrAdd(data.User.Id, data.GuildId);
|
||||
user.Update(data);
|
||||
user.UpdateActivity();
|
||||
@@ -537,7 +533,7 @@ namespace Discord
|
||||
break;
|
||||
case "GUILD_MEMBER_UPDATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<MemberUpdateEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildMemberUpdateEvent>(_webSocket.Serializer);
|
||||
var user = _users[data.User.Id, data.GuildId];
|
||||
if (user != null)
|
||||
{
|
||||
@@ -548,7 +544,7 @@ namespace Discord
|
||||
break;
|
||||
case "GUILD_MEMBER_REMOVE":
|
||||
{
|
||||
var data = e.Payload.ToObject<MemberRemoveEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildMemberRemoveEvent>(_webSocket.Serializer);
|
||||
var user = _users.TryRemove(data.User.Id, data.GuildId);
|
||||
if (user != null)
|
||||
RaiseUserLeft(user);
|
||||
@@ -556,7 +552,7 @@ namespace Discord
|
||||
break;
|
||||
case "GUILD_MEMBERS_CHUNK":
|
||||
{
|
||||
var data = e.Payload.ToObject<MembersChunkEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildMembersChunkEvent>(_webSocket.Serializer);
|
||||
foreach (var memberData in data.Members)
|
||||
{
|
||||
var user = _users.GetOrAdd(memberData.User.Id, memberData.GuildId);
|
||||
@@ -569,7 +565,7 @@ namespace Discord
|
||||
//Roles
|
||||
case "GUILD_ROLE_CREATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<RoleCreateEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildRoleCreateEvent>(_webSocket.Serializer);
|
||||
var role = _roles.GetOrAdd(data.Data.Id, data.GuildId);
|
||||
role.Update(data.Data);
|
||||
var server = _servers[data.GuildId];
|
||||
@@ -580,7 +576,7 @@ namespace Discord
|
||||
break;
|
||||
case "GUILD_ROLE_UPDATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<RoleUpdateEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildRoleUpdateEvent>(_webSocket.Serializer);
|
||||
var role = _roles[data.Data.Id];
|
||||
if (role != null)
|
||||
{
|
||||
@@ -591,7 +587,7 @@ namespace Discord
|
||||
break;
|
||||
case "GUILD_ROLE_DELETE":
|
||||
{
|
||||
var data = e.Payload.ToObject<RoleDeleteEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildRoleDeleteEvent>(_webSocket.Serializer);
|
||||
var role = _roles.TryRemove(data.RoleId);
|
||||
if (role != null)
|
||||
{
|
||||
@@ -606,25 +602,23 @@ namespace Discord
|
||||
//Bans
|
||||
case "GUILD_BAN_ADD":
|
||||
{
|
||||
var data = e.Payload.ToObject<BanAddEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildBanAddEvent>(_webSocket.Serializer);
|
||||
var server = _servers[data.GuildId];
|
||||
if (server != null)
|
||||
{
|
||||
var id = data.User?.Id ?? data.UserId;
|
||||
server.AddBan(id);
|
||||
RaiseUserBanned(id, server);
|
||||
server.AddBan(data.UserId);
|
||||
RaiseUserBanned(data.UserId, server);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "GUILD_BAN_REMOVE":
|
||||
{
|
||||
var data = e.Payload.ToObject<BanRemoveEvent>(_webSocket.Serializer);
|
||||
var data = e.Payload.ToObject<GuildBanRemoveEvent>(_webSocket.Serializer);
|
||||
var server = _servers[data.GuildId];
|
||||
if (server != null)
|
||||
{
|
||||
var id = data.User?.Id ?? data.UserId;
|
||||
if (server.RemoveBan(id))
|
||||
RaiseUserUnbanned(id, server);
|
||||
if (server.RemoveBan(data.UserId))
|
||||
RaiseUserUnbanned(data.UserId, server);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -689,7 +683,7 @@ namespace Discord
|
||||
case "MESSAGE_ACK":
|
||||
{
|
||||
var data = e.Payload.ToObject<MessageAckEvent>(_webSocket.Serializer);
|
||||
var msg = GetMessage(data.MessageId);
|
||||
var msg = _messages[data.MessageId];
|
||||
if (msg != null)
|
||||
RaiseMessageAcknowledged(msg);
|
||||
}
|
||||
@@ -727,8 +721,8 @@ namespace Discord
|
||||
//Voice
|
||||
case "VOICE_STATE_UPDATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<MemberVoiceStateUpdateEvent>(_webSocket.Serializer);
|
||||
var user = _users[data.UserId, data.GuildId];
|
||||
var data = e.Payload.ToObject<VoiceStateUpdateEvent>(_webSocket.Serializer);
|
||||
var user = _users[data.User.Id, data.GuildId];
|
||||
if (user != null)
|
||||
{
|
||||
/*var voiceChannel = user.VoiceChannel;
|
||||
@@ -779,13 +773,6 @@ namespace Discord
|
||||
}
|
||||
}
|
||||
|
||||
private void SendInitialLog()
|
||||
{
|
||||
if (_config.LogLevel >= LogSeverity.Verbose)
|
||||
_logger.Verbose( $"Config: {JsonConvert.SerializeObject(_config)}");
|
||||
_sentInitialLog = true;
|
||||
}
|
||||
|
||||
#region Async Wrapper
|
||||
/// <summary> Blocking call that will not return until client has been stopped. This is mainly intended for use in console applications. </summary>
|
||||
public void Run(Func<Task> asyncAction)
|
||||
@@ -946,5 +933,21 @@ namespace Discord
|
||||
_logger.Warning("Failed to cache token", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Base64Image(ImageType type, Stream stream, string existingId)
|
||||
{
|
||||
if (type == ImageType.None)
|
||||
return null;
|
||||
else if (stream != null)
|
||||
{
|
||||
byte[] bytes = new byte[stream.Length - stream.Position];
|
||||
stream.Read(bytes, 0, bytes.Length);
|
||||
|
||||
string base64 = Convert.ToBase64String(bytes);
|
||||
string imageType = type == ImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64";
|
||||
return $"data:{imageType},{base64}";
|
||||
}
|
||||
return existingId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Discord
|
||||
@@ -35,18 +36,28 @@ namespace Discord
|
||||
|
||||
public class DiscordConfig : BaseConfig<DiscordConfig>
|
||||
{
|
||||
//Global
|
||||
public static string LibName => "Discord.Net";
|
||||
public static string LibVersion => typeof(DiscordClient).GetTypeInfo().Assembly.GetName().Version.ToString(3);
|
||||
public static string LibUrl => "https://github.com/RogueException/Discord.Net";
|
||||
|
||||
/// <summary> Specifies the minimum log level severity that will be sent to the LogMessage event. Warning: setting this to debug will really hurt performance but should help investigate any internal issues. </summary>
|
||||
public LogSeverity LogLevel { get { return _logLevel; } set { SetValue(ref _logLevel, value); } }
|
||||
private LogSeverity _logLevel = LogSeverity.Info;
|
||||
public static string ClientAPIUrl => "https://discordapp.com/api/";
|
||||
public static string StatusAPIUrl => "https://status.discordapp.com/api/v2/";
|
||||
public static string CDNUrl => "https://cdn.discordapp.com/";
|
||||
public static string InviteUrl => "https://discord.gg/";
|
||||
|
||||
/// <summary> Name of your application. </summary>
|
||||
public string AppName { get { return _appName; } set { SetValue(ref _appName, value); UpdateUserAgent(); } }
|
||||
//Global
|
||||
|
||||
/// <summary> Name of your application. </summary>
|
||||
public string AppName { get { return _appName; } set { SetValue(ref _appName, value); UpdateUserAgent(); } }
|
||||
private string _appName = null;
|
||||
/// <summary> Version of your application. </summary>
|
||||
public string AppVersion { get { return _appVersion; } set { SetValue(ref _appVersion, value); UpdateUserAgent(); } }
|
||||
private string _appVersion = null;
|
||||
|
||||
/// <summary> Specifies the minimum log level severity that will be sent to the LogMessage event. Warning: setting this to debug will really hurt performance but should help investigate any internal issues. </summary>
|
||||
public LogSeverity LogLevel { get { return _logLevel; } set { SetValue(ref _logLevel, value); } }
|
||||
private LogSeverity _logLevel = LogSeverity.Info;
|
||||
|
||||
/// <summary> User Agent string to use when connecting to Discord. </summary>
|
||||
[JsonIgnore]
|
||||
public string UserAgent { get { return _userAgent; } }
|
||||
@@ -114,7 +125,7 @@ namespace Discord
|
||||
}
|
||||
builder.Append(' ');
|
||||
}
|
||||
builder.Append($"DiscordBot (https://github.com/RogueException/Discord.Net, v{DiscordClient.Version})");
|
||||
builder.Append($"DiscordBot ({LibUrl}, v{LibVersion})");
|
||||
_userAgent = builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +106,7 @@ namespace Discord.Net.WebSockets
|
||||
RaiseBinaryMessage(e.Data);
|
||||
}
|
||||
|
||||
public IEnumerable<Task> GetTasks(CancellationToken cancelToken)
|
||||
{
|
||||
return new Task[]
|
||||
{
|
||||
SendAsync(cancelToken)
|
||||
};
|
||||
}
|
||||
public IEnumerable<Task> GetTasks(CancellationToken cancelToken) => new Task[] { SendAsync(cancelToken) };
|
||||
|
||||
private Task SendAsync(CancellationToken cancelToken)
|
||||
{
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<StyleCopSettings Version="105" />
|
||||
Reference in New Issue
Block a user