* 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.Linq; | |||
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.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.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> | |||
/// from Discord, or <c>null</c> if none. | |||
/// </returns> | |||
public int? DiscordCode { get; } | |||
public DiscordErrorCode? DiscordCode { get; } | |||
/// <summary> | |||
/// Gets the reason of the exception. | |||
/// </summary> | |||
@@ -35,12 +37,9 @@ namespace Discord.Net | |||
/// </summary> | |||
public IRequest Request { get; } | |||
/// <summary> | |||
/// The error object returned from discord. | |||
/// Gets a collection of json errors describing what went wrong with the request. | |||
/// </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> | |||
/// 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="discordCode">The Discord status code returned.</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; | |||
Request = request; | |||
DiscordCode = discordCode; | |||
Reason = reason; | |||
Error = errors; | |||
Errors = errors?.ToImmutableArray() ?? ImmutableArray<DiscordJsonError>.Empty; | |||
} | |||
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) | |||
{ | |||
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) | |||
{ | |||
var json = (x.Request as JsonRestRequest).Json; | |||
throw new ApplicationCommandException(json, x); | |||
throw new ApplicationCommandException(x); | |||
} | |||
throw; | |||
@@ -12,8 +12,8 @@ namespace Discord.Net.Converters | |||
{ | |||
#region DiscordContractResolver | |||
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) | |||
{ | |||
var property = base.CreateProperty(member, memberSerialization); | |||
@@ -58,7 +58,7 @@ namespace Discord.Net.Converters | |||
else if (genericType == typeof(EntityOrId<>)) | |||
return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth); | |||
} | |||
#endregion | |||
#endregion | |||
#region Primitives | |||
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null; | |||
@@ -87,6 +87,8 @@ namespace Discord.Net.Converters | |||
return MessageComponentConverter.Instance; | |||
if (type == typeof(API.Interaction)) | |||
return InteractionConverter.Instance; | |||
if (type == typeof(API.DiscordError)) | |||
return DiscordErrorConverter.Instance; | |||
if (type == typeof(GuildFeatures)) | |||
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.Linq; | |||
using System; | |||
@@ -5,6 +6,7 @@ using System; | |||
using System.Diagnostics; | |||
#endif | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
@@ -99,9 +101,7 @@ namespace Discord.Net.Queue | |||
continue; //Retry | |||
default: | |||
int? code = null; | |||
string reason = null; | |||
object errors = null; | |||
API.DiscordError error = null; | |||
if (response.Stream != null) | |||
{ | |||
try | |||
@@ -109,15 +109,14 @@ namespace Discord.Net.Queue | |||
using (var reader = new StreamReader(response.Stream)) | |||
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 { } | |||
} | |||
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 | |||
@@ -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, | |||
} | |||
} |