forked from FoundKeyGang/FoundKey
396 lines
9.1 KiB
TypeScript
396 lines
9.1 KiB
TypeScript
import Koa from 'koa';
|
|
|
|
export class ApiError extends Error {
|
|
public message: string;
|
|
public code: string;
|
|
public httpStatusCode: number;
|
|
public info?: any;
|
|
|
|
constructor(
|
|
code: keyof errors = 'INTERNAL_ERROR',
|
|
info?: any | null,
|
|
) {
|
|
let _info = info, _code = code;
|
|
if (!(code in errors)) {
|
|
_code = 'INTERNAL_ERROR';
|
|
_info = `Unknown error "${code}" occurred.`;
|
|
}
|
|
|
|
const { message, httpStatusCode } = errors[_code];
|
|
super(message);
|
|
this.code = _code;
|
|
this.info = _info;
|
|
this.message = message;
|
|
this.httpStatusCode = httpStatusCode;
|
|
}
|
|
|
|
/**
|
|
* Makes the response of ctx the current error, given the respective endpoint name.
|
|
*/
|
|
public apply(ctx: Koa.Context, endpoint: string): void {
|
|
ctx.status = this.httpStatusCode;
|
|
// set additional headers
|
|
switch (ctx.status) {
|
|
case 401:
|
|
ctx.response.set('WWW-Authenticate', 'Bearer');
|
|
break;
|
|
case 429:
|
|
if (typeof this.info === 'object' && typeof this.info.reset === 'number') {
|
|
ctx.response.set('Retry-After', Math.floor(this.info.reset - (Date.now() / 1000)));
|
|
}
|
|
break;
|
|
}
|
|
ctx.body = {
|
|
error: {
|
|
message: this.message,
|
|
code: this.code,
|
|
info: this.info ?? undefined,
|
|
endpoint,
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
export const errors: Record<string, { message: string, httpStatusCode: number }> = {
|
|
ACCESS_DENIED: {
|
|
message: 'Access denied.',
|
|
httpStatusCode: 403,
|
|
},
|
|
ALREADY_ADDED: {
|
|
message: 'That user has already been added to that list or group.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_BLOCKING: {
|
|
message: 'You are already blocking that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_CLIPPED: {
|
|
message: 'That note is already added to that clip.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_FAVORITED: {
|
|
message: 'That note is already favorited.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_FOLLOWING: {
|
|
message: 'You are already following that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_INVITED: {
|
|
message: 'That user has already been invited to that group.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_LIKED: {
|
|
message: 'You already liked that page.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_MUTING: {
|
|
message: 'You are already muting that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_PINNED: {
|
|
message: 'You already pinned that note.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_REACTED: {
|
|
message: 'You already reacted to that note.',
|
|
httpStatusCode: 409,
|
|
},
|
|
ALREADY_VOTED: {
|
|
message: 'You have already voted in that poll.',
|
|
httpStatusCode: 409,
|
|
},
|
|
AUTHENTICATION_FAILED: {
|
|
message: 'Authentication failed.',
|
|
httpStatusCode: 401,
|
|
},
|
|
AUTHENTICATION_REQUIRED: {
|
|
message: 'Authentication is required, but authenticating information was not or not appropriately provided.',
|
|
httpStatusCode: 401,
|
|
},
|
|
BLOCKED: {
|
|
message: 'You are blocked by that user.',
|
|
httpStatusCode: 400,
|
|
},
|
|
BLOCKEE_IS_YOURSELF: {
|
|
message: 'You cannot block yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
BLOCKING: {
|
|
message: 'You are blocking that user.',
|
|
httpStatusCode: 400,
|
|
},
|
|
CANNOT_REPORT_ADMIN: {
|
|
message: 'You cannot report an administrator.',
|
|
httpStatusCode: 400,
|
|
},
|
|
CANNOT_REPORT_YOURSELF: {
|
|
message: 'You cannot report yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
EMPTY_FILE: {
|
|
message: 'The provided file is empty.',
|
|
httpStatusCode: 400,
|
|
},
|
|
EXPIRED_POLL: {
|
|
message: 'Poll is already expired.',
|
|
httpStatusCode: 400,
|
|
},
|
|
FAILED_TO_RESOLVE_REMOTE_USER: {
|
|
message: 'Failed to resolve remote user.',
|
|
httpStatusCode: 502,
|
|
},
|
|
FILE_TOO_BIG: {
|
|
message: 'The provided file is too big.',
|
|
httpStatusCode: 400,
|
|
},
|
|
FILE_REQUIRED: {
|
|
message: 'This operation requires a file to be provided.',
|
|
httpStatusCode: 400,
|
|
},
|
|
FOLLOWEE_IS_YOURSELF: {
|
|
message: 'You cannot follow yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
FOLLOWER_IS_YOURSELF: {
|
|
message: 'You cannot unfollow yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
GROUP_OWNER: {
|
|
message: 'The owner of a group may not leave. Instead, ownership can be transferred or the group deleted.',
|
|
httpStatusCode: 400,
|
|
},
|
|
HAS_CHILD_FILES_OR_FOLDERS: {
|
|
message: 'That folder is not empty.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INTERNAL_ERROR: {
|
|
message: 'Internal error occurred. Please contact us if the error persists.',
|
|
httpStatusCode: 500,
|
|
},
|
|
INVALID_CHOICE: {
|
|
message: 'Choice index is invalid.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_FILE_NAME: {
|
|
message: 'Invalid file name.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_PARAM: {
|
|
message: 'One or more parameters do not match the API definition.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_PASSWORD: {
|
|
message: 'The provided password is not suitable.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_REGEXP: {
|
|
message: 'Invalid Regular Expression',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_URL: {
|
|
message: 'Invalid URL.',
|
|
httpStatusCode: 400,
|
|
},
|
|
INVALID_USERNAME: {
|
|
message: 'Invalid username.',
|
|
httpStatusCode: 400,
|
|
},
|
|
IS_ADMIN: {
|
|
message: 'This action cannot be done to an administrator account.',
|
|
httpStatusCode: 400,
|
|
},
|
|
IS_MODERATOR: {
|
|
message: 'This action cannot be done to a moderator account.',
|
|
httpStatusCode: 400,
|
|
},
|
|
LESS_RESTRICTIVE_VISIBILITY: {
|
|
message: 'The visibility cannot be less restrictive than the parent note.',
|
|
httpStatusCode: 400,
|
|
},
|
|
MUTEE_IS_YOURSELF: {
|
|
message: 'You cannot mute yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
NAME_ALREADY_EXISTS: {
|
|
message: 'The specified name already exists.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NO_POLL: {
|
|
message: 'The note does not have an attached poll.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_ANNOUNCEMENT: {
|
|
message: 'No such announcement.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_ANTENNA: {
|
|
message: 'No such antenna.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_APP: {
|
|
message: 'No such app.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_CLIP: {
|
|
message: 'No such clip.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_CHANNEL: {
|
|
message: 'No such channel.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_EMOJI: {
|
|
message: 'No such emoji.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_ENDPOINT: {
|
|
message: 'No such endpoint.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_FILE: {
|
|
message: 'No such file.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_FOLDER: {
|
|
message: 'No such folder.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_FOLLOW_REQUEST: {
|
|
message: 'No such follow request.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_GROUP: {
|
|
message: 'No such user group.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_HASHTAG: {
|
|
message: 'No such hashtag.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_INVITATION: {
|
|
message: 'No such group invitation.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_KEY: {
|
|
message: 'No such key.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_NOTE: {
|
|
message: 'No such note.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_NOTIFICATION: {
|
|
message: 'No such notification.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_MESSAGE: {
|
|
message: 'No such message.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_OBJECT: {
|
|
message: 'No such object.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_PAGE: {
|
|
message: 'No such page.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_PARENT_FOLDER: {
|
|
message: 'No such parent folder.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_RESET_REQUEST: {
|
|
message: 'No such password reset request.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_SESSION: {
|
|
message: 'No such session',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_USER: {
|
|
message: 'No such user.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_USER_LIST: {
|
|
message: 'No such user list.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NO_SUCH_WEBHOOK: {
|
|
message: 'No such webhook.',
|
|
httpStatusCode: 404,
|
|
},
|
|
NOT_AN_IMAGE: {
|
|
message: 'The file specified was expected to be an image, but it is not.',
|
|
httpStatusCode: 400,
|
|
},
|
|
NOT_BLOCKING: {
|
|
message: 'You are not blocking that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_CLIPPED: {
|
|
message: 'That note is not added to that clip.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_FAVORITED: {
|
|
message: 'You have not favorited that note.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_FOLLOWING: {
|
|
message: 'You are not following that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_FOLLOWED: {
|
|
message: 'You are not followed by that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_LIKED: {
|
|
message: 'You have not liked that page.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_MUTING: {
|
|
message: 'You are not muting that user.',
|
|
httpStatusCode: 409,
|
|
},
|
|
NOT_REACTED: {
|
|
message: 'You have not reacted to that note.',
|
|
httpStatusCode: 409,
|
|
},
|
|
PENDING_SESSION: {
|
|
message: 'That authorization process has not been completed yet.',
|
|
httpStatusCode: 400,
|
|
},
|
|
PIN_LIMIT_EXCEEDED: {
|
|
message: 'You can not pin any more notes.',
|
|
httpStatusCode: 400,
|
|
},
|
|
PURE_RENOTE: {
|
|
message: 'You cannot renote or reply to a pure renote.',
|
|
httpStatusCode: 400,
|
|
},
|
|
RATE_LIMIT_EXCEEDED: {
|
|
message: 'Rate limit exceeded. Please try again later.',
|
|
httpStatusCode: 429,
|
|
},
|
|
RECIPIENT_IS_YOURSELF: {
|
|
message: 'You cannot send a message to yourself.',
|
|
httpStatusCode: 400,
|
|
},
|
|
RECURSIVE_FOLDER: {
|
|
message: 'Folder cannot be its own parent.',
|
|
httpStatusCode: 400,
|
|
},
|
|
SUSPENDED: {
|
|
message: 'Your account has been suspended.',
|
|
httpStatusCode: 403,
|
|
},
|
|
TIMELINE_DISABLED: {
|
|
message: 'This timeline is disabled by an administrator.',
|
|
httpStatusCode: 503,
|
|
},
|
|
USED_USERNAME: {
|
|
message: 'That username is not available because it is being used or has been used before. Usernames cannot be reassigned.',
|
|
httpStatusCode: 409,
|
|
},
|
|
};
|