* Initial error parsing * Implement better errors * Add missing error codes * Add voice disconnect opcodes * Remove unused class, add summaries to discordjsonerror, and remove public constructor of slash command properties * Add error code summary * Update error message summary * Update src/Discord.Net.Core/DiscordJsonError.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Update src/Discord.Net.WebSocket/API/Voice/VoiceCloseCode.cs Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com> * Fix autocomplete result value Co-authored-by: Jared L <48422312+lhjt@users.noreply.github.com>pull/1923/head
@@ -0,0 +1,197 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// Represents a set of json error codes received by discord. | |||||
/// </summary> | |||||
public enum DiscordErrorCode | |||||
{ | |||||
GeneralError = 0, | |||||
#region UnknownXYZ (10XXX) | |||||
UnknownAccount = 10001, | |||||
UnknownApplication = 10002, | |||||
UnknownChannel = 10003, | |||||
UnknownGuild = 10004, | |||||
UnknownIntegration = 10005, | |||||
UnknownInvite = 10006, | |||||
UnknownMember = 10007, | |||||
UnknownMessage = 10008, | |||||
UnknownPermissionOverwrite = 10009, | |||||
UnknownProvider = 10010, | |||||
UnknownRole = 10011, | |||||
UnknownToken = 10012, | |||||
UnknownUser = 10013, | |||||
UnknownEmoji = 10014, | |||||
UnknownWebhook = 10015, | |||||
UnknownWebhookService = 10016, | |||||
UnknownSession = 10020, | |||||
UnknownBan = 10026, | |||||
UnknownSKU = 10027, | |||||
UnknownStoreListing = 10028, | |||||
UnknownEntitlement = 10029, | |||||
UnknownBuild = 10030, | |||||
UnknownLobby = 10031, | |||||
UnknownBranch = 10032, | |||||
UnknownStoreDirectoryLayout = 10033, | |||||
UnknownRedistributable = 10036, | |||||
UnknownGiftCode = 10038, | |||||
UnknownStream = 10049, | |||||
UnknownPremiumServerSubscribeCooldown = 10050, | |||||
UnknownGuildTemplate = 10057, | |||||
UnknownDiscoverableServerCategory = 10059, | |||||
UnknownSticker = 10060, | |||||
UnknownInteraction = 10062, | |||||
UnknownApplicationCommand = 10063, | |||||
UnknownApplicationCommandPermissions = 10066, | |||||
UnknownStageInstance = 10067, | |||||
UnknownGuildMemberVerificationForm = 10068, | |||||
UnknownGuildWelcomeScreen = 10069, | |||||
UnknownGuildScheduledEvent = 10070, | |||||
UnknownGuildScheduledEventUser = 10071, | |||||
#endregion | |||||
#region General Actions (20XXX) | |||||
BotsCannotUse = 20001, | |||||
OnlyBotsCanUse = 20002, | |||||
CannotSendExplicitContent = 20009, | |||||
ApplicationActionUnauthorized = 20012, | |||||
ActionSlowmode = 20016, | |||||
OnlyOwnerAction = 20018, | |||||
AnnouncementEditRatelimit = 20022, | |||||
ChannelWriteRatelimit = 20028, | |||||
WordsNotAllowed = 20031, | |||||
GuildPremiumTooLow = 20035, | |||||
#endregion | |||||
#region Numeric Limits Reached (30XXX) | |||||
MaximumGuildsReached = 30001, | |||||
MaximumFriendsReached = 30002, | |||||
MaximumPinsReached = 30003, | |||||
MaximumRecipientsReached = 30004, | |||||
MaximumGuildRolesReached = 30005, | |||||
MaximumWebhooksReached = 30007, | |||||
MaximumEmojisReached = 30008, | |||||
MaximumReactionsReached = 30010, | |||||
MaximumGuildChannelsReached = 30013, | |||||
MaximumAttachmentsReached = 30015, | |||||
MaximumInvitesReached = 30016, | |||||
MaximumAnimatedEmojisReached = 30018, | |||||
MaximumServerMembersReached = 30019, | |||||
MaximumServerCategoriesReached = 30030, | |||||
GuildTemplateAlreadyExists = 30031, | |||||
MaximumThreadMembersReached = 30033, | |||||
MaximumBansForNonGuildMembersReached = 30035, | |||||
MaximumBanFetchesReached = 30037, | |||||
MaximumUncompleteGuildScheduledEvents = 30038, | |||||
MaximumStickersReached = 30039, | |||||
MaximumPruneRequestReached = 30040, | |||||
MaximumGuildWigitsReached = 30042, | |||||
#endregion | |||||
#region General Request Errors (40XXX) | |||||
TokenUnauthorized = 40001, | |||||
InvalidVerification = 40002, | |||||
OpeningDMTooFast = 40003, | |||||
RequestEntityTooLarge = 40005, | |||||
FeatureDisabled = 40006, | |||||
UserBanned = 40007, | |||||
TargetUserNotInVoice = 40032, | |||||
MessageAlreadyCrossposted = 40033, | |||||
ApplicationNameAlreadyExists = 40041, | |||||
#endregion | |||||
#region Action Preconditions/Checks (50XXX) | |||||
MissingPermissions = 50001, | |||||
InvalidAccountType = 50002, | |||||
CannotExecuteForDM = 50003, | |||||
GuildWigitDisabled = 50004, | |||||
CannotEditOtherUsersMessage = 50005, | |||||
CannotSendEmptyMessage = 50006, | |||||
CannotSendMessageToUser = 50007, | |||||
CannotSendMessageToVoiceChannel = 50008, | |||||
ChannelVerificationTooHight = 50009, | |||||
OAuth2ApplicationDoesntHaveBot = 50010, | |||||
OAuth2ApplicationLimitReached = 50011, | |||||
InvalidOAuth2State = 50012, | |||||
InsufficientPermissions = 50013, | |||||
InvalidAuthenticationToken = 50014, | |||||
NoteTooLong = 50015, | |||||
ProvidedMessageDeleteCountOutOfBounds = 50016, | |||||
InvalidPinChannel = 50019, | |||||
InvalidInvite = 50020, | |||||
CannotExecuteOnSystemMessage = 50021, | |||||
CannotExecuteOnChannelType = 50024, | |||||
InvalidOAuth2Token = 50025, | |||||
MissingOAuth2Scope = 50026, | |||||
InvalidWebhookToken = 50027, | |||||
InvalidRole = 50028, | |||||
InvalidRecipients = 50033, | |||||
BulkDeleteMessageTooOld = 50034, | |||||
InvalidFormBody = 50035, | |||||
InviteAcceptedForGuildThatBotIsntIn = 50036, | |||||
InvalidAPIVersion = 50041, | |||||
FileUploadTooBig = 50045, | |||||
InvalidFileUpload = 50046, | |||||
CannotSelfRedeemGift = 50054, | |||||
PaymentSourceRequiredForGift = 50070, | |||||
CannotDeleteRequiredCommunityChannel = 50074, | |||||
InvalidSticker = 50081, | |||||
CannotExecuteOnArchivedThread = 50083, | |||||
InvalidThreadNotificationSettings = 50084, | |||||
BeforeValueEarlierThanThreadCreation = 50085, | |||||
ServerLocaleUnavailable = 50095, | |||||
ServerRequiresMonetization = 50097, | |||||
ServerRequiresBoosts = 50101, | |||||
#endregion | |||||
#region 2FA (60XXX) | |||||
Requires2FA = 60003, | |||||
#endregion | |||||
#region User Searches (80XXX) | |||||
NoUsersWithTag = 80004, | |||||
#endregion | |||||
#region Reactions (90XXX) | |||||
ReactionBlocked = 90001, | |||||
#endregion | |||||
#region API Status (130XXX) | |||||
APIOverloaded = 130000, | |||||
#endregion | |||||
#region Stage Errors (150XXX) | |||||
StageAlreadyOpened = 150006, | |||||
#endregion | |||||
#region Reply and Thread Errors (160XXX) | |||||
CannotReplyWithoutReadMessageHistory = 160002, | |||||
MessageAlreadyContainsThread = 160004, | |||||
ThreadIsLocked = 160005, | |||||
MaximumActiveThreadsReached = 160006, | |||||
MaximumAnnouncementThreadsReached = 160007, | |||||
#endregion | |||||
#region Sticker Uploads (170XXX) | |||||
InvalidJSONLottie = 170001, | |||||
LottieCantContainRasters = 170002, | |||||
StickerMaximumFramerateExceeded = 170003, | |||||
StickerMaximumFrameCountExceeded = 170004, | |||||
LottieMaximumDimentionsExceeded = 170005, | |||||
StickerFramerateBoundsExceeed = 170006, | |||||
StickerAnimationDurationTooLong = 170007, | |||||
#endregion | |||||
#region Guild Scheduled Events | |||||
CannotUpdateFinishedEvent = 180000, | |||||
FailedStageCreation = 180002, | |||||
#endregion | |||||
} | |||||
} |
@@ -0,0 +1,53 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord | |||||
{ | |||||
/// <summary> | |||||
/// Represents a generic parsed json error received from discord after performing a rest request. | |||||
/// </summary> | |||||
public struct DiscordJsonError | |||||
{ | |||||
/// <summary> | |||||
/// Gets the json path of the error. | |||||
/// </summary> | |||||
public string Path { get; } | |||||
/// <summary> | |||||
/// Gets a collection of errors associated with the specific property at the path. | |||||
/// </summary> | |||||
public IReadOnlyCollection<DiscordError> Errors { get; } | |||||
internal DiscordJsonError(string path, DiscordError[] errors) | |||||
{ | |||||
Path = path; | |||||
Errors = errors.ToImmutableArray(); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// Represents an error with a property. | |||||
/// </summary> | |||||
public struct DiscordError | |||||
{ | |||||
/// <summary> | |||||
/// Gets the code of the error. | |||||
/// </summary> | |||||
public string Code { get; } | |||||
/// <summary> | |||||
/// Gets the message describing what went wrong. | |||||
/// </summary> | |||||
public string Message { get; } | |||||
internal DiscordError(string code, string message) | |||||
{ | |||||
Code = code; | |||||
Message = message; | |||||
} | |||||
} | |||||
} |
@@ -1,60 +1,15 @@ | |||||
using System; | using System; | ||||
using System.Linq; | |||||
namespace Discord.Net | namespace Discord.Net | ||||
{ | { | ||||
public class ApplicationCommandException : Exception | |||||
[Obsolete("Please use HttpException instead of this. Will be removed in next major version.", false)] | |||||
public class ApplicationCommandException : HttpException | |||||
{ | { | ||||
/// <summary> | |||||
/// Gets the JSON error code returned by Discord. | |||||
/// </summary> | |||||
/// <returns> | |||||
/// A | |||||
/// <see href="https://discord.com/developers/docs/topics/opcodes-and-status-codes#json">JSON error code</see> | |||||
/// from Discord, or <c>null</c> if none. | |||||
/// </returns> | |||||
public int? DiscordCode { get; } | |||||
/// <summary> | |||||
/// Gets the reason of the exception. | |||||
/// </summary> | |||||
public string Reason { get; } | |||||
/// <summary> | |||||
/// Gets the request object used to send the request. | |||||
/// </summary> | |||||
public IRequest Request { get; } | |||||
/// <summary> | |||||
/// The error object returned from discord. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// Note: This object can be null if discord didn't provide it. | |||||
/// </remarks> | |||||
public object Error { get; } | |||||
/// <summary> | |||||
/// The request json used to create the application command. This is useful for checking your commands for any format errors. | |||||
/// </summary> | |||||
public string RequestJson { get; } | |||||
/// <summary> | |||||
/// The underlying <see cref="HttpException"/> that caused this exception to be thrown. | |||||
/// </summary> | |||||
public HttpException InnerHttpException { get; } | |||||
/// <summary> | |||||
/// Initializes a new instance of the <see cref="ApplicationCommandException" /> class. | |||||
/// </summary> | |||||
/// <param name="requestJson"></param> | |||||
/// <param name="httpError"></param> | |||||
public ApplicationCommandException(string requestJson, HttpException httpError) | |||||
: base("The application command failed to be created!", httpError) | |||||
public ApplicationCommandException(HttpException httpError) | |||||
: base(httpError.HttpCode, httpError.Request, httpError.DiscordCode, httpError.Reason, httpError.Errors.ToArray()) | |||||
{ | { | ||||
Request = httpError.Request; | |||||
DiscordCode = httpError.DiscordCode; | |||||
Reason = httpError.Reason; | |||||
Error = httpError.Error; | |||||
RequestJson = requestJson; | |||||
InnerHttpException = httpError; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,4 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Collections.Immutable; | |||||
using System.Net; | using System.Net; | ||||
namespace Discord.Net | namespace Discord.Net | ||||
@@ -25,7 +27,7 @@ namespace Discord.Net | |||||
/// <see href="https://discord.com/developers/docs/topics/opcodes-and-status-codes#json">JSON error code</see> | /// <see href="https://discord.com/developers/docs/topics/opcodes-and-status-codes#json">JSON error code</see> | ||||
/// from Discord, or <c>null</c> if none. | /// from Discord, or <c>null</c> if none. | ||||
/// </returns> | /// </returns> | ||||
public int? DiscordCode { get; } | |||||
public DiscordErrorCode? DiscordCode { get; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets the reason of the exception. | /// Gets the reason of the exception. | ||||
/// </summary> | /// </summary> | ||||
@@ -35,12 +37,9 @@ namespace Discord.Net | |||||
/// </summary> | /// </summary> | ||||
public IRequest Request { get; } | public IRequest Request { get; } | ||||
/// <summary> | /// <summary> | ||||
/// The error object returned from discord. | |||||
/// Gets a collection of json errors describing what went wrong with the request. | |||||
/// </summary> | /// </summary> | ||||
/// <remarks> | |||||
/// Note: This object can be null if discord didn't provide it. | |||||
/// </remarks> | |||||
public object Error { get; } | |||||
public IReadOnlyCollection<DiscordJsonError> Errors { get; } | |||||
/// <summary> | /// <summary> | ||||
/// Initializes a new instance of the <see cref="HttpException" /> class. | /// Initializes a new instance of the <see cref="HttpException" /> class. | ||||
@@ -49,14 +48,14 @@ namespace Discord.Net | |||||
/// <param name="request">The request that was sent prior to the exception.</param> | /// <param name="request">The request that was sent prior to the exception.</param> | ||||
/// <param name="discordCode">The Discord status code returned.</param> | /// <param name="discordCode">The Discord status code returned.</param> | ||||
/// <param name="reason">The reason behind the exception.</param> | /// <param name="reason">The reason behind the exception.</param> | ||||
public HttpException(HttpStatusCode httpCode, IRequest request, int? discordCode = null, string reason = null, object errors = null) | |||||
: base(CreateMessage(httpCode, discordCode, reason)) | |||||
public HttpException(HttpStatusCode httpCode, IRequest request, DiscordErrorCode? discordCode = null, string reason = null, DiscordJsonError[] errors = null) | |||||
: base(CreateMessage(httpCode, (int?)discordCode, reason)) | |||||
{ | { | ||||
HttpCode = httpCode; | HttpCode = httpCode; | ||||
Request = request; | Request = request; | ||||
DiscordCode = discordCode; | DiscordCode = discordCode; | ||||
Reason = reason; | Reason = reason; | ||||
Error = errors; | |||||
Errors = errors?.ToImmutableArray() ?? ImmutableArray<DiscordJsonError>.Empty; | |||||
} | } | ||||
private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string reason = null) | private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string reason = null) | ||||
@@ -0,0 +1,20 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.API | |||||
{ | |||||
[JsonConverter(typeof(Discord.Net.Converters.DiscordErrorConverter))] | |||||
internal class DiscordError | |||||
{ | |||||
[JsonProperty("message")] | |||||
public string Message { get; set; } | |||||
[JsonProperty("code")] | |||||
public DiscordErrorCode Code { get; set; } | |||||
[JsonProperty("errors")] | |||||
public Optional<ErrorDetails[]> Errors { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,12 @@ | |||||
using Newtonsoft.Json; | |||||
namespace Discord.API | |||||
{ | |||||
internal class Error | |||||
{ | |||||
[JsonProperty("code")] | |||||
public string Code { get; set; } | |||||
[JsonProperty("message")] | |||||
public string Message { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using Newtonsoft.Json; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.API | |||||
{ | |||||
internal class ErrorDetails | |||||
{ | |||||
[JsonProperty("name")] | |||||
public Optional<string> Name { get; set; } | |||||
[JsonProperty("errors")] | |||||
public Error[] Errors { get; set; } | |||||
} | |||||
} |
@@ -2235,7 +2235,7 @@ namespace Discord.API | |||||
if (x.HttpCode == HttpStatusCode.BadRequest) | if (x.HttpCode == HttpStatusCode.BadRequest) | ||||
{ | { | ||||
var json = (x.Request as JsonRestRequest).Json; | var json = (x.Request as JsonRestRequest).Json; | ||||
throw new ApplicationCommandException(json, x); | |||||
throw new ApplicationCommandException(x); | |||||
} | } | ||||
} | } | ||||
@@ -2249,7 +2249,7 @@ namespace Discord.API | |||||
if (x.HttpCode == HttpStatusCode.BadRequest) | if (x.HttpCode == HttpStatusCode.BadRequest) | ||||
{ | { | ||||
var json = (x.Request as JsonRestRequest).Json; | var json = (x.Request as JsonRestRequest).Json; | ||||
throw new ApplicationCommandException(json, x); | |||||
throw new ApplicationCommandException(x); | |||||
} | } | ||||
throw; | throw; | ||||
@@ -12,8 +12,8 @@ namespace Discord.Net.Converters | |||||
{ | { | ||||
#region DiscordContractResolver | #region DiscordContractResolver | ||||
private static readonly TypeInfo _ienumerable = typeof(IEnumerable<ulong[]>).GetTypeInfo(); | private static readonly TypeInfo _ienumerable = typeof(IEnumerable<ulong[]>).GetTypeInfo(); | ||||
private static readonly MethodInfo _shouldSerialize = typeof(DiscordContractResolver).GetTypeInfo().GetDeclaredMethod("ShouldSerialize"); | |||||
private static readonly MethodInfo _shouldSerialize = typeof(DiscordContractResolver).GetTypeInfo().GetDeclaredMethod("ShouldSerialize"); | |||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) | protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) | ||||
{ | { | ||||
var property = base.CreateProperty(member, memberSerialization); | var property = base.CreateProperty(member, memberSerialization); | ||||
@@ -58,7 +58,7 @@ namespace Discord.Net.Converters | |||||
else if (genericType == typeof(EntityOrId<>)) | else if (genericType == typeof(EntityOrId<>)) | ||||
return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth); | return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth); | ||||
} | } | ||||
#endregion | |||||
#endregion | |||||
#region Primitives | #region Primitives | ||||
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null; | bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null; | ||||
@@ -87,6 +87,8 @@ namespace Discord.Net.Converters | |||||
return MessageComponentConverter.Instance; | return MessageComponentConverter.Instance; | ||||
if (type == typeof(API.Interaction)) | if (type == typeof(API.Interaction)) | ||||
return InteractionConverter.Instance; | return InteractionConverter.Instance; | ||||
if (type == typeof(API.DiscordError)) | |||||
return DiscordErrorConverter.Instance; | |||||
if (type == typeof(GuildFeatures)) | if (type == typeof(GuildFeatures)) | ||||
return GuildFeaturesConverter.Instance; | return GuildFeaturesConverter.Instance; | ||||
@@ -0,0 +1,88 @@ | |||||
using Discord.API; | |||||
using Newtonsoft.Json; | |||||
using Newtonsoft.Json.Linq; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.Net.Converters | |||||
{ | |||||
internal class DiscordErrorConverter : JsonConverter | |||||
{ | |||||
public static DiscordErrorConverter Instance | |||||
=> new DiscordErrorConverter(); | |||||
public override bool CanConvert(Type objectType) => objectType == typeof(DiscordError); | |||||
public override bool CanRead => true; | |||||
public override bool CanWrite => false; | |||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
{ | |||||
var obj = JObject.Load(reader); | |||||
var err = new API.DiscordError(); | |||||
var result = obj.GetValue("errors", StringComparison.OrdinalIgnoreCase); | |||||
result?.Parent.Remove(); | |||||
// Populate the remaining properties. | |||||
using (var subReader = obj.CreateReader()) | |||||
{ | |||||
serializer.Populate(subReader, err); | |||||
} | |||||
if (result != null) | |||||
{ | |||||
var innerReader = result.CreateReader(); | |||||
var errors = ReadErrors(innerReader); | |||||
err.Errors = errors.ToArray(); | |||||
} | |||||
return err; | |||||
} | |||||
private List<ErrorDetails> ReadErrors(JsonReader reader, string path = "") | |||||
{ | |||||
List<ErrorDetails> errs = new List<ErrorDetails>(); | |||||
var obj = JObject.Load(reader); | |||||
var props = obj.Properties(); | |||||
foreach (var prop in props) | |||||
{ | |||||
if (prop.Name == "_errors" && path == "") // root level error | |||||
{ | |||||
errs.Add(new ErrorDetails() | |||||
{ | |||||
Name = Optional<string>.Unspecified, | |||||
Errors = prop.Value.ToObject<Error[]>() | |||||
}); | |||||
} | |||||
else if (prop.Name == "_errors") // path errors (not root level) | |||||
{ | |||||
errs.Add(new ErrorDetails() | |||||
{ | |||||
Name = path, | |||||
Errors = prop.Value.ToObject<Error[]>() | |||||
}); | |||||
} | |||||
else if(int.TryParse(prop.Name, out var i)) // array value | |||||
{ | |||||
var r = prop.Value.CreateReader(); | |||||
errs.AddRange(ReadErrors(r, path + $"[{i}]")); | |||||
} | |||||
else // property name | |||||
{ | |||||
var r = prop.Value.CreateReader(); | |||||
errs.AddRange(ReadErrors(r, path + $"{(path != "" ? "." : "")}{prop.Name[0].ToString().ToUpper() + new string(prop.Name.Skip(1).ToArray())}")); | |||||
} | |||||
} | |||||
return errs; | |||||
} | |||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); | |||||
} | |||||
} |
@@ -1,3 +1,4 @@ | |||||
using Discord.API; | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
using System; | using System; | ||||
@@ -5,6 +6,7 @@ using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
#endif | #endif | ||||
using System.IO; | using System.IO; | ||||
using System.Linq; | |||||
using System.Net; | using System.Net; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -99,9 +101,7 @@ namespace Discord.Net.Queue | |||||
continue; //Retry | continue; //Retry | ||||
default: | default: | ||||
int? code = null; | |||||
string reason = null; | |||||
object errors = null; | |||||
API.DiscordError error = null; | |||||
if (response.Stream != null) | if (response.Stream != null) | ||||
{ | { | ||||
try | try | ||||
@@ -109,15 +109,14 @@ namespace Discord.Net.Queue | |||||
using (var reader = new StreamReader(response.Stream)) | using (var reader = new StreamReader(response.Stream)) | ||||
using (var jsonReader = new JsonTextReader(reader)) | using (var jsonReader = new JsonTextReader(reader)) | ||||
{ | { | ||||
var json = JToken.Load(jsonReader); | |||||
try { code = json.Value<int>("code"); } catch { }; | |||||
try { reason = json.Value<string>("message"); } catch { }; | |||||
try { errors = json.Value<object>("errors"); } catch { }; | |||||
error = Discord.Rest.DiscordRestClient.Serializer.Deserialize<API.DiscordError>(jsonReader); | |||||
} | } | ||||
} | } | ||||
catch { } | catch { } | ||||
} | } | ||||
throw new HttpException(response.StatusCode, request, code, reason, errors); | |||||
throw new HttpException(response.StatusCode, request, error?.Code, error.Message, error.Errors.IsSpecified | |||||
? error.Errors.Value.Select(x => new DiscordJsonError(x.Name.GetValueOrDefault("root"), x.Errors.Select(y => new DiscordError(y.Code, y.Message)).ToArray())).ToArray() | |||||
: null); | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -0,0 +1,63 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace Discord.API.Voice | |||||
{ | |||||
/// <summary> | |||||
/// Represents generic op codes for voice disconnect. | |||||
/// </summary> | |||||
public enum VoiceCloseCode | |||||
{ | |||||
/// <summary> | |||||
/// You sent an invalid opcode. | |||||
/// </summary> | |||||
UnknownOpcode = 4001, | |||||
/// <summary> | |||||
/// You sent an invalid payload in your identifying to the Gateway. | |||||
/// </summary> | |||||
DecodeFailure = 4002, | |||||
/// <summary> | |||||
/// You sent a payload before identifying with the Gateway. | |||||
/// </summary> | |||||
NotAuthenticated = 4003, | |||||
/// <summary> | |||||
/// The token you sent in your identify payload is incorrect. | |||||
/// </summary> | |||||
AuthenticationFailed = 4004, | |||||
/// <summary> | |||||
/// You sent more than one identify payload. Stahp. | |||||
/// </summary> | |||||
AlreadyAuthenticated = 4005, | |||||
/// <summary> | |||||
/// Your session is no longer valid. | |||||
/// </summary> | |||||
SessionNolongerValid = 4006, | |||||
/// <summary> | |||||
/// Your session has timed out. | |||||
/// </summary> | |||||
SessionTimeout = 4009, | |||||
/// <summary> | |||||
/// We can't find the server you're trying to connect to. | |||||
/// </summary> | |||||
ServerNotFound = 4011, | |||||
/// <summary> | |||||
/// We didn't recognize the protocol you sent. | |||||
/// </summary> | |||||
UnknownProtocol = 4012, | |||||
/// <summary> | |||||
/// Channel was deleted, you were kicked, voice server changed, or the main gateway session was dropped. Should not reconnect. | |||||
/// </summary> | |||||
Disconnected = 4014, | |||||
/// <summary> | |||||
/// The server crashed. Our bad! Try resuming. | |||||
/// </summary> | |||||
VoiceServerCrashed = 4015, | |||||
/// <summary> | |||||
/// We didn't recognize your encryption. | |||||
/// </summary> | |||||
UnknownEncryptionMode = 4016, | |||||
} | |||||
} |