From e0c493f9993a6f135602f6a4323961012f896552 Mon Sep 17 00:00:00 2001 From: shalvah Date: Mon, 8 Feb 2021 22:02:31 +0100 Subject: [PATCH] Add undocumented codes --- index.d.ts | 224 ++++++++++++++++++++++++++++++++---------------- index.js | 246 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 323 insertions(+), 147 deletions(-) diff --git a/index.d.ts b/index.d.ts index c0a8f5d..e68f2db 100644 --- a/index.d.ts +++ b/index.d.ts @@ -12,86 +12,109 @@ export type TwitResponse = { twitterReply: any; }; export namespace codes { - export const INVALID_COORDINATES: number; - export const NO_DATA_FOR_COORDINATES_AND_RADIUS: number; - export const NO_DATA_FOR_THAT_ID: number; - export const MUST_PROVIDE_VALID_GEO_DATA: number; - export const NO_LOCATION_FOR_THAT_IP_ADDRESS: number; - export const NO_USER_MATCHES_THOSE_TERMS: number; - export const MISSING_QUERY_PARAMS: number; - export const AUTH_FAILED: number; - export const NOT_FOUND: number; - export const CANT_REPORT_YOURSELF_FOR_SPAM: number; - export const PARAMETER_MISSING: number; - export const ATTACHMENT_URL_INVALID: number; - export const COULDNT_FIND_USER: number; - export const USER_SUSPENDED: number; - export const ACCOUNT_SUSPENDED: number; - export const GOTO_NEW_API: number; - export const CLIENT_NOT_PERMITTED_TO_DO_THAT: number; - export const RATE_LIMIT_EXCEEDED: number; - export const INVALID_OR_EXPIRED_TOKEN: number; - export const SSL_REQUIRED: number; - export const APP_NOT_ALLOWED_TO_ACCESS_DMS: number; - export const UNABLE_TO_VERIFY_CREDENTIALS: number; - export const USER_NOT_FOUND_IN_THE_LIST: number; - export const USER_NOT_IN_THE_LIST: number; - export const ACCOUNT_UPDATE_FAILED: number; - export const TWITTER_NEEDS_A_BREAK: number; - export const TWITTERS_DOWN_SORRY: number; - export const ALSO_AUTH_FAILED: number; - export const ALREADY_LIKED_THAT_SHIT: number; - export const NO_SUCH_TWEET: number; - export const CANT_DM_THIS_USER: number; - export const COULDNT_DM: number; - export const ALREADY_FOLLOWED: number; - export const CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL: number; - export const COULDNT_DETERMINE_SOURCE_USER: number; - export const TWEET_PROTECTED: number; - export const HIT_TWEET_LIMIT: number; - export const TWEET_TOO_LONG: number; - export const DUPLICATE_TWEET: number; - export const INVALID_URL_PARAMETER: number; - export const DEVICE_ERROR: number; - export const REACHED_LIMIT_FOR_SPAM_REPORTS: number; - export const OWNER_MUST_ALLOW_DMS_FROM_ANYONE: number; - export const BAD_AUTH_DATA: number; - export const YOUR_CREDENTIALS_DONT_COVER_THIS: number; - export const WE_FELT_LIKE_FLAGGING_YOU: number; - export const THIS_ENDPOINT_HAS_BEEN_RETIRED: number; - export const APP_MUZZLED: number; - export const HAHA_CANT_MUTE_YOURSELF: number; - export const CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING: number; - export const GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES: number; - export const MEDIA_ID_GOT_A_PROBLEM: number; - export const DIDNT_FIND_A_MEDIA_ID: number; - export const ACCOUNT_LOCKED_TEMPORARILY: number; - export const ALREADY_RETWEETED: number; - export const CANT_DM_THE_FELLA: number; - export const DM_TOO_LONG: number; - export const SUBSCRIPTION_ALREADY_EXISTS: number; - export const REPLIED_TO_UNAVAILABLE_TWEET: number; - export const ONLY_ONE_ATTACHMENT_TYPE_ALLOWED: number; - export const YOU_NEED_TO_ENABLE_COOKIES: number; - export const INVALID_URL: number; - export const CALLBACK_URL_NOT_APPROVED: number; - export const APP_SUSPENDED: number; - export const DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH: number; - export const TWEET_UNAVAILABLE: number; - export const TWEET_UNAVAILABLE_FOR_VIOLATING_RULES: number; - export const TWEET_RESTRICTED_BY_TWITTER: number; - export const INVALID_CONVERSATION_CONTROLS: number; - export const REPLIES_RESTRICTED: number; + export const INVALID_COORDINATES: 3; + export const NO_DATA_FOR_COORDINATES_AND_RADIUS: 7; + export const NO_DATA_FOR_THAT_ID: 8; + export const MUST_PROVIDE_VALID_GEO_DATA: 12; + export const NO_LOCATION_FOR_THAT_IP_ADDRESS: 13; + export const NO_USER_MATCHES_THOSE_TERMS: 17; + export const MISSING_QUERY_PARAMS: 25; + export const AUTH_FAILED: 32; + export const NOT_FOUND: 34; + export const CANT_REPORT_YOURSELF_FOR_SPAM: 36; + export const PARAMETER_MISSING: 38; + export const ATTACHMENT_URL_INVALID: 44; + export const COULDNT_FIND_USER: 50; + export const USER_SUSPENDED: 63; + export const ACCOUNT_SUSPENDED: 64; + export const GOTO_NEW_API: 68; + export const CLIENT_NOT_PERMITTED_TO_DO_THAT: 87; + export const RATE_LIMIT_EXCEEDED: 88; + export const INVALID_OR_EXPIRED_TOKEN: 89; + export const SSL_REQUIRED: 92; + export const APP_NOT_ALLOWED_TO_ACCESS_DMS: 93; + export const UNABLE_TO_VERIFY_CREDENTIALS: 99; + export const USER_NOT_FOUND_IN_THE_LIST: 109; + export const USER_NOT_IN_THE_LIST: 110; + export const ACCOUNT_UPDATE_FAILED: 120; + export const TWITTER_NEEDS_A_BREAK: 130; + export const TWITTERS_DOWN_SORRY: 131; + export const AUTH_FAILED_DUE_TO_TIMESTAMPS: 135; + export const BLOCKED_BY_USER: 136; + export const ALREADY_LIKED_THAT_SHIT: 139; + export const NO_SUCH_TWEET: 144; + export const CANT_DM_THIS_USER: 150; + export const COULDNT_DM: 151; + export const ALREADY_FOLLOWED: 160; + export const CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL: 161; + export const COULDNT_DETERMINE_SOURCE_USER: 163; + export const TWEET_PROTECTED: 179; + export const HIT_TWEET_LIMIT: 185; + export const TWEET_TOO_LONG: 186; + export const DUPLICATE_TWEET: 187; + export const INVALID_URL_PARAMETER: 195; + export const DEVICE_ERROR: 203; + export const REACHED_LIMIT_FOR_SPAM_REPORTS: 205; + export const OWNER_MUST_ALLOW_DMS_FROM_ANYONE: 214; + export const BAD_AUTH_DATA: 215; + export const YOUR_CREDENTIALS_DONT_COVER_THIS: 220; + export const WE_FELT_LIKE_FLAGGING_YOU: 226; + export const USER_MUST_VERIFY_LOGIN: 231; + export const THIS_ENDPOINT_HAS_BEEN_RETIRED: 251; + export const APP_MUZZLED: 261; + export const HAHA_CANT_MUTE_YOURSELF: 271; + export const CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING: 272; + export const GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES: 323; + export const MEDIA_ID_GOT_A_PROBLEM: 324; + export const DIDNT_FIND_A_MEDIA_ID: 325; + export const ACCOUNT_LOCKED_TEMPORARILY: 326; + export const ALREADY_RETWEETED: 327; + export const CANT_DM_THE_FELLA: 349; + export const DM_TOO_LONG: 354; + export const SUBSCRIPTION_ALREADY_EXISTS: 355; + export const REPLIED_TO_UNAVAILABLE_TWEET: 385; + export const ONLY_ONE_ATTACHMENT_TYPE_ALLOWED: 386; + export const YOU_NEED_TO_ENABLE_COOKIES: 404; + export const INVALID_URL: 407; + export const CALLBACK_URL_NOT_APPROVED: 415; + export const APP_SUSPENDED: 416; + export const DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH: 417; + export const TWEET_UNAVAILABLE: 63; + export const TWEET_UNAVAILABLE_FOR_VIOLATING_RULES: 422; + export const TWEET_RESTRICTED_BY_TWITTER: 425; + export const INVALID_CONVERSATION_CONTROLS: 431; + export const REPLIES_RESTRICTED: 433; } /** * For when your Twitter app or user account is having issues (for instance, account locked or app suspended by Twitter). * You'll probably want to take action ASAP. + * Covers: + * - ACCOUNT_LOCKED_TEMPORARILY (326) + * - ACCOUNT_SUSPENDED (64) + * - APP_SUSPENDED (416) + * - APP_MUZZLED (261) + * - CALLBACK_URL_NOT_APPROVED (415) + * - DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH (417) + * - CLIENT_NOT_PERMITTED_TO_DO_THAT (87) + * - APP_NOT_ALLOWED_TO_ACCESS_DMS (93) + * - YOUR_CREDENTIALS_DONT_COVER_THIS (220) + * - WE_FELT_LIKE_FLAGGING_YOU (226) */ declare class ProblemWithYourAppOrAccount extends TwitterApiError { constructor(endpoint: any, errors: any); } /** - * For when the requested resource (eg Tweet/user) wasn't found + * For when the requested resource (eg Tweet/user) wasn't found. + * Covers: + * - NO_LOCATION_FOR_THAT_IP_ADDRESS (13) + * - NO_USER_MATCHES_THOSE_TERMS (17) + * - NOT_FOUND (34) + * - COULDNT_FIND_USER (50) + * - USER_NOT_FOUND_IN_THE_LIST (109) + * - NO_SUCH_TWEET (144) + * - USER_SUSPENDED (63) + * - TWEET_UNAVAILABLE (422) + * - TWEET_UNAVAILABLE_FOR_VIOLATING_RULES (421) */ declare class NotFound extends TwitterApiError { constructor(endpoint: any, errors: any); @@ -99,24 +122,75 @@ declare class NotFound extends TwitterApiError { /** * For errors caused by permissions issues. * For example, not allowed to view a protected tweet or DM a user. + * Covers: + * - CANT_DM_THIS_USER (150) + * - COULDNT_DM (151) + * - TWEET_PROTECTED (179) + * - REPLIES_RESTRICTED (433) + * - BLOCKED_BY_USER (136) + * - OWNER_MUST_ALLOW_DMS_FROM_ANYONE (214) + * - CANT_DM_THE_FELLA (349) + * - TWEET_RESTRICTED_BY_TWITTER (425) */ declare class ProblemWithPermissions extends TwitterApiError { constructor(endpoint: any, errors: any); } /** * For errors caused by hitting a rate limit. You should implement backoff to avoid being banned by Twitter. + * Covers: + * - RATE_LIMIT_EXCEEDED (88) + * - HIT_TWEET_LIMIT (185) + * - CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL (161) + * - REACHED_LIMIT_FOR_SPAM_REPORTS (205) */ declare class RateLimited extends TwitterApiError { constructor(endpoint: any, errors: any); } /** * For errors caused by bad requests (invalid parameters, overly long values etc) + * Covers: + * - INVALID_COORDINATES (3) + * - NO_DATA_FOR_COORDINATES_AND_RADIUS (7) + * - NO_DATA_FOR_THAT_ID (8) + * - MUST_PROVIDE_VALID_GEO_DATA (12) + * - CANT_REPORT_YOURSELF_FOR_SPAM (36) + * - REPLIED_TO_UNAVAILABLE_TWEET (385) + * - MISSING_QUERY_PARAMS (25) + * - PARAMETER_MISSING (38) + * - ATTACHMENT_URL_INVALID (44) + * - TWEET_TOO_LONG (186) + * - DUPLICATE_TWEET (187) + * - INVALID_URL_PARAMETER (195) + * - ACCOUNT_UPDATE_FAILED (120) + * - ALREADY_LIKED_THAT_SHIT (129) + * - ALREADY_FOLLOWED (160) + * - USER_NOT_IN_THE_LIST (110) + * - COULDNT_DETERMINE_SOURCE_USER (163) + * - DEVICE_ERROR (203) + * - HAHA_CANT_MUTE_YOURSELF (271) + * - CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING (272) + * - GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES (323) + * - MEDIA_ID_GOT_A_PROBLEM (324) + * - DIDNT_FIND_A_MEDIA_ID (325) + * - ALREADY_RETWEETED (327) + * - DM_TOO_LONG (354) + * - SUBSCRIPTION_ALREADY_EXISTS (355) + * - ONLY_ONE_ATTACHMENT_TYPE_ALLOWED (386) + * - YOU_NEED_TO_ENABLE_COOKIES (404) + * - INVALID_URL (407) + * - INVALID_CONVERSATION_CONTROLS (431) */ declare class BadRequest extends TwitterApiError { constructor(endpoint: any, errors: any); } /** * For errors caused by authentication issues. + * Covers: + * - INVALID_OR_EXPIRED_TOKEN (89) + * - AUTH_FAILED (32) + * - AUTH_FAILED_DUE_TO_TIMESTAMPS (135) + * - UNABLE_TO_VERIFY_CREDENTIALS (99) + * - BAD_AUTH_DATA (215) */ declare class ProblemWithAuth extends TwitterApiError { constructor(endpoint: any, errors: any); @@ -124,6 +198,9 @@ declare class ProblemWithAuth extends TwitterApiError { /** * For internal server errors and "Twitter is over capacity" errors. * It's recommended to wait a few minutes before retrying. + * Covers: + * - TWITTER_NEEDS_A_BREAK (130) + * - TWITTERS_DOWN_SORRY (131) */ declare class ProblemWithTwitter extends TwitterApiError { constructor(endpoint: any, errors: any); @@ -133,6 +210,11 @@ declare class TwitterApiError extends Error { * @param {string} endpoint The endpoint which triggered the error * @param {TwitError[]} errors The errors object from the Twitter response * @param {string} type Category of the error + * + * Base error class covers: + * - GOTO_NEW_API (68) + * - SSL_REQUIRED (92) + * - THIS_ENDPOINT_HAS_BEEN_RETIRED (251) */ constructor(endpoint: string, errors: (string | { code: number; diff --git a/index.js b/index.js index f039ad9..8bbec30 100644 --- a/index.js +++ b/index.js @@ -5,78 +5,90 @@ * @typedef {{allErrors: TwitError[], message?: string, code: number, twitterReply: Object|string}} TwitResponse */ +/** + * Identity function. Coerces string/number literals to literal types. + * @template {number} T + * @param {T} v + * @return {T} + */ +function c(v) { + return v; +} + // See https://developer.twitter.com/en/docs/basics/response-codes.html const codes = { - INVALID_COORDINATES: 3, - NO_DATA_FOR_COORDINATES_AND_RADIUS: 7, - NO_DATA_FOR_THAT_ID: 8, - MUST_PROVIDE_VALID_GEO_DATA: 12, - NO_LOCATION_FOR_THAT_IP_ADDRESS: 13, - NO_USER_MATCHES_THOSE_TERMS: 17, - MISSING_QUERY_PARAMS: 25, - AUTH_FAILED: 32, - NOT_FOUND: 34, - CANT_REPORT_YOURSELF_FOR_SPAM: 36, - PARAMETER_MISSING: 38, - ATTACHMENT_URL_INVALID: 44, - COULDNT_FIND_USER: 50, - USER_SUSPENDED: 63, - ACCOUNT_SUSPENDED: 64, - GOTO_NEW_API: 68, - CLIENT_NOT_PERMITTED_TO_DO_THAT: 87, - RATE_LIMIT_EXCEEDED: 88, - INVALID_OR_EXPIRED_TOKEN: 89, - SSL_REQUIRED: 92, - APP_NOT_ALLOWED_TO_ACCESS_DMS: 93, - UNABLE_TO_VERIFY_CREDENTIALS: 99, - USER_NOT_FOUND_IN_THE_LIST: 109, - USER_NOT_IN_THE_LIST: 110, - ACCOUNT_UPDATE_FAILED: 120, - TWITTER_NEEDS_A_BREAK: 130, - TWITTERS_DOWN_SORRY: 131, - ALSO_AUTH_FAILED: 135, - ALREADY_LIKED_THAT_SHIT: 139, - NO_SUCH_TWEET: 144, - CANT_DM_THIS_USER: 150, - COULDNT_DM: 151, - ALREADY_FOLLOWED: 160, - CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL: 161, - COULDNT_DETERMINE_SOURCE_USER: 163, - TWEET_PROTECTED: 179, - HIT_TWEET_LIMIT: 185, - TWEET_TOO_LONG: 186, - DUPLICATE_TWEET: 187, - INVALID_URL_PARAMETER: 195, - DEVICE_ERROR: 203, - REACHED_LIMIT_FOR_SPAM_REPORTS: 205, - OWNER_MUST_ALLOW_DMS_FROM_ANYONE: 214, - BAD_AUTH_DATA: 215, - YOUR_CREDENTIALS_DONT_COVER_THIS: 220, - WE_FELT_LIKE_FLAGGING_YOU: 226, - THIS_ENDPOINT_HAS_BEEN_RETIRED: 251, - APP_MUZZLED: 261, - HAHA_CANT_MUTE_YOURSELF: 271, - CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING: 272, - GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES: 323, - MEDIA_ID_GOT_A_PROBLEM: 324, - DIDNT_FIND_A_MEDIA_ID: 325, - ACCOUNT_LOCKED_TEMPORARILY: 326, - ALREADY_RETWEETED: 327, - CANT_DM_THE_FELLA: 349, - DM_TOO_LONG: 354, - SUBSCRIPTION_ALREADY_EXISTS: 355, - REPLIED_TO_UNAVAILABLE_TWEET: 385, - ONLY_ONE_ATTACHMENT_TYPE_ALLOWED: 386, - YOU_NEED_TO_ENABLE_COOKIES: 404, - INVALID_URL: 407, - CALLBACK_URL_NOT_APPROVED: 415, - APP_SUSPENDED: 416, - DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH: 417, - TWEET_UNAVAILABLE: 421, - TWEET_UNAVAILABLE_FOR_VIOLATING_RULES: 422, - TWEET_RESTRICTED_BY_TWITTER: 425, - INVALID_CONVERSATION_CONTROLS: 431, - REPLIES_RESTRICTED: 433, + INVALID_COORDINATES: c(3), + NO_DATA_FOR_COORDINATES_AND_RADIUS: c(7), + NO_DATA_FOR_THAT_ID: c(8), + MUST_PROVIDE_VALID_GEO_DATA: c(12), + NO_LOCATION_FOR_THAT_IP_ADDRESS: c(13), + NO_USER_MATCHES_THOSE_TERMS: c(17), + MISSING_QUERY_PARAMS: c(25), + AUTH_FAILED: c(32), + NOT_FOUND: c(34), + CANT_REPORT_YOURSELF_FOR_SPAM: c(36), + PARAMETER_MISSING: c(38), + ATTACHMENT_URL_INVALID: c(44), + COULDNT_FIND_USER: c(50), + USER_SUSPENDED: c(63), + ACCOUNT_SUSPENDED: c(64), + GOTO_NEW_API: c(68), + CLIENT_NOT_PERMITTED_TO_DO_THAT: c(87), + RATE_LIMIT_EXCEEDED: c(88), + INVALID_OR_EXPIRED_TOKEN: c(89), + SSL_REQUIRED: c(92), + APP_NOT_ALLOWED_TO_ACCESS_DMS: c(93), + UNABLE_TO_VERIFY_CREDENTIALS: c(99), + USER_NOT_FOUND_IN_THE_LIST: c(109), + USER_NOT_IN_THE_LIST: c(110), + ACCOUNT_UPDATE_FAILED: c(120), + TWITTER_NEEDS_A_BREAK: c(130), + TWITTERS_DOWN_SORRY: c(131), + AUTH_FAILED_DUE_TO_TIMESTAMPS: c(135), + BLOCKED_BY_USER: c(136), // Didn't find in docs, but I got it in a response as recently as last week🤷‍♀️ + ALREADY_LIKED_THAT_SHIT: c(139), + NO_SUCH_TWEET: c(144), + CANT_DM_THIS_USER: c(150), + COULDNT_DM: c(151), + ALREADY_FOLLOWED: c(160), + CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL: c(161), + COULDNT_DETERMINE_SOURCE_USER: c(163), + TWEET_PROTECTED: c(179), + HIT_TWEET_LIMIT: c(185), + TWEET_TOO_LONG: c(186), + DUPLICATE_TWEET: c(187), + INVALID_URL_PARAMETER: c(195), + DEVICE_ERROR: c(203), + REACHED_LIMIT_FOR_SPAM_REPORTS: c(205), + OWNER_MUST_ALLOW_DMS_FROM_ANYONE: c(214), + BAD_AUTH_DATA: c(215), + YOUR_CREDENTIALS_DONT_COVER_THIS: c(220), + WE_FELT_LIKE_FLAGGING_YOU: c(226), + USER_MUST_VERIFY_LOGIN: c(231), + THIS_ENDPOINT_HAS_BEEN_RETIRED: c(251), + APP_MUZZLED: c(261), + HAHA_CANT_MUTE_YOURSELF: c(271), + CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING: c(272), + GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES: c(323), + MEDIA_ID_GOT_A_PROBLEM: c(324), + DIDNT_FIND_A_MEDIA_ID: c(325), + ACCOUNT_LOCKED_TEMPORARILY: c(326), + ALREADY_RETWEETED: c(327), + CANT_DM_THE_FELLA: c(349), + DM_TOO_LONG: c(354), + SUBSCRIPTION_ALREADY_EXISTS: c(355), + REPLIED_TO_UNAVAILABLE_TWEET: c(385), + ONLY_ONE_ATTACHMENT_TYPE_ALLOWED: c(386), + YOU_NEED_TO_ENABLE_COOKIES: c(404), + INVALID_URL: c(407), + CALLBACK_URL_NOT_APPROVED: c(415), + APP_SUSPENDED: c(416), + DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH: c(417), + TWEET_UNAVAILABLE: c(63), + TWEET_UNAVAILABLE_FOR_VIOLATING_RULES: c(422), + TWEET_RESTRICTED_BY_TWITTER: c(425), + INVALID_CONVERSATION_CONTROLS: c(431), + REPLIES_RESTRICTED: c(433), }; class TwitterApiError extends Error { @@ -84,6 +96,11 @@ class TwitterApiError extends Error { * @param {string} endpoint The endpoint which triggered the error * @param {TwitError[]} errors The errors object from the Twitter response * @param {string} type Category of the error + * + * Base error class covers: + * - GOTO_NEW_API (68) + * - SSL_REQUIRED (92) + * - THIS_ENDPOINT_HAS_BEEN_RETIRED (251) */ constructor(endpoint, errors, type = 'Unknown') { super(`[${type}]: Twitter API Error; endpoint=${endpoint}; error=${JSON.stringify(errors[0])}`); @@ -106,6 +123,17 @@ class TwitterApiError extends Error { /** * For when your Twitter app or user account is having issues (for instance, account locked or app suspended by Twitter). * You'll probably want to take action ASAP. + * Covers: + * - ACCOUNT_LOCKED_TEMPORARILY (326) + * - ACCOUNT_SUSPENDED (64) + * - APP_SUSPENDED (416) + * - APP_MUZZLED (261) + * - CALLBACK_URL_NOT_APPROVED (415) + * - DESKTOP_APPLICATIONS_ONLY_SUPPORT_OOB_OAUTH (417) + * - CLIENT_NOT_PERMITTED_TO_DO_THAT (87) + * - APP_NOT_ALLOWED_TO_ACCESS_DMS (93) + * - YOUR_CREDENTIALS_DONT_COVER_THIS (220) + * - WE_FELT_LIKE_FLAGGING_YOU (226) */ class ProblemWithYourAppOrAccount extends TwitterApiError { constructor(endpoint, errors) { @@ -115,7 +143,17 @@ class ProblemWithYourAppOrAccount extends TwitterApiError { } /** - * For when the requested resource (eg Tweet/user) wasn't found + * For when the requested resource (eg Tweet/user) wasn't found. + * Covers: + * - NO_LOCATION_FOR_THAT_IP_ADDRESS (13) + * - NO_USER_MATCHES_THOSE_TERMS (17) + * - NOT_FOUND (34) + * - COULDNT_FIND_USER (50) + * - USER_NOT_FOUND_IN_THE_LIST (109) + * - NO_SUCH_TWEET (144) + * - USER_SUSPENDED (63) + * - TWEET_UNAVAILABLE (422) + * - TWEET_UNAVAILABLE_FOR_VIOLATING_RULES (421) */ class NotFound extends TwitterApiError { constructor(endpoint, errors) { @@ -127,6 +165,9 @@ class NotFound extends TwitterApiError { /** * For internal server errors and "Twitter is over capacity" errors. * It's recommended to wait a few minutes before retrying. + * Covers: + * - TWITTER_NEEDS_A_BREAK (130) + * - TWITTERS_DOWN_SORRY (131) */ class ProblemWithTwitter extends TwitterApiError { constructor(endpoint, errors) { @@ -137,6 +178,37 @@ class ProblemWithTwitter extends TwitterApiError { /** * For errors caused by bad requests (invalid parameters, overly long values etc) + * Covers: + * - INVALID_COORDINATES (3) + * - NO_DATA_FOR_COORDINATES_AND_RADIUS (7) + * - NO_DATA_FOR_THAT_ID (8) + * - MUST_PROVIDE_VALID_GEO_DATA (12) + * - CANT_REPORT_YOURSELF_FOR_SPAM (36) + * - REPLIED_TO_UNAVAILABLE_TWEET (385) + * - MISSING_QUERY_PARAMS (25) + * - PARAMETER_MISSING (38) + * - ATTACHMENT_URL_INVALID (44) + * - TWEET_TOO_LONG (186) + * - DUPLICATE_TWEET (187) + * - INVALID_URL_PARAMETER (195) + * - ACCOUNT_UPDATE_FAILED (120) + * - ALREADY_LIKED_THAT_SHIT (129) + * - ALREADY_FOLLOWED (160) + * - USER_NOT_IN_THE_LIST (110) + * - COULDNT_DETERMINE_SOURCE_USER (163) + * - DEVICE_ERROR (203) + * - HAHA_CANT_MUTE_YOURSELF (271) + * - CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING (272) + * - GIFS_NOT_ALLOWED_WITH_OTHER_IMAGES (323) + * - MEDIA_ID_GOT_A_PROBLEM (324) + * - DIDNT_FIND_A_MEDIA_ID (325) + * - ALREADY_RETWEETED (327) + * - DM_TOO_LONG (354) + * - SUBSCRIPTION_ALREADY_EXISTS (355) + * - ONLY_ONE_ATTACHMENT_TYPE_ALLOWED (386) + * - YOU_NEED_TO_ENABLE_COOKIES (404) + * - INVALID_URL (407) + * - INVALID_CONVERSATION_CONTROLS (431) */ class BadRequest extends TwitterApiError { constructor(endpoint, errors) { @@ -147,6 +219,11 @@ class BadRequest extends TwitterApiError { /** * For errors caused by hitting a rate limit. You should implement backoff to avoid being banned by Twitter. + * Covers: + * - RATE_LIMIT_EXCEEDED (88) + * - HIT_TWEET_LIMIT (185) + * - CANT_FOLLOW_MORE_PEOPLE_NOW_SO_CHILL (161) + * - REACHED_LIMIT_FOR_SPAM_REPORTS (205) */ class RateLimited extends TwitterApiError { constructor(endpoint, errors) { @@ -157,6 +234,12 @@ class RateLimited extends TwitterApiError { /** * For errors caused by authentication issues. + * Covers: + * - INVALID_OR_EXPIRED_TOKEN (89) + * - AUTH_FAILED (32) + * - AUTH_FAILED_DUE_TO_TIMESTAMPS (135) + * - UNABLE_TO_VERIFY_CREDENTIALS (99) + * - BAD_AUTH_DATA (215) */ class ProblemWithAuth extends TwitterApiError { constructor(endpoint, errors) { @@ -168,6 +251,15 @@ class ProblemWithAuth extends TwitterApiError { /** * For errors caused by permissions issues. * For example, not allowed to view a protected tweet or DM a user. + * Covers: + * - CANT_DM_THIS_USER (150) + * - COULDNT_DM (151) + * - TWEET_PROTECTED (179) + * - REPLIES_RESTRICTED (433) + * - BLOCKED_BY_USER (136) + * - OWNER_MUST_ALLOW_DMS_FROM_ANYONE (214) + * - CANT_DM_THE_FELLA (349) + * - TWEET_RESTRICTED_BY_TWITTER (425) */ class ProblemWithPermissions extends TwitterApiError { constructor(endpoint, errors) { @@ -218,16 +310,17 @@ const wrapTwitterErrors = (endpoint, response) => { case codes.MUST_PROVIDE_VALID_GEO_DATA: case codes.CANT_REPORT_YOURSELF_FOR_SPAM: case codes.REPLIED_TO_UNAVAILABLE_TWEET: + case codes.MISSING_QUERY_PARAMS: case codes.PARAMETER_MISSING: case codes.ATTACHMENT_URL_INVALID: case codes.TWEET_TOO_LONG: + case codes.DUPLICATE_TWEET: + case codes.INVALID_URL_PARAMETER: case codes.ACCOUNT_UPDATE_FAILED: case codes.ALREADY_LIKED_THAT_SHIT: case codes.ALREADY_FOLLOWED: case codes.USER_NOT_IN_THE_LIST: case codes.COULDNT_DETERMINE_SOURCE_USER: - case codes.DUPLICATE_TWEET: - case codes.INVALID_URL_PARAMETER: case codes.DEVICE_ERROR: case codes.HAHA_CANT_MUTE_YOURSELF: case codes.CANT_UNMUTE_BECAUSE_YOU_WERENT_MUTING: @@ -235,7 +328,6 @@ const wrapTwitterErrors = (endpoint, response) => { case codes.MEDIA_ID_GOT_A_PROBLEM: case codes.DIDNT_FIND_A_MEDIA_ID: case codes.ALREADY_RETWEETED: - case codes.CANT_DM_THE_FELLA: case codes.DM_TOO_LONG: case codes.SUBSCRIPTION_ALREADY_EXISTS: case codes.ONLY_ONE_ATTACHMENT_TYPE_ALLOWED: @@ -245,7 +337,6 @@ const wrapTwitterErrors = (endpoint, response) => { throw new BadRequest(endpoint, errors); case codes.NO_LOCATION_FOR_THAT_IP_ADDRESS: case codes.NO_USER_MATCHES_THOSE_TERMS: - case codes.MISSING_QUERY_PARAMS: case codes.NOT_FOUND: case codes.COULDNT_FIND_USER: case codes.USER_NOT_FOUND_IN_THE_LIST: @@ -256,7 +347,7 @@ const wrapTwitterErrors = (endpoint, response) => { throw new NotFound(endpoint, errors); case codes.INVALID_OR_EXPIRED_TOKEN: case codes.AUTH_FAILED: - case codes.ALSO_AUTH_FAILED: + case codes.AUTH_FAILED_DUE_TO_TIMESTAMPS: case codes.UNABLE_TO_VERIFY_CREDENTIALS: case codes.BAD_AUTH_DATA: throw new ProblemWithAuth(endpoint, errors); @@ -264,7 +355,10 @@ const wrapTwitterErrors = (endpoint, response) => { case codes.COULDNT_DM: case codes.TWEET_PROTECTED: case codes.REPLIES_RESTRICTED: + case codes.BLOCKED_BY_USER: case codes.OWNER_MUST_ALLOW_DMS_FROM_ANYONE: + case codes.CANT_DM_THE_FELLA: + case codes.TWEET_RESTRICTED_BY_TWITTER: throw new ProblemWithPermissions(endpoint, errors); case codes.GOTO_NEW_API: case codes.SSL_REQUIRED: