namespace WebDrop.Core; public enum ErrorCode { BadRequest, Unauthorized, Forbidden, NotJoined, MembersFull, ModeMismatch, NotFound, Conflict, Gone, TooLarge, CaptchaRequired, CaptchaUnavailable, RateLimited, VisitorsFull, Sealed, AccountRequired, InvitationRequired, ChannelPasswordRequired, ChannelPasswordInvalid, SpaceNameRequired, } /// 预期内的业务失败。消息只含错误码,绝不回显用户提交的内容。 public sealed class WebDropException : Exception { public ErrorCode Code { get; } /// 仅在 410 日志续传失败时有值,见 api.md。 public long? OldestSeq { get; } public WebDropException(ErrorCode code, long? oldestSeq = null) : base(code.ToWire()) { Code = code; OldestSeq = oldestSeq; } } public static class ErrorCodes { public static string ToWire(this ErrorCode code) => code switch { ErrorCode.BadRequest => "bad_request", ErrorCode.Unauthorized => "unauthorized", ErrorCode.Forbidden => "forbidden", ErrorCode.NotJoined => "not_joined", ErrorCode.MembersFull => "members_full", ErrorCode.ModeMismatch => "mode_mismatch", ErrorCode.NotFound => "not_found", ErrorCode.Conflict => "conflict", ErrorCode.Gone => "gone", ErrorCode.TooLarge => "too_large", ErrorCode.CaptchaRequired => "captcha_required", ErrorCode.CaptchaUnavailable => "captcha_unavailable", ErrorCode.RateLimited => "rate_limited", ErrorCode.VisitorsFull => "visitors_full", ErrorCode.Sealed => "sealed", ErrorCode.AccountRequired => "account_required", ErrorCode.InvitationRequired => "invitation_required", ErrorCode.ChannelPasswordRequired => "channel_password_required", ErrorCode.ChannelPasswordInvalid => "channel_password_invalid", ErrorCode.SpaceNameRequired => "space_name_required", _ => "bad_request", }; public static int ToStatus(this ErrorCode code) => code switch { ErrorCode.BadRequest => 400, ErrorCode.Unauthorized => 401, ErrorCode.Forbidden or ErrorCode.NotJoined or ErrorCode.MembersFull or ErrorCode.ModeMismatch => 403, ErrorCode.NotFound => 404, ErrorCode.Conflict => 409, ErrorCode.Sealed => 409, ErrorCode.SpaceNameRequired => 400, ErrorCode.Gone => 410, ErrorCode.TooLarge => 413, ErrorCode.CaptchaRequired => 428, ErrorCode.CaptchaUnavailable => 503, ErrorCode.RateLimited => 429, ErrorCode.VisitorsFull => 403, ErrorCode.AccountRequired => 401, ErrorCode.InvitationRequired or ErrorCode.ChannelPasswordRequired or ErrorCode.ChannelPasswordInvalid => 403, _ => 400, }; }