* 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, | |||
| } | |||
| } | |||