From e9155b1c698415cd7ef9db1267bd2e2787a5222f Mon Sep 17 00:00:00 2001 From: bowzee Date: Thu, 11 Apr 2019 01:53:15 +0300 Subject: [PATCH] (Exceptions) clean up exceptions --- src/core/request.ts | 28 +++++++--- src/exceptions.ts | 67 +++++------------------- src/responses/index.ts | 2 + src/responses/login-required.response.ts | 5 ++ src/responses/spam.response.ts | 11 ++++ 5 files changed, 51 insertions(+), 62 deletions(-) create mode 100644 src/responses/login-required.response.ts create mode 100644 src/responses/spam.response.ts diff --git a/src/core/request.ts b/src/core/request.ts index d1d1f2463..688c9ff28 100644 --- a/src/core/request.ts +++ b/src/core/request.ts @@ -2,7 +2,14 @@ import { IgApiClient } from '../client'; import { inRange, random } from 'lodash'; import * as request from 'request-promise'; import { Options, Response } from 'request'; -import { ActionSpamError, AuthenticationError, CheckpointError, RequestError, SentryBlockError } from '../exceptions'; +import { + ActionSpamError, + AuthenticationError, + CheckpointError, + PrivateUserError, + RequestError, + SentryBlockError, +} from '../exceptions'; import { plainToClass } from 'class-transformer'; import { CheckpointResponse } from '../responses'; import hmac = require('crypto-js/hmac-sha256'); @@ -33,14 +40,19 @@ export class Request { private static handleError(response: Response) { const json = response.body; if (json.spam) { - return new ActionSpamError(json); + return new ActionSpamError(response); } - if (json.message === 'challenge_required') { - const checkpointResponse = plainToClass(CheckpointResponse, json as CheckpointResponse); - return new CheckpointError(checkpointResponse); - } - if (json.message === 'login_required') { - return new AuthenticationError('Login required to process this request'); + if (typeof json.message === 'string') { + if (json.message === 'challenge_required') { + const checkpointResponse = plainToClass(CheckpointResponse, json as CheckpointResponse); + return new CheckpointError(checkpointResponse); + } + if (json.message === 'login_required') { + return new AuthenticationError(response); + } + if (json.message.toLowerCase() === 'not authorized to view user') { + return new PrivateUserError(response); + } } if (json.error_type === 'sentry_block') { return new SentryBlockError(json); diff --git a/src/exceptions.ts b/src/exceptions.ts index b987891be..6e4cd97ad 100644 --- a/src/exceptions.ts +++ b/src/exceptions.ts @@ -3,36 +3,26 @@ import { CustomError } from 'ts-custom-error'; import * as routes from './core/routes'; import { CheckpointResponse } from './responses'; import { Response } from 'request'; +import { LoginRequiredResponse, SpamResponse } from './responses'; // Basic error export class APIError extends CustomError { constructor(message = 'Instagram API error was made.') { super(message); } - - serialize() { - return { - error: this.constructor.name, - errorMessage: this.message, - }; - } } -export class RequestError extends APIError { - constructor(public response: Response) { +export class RequestError extends APIError { + constructor(public response: Pick> & { body: TBody }) { super( - `${response.request.method} ${response.request.uri.path} - ${response.statusCode} ${ - response.statusMessage - } ${response.body.message || ''}`, + `${response.body.message || ''}; ${response.request.method} ${response.request.uri.path} - ${ + response.statusCode + } ${response.statusMessage}`, ); } } -export class AuthenticationError extends APIError { - constructor(message = 'Not possible to authenticate') { - super(message); - } -} +export class AuthenticationError extends RequestError {} export class ParseError extends APIError { constructor(public body: string) { @@ -40,38 +30,11 @@ export class ParseError extends APIError { } } -export class ActionSpamError extends APIError { - constructor(public json) { - super('This action was disabled due to block from instagram!'); - this.json = json; - } - - serialize() { - return _.extend(APIError.prototype.serialize.call(this), { - errorData: { - blockTime: this.getBlockTime(), - message: this.getFeedbackMessage(), - }, - }); - } - - getBlockTime() { - if (_.isObject(this.json) && _.isString(this.json.feedback_message)) { - const hours = this.json.feedback_message.match(/(\d+)(\s)*hour(s)/); - if (!hours || !_.isArray(hours)) return 0; - const blockTime = parseInt(hours[1]) * 60 * 60 * 1000; - return blockTime + 1000 * 60 * 5; - } - return 0; - } - - getFeedbackMessage() { - let message = 'No feedback message'; - if (_.isString(this.json.feedback_message)) { - const title = _.isString(this.json.feedback_title) ? this.json.feedback_title + ': ' : ''; - message = title + this.json.feedback_message; - } - return message; +export class ActionSpamError extends RequestError { + get expirationDate(): string | null { + const date = this.response.body.feedback_message.match(/(\d{4}-\d{2}-\d{2})/); + if (date === null) return null; + return date[0]; } } @@ -110,11 +73,7 @@ export class NotFoundError extends APIError { } } -export class PrivateUserError extends APIError { - constructor(message = 'User is private and you are not authorized to view his content!') { - super(message); - } -} +export class PrivateUserError extends RequestError {} export class TooManyFollowsError extends APIError { constructor() { diff --git a/src/responses/index.ts b/src/responses/index.ts index 29a8ebe49..2c2647f7e 100644 --- a/src/responses/index.ts +++ b/src/responses/index.ts @@ -6,3 +6,5 @@ export * from './account.repository.login.response'; export * from './user.repository.info.response'; export * from './user.repository.search.response'; export * from './user.feed.response'; +export * from './spam.response'; +export * from './login-required.response'; diff --git a/src/responses/login-required.response.ts b/src/responses/login-required.response.ts new file mode 100644 index 000000000..246c330dd --- /dev/null +++ b/src/responses/login-required.response.ts @@ -0,0 +1,5 @@ +export interface LoginRequiredResponse { + message: 'login_required'; + logout_reason: number; + status: 'fail'; +} diff --git a/src/responses/spam.response.ts b/src/responses/spam.response.ts new file mode 100644 index 000000000..a85c4e24d --- /dev/null +++ b/src/responses/spam.response.ts @@ -0,0 +1,11 @@ +export interface SpamResponse { + message: 'feedback_required'; + spam: true; + feedback_title: string; + feedback_message: string; + feedback_url: string; + feedback_appeal_label: string; + feedback_ignore_label: string; + feedback_action: string; + status: 'fail'; +}