server: refactor ApiError to store error descriptions centrally

The UUIDs are no longer used for errors and all errors should now have
a descriptive message attached to them. Also, all errors should now have
the proper HTTP status code for a reply instead of the generic 400 and 500
response codes. Because the errors all have more specific error codes, the
"kind" of client or server is also abolished.
This commit is contained in:
Johann150 2022-10-20 23:04:24 +02:00
parent 66d7b69377
commit 934ee82b8f
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1
139 changed files with 768 additions and 2241 deletions

View file

@ -13,7 +13,7 @@ export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise<vo
: ctx.request.body;
const error = (e: ApiError): void => {
ctx.status = e.httpStatusCode ?? 500;
ctx.status = e.httpStatusCode;
if (e.httpStatusCode === 401) {
ctx.response.set('WWW-Authenticate', 'Bearer');
}
@ -47,12 +47,7 @@ export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise<vo
});
}).catch(e => {
if (e instanceof AuthenticationError) {
error({
message: 'Authentication failed: ' + e.message,
code: 'AUTHENTICATION_FAILED',
id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14',
httpStatusCode: 401,
});
error(new ApiError('AUTHENTICATION_FAILED', e.message));
} else {
error(new ApiError());
}

View file

@ -8,29 +8,16 @@ import endpoints, { IEndpointMeta } from './endpoints.js';
import { ApiError } from './error.js';
import { apiLogger } from './logger.js';
const accessDenied = {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '56f35758-7dd5-468b-8439-5d6fb8ec9b8e',
};
export default async (endpoint: string, user: CacheableLocalUser | null | undefined, token: AccessToken | null | undefined, data: any, ctx?: Koa.Context) => {
const isSecure = user != null && token == null;
const isModerator = user != null && (user.isModerator || user.isAdmin);
const ep = endpoints.find(e => e.name === endpoint);
if (ep == null) {
throw new ApiError({
message: 'No such endpoint.',
code: 'NO_SUCH_ENDPOINT',
id: 'f8080b67-5f9c-4eb7-8c18-7f1eeae8f709',
httpStatusCode: 404,
});
}
if (ep == null) throw new ApiError('NO_SUCH_ENDPOINT');
if (ep.meta.secure && !isSecure) {
throw new ApiError(accessDenied);
throw new ApiError('ACCESS_DENIED', 'This operation can only be performed with a native token.');
}
if (ep.meta.limit && !isModerator) {
@ -50,47 +37,28 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi
// Rate limit
await limiter(limit as IEndpointMeta['limit'] & { key: NonNullable<string> }, limitActor).catch(e => {
throw new ApiError({
message: 'Rate limit exceeded. Please try again later.',
code: 'RATE_LIMIT_EXCEEDED',
id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef',
httpStatusCode: 429,
});
throw new ApiError('RATE_LIMIT_EXCEEDED');
});
}
if (ep.meta.requireCredential && user == null) {
throw new ApiError({
message: 'Credential required.',
code: 'CREDENTIAL_REQUIRED',
id: '1384574d-a912-4b81-8601-c7b1c4085df1',
httpStatusCode: 401,
});
throw new ApiError('AUTHENTICATION_REQUIRED');
}
if (ep.meta.requireCredential && user!.isSuspended) {
throw new ApiError({
message: 'Your account has been suspended.',
code: 'YOUR_ACCOUNT_SUSPENDED',
id: 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370',
httpStatusCode: 403,
});
throw new ApiError('SUSPENDED');
}
if (ep.meta.requireAdmin && !user!.isAdmin) {
throw new ApiError(accessDenied, { reason: 'You are not the admin.' });
throw new ApiError('ACCESS_DENIED', 'This operation requires administrator privileges.');
}
if (ep.meta.requireModerator && !isModerator) {
throw new ApiError(accessDenied, { reason: 'You are not a moderator.' });
throw new ApiError('ACCESS_DENIED', 'This operation requires moderator privileges.');
}
if (token && ep.meta.kind && !token.permission.some(p => p === ep.meta.kind)) {
throw new ApiError({
message: 'Your app does not have the necessary permissions to use this endpoint.',
code: 'PERMISSION_DENIED',
id: '1370e5b7-d4eb-4566-bb1d-7748ee6a1838',
});
throw new ApiError('ACCESS_DENIED', 'This operation requires privileges which this token does not grant.');
}
// Cast non JSON input
@ -101,11 +69,7 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi
try {
data[k] = JSON.parse(data[k]);
} catch (e) {
throw new ApiError({
message: 'Invalid param.',
code: 'INVALID_PARAM',
id: '0b5f1631-7c1a-41a6-b399-cce335f34d85',
}, {
throw new ApiError('INVALID_PARAM', {
param: k,
reason: `cannot cast to ${param.type}`,
});
@ -129,7 +93,7 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi
stack: e.stack,
},
});
throw new ApiError(null, {
throw new ApiError('INTERNAL_ERROR', {
e: {
message: e.message,
code: e.name,

View file

@ -24,25 +24,13 @@ export async function signup(opts: {
// Validate username
if (!Users.validateLocalUsername(username)) {
throw new ApiError({
message: 'This username is invalid.',
code: 'INVALID_USERNAME',
id: 'ece89f3c-d845-4d9a-850b-1735285e8cd4',
kind: 'client',
httpStatusCode: 400,
});
throw new ApiError('INVALID_USERNAME');
}
if (password != null && passwordHash == null) {
// Validate password
if (!Users.validatePassword(password)) {
throw new ApiError({
message: 'This password is invalid.',
code: 'INVALID_PASSWORD',
id: 'a941905b-fe7b-43e2-8ecd-50ad3a2287ab',
kind: 'client',
httpStatusCode: 400,
});
throw new ApiError('INVALID_PASSWORD');
}
// Generate hash of password
@ -53,22 +41,14 @@ export async function signup(opts: {
// Generate secret
const secret = generateUserToken();
const duplicateUsernameError = {
message: 'This username is not available.',
code: 'USED_USERNAME',
id: '7ddd595e-6860-4593-93c5-9fdbcb80cd81',
kind: 'client',
httpStatusCode: 409,
};
// Check username duplication
if (await Users.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull() })) {
throw new ApiError(duplicateUsernameError);
throw new ApiError('USED_USERNAME');
}
// Check deleted username duplication
if (await UsedUsernames.findOneBy({ username: username.toLowerCase() })) {
throw new ApiError(duplicateUsernameError);
throw new ApiError('USED_USERNAME');
}
const keyPair = await new Promise<string[]>((res, rej) =>
@ -97,7 +77,7 @@ export async function signup(opts: {
host: IsNull(),
});
if (exist) throw new ApiError(duplicateUsernameError);
if (exist) throw new ApiError('USED_USERNAME');
account = await transactionalEntityManager.save(new User({
id: genId(),

View file

@ -28,22 +28,16 @@ export default function <T extends IEndpointMeta, Ps extends Schema>(meta: T, pa
fs.unlink(file.path, () => {});
}
if (meta.requireFile && file == null) return Promise.reject(new ApiError({
message: 'File required.',
code: 'FILE_REQUIRED',
id: '4267801e-70d1-416a-b011-4ee502885d8b',
}));
if (meta.requireFile && file == null) {
return Promise.reject(new ApiError('FILE_REQUIRED'));
}
const valid = validate(params);
if (!valid) {
if (file) cleanup();
const errors = validate.errors!;
const err = new ApiError({
message: 'Invalid param.',
code: 'INVALID_PARAM',
id: '3d81ceae-475f-4600-b2a8-2bc116157532',
}, {
const err = new ApiError('INVALID_PARAM', {
param: errors[0].schemaPath,
reason: errors[0].message,
});

View file

@ -8,13 +8,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchAnnouncement: {
message: 'No such announcement.',
code: 'NO_SUCH_ANNOUNCEMENT',
id: 'ecad8040-a276-4e85-bda9-015a708d291e',
},
},
errors: ['NO_SUCH_ANNOUNCEMENT'],
} as const;
export const paramDef = {
@ -29,7 +23,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const announcement = await Announcements.findOneBy({ id: ps.id });
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT');
await Announcements.delete(announcement.id);
});

View file

@ -8,13 +8,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchAnnouncement: {
message: 'No such announcement.',
code: 'NO_SUCH_ANNOUNCEMENT',
id: 'd3aae5a7-6372-4cb4-b61c-f511ffc2d7cc',
},
},
errors: ['NO_SUCH_ANNOUNCEMENT'],
} as const;
export const paramDef = {
@ -32,7 +26,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const announcement = await Announcements.findOneBy({ id: ps.id });
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT');
await Announcements.update(announcement.id, {
updatedAt: new Date(),

View file

@ -8,13 +8,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'caf3ca38-c6e5-472e-a30c-b05377dcc240',
},
},
errors: ['NO_SUCH_FILE'],
res: {
type: 'object',
@ -180,9 +174,7 @@ export default define(meta, paramDef, async (ps, me) => {
}],
});
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
return file;
});

View file

@ -13,13 +13,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf',
},
},
errors: ['NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -34,7 +28,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) throw new ApiError(meta.errors.noSuchFile);
if (file == null) throw new ApiError('NO_SUCH_FILE');
const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`;

View file

@ -13,13 +13,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchEmoji: {
message: 'No such emoji.',
code: 'NO_SUCH_EMOJI',
id: 'e2785b66-dca3-4087-9cac-b93c541cc425',
},
},
errors: ['NO_SUCH_EMOJI', 'INTERNAL_ERROR'],
res: {
type: 'object',
@ -46,9 +40,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const emoji = await Emojis.findOneBy({ id: ps.emojiId });
if (emoji == null) {
throw new ApiError(meta.errors.noSuchEmoji);
}
if (emoji == null) throw new ApiError('NO_SUCH_EMOJI');
let driveFile: DriveFile;
@ -56,7 +48,7 @@ export default define(meta, paramDef, async (ps, me) => {
// Create file
driveFile = await uploadFromUrl({ url: emoji.originalUrl, user: null, force: true });
} catch (e) {
throw new ApiError();
throw new ApiError('INTERNAL_ERROR', e);
}
const copied = await Emojis.insert({

View file

@ -10,13 +10,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchEmoji: {
message: 'No such emoji.',
code: 'NO_SUCH_EMOJI',
id: 'be83669b-773a-44b7-b1f8-e5e5170ac3c2',
},
},
errors: ['NO_SUCH_EMOJI'],
} as const;
export const paramDef = {
@ -31,7 +25,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, me) => {
const emoji = await Emojis.findOneBy({ id: ps.id });
if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
if (emoji == null) throw new ApiError('NO_SUCH_EMOJI');
await Emojis.delete(emoji.id);

View file

@ -9,13 +9,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
noSuchEmoji: {
message: 'No such emoji.',
code: 'NO_SUCH_EMOJI',
id: '684dec9d-a8c2-4364-9aa8-456c49cb1dc8',
},
},
errors: ['NO_SUCH_EMOJI'],
} as const;
export const paramDef = {
@ -39,7 +33,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps) => {
const emoji = await Emojis.findOneBy({ id: ps.id });
if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji);
if (emoji == null) throw new ApiError('NO_SUCH_EMOJI');
await Emojis.update(emoji.id, {
updatedAt: new Date(),

View file

@ -9,13 +9,7 @@ export const meta = {
requireCredential: true,
requireModerator: true,
errors: {
invalidUrl: {
message: 'Invalid URL',
code: 'INVALID_URL',
id: 'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c',
},
},
errors: ['INVALID_URL'],
res: {
type: 'object',
@ -58,8 +52,8 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
try {
if (new URL(ps.inbox).protocol !== 'https:') throw new Error('https only');
} catch {
throw new ApiError(meta.errors.invalidUrl);
} catch (e) {
throw new ApiError('INVALID_URL', e);
}
return await addRelay(ps.inbox);

View file

@ -11,19 +11,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchUserList: {
message: 'No such user list.',
code: 'NO_SUCH_USER_LIST',
id: '95063e93-a283-4b8b-9aa5-bcdb8df69a7f',
},
noSuchUserGroup: {
message: 'No such user group.',
code: 'NO_SUCH_USER_GROUP',
id: 'aa3c0b9a-8cae-47c0-92ac-202ce5906682',
},
},
errors: ['NO_SUCH_USER_LIST', 'NO_SUCH_GROUP'],
res: {
type: 'object',
@ -71,18 +59,14 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
if (userList == null) throw new ApiError('NO_SUCH_USER_LIST');
} else if (ps.src === 'group' && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id,
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
if (userGroupJoining == null) throw new ApiError('NO_SUCH_GROUP');
}
const antenna = await Antennas.insert({

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchAntenna: {
message: 'No such antenna.',
code: 'NO_SUCH_ANTENNA',
id: 'b34dcf9d-348f-44bb-99d0-6c9314cfe2df',
},
},
errors: ['NO_SUCH_ANTENNA'],
} as const;
export const paramDef = {
@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA');
await Antennas.delete(antenna.id);

View file

@ -14,13 +14,7 @@ export const meta = {
kind: 'read:account',
errors: {
noSuchAntenna: {
message: 'No such antenna.',
code: 'NO_SUCH_ANTENNA',
id: '850926e0-fd3b-49b6-b69a-b28a5dbd82fe',
},
},
errors: ['NO_SUCH_ANTENNA'],
res: {
type: 'array',
@ -53,9 +47,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA');
const query = makePaginationQuery(Notes.createQueryBuilder('note'),
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'read:account',
errors: {
noSuchAntenna: {
message: 'No such antenna.',
code: 'NO_SUCH_ANTENNA',
id: 'c06569fb-b025-4f23-b22d-1fcd20d2816b',
},
},
errors: ['NO_SUCH_ANTENNA'],
res: {
type: 'object',
@ -40,9 +34,7 @@ export default define(meta, paramDef, async (ps, me) => {
userId: me.id,
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA');
return await Antennas.pack(antenna);
});

View file

@ -10,25 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchAntenna: {
message: 'No such antenna.',
code: 'NO_SUCH_ANTENNA',
id: '10c673ac-8852-48eb-aa1f-f5b67f069290',
},
noSuchUserList: {
message: 'No such user list.',
code: 'NO_SUCH_USER_LIST',
id: '1c6b35c9-943e-48c2-81e4-2844989407f7',
},
noSuchUserGroup: {
message: 'No such user group.',
code: 'NO_SUCH_USER_GROUP',
id: '109ed789-b6eb-456e-b8a9-6059d567d385',
},
},
errors: ['NO_SUCH_ANTENNA', 'NO_SUCH_USER_LIST', 'NO_SUCH_GROUP'],
res: {
type: 'object',
@ -74,9 +56,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (antenna == null) {
throw new ApiError(meta.errors.noSuchAntenna);
}
if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA');
let userList;
let userGroupJoining;
@ -87,18 +67,14 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
if (userList == null) throw new ApiError('NO_SUCH_USER_LIST');
} else if (ps.src === 'group' && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id,
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
if (userGroupJoining == null) throw new ApiError('NO_SUCH_GROUP');
}
await Antennas.update(antenna.id, {

View file

@ -12,9 +12,6 @@ export const meta = {
max: 30,
},
errors: {
},
res: {
type: 'object',
optional: false, nullable: false,

View file

@ -24,13 +24,7 @@ export const meta = {
max: 30,
},
errors: {
noSuchObject: {
message: 'No such object.',
code: 'NO_SUCH_OBJECT',
id: 'dc94d745-1262-4e63-a17d-fecaa57efc82',
},
},
errors: ['NO_SUCH_OBJECT'],
res: {
optional: false, nullable: false,
@ -83,7 +77,7 @@ export default define(meta, paramDef, async (ps, me) => {
if (object) {
return object;
} else {
throw new ApiError(meta.errors.noSuchObject);
throw new ApiError('NO_SUCH_OBJECT');
}
});

View file

@ -5,13 +5,7 @@ import { ApiError } from '../../error.js';
export const meta = {
tags: ['app'],
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: 'dce83913-2dc6-4093-8a7b-71dbb11718a3',
},
},
errors: ['NO_SUCH_APP'],
res: {
type: 'object',
@ -33,14 +27,12 @@ export default define(meta, paramDef, async (ps, user, token) => {
const isSecure = user != null && token == null;
// Lookup app
const ap = await Apps.findOneBy({ id: ps.appId });
const app = await Apps.findOneBy({ id: ps.appId });
if (ap == null) {
throw new ApiError(meta.errors.noSuchApp);
}
if (app == null) throw new ApiError('NO_SUCH_APP');
return await Apps.pack(ap, user, {
return await Apps.pack(app, user, {
detail: true,
includeSecret: isSecure && (ap.userId === user!.id),
includeSecret: isSecure && (app.userId === user!.id),
});
});

View file

@ -12,13 +12,7 @@ export const meta = {
secure: true,
errors: {
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: '9c72d8de-391a-43c1-9d06-08d29efde8df',
},
},
errors: ['NO_SUCH_SESSION'],
} as const;
export const paramDef = {
@ -35,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => {
const session = await AuthSessions
.findOneBy({ token: ps.token });
if (session == null) {
throw new ApiError(meta.errors.noSuchSession);
}
if (session == null) throw new ApiError('NO_SUCH_SESSION');
// Generate access token
const accessToken = secureRndstr(32, true);

View file

@ -26,13 +26,7 @@ export const meta = {
},
},
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: '92f93e63-428e-4f2f-a5a4-39e1407fe998',
},
},
errors: ['NO_SUCH_APP'],
} as const;
export const paramDef = {
@ -51,7 +45,7 @@ export default define(meta, paramDef, async (ps) => {
});
if (app == null) {
throw new ApiError(meta.errors.noSuchApp);
throw new ApiError('NO_SUCH_APP');
}
// Generate token

View file

@ -7,13 +7,7 @@ export const meta = {
requireCredential: false,
errors: {
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: 'bd72c97d-eba7-4adb-a467-f171b8847250',
},
},
errors: ['NO_SUCH_SESSION'],
res: {
type: 'object',
@ -52,9 +46,7 @@ export default define(meta, paramDef, async (ps, user) => {
token: ps.token,
});
if (session == null) {
throw new ApiError(meta.errors.noSuchSession);
}
if (session == null) throw new ApiError('NO_SUCH_SESSION');
return await AuthSessions.pack(session, user);
});

View file

@ -24,25 +24,7 @@ export const meta = {
},
},
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: 'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d',
},
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: '5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3',
},
pendingSession: {
message: 'This session is not completed yet.',
code: 'PENDING_SESSION',
id: '8c8a4145-02cc-4cca-8e66-29ba60445a8e',
},
},
errors: ['NO_SUCH_APP', 'NO_SUCH_SESSION', 'PENDING_SESSION'],
} as const;
export const paramDef = {
@ -61,9 +43,7 @@ export default define(meta, paramDef, async (ps) => {
secret: ps.appSecret,
});
if (app == null) {
throw new ApiError(meta.errors.noSuchApp);
}
if (app == null) throw new ApiError('NO_SUCH_APP');
// Fetch token
const session = await AuthSessions.findOneBy({
@ -71,13 +51,9 @@ export default define(meta, paramDef, async (ps) => {
appId: app.id,
});
if (session == null) {
throw new ApiError(meta.errors.noSuchSession);
}
if (session == null) throw new ApiError('NO_SUCH_SESSION');
if (session.userId == null) {
throw new ApiError(meta.errors.pendingSession);
}
if (session.userId == null) throw new ApiError('PENDING_SESSION');
// Lookup access token
const accessToken = await AccessTokens.findOneByOrFail({

View file

@ -17,25 +17,7 @@ export const meta = {
kind: 'write:blocks',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '7cc4f851-e2f1-4621-9633-ec9e1d00c01e',
},
blockeeIsYourself: {
message: 'Blockee is yourself.',
code: 'BLOCKEE_IS_YOURSELF',
id: '88b19138-f28d-42c0-8499-6a31bbd0fdc6',
},
alreadyBlocking: {
message: 'You are already blocking that user.',
code: 'ALREADY_BLOCKING',
id: '787fed64-acb9-464a-82eb-afbd745b9614',
},
},
errors: ['NO_SUCH_USER', 'BLOCKEE_IS_YOURSELF', 'ALREADY_BLOCKING'],
res: {
type: 'object',
@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => {
const blocker = await Users.findOneByOrFail({ id: user.id });
// 自分自身
if (user.id === ps.userId) {
throw new ApiError(meta.errors.blockeeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('BLOCKEE_IS_YOURSELF');
// Get blockee
const blockee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
blockeeId: blockee.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyBlocking);
}
if (exist != null) throw new ApiError('ALREADY_BLOCKING');
await create(blocker, blockee);

View file

@ -17,25 +17,7 @@ export const meta = {
kind: 'write:blocks',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '8621d8bf-c358-4303-a066-5ea78610eb3f',
},
blockeeIsYourself: {
message: 'Blockee is yourself.',
code: 'BLOCKEE_IS_YOURSELF',
id: '06f6fac6-524b-473c-a354-e97a40ae6eac',
},
notBlocking: {
message: 'You are not blocking that user.',
code: 'NOT_BLOCKING',
id: '291b2efa-60c6-45c0-9f6a-045c8f9b02cd',
},
},
errors: ['NO_SUCH_USER', 'BLOCKEE_IS_YOURSELF', 'NOT_BLOCKING'],
res: {
type: 'object',
@ -54,16 +36,14 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const blocker = await Users.findOneByOrFail({ id: user.id });
// Check if the blockee is yourself
if (user.id === ps.userId) {
throw new ApiError(meta.errors.blockeeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('BLOCKEE_IS_YOURSELF');
const blocker = await Users.findOneByOrFail({ id: user.id });
// Get blockee
const blockee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
blockeeId: blockee.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notBlocking);
}
if (exist == null) throw new ApiError('NOT_BLOCKING');
// Delete blocking
await deleteBlocking(blocker, blockee);

View file

@ -17,13 +17,7 @@ export const meta = {
ref: 'Channel',
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050',
},
},
errors: ['NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -45,9 +39,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (banner == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (banner == null) throw new ApiError('NO_SUCH_FILE');
}
const channel = await Channels.insert({

View file

@ -11,13 +11,7 @@ export const meta = {
kind: 'write:channels',
errors: {
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: 'c0031718-d573-4e85-928e-10039f1fbb68',
},
},
errors: ['NO_SUCH_CHANNEL'],
} as const;
export const paramDef = {
@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => {
id: ps.channelId,
});
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
await ChannelFollowings.insert({
id: genId(),

View file

@ -13,13 +13,7 @@ export const meta = {
ref: 'Channel',
},
errors: {
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: '6f6c314b-7486-4897-8966-c04a66a02923',
},
},
errors: ['NO_SUCH_CHANNEL'],
} as const;
export const paramDef = {
@ -36,9 +30,7 @@ export default define(meta, paramDef, async (ps, me) => {
id: ps.channelId,
});
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
return await Channels.pack(channel, me);
});

View file

@ -19,13 +19,7 @@ export const meta = {
},
},
errors: {
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: '4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f',
},
},
errors: ['NO_SUCH_CHANNEL'],
} as const;
export const paramDef = {
@ -47,9 +41,7 @@ export default define(meta, paramDef, async (ps, user) => {
id: ps.channelId,
});
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
//#region Construct query
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:channels',
errors: {
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: '19959ee9-0153-4c51-bbd9-a98c49dc59d6',
},
},
errors: ['NO_SUCH_CHANNEL'],
} as const;
export const paramDef = {
@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
id: ps.channelId,
});
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
await ChannelFollowings.delete({
followerId: user.id,

View file

@ -15,25 +15,7 @@ export const meta = {
ref: 'Channel',
},
errors: {
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: 'f9c5467f-d492-4c3c-9a8d-a70dacc86512',
},
accessDenied: {
message: 'You do not have edit privilege of the channel.',
code: 'ACCESS_DENIED',
id: '1fb7cb09-d46a-4fdf-b8df-057788cce513',
},
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e86c14a4-0da2-4032-8df3-e737a04c7f3b',
},
},
errors: ['ACCESS_DENIED', 'NO_SUCH_CHANNEL', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -53,13 +35,9 @@ export default define(meta, paramDef, async (ps, me) => {
id: ps.channelId,
});
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
if (channel.userId !== me.id) {
throw new ApiError(meta.errors.accessDenied);
}
if (channel.userId !== me.id) throw new ApiError('ACCESS_DENIED', 'You are not the owner of this channel.');
// eslint:disable-next-line:no-unnecessary-initializer
let banner = undefined;
@ -69,9 +47,7 @@ export default define(meta, paramDef, async (ps, me) => {
userId: me.id,
});
if (banner == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (banner == null) throw new ApiError('NO_SUCH_FILE');
} else if (ps.bannerId === null) {
banner = null;
}

View file

@ -11,25 +11,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: 'd6e76cc0-a1b5-4c7c-a287-73fa9c716dcf',
},
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b',
},
alreadyClipped: {
message: 'The note has already been clipped.',
code: 'ALREADY_CLIPPED',
id: '734806c4-542c-463a-9311-15c512803965',
},
},
errors: ['ALREADY_CLIPPED', 'NO_SUCH_CLIP', 'NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -48,12 +30,10 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
@ -62,9 +42,7 @@ export default define(meta, paramDef, async (ps, user) => {
clipId: clip.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyClipped);
}
if (exist != null) throw new ApiError('ALREADY_CLIPPED');
await ClipNotes.insert({
id: genId(),

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: '70ca08ba-6865-4630-b6fb-8494759aa754',
},
},
errors: ['NO_SUCH_CLIP'],
} as const;
export const paramDef = {
@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
await Clips.delete(clip.id);
});

View file

@ -13,13 +13,7 @@ export const meta = {
kind: 'read:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: '1d7645e6-2b6d-4635-b0fe-fe22b0e72e00',
},
},
errors: ['NO_SUCH_CLIP'],
res: {
type: 'array',
@ -49,12 +43,10 @@ export default define(meta, paramDef, async (ps, user) => {
id: ps.clipId,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
if (!clip.isPublic && (user == null || (clip.userId !== user.id))) {
throw new ApiError(meta.errors.noSuchClip);
throw new ApiError('NO_SUCH_CLIP');
}
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)

View file

@ -10,26 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: 'b80525c6-97f7-49d7-a42d-ebccd49cfd52',
},
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'aff017de-190e-434b-893e-33a9ff5049d8',
},
notClipped: {
message: 'That note is not added to this clip.',
code: 'NOT_CLIPPED',
id: '6b20c697-6e51-4120-b340-0e47899c7a20',
httpStatusCode: 409,
},
},
errors: ['NO_SUCH_CLIP', 'NO_SUCH_NOTE', 'NOT_CLIPPED'],
} as const;
export const paramDef = {
@ -48,12 +29,10 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
const note = await getNote(ps.noteId).catch(e => {
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw e;
});
@ -62,7 +41,5 @@ export default define(meta, paramDef, async (ps, user) => {
clipId: clip.id,
});
if (affected === 0) {
throw new ApiError(meta.errors.notClipped);
}
if (affected === 0) throw new ApiError('NOT_CLIPPED');
});

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'read:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: 'c3c5fe33-d62c-44d2-9ea5-d997703f5c20',
},
},
errors: ['NO_SUCH_CLIP'],
res: {
type: 'object',
@ -39,12 +33,10 @@ export default define(meta, paramDef, async (ps, me) => {
id: ps.clipId,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
if (!clip.isPublic && (me == null || (clip.userId !== me.id))) {
throw new ApiError(meta.errors.noSuchClip);
throw new ApiError('NO_SUCH_CLIP');
}
return await Clips.pack(clip);

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchClip: {
message: 'No such clip.',
code: 'NO_SUCH_CLIP',
id: 'b4d92d70-b216-46fa-9a3f-a8c811699257',
},
},
errors: ['NO_SUCH_CLIP'],
res: {
type: 'object',
@ -43,9 +37,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (clip == null) {
throw new ApiError(meta.errors.noSuchClip);
}
if (clip == null) throw new ApiError('NO_SUCH_CLIP');
await Clips.update(clip.id, {
name: ps.name,

View file

@ -21,13 +21,7 @@ export const meta = {
},
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'c118ece3-2e4b-4296-99d1-51756e32d232',
},
},
errors: ['NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -46,9 +40,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
const notes = await Notes.createQueryBuilder('note')
.where(':file = ANY(note.fileIds)', { file: file.id })

View file

@ -28,13 +28,7 @@ export const meta = {
ref: 'DriveFile',
},
errors: {
invalidFileName: {
message: 'Invalid file name.',
code: 'INVALID_FILE_NAME',
id: 'f449b209-0c60-4e51-84d5-29486263bfd4',
},
},
errors: ['INTERNAL_ERROR', 'INVALID_FILE_NAME'],
} as const;
export const paramDef = {
@ -60,7 +54,7 @@ export default define(meta, paramDef, async (ps, user, _, file, cleanup) => {
} else if (name === 'blob') {
name = null;
} else if (!DriveFiles.validateFileName(name)) {
throw new ApiError(meta.errors.invalidFileName);
throw new ApiError('INVALID_FILE_NAME');
}
} else {
name = null;
@ -74,7 +68,7 @@ export default define(meta, paramDef, async (ps, user, _, file, cleanup) => {
if (e instanceof Error || typeof e === 'string') {
apiLogger.error(e);
}
throw new ApiError();
throw new ApiError('INTERNAL_ERROR');
} finally {
cleanup!();
}

View file

@ -13,19 +13,7 @@ export const meta = {
description: 'Delete an existing drive file.',
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '908939ec-e52b-4458-b395-1025195cea58',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '5eb8d909-2540-4970-90b8-dd6f86088121',
},
},
errors: ['ACCESS_DENIED', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -40,12 +28,10 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) {
throw new ApiError(meta.errors.accessDenied);
throw new ApiError('ACCESS_DENIED');
}
// Delete

View file

@ -18,19 +18,7 @@ export const meta = {
ref: 'DriveFile',
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '067bc436-2718-4795-b0fb-ecbe43949e31',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '25b73c73-68b1-41d0-bad1-381cfdf6579f',
},
},
errors: ['ACCESS_DENIED', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -69,12 +57,10 @@ export default define(meta, paramDef, async (ps, user) => {
});
}
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) {
throw new ApiError(meta.errors.accessDenied);
throw new ApiError('ACCESS_DENIED');
}
return await DriveFiles.pack(file, {

View file

@ -12,31 +12,7 @@ export const meta = {
description: 'Update the properties of a drive file.',
errors: {
invalidFileName: {
message: 'Invalid file name.',
code: 'INVALID_FILE_NAME',
id: '395e7156-f9f0-475e-af89-53c3c23080c2',
},
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '01a53b27-82fc-445b-a0c1-b558465a8ed2',
},
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'ea8fb7a5-af77-4a08-b608-c0218176cd73',
},
},
errors: ['ACCESS_DENIED', 'INVALID_FILE_NAME', 'NO_SUCH_FILE', 'NO_SUCH_FOLDER'],
res: {
type: 'object',
@ -61,17 +37,15 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) {
throw new ApiError(meta.errors.accessDenied);
throw new ApiError('ACCESS_DENIED');
}
if (ps.name) file.name = ps.name;
if (!DriveFiles.validateFileName(file.name)) {
throw new ApiError(meta.errors.invalidFileName);
throw new ApiError('INVALID_FILE_NAME');
}
if (ps.comment !== undefined) file.comment = ps.comment;
@ -87,9 +61,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (folder == null) {
throw new ApiError(meta.errors.noSuchFolder);
}
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
file.folderId = folder.id;
}

View file

@ -11,13 +11,7 @@ export const meta = {
kind: 'write:drive',
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: '53326628-a00d-40a6-a3cd-8975105c0f95',
},
},
errors: ['NO_SUCH_FOLDER'],
res: {
type: 'object' as const,
@ -46,9 +40,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (parent == null) {
throw new ApiError(meta.errors.noSuchFolder);
}
if (parent == null) throw new ApiError('NO_SUCH_FOLDER');
}
// Create folder

View file

@ -10,19 +10,7 @@ export const meta = {
kind: 'write:drive',
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: '1069098f-c281-440f-b085-f9932edbe091',
},
hasChildFilesOrFolders: {
message: 'This folder has child files or folders.',
code: 'HAS_CHILD_FILES_OR_FOLDERS',
id: 'b0fc8a17-963c-405d-bfbc-859a487295e1',
},
},
errors: ['HAS_CHILD_FILES_OR_FOLDERS', 'NO_SUCH_FOLDER'],
} as const;
export const paramDef = {
@ -41,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (folder == null) {
throw new ApiError(meta.errors.noSuchFolder);
}
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
const [childFoldersCount, childFilesCount] = await Promise.all([
DriveFolders.countBy({ parentId: folder.id }),
@ -51,7 +37,7 @@ export default define(meta, paramDef, async (ps, user) => {
]);
if (childFoldersCount !== 0 || childFilesCount !== 0) {
throw new ApiError(meta.errors.hasChildFilesOrFolders);
throw new ApiError('HAS_CHILD_FILES_OR_FOLDERS');
}
await DriveFolders.delete(folder.id);

View file

@ -15,13 +15,7 @@ export const meta = {
ref: 'DriveFolder',
},
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'd74ab9eb-bb09-4bba-bf24-fb58f761e1e9',
},
},
errors: ['NO_SUCH_FOLDER'],
} as const;
export const paramDef = {
@ -40,9 +34,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (folder == null) {
throw new ApiError(meta.errors.noSuchFolder);
}
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
return await DriveFolders.pack(folder, {
detail: true,

View file

@ -10,25 +10,7 @@ export const meta = {
kind: 'write:drive',
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'f7974dac-2c0d-4a27-926e-23583b28e98e',
},
noSuchParentFolder: {
message: 'No such parent folder.',
code: 'NO_SUCH_PARENT_FOLDER',
id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1',
},
recursiveNesting: {
message: 'It can not be structured like nesting folders recursively.',
code: 'NO_SUCH_PARENT_FOLDER',
id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1',
},
},
errors: ['NO_SUCH_FOLDER', 'NO_SUCH_PARENT_FOLDER', 'RECURSIVE_FOLDER'],
res: {
type: 'object',
@ -55,15 +37,13 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (folder == null) {
throw new ApiError(meta.errors.noSuchFolder);
}
if (folder == null) throw new ApiError('NO_SUCH_FOLDER');
if (ps.name) folder.name = ps.name;
if (ps.parentId !== undefined) {
if (ps.parentId === folder.id) {
throw new ApiError(meta.errors.recursiveNesting);
throw new ApiError('RECURSIVE_FOLDER');
} else if (ps.parentId === null) {
folder.parentId = null;
} else {
@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (parent == null) {
throw new ApiError(meta.errors.noSuchParentFolder);
}
if (parent == null) throw new ApiError('NO_SUCH_PARENT_FOLDER');
// Check if the circular reference will occur
async function checkCircle(folderId: string): Promise<boolean> {
@ -95,7 +73,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (parent.parentId !== null) {
if (await checkCircle(parent.parentId)) {
throw new ApiError(meta.errors.recursiveNesting);
throw new ApiError('RECURSIVE_FOLDER');
}
}

View file

@ -18,37 +18,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5',
},
followeeIsYourself: {
message: 'Followee is yourself.',
code: 'FOLLOWEE_IS_YOURSELF',
id: '26fbe7bb-a331-4857-af17-205b426669a9',
},
alreadyFollowing: {
message: 'You are already following that user.',
code: 'ALREADY_FOLLOWING',
id: '35387507-38c7-4cb9-9197-300b93783fa0',
},
blocking: {
message: 'You are blocking that user.',
code: 'BLOCKING',
id: '4e2206ec-aa4f-4960-b865-6c23ac38e2d9',
},
blocked: {
message: 'You are blocked by that user.',
code: 'BLOCKED',
id: 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0',
},
},
errors: ['ALREADY_FOLLOWING', 'BLOCKING', 'BLOCKED', 'FOLLOWEE_IS_YOURSELF', 'NO_SUCH_USER'],
res: {
type: 'object',
@ -70,13 +40,11 @@ export default define(meta, paramDef, async (ps, user) => {
const follower = user;
// 自分自身
if (user.id === ps.userId) {
throw new ApiError(meta.errors.followeeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('FOLLOWEE_IS_YOURSELF');
// Get followee
const followee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -86,16 +54,14 @@ export default define(meta, paramDef, async (ps, user) => {
followeeId: followee.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyFollowing);
}
if (exist != null) throw new ApiError('ALREADY_FOLLOWING');
try {
await create(follower, followee);
} catch (e) {
if (e instanceof IdentifiableError) {
if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking);
if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError(meta.errors.blocked);
if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError('BLOCKING');
if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError('BLOCKED');
}
throw e;
}

View file

@ -17,25 +17,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8',
},
followeeIsYourself: {
message: 'Followee is yourself.',
code: 'FOLLOWEE_IS_YOURSELF',
id: 'd9e400b9-36b0-4808-b1d8-79e707f1296c',
},
notFollowing: {
message: 'You are not following that user.',
code: 'NOT_FOLLOWING',
id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09',
},
},
errors: ['FOLLOWEE_IS_YOURSELF', 'NO_SUCH_USER', 'NOT_FOLLOWING'],
res: {
type: 'object',
@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => {
const follower = user;
// Check if the followee is yourself
if (user.id === ps.userId) {
throw new ApiError(meta.errors.followeeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('FOLLOWEE_IS_YOURSELF');
// Get followee
const followee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
followeeId: followee.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notFollowing);
}
if (exist == null) throw new ApiError('NOT_FOLLOWING');
await deleteFollowing(follower, followee);

View file

@ -17,25 +17,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8',
},
followerIsYourself: {
message: 'Follower is yourself.',
code: 'FOLLOWER_IS_YOURSELF',
id: '07dc03b9-03da-422d-885b-438313707662',
},
notFollowing: {
message: 'The other use is not following you.',
code: 'NOT_FOLLOWING',
id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09',
},
},
errors: ['FOLLOWER_IS_YOURSELF', 'NO_SUCH_USER', 'NOT_FOLLOWING'],
res: {
type: 'object',
@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => {
const followee = user;
// Check if the follower is yourself
if (user.id === ps.userId) {
throw new ApiError(meta.errors.followerIsYourself);
}
if (user.id === ps.userId) throw new ApiError('FOLLOWER_IS_YOURSELF');
// Get follower
const follower = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
followeeId: followee.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notFollowing);
}
if (exist == null) throw new ApiError('NOT_FOLLOWING');
await deleteFollowing(follower, followee);

View file

@ -10,18 +10,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '66ce1645-d66c-46bb-8b79-96739af885bd',
},
noFollowRequest: {
message: 'No follow request.',
code: 'NO_FOLLOW_REQUEST',
id: 'bcde4f8b-0913-4614-8881-614e522fb041',
},
},
errors: ['NO_SUCH_USER', 'NO_SUCH_FOLLOW_REQUEST'],
} as const;
export const paramDef = {
@ -36,12 +25,12 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// Fetch follower
const follower = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
await acceptFollowRequest(user, follower).catch(e => {
if (e.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError(meta.errors.noFollowRequest);
if (e.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError('NO_SUCH_FOLLOW_REQUEST');
throw e;
});

View file

@ -12,19 +12,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab',
},
followRequestNotFound: {
message: 'Follow request not found.',
code: 'FOLLOW_REQUEST_NOT_FOUND',
id: '089b125b-d338-482a-9a09-e2622ac9f8d4',
},
},
errors: ['NO_SUCH_USER', 'NO_SUCH_FOLLOW_REQUEST'],
res: {
type: 'object',
@ -45,7 +33,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// Fetch followee
const followee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -53,7 +41,7 @@ export default define(meta, paramDef, async (ps, user) => {
await cancelFollowRequest(followee, user);
} catch (e) {
if (e instanceof IdentifiableError) {
if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(meta.errors.followRequestNotFound);
if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError('NO_SUCH_FOLLOW_REQUEST');
}
throw e;
}

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:following',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555',
},
},
errors: ['NO_SUCH_USER'],
} as const;
export const paramDef = {
@ -31,7 +25,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// Fetch follower
const follower = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});

View file

@ -22,10 +22,6 @@ export const meta = {
optional: false, nullable: false,
ref: 'GalleryPost',
},
errors: {
},
} as const;
export const paramDef = {

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'write:gallery',
errors: {
noSuchPost: {
message: 'No such post.',
code: 'NO_SUCH_POST',
id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5',
},
},
errors: ['NO_SUCH_POST'],
} as const;
export const paramDef = {
@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (post == null) {
throw new ApiError(meta.errors.noSuchPost);
}
if (post == null) throw new ApiError('NO_SUCH_POST');
await GalleryPosts.delete(post.id);
});

View file

@ -10,19 +10,7 @@ export const meta = {
kind: 'write:gallery-likes',
errors: {
noSuchPost: {
message: 'No such post.',
code: 'NO_SUCH_POST',
id: '56c06af3-1287-442f-9701-c93f7c4a62ff',
},
alreadyLiked: {
message: 'The post has already been liked.',
code: 'ALREADY_LIKED',
id: '40e9ed56-a59c-473a-bf3f-f289c54fb5a7',
},
},
errors: ['NO_SUCH_POST', 'ALREADY_LIKED'],
} as const;
export const paramDef = {
@ -36,9 +24,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const post = await GalleryPosts.findOneBy({ id: ps.postId });
if (post == null) {
throw new ApiError(meta.errors.noSuchPost);
}
if (post == null) throw new ApiError('NO_SUCH_POST');
// if already liked
const exist = await GalleryLikes.findOneBy({
@ -46,9 +32,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyLiked);
}
if (exist != null) throw new ApiError('ALREADY_LIKED');
// Create like
await GalleryLikes.insert({

View file

@ -7,13 +7,7 @@ export const meta = {
requireCredential: false,
errors: {
noSuchPost: {
message: 'No such post.',
code: 'NO_SUCH_POST',
id: '1137bf14-c5b0-4604-85bb-5b5371b1cd45',
},
},
errors: ['NO_SUCH_POST'],
res: {
type: 'object',
@ -36,9 +30,7 @@ export default define(meta, paramDef, async (ps, me) => {
id: ps.postId,
});
if (post == null) {
throw new ApiError(meta.errors.noSuchPost);
}
if (post == null) throw new ApiError('NO_SUCH_POST');
return await GalleryPosts.pack(post, me);
});

View file

@ -9,19 +9,7 @@ export const meta = {
kind: 'write:gallery-likes',
errors: {
noSuchPost: {
message: 'No such post.',
code: 'NO_SUCH_POST',
id: 'c32e6dd0-b555-4413-925e-b3757d19ed84',
},
notLiked: {
message: 'You have not liked that post.',
code: 'NOT_LIKED',
id: 'e3e8e06e-be37-41f7-a5b4-87a8250288f0',
},
},
errors: ['NO_SUCH_POST', 'NOT_LIKED'],
} as const;
export const paramDef = {
@ -35,18 +23,14 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const post = await GalleryPosts.findOneBy({ id: ps.postId });
if (post == null) {
throw new ApiError(meta.errors.noSuchPost);
}
if (post == null) throw new ApiError('NO_SUCH_POST');
const exist = await GalleryLikes.findOneBy({
postId: post.id,
userId: user.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notLiked);
}
if (exist == null) throw new ApiError('NOT_LIKED');
// Delete like
await GalleryLikes.delete(exist.id);

View file

@ -20,10 +20,6 @@ export const meta = {
optional: false, nullable: false,
ref: 'GalleryPost',
},
errors: {
},
} as const;
export const paramDef = {

View file

@ -14,13 +14,7 @@ export const meta = {
ref: 'Hashtag',
},
errors: {
noSuchHashtag: {
message: 'No such hashtag.',
code: 'NO_SUCH_HASHTAG',
id: '110ee688-193e-4a3a-9ecf-c167b2e6981e',
},
},
errors: ['NO_SUCH_HASHTAG'],
} as const;
export const paramDef = {
@ -34,9 +28,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const hashtag = await Hashtags.findOneBy({ name: normalizeForSearch(ps.tag) });
if (hashtag == null) {
throw new ApiError(meta.errors.noSuchHashtag);
}
if (hashtag == null) throw new ApiError('NO_SUCH_HASHTAG');
return await Hashtags.pack(hashtag);
});

View file

@ -13,31 +13,7 @@ export const meta = {
max: 1,
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e',
},
unexpectedFileType: {
message: 'We need csv file.',
code: 'UNEXPECTED_FILE_TYPE',
id: 'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe',
},
tooBigFile: {
message: 'That file is too big.',
code: 'TOO_BIG_FILE',
id: 'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf',
},
emptyFile: {
message: 'That file is empty.',
code: 'EMPTY_FILE',
id: '6f3a4dcc-f060-a707-4950-806fbdbe60d6',
},
},
errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -52,10 +28,9 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) throw new ApiError(meta.errors.noSuchFile);
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
if (file == null) throw new ApiError('EMPTY_FILE');
if (file.size > 50000) throw new ApiError('FILE_TOO_BIG');
if (file.size === 0) throw new ApiError('EMPTY_FILE');
createImportBlockingJob(user, file.id);
});

View file

@ -12,31 +12,7 @@ export const meta = {
max: 1,
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'b98644cf-a5ac-4277-a502-0b8054a709a3',
},
unexpectedFileType: {
message: 'We need csv file.',
code: 'UNEXPECTED_FILE_TYPE',
id: '660f3599-bce0-4f95-9dde-311fd841c183',
},
tooBigFile: {
message: 'That file is too big.',
code: 'TOO_BIG_FILE',
id: 'dee9d4ed-ad07-43ed-8b34-b2856398bc60',
},
emptyFile: {
message: 'That file is empty.',
code: 'EMPTY_FILE',
id: '31a1b42c-06f7-42ae-8a38-a661c5c9f691',
},
},
errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -51,10 +27,9 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) throw new ApiError(meta.errors.noSuchFile);
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
if (file == null) throw new ApiError('NO_SUCH_FILE');
if (file.size > 50000) throw new ApiError('FILE_TOO_BIG');
if (file.size === 0) throw new ApiError('EMPTY_FILE');
createImportFollowingJob(user, file.id);
});

View file

@ -13,31 +13,7 @@ export const meta = {
max: 1,
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e674141e-bd2a-ba85-e616-aefb187c9c2a',
},
unexpectedFileType: {
message: 'We need csv file.',
code: 'UNEXPECTED_FILE_TYPE',
id: '568c6e42-c86c-ba09-c004-517f83f9f1a8',
},
tooBigFile: {
message: 'That file is too big.',
code: 'TOO_BIG_FILE',
id: '9b4ada6d-d7f7-0472-0713-4f558bd1ec9c',
},
emptyFile: {
message: 'That file is empty.',
code: 'EMPTY_FILE',
id: 'd2f12af1-e7b4-feac-86a3-519548f2728e',
},
},
errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -52,10 +28,9 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) throw new ApiError(meta.errors.noSuchFile);
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
if (file == null) throw new ApiError('NO_SUCH_FILE');
if (file.size > 50000) throw new ApiError('FILE_TOO_BIG');
if (file.size === 0) throw new ApiError('EMPTY_FILE');
createImportMutingJob(user, file.id);
});

View file

@ -12,31 +12,7 @@ export const meta = {
max: 1,
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'ea9cc34f-c415-4bc6-a6fe-28ac40357049',
},
unexpectedFileType: {
message: 'We need csv file.',
code: 'UNEXPECTED_FILE_TYPE',
id: 'a3c9edda-dd9b-4596-be6a-150ef813745c',
},
tooBigFile: {
message: 'That file is too big.',
code: 'TOO_BIG_FILE',
id: 'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9',
},
emptyFile: {
message: 'That file is empty.',
code: 'EMPTY_FILE',
id: '99efe367-ce6e-4d44-93f8-5fae7b040356',
},
},
errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'],
} as const;
export const paramDef = {
@ -51,10 +27,9 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOneBy({ id: ps.fileId });
if (file == null) throw new ApiError(meta.errors.noSuchFile);
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
if (file.size > 30000) throw new ApiError(meta.errors.tooBigFile);
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
if (file == null) throw new ApiError('NO_SUCH_FILE');
if (file.size > 30000) throw new ApiError('FILE_TOO_BIG');
if (file.size === 0) throw new ApiError('EMPTY_FILE');
createImportUserListsJob(user, file.id);
});

View file

@ -10,25 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '56734f8b-3928-431e-bf80-6ff87df40cb3',
},
pinLimitExceeded: {
message: 'You can not pin notes any more.',
code: 'PIN_LIMIT_EXCEEDED',
id: '72dab508-c64d-498f-8740-a8eec1ba385a',
},
alreadyPinned: {
message: 'That note has already been pinned.',
code: 'ALREADY_PINNED',
id: '8b18c2b7-68fe-4edb-9892-c0cbaeb6c913',
},
},
errors: ['ALREADY_PINNED', 'NO_SUCH_NOTE', 'PIN_LIMIT_EXCEEDED'],
res: {
type: 'object',
@ -48,9 +30,9 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
await addPinned(user, ps.noteId).catch(e => {
if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote);
if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError(meta.errors.pinLimitExceeded);
if (e.id === '23f0cf4e-59a3-4276-a91d-61a5891c1514') throw new ApiError(meta.errors.alreadyPinned);
if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError('NO_SUCH_NOTE');
if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError('PIN_LIMIT_EXCEEDED');
if (e.id === '23f0cf4e-59a3-4276-a91d-61a5891c1514') throw new ApiError('ALREADY_PINNED');
throw e;
});

View file

@ -11,13 +11,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchAnnouncement: {
message: 'No such announcement.',
code: 'NO_SUCH_ANNOUNCEMENT',
id: '184663db-df88-4bc2-8b52-fb85f0681939',
},
},
errors: ['NO_SUCH_ANNOUNCEMENT'],
} as const;
export const paramDef = {
@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
// Check if announcement exists
const announcement = await Announcements.findOneBy({ id: ps.announcementId });
if (announcement == null) {
throw new ApiError(meta.errors.noSuchAnnouncement);
}
if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT');
// Check if already read
const read = await AnnouncementReads.findOneBy({
@ -43,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (read != null) {
return;
}
if (read != null) return;
// Create read
await AnnouncementReads.insert({

View file

@ -7,13 +7,7 @@ export const meta = {
secure: true,
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: '97a1e8e7-c0f7-47d2-957a-92e61256e01a',
},
},
errors: ['NO_SUCH_KEY'],
} as const;
export const paramDef = {
@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => {
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
if (item == null) throw new ApiError('NO_SUCH_KEY');
return {
updatedAt: item.updatedAt,

View file

@ -7,13 +7,7 @@ export const meta = {
secure: true,
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a',
},
},
errors: ['NO_SUCH_KEY'],
} as const;
export const paramDef = {
@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => {
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
if (item == null) throw new ApiError('NO_SUCH_KEY');
return item.value;
});

View file

@ -7,13 +7,7 @@ export const meta = {
secure: true,
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019',
},
},
errors: ['NO_SUCH_KEY'],
} as const;
export const paramDef = {
@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => {
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
if (item == null) throw new ApiError('NO_SUCH_KEY');
await RegistryItems.remove(item);
});

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '454170ce-9d63-4a43-9da1-ea10afe81e21',
},
},
errors: ['NO_SUCH_NOTE'],
res: {
type: 'object',
@ -36,7 +30,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
await removePinned(user, ps.noteId).catch(e => {
if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote);
if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError('NO_SUCH_NOTE');
throw e;
});

View file

@ -19,19 +19,9 @@ export const meta = {
max: 3,
},
errors: {
incorrectPassword: {
message: 'Incorrect password.',
code: 'INCORRECT_PASSWORD',
id: 'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3',
},
unavailable: {
message: 'Unavailable email address.',
code: 'UNAVAILABLE',
id: 'a2defefb-f220-8849-0af6-17f816099323',
},
},
// FIXME: refactor to remove both of these errors?
// the password should not be passed as it is not compatible with using OAuth
errors: ['ACCESS_DENIED', 'INTERNAL_ERROR'],
} as const;
export const paramDef = {
@ -50,15 +40,11 @@ export default define(meta, paramDef, async (ps, user) => {
// Compare password
const same = await bcrypt.compare(ps.password, profile.password!);
if (!same) {
throw new ApiError(meta.errors.incorrectPassword);
}
if (!same) throw new ApiError('ACCESS_DENIED');
if (ps.email != null) {
const available = await validateEmailForAccount(ps.email);
if (!available) {
throw new ApiError(meta.errors.unavailable);
}
if (!available) throw new ApiError('INTERNAL_ERROR');
}
await UserProfiles.update(user.id, {

View file

@ -22,43 +22,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchAvatar: {
message: 'No such avatar file.',
code: 'NO_SUCH_AVATAR',
id: '539f3a45-f215-4f81-a9a8-31293640207f',
},
noSuchBanner: {
message: 'No such banner file.',
code: 'NO_SUCH_BANNER',
id: '0d8f5629-f210-41c2-9433-735831a58595',
},
avatarNotAnImage: {
message: 'The file specified as an avatar is not an image.',
code: 'AVATAR_NOT_AN_IMAGE',
id: 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191',
},
bannerNotAnImage: {
message: 'The file specified as a banner is not an image.',
code: 'BANNER_NOT_AN_IMAGE',
id: '75aedb19-2afd-4e6d-87fc-67941256fa60',
},
noSuchPage: {
message: 'No such page.',
code: 'NO_SUCH_PAGE',
id: '8e01b590-7eb9-431b-a239-860e086c408e',
},
invalidRegexp: {
message: 'Invalid Regular Expression.',
code: 'INVALID_REGEXP',
id: '0d786918-10df-41cd-8f33-8dec7d9a89a5',
},
},
errors: ['INVALID_REGEXP', 'NO_SUCH_FILE', 'NO_SUCH_PAGE', 'NOT_AN_IMAGE'],
res: {
type: 'object',
@ -142,12 +106,12 @@ export default define(meta, paramDef, async (ps, _user, token) => {
// validate regular expression syntax
ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => {
const regexp = x.match(/^\/(.+)\/(.*)$/);
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
if (!regexp) throw new ApiError('INVALID_REGEXP');
try {
new RE2(regexp[1], regexp[2]);
} catch (err) {
throw new ApiError(meta.errors.invalidRegexp);
throw new ApiError('INVALID_REGEXP');
}
});
@ -174,21 +138,21 @@ export default define(meta, paramDef, async (ps, _user, token) => {
if (ps.avatarId) {
const avatar = await DriveFiles.findOneBy({ id: ps.avatarId });
if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar);
if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage);
if (avatar == null || avatar.userId !== user.id) throw new ApiError('NO_SUCH_FILE', 'Avatar file not found.');
if (!avatar.type.startsWith('image/')) throw new ApiError('NOT_AN_IMAGE', 'Avatar file is not an image.');
}
if (ps.bannerId) {
const banner = await DriveFiles.findOneBy({ id: ps.bannerId });
if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner);
if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage);
if (banner == null || banner.userId !== user.id) throw new ApiError('NO_SUCH_FILE', 'Banner file not found.');
if (!banner.type.startsWith('image/')) throw new ApiError('BANNER_NOT_AN_IMAGE', 'Banner file is not an image.');
}
if (ps.pinnedPageId) {
const page = await Pages.findOneBy({ id: ps.pinnedPageId });
if (page == null || page.userId !== user.id) throw new ApiError(meta.errors.noSuchPage);
if (page == null || page.userId !== user.id) throw new ApiError('NO_SUCH_PAGE');
profileUpdates.pinnedPageId = page.id;
} else if (ps.pinnedPageId === null) {

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchWebhook: {
message: 'No such webhook.',
code: 'NO_SUCH_WEBHOOK',
id: 'bae73e5a-5522-4965-ae19-3a8688e71d82',
},
},
errors: ['NO_SUCH_WEBHOOK'],
} as const;
export const paramDef = {
@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (webhook == null) {
throw new ApiError(meta.errors.noSuchWebhook);
}
if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK');
await Webhooks.delete(webhook.id);

View file

@ -9,13 +9,7 @@ export const meta = {
kind: 'read:account',
errors: {
noSuchWebhook: {
message: 'No such webhook.',
code: 'NO_SUCH_WEBHOOK',
id: '50f614d9-3047-4f7e-90d8-ad6b2d5fb098',
},
},
errors: ['NO_SUCH_WEBHOOK'],
} as const;
export const paramDef = {
@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (webhook == null) {
throw new ApiError(meta.errors.noSuchWebhook);
}
if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK');
return webhook;
});

View file

@ -11,14 +11,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchWebhook: {
message: 'No such webhook.',
code: 'NO_SUCH_WEBHOOK',
id: 'fb0fea69-da18-45b1-828d-bd4fd1612518',
},
},
errors: ['NO_SUCH_WEBHOOK'],
} as const;
export const paramDef = {
@ -43,9 +36,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (webhook == null) {
throw new ApiError(meta.errors.noSuchWebhook);
}
if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK');
await Webhooks.update(webhook.id, {
name: ps.name,

View file

@ -23,25 +23,7 @@ export const meta = {
},
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '11795c64-40ea-4198-b06e-3c873ed9039d',
},
noSuchGroup: {
message: 'No such group.',
code: 'NO_SUCH_GROUP',
id: 'c4d9f88c-9270-4632-b032-6ed8cee36f7f',
},
groupAccessDenied: {
message: 'You can not read messages of groups that you have not joined.',
code: 'GROUP_ACCESS_DENIED',
id: 'a053a8dd-a491-4718-8f87-50775aad9284',
},
},
errors: ['ACCESS_DENIED', 'NO_SUCH_USER', 'NO_SUCH_GROUP'],
} as const;
export const paramDef = {
@ -73,7 +55,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (ps.userId != null) {
// Fetch recipient (user)
const recipient = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -110,9 +92,7 @@ export default define(meta, paramDef, async (ps, user) => {
// Fetch recipient (group)
const recipientGroup = await UserGroups.findOneBy({ id: ps.groupId });
if (recipientGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
if (recipientGroup == null) throw new ApiError('NO_SUCH_GROUP');
// check joined
const joining = await UserGroupJoinings.findOneBy({
@ -120,9 +100,7 @@ export default define(meta, paramDef, async (ps, user) => {
userGroupId: recipientGroup.id,
});
if (joining == null) {
throw new ApiError(meta.errors.groupAccessDenied);
}
if (joining == null) throw new ApiError('ACCESS_DENIED', 'You have to join a group to read messages in it.');
const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId)
.andWhere('message.groupId = :groupId', { groupId: recipientGroup.id });

View file

@ -19,51 +19,11 @@ export const meta = {
ref: 'MessagingMessage',
},
errors: {
recipientIsYourself: {
message: 'You can not send a message to yourself.',
code: 'RECIPIENT_IS_YOURSELF',
id: '17e2ba79-e22a-4cbc-bf91-d327643f4a7e',
},
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '11795c64-40ea-4198-b06e-3c873ed9039d',
},
noSuchGroup: {
message: 'No such group.',
code: 'NO_SUCH_GROUP',
id: 'c94e2a5d-06aa-4914-8fa6-6a42e73d6537',
},
groupAccessDenied: {
message: 'You can not send messages to groups that you have not joined.',
code: 'GROUP_ACCESS_DENIED',
id: 'd96b3cca-5ad1-438b-ad8b-02f931308fbd',
},
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '4372b8e2-185d-4146-8749-2f68864a3e5f',
},
youHaveBeenBlocked: {
message: 'You cannot send a message because you have been blocked by this user.',
code: 'YOU_HAVE_BEEN_BLOCKED',
id: 'c15a5199-7422-4968-941a-2a462c478f7d',
},
},
errors: ['ACCESS_DENIED', 'BLOCKED', 'NO_SUCH_FILE', 'NO_SUCH_USER', 'NO_SUCH_GROUP', 'RECIPIENT_IS_YOURSELF'],
} as const;
export const paramDef = {
type: 'object',
properties: {
text: { type: 'string', nullable: true, maxLength: 3000 },
fileId: { type: 'string', format: 'misskey:id' },
},
anyOf: [
{
properties: {
@ -137,13 +97,11 @@ export default define(meta, paramDef, async (ps, user) => {
if (ps.userId != null) {
// Myself
if (ps.userId === user.id) {
throw new ApiError(meta.errors.recipientIsYourself);
}
if (ps.userId === user.id) throw new ApiError('RECIPIENT_IS_YOURSELF');
// Fetch recipient (user)
recipientUser = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -152,16 +110,12 @@ export default define(meta, paramDef, async (ps, user) => {
blockerId: recipientUser.id,
blockeeId: user.id,
});
if (block) {
throw new ApiError(meta.errors.youHaveBeenBlocked);
}
if (block) throw new ApiError('BLOCKED');
} else if (ps.groupId != null) {
// Fetch recipient (group)
recipientGroup = await UserGroups.findOneBy({ id: ps.groupId! });
if (recipientGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
if (recipientGroup == null) throw new ApiError('NO_SUCH_GROUP');
// check joined
const joining = await UserGroupJoinings.findOneBy({
@ -169,9 +123,7 @@ export default define(meta, paramDef, async (ps, user) => {
userGroupId: recipientGroup.id,
});
if (joining == null) {
throw new ApiError(meta.errors.groupAccessDenied);
}
if (joining == null) throw new ApiError('ACCESS_DENIED', 'You have to join a group to send a message in it.');
}
let file = null;
@ -181,9 +133,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (file == null) {
throw new ApiError(meta.errors.noSuchFile);
}
if (file == null) throw new ApiError('NO_SUCH_FILE');
}
return await createMessage(user, recipientUser, recipientGroup, ps.text, file);

View file

@ -17,13 +17,7 @@ export const meta = {
minInterval: SECOND,
},
errors: {
noSuchMessage: {
message: 'No such message.',
code: 'NO_SUCH_MESSAGE',
id: '54b5b326-7925-42cf-8019-130fda8b56af',
},
},
errors: ['NO_SUCH_MESSAGE'],
} as const;
export const paramDef = {
@ -41,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (message == null) {
throw new ApiError(meta.errors.noSuchMessage);
}
if (message == null) throw new ApiError('NO_SUCH_MESSAGE');
await deleteMessage(message);
});

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:messaging',
errors: {
noSuchMessage: {
message: 'No such message.',
code: 'NO_SUCH_MESSAGE',
id: '86d56a2f-a9c3-4afb-b13c-3e9bfef9aa14',
},
},
errors: ['NO_SUCH_MESSAGE'],
} as const;
export const paramDef = {
@ -31,18 +25,16 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const message = await MessagingMessages.findOneBy({ id: ps.messageId });
if (message == null) {
throw new ApiError(meta.errors.noSuchMessage);
}
if (message == null) throw new ApiError('NO_SUCH_MESSAGE');
if (message.recipientId) {
await readUserMessagingMessage(user.id, message.userId, [message.id]).catch(e => {
if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError(meta.errors.noSuchMessage);
if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError('NO_SUCH_MESSAGE');
throw e;
});
} else if (message.groupId) {
await readGroupMessagingMessage(user.id, message.groupId, [message.id]).catch(e => {
if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError(meta.errors.noSuchMessage);
if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError('NO_SUCH_MESSAGE');
throw e;
});
}

View file

@ -13,25 +13,7 @@ export const meta = {
kind: 'write:mutes',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '6fef56f3-e765-4957-88e5-c6f65329b8a5',
},
muteeIsYourself: {
message: 'Mutee is yourself.',
code: 'MUTEE_IS_YOURSELF',
id: 'a4619cb2-5f23-484b-9301-94c903074e10',
},
alreadyMuting: {
message: 'You are already muting that user.',
code: 'ALREADY_MUTING',
id: '7e7359cb-160c-4956-b08f-4d1c653cd007',
},
},
errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'ALREADY_MUTING'],
} as const;
export const paramDef = {
@ -52,13 +34,11 @@ export default define(meta, paramDef, async (ps, user) => {
const muter = user;
// 自分自身
if (user.id === ps.userId) {
throw new ApiError(meta.errors.muteeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF');
// Get mutee
const mutee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -68,9 +48,7 @@ export default define(meta, paramDef, async (ps, user) => {
muteeId: mutee.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyMuting);
}
if (exist != null) throw new ApiError('ALREADY_MUTING');
if (ps.expiresAt && ps.expiresAt <= Date.now()) {
return;

View file

@ -11,25 +11,7 @@ export const meta = {
kind: 'write:mutes',
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: 'b851d00b-8ab1-4a56-8b1b-e24187cb48ef',
},
muteeIsYourself: {
message: 'Mutee is yourself.',
code: 'MUTEE_IS_YOURSELF',
id: 'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9',
},
notMuting: {
message: 'You are not muting that user.',
code: 'NOT_MUTING',
id: '5467d020-daa9-4553-81e1-135c0c35a96d',
},
},
errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'NOT_MUTING'],
} as const;
export const paramDef = {
@ -45,13 +27,11 @@ export default define(meta, paramDef, async (ps, user) => {
const muter = user;
// Check if the mutee is yourself
if (user.id === ps.userId) {
throw new ApiError(meta.errors.muteeIsYourself);
}
if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF');
// Get mutee
const mutee = await getUser(ps.userId).catch(e => {
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser);
if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER');
throw e;
});
@ -61,9 +41,7 @@ export default define(meta, paramDef, async (ps, user) => {
muteeId: mutee.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notMuting);
}
if (exist == null) throw new ApiError('NOT_MUTING');
// Delete mute
await Mutings.delete({

View file

@ -19,13 +19,7 @@ export const meta = {
},
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '47db1a1c-b0af-458d-8fb4-986e4efafe1e',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -39,7 +33,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, me) => {
const note = await getNote(ps.noteId, me).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -19,13 +19,7 @@ export const meta = {
},
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'e1035875-9551-45ec-afa8-1ded1fcb53c8',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -41,7 +35,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -37,55 +37,7 @@ export const meta = {
},
},
errors: {
noSuchRenoteTarget: {
message: 'No such renote target.',
code: 'NO_SUCH_RENOTE_TARGET',
id: 'b5c90186-4ab0-49c8-9bba-a1f76c282ba4',
},
cannotReRenote: {
message: 'You can not Renote a pure Renote.',
code: 'CANNOT_RENOTE_TO_A_PURE_RENOTE',
id: 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a',
},
noSuchReplyTarget: {
message: 'No such reply target.',
code: 'NO_SUCH_REPLY_TARGET',
id: '749ee0f6-d3da-459a-bf02-282e2da4292c',
},
cannotReplyToPureRenote: {
message: 'You can not reply to a pure Renote.',
code: 'CANNOT_REPLY_TO_A_PURE_RENOTE',
id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15',
},
cannotCreateAlreadyExpiredPoll: {
message: 'Poll is already expired.',
code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL',
id: '04da457d-b083-4055-9082-955525eda5a5',
},
noSuchChannel: {
message: 'No such channel.',
code: 'NO_SUCH_CHANNEL',
id: 'b1653923-5453-4edc-b786-7c4f39bb0bbb',
},
youHaveBeenBlocked: {
message: 'You have been blocked by this user.',
code: 'YOU_HAVE_BEEN_BLOCKED',
id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3',
},
lessRestrictiveVisibility: {
message: 'The visibility cannot be less restrictive than the parent note.',
code: 'LESS_RESTRICTIVE_VISIBILITY',
id: 'c8ab7a7a-8852-41e2-8b24-079bbaceb585',
},
},
errors: ['NO_SUCH_NOTE', 'PURE_RENOTE', 'EXPIRED_POLL', 'NO_SUCH_CHANNEL', 'BLOCKED', 'LESS_RESTRICTIVE_VISIBILITY'],
} as const;
export const paramDef = {
@ -199,17 +151,15 @@ export default define(meta, paramDef, async (ps, user) => {
if (ps.renoteId != null) {
// Fetch renote to note
renote = await getNote(ps.renoteId, user).catch(e => {
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchRenoteTarget);
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE', 'Note to be renoted not found.');
throw e;
});
if (isPureRenote(renote)) {
throw new ApiError(meta.errors.cannotReRenote);
}
if (isPureRenote(renote)) throw new ApiError('PURE_RENOTE', 'Cannot renote a pure renote.');
// check that the visibility is not less restrictive
if (noteVisibilities.indexOf(renote.visibility) > noteVisibilities.indexOf(ps.visibility)) {
throw new ApiError(meta.errors.lessRestrictiveVisibility);
throw new ApiError('LESS_RESTRICTIVE_VISIBILITY', `The renote has visibility ${renote.visibility}.`);
}
// Check blocking
@ -218,9 +168,7 @@ export default define(meta, paramDef, async (ps, user) => {
blockerId: renote.userId,
blockeeId: user.id,
});
if (block) {
throw new ApiError(meta.errors.youHaveBeenBlocked);
}
if (block) throw new ApiError('BLOCKED', 'Blocked by author of note to be renoted.');
}
}
@ -228,17 +176,15 @@ export default define(meta, paramDef, async (ps, user) => {
if (ps.replyId != null) {
// Fetch reply
reply = await getNote(ps.replyId, user).catch(e => {
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchReplyTarget);
if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE', 'Replied to note not found.');
throw e;
});
if (isPureRenote(reply)) {
throw new ApiError(meta.errors.cannotReplyToPureRenote);
}
if (isPureRenote(reply)) throw new ApiError('PURE_RENOTE', 'Cannot reply to a pure renote.');
// check that the visibility is not less restrictive
if (noteVisibilities.indexOf(reply.visibility) > noteVisibilities.indexOf(ps.visibility)) {
throw new ApiError(meta.errors.lessRestrictiveVisibility);
throw new ApiError('LESS_RESTRICTIVE_VISIBILITY', `The replied to note has visibility ${reply.visibility}.`);
}
// Check blocking
@ -247,16 +193,14 @@ export default define(meta, paramDef, async (ps, user) => {
blockerId: reply.userId,
blockeeId: user.id,
});
if (block) {
throw new ApiError(meta.errors.youHaveBeenBlocked);
}
if (block) throw new ApiError('BLOCKED', 'Blocked by author of replied to note.');
}
}
if (ps.poll) {
if (typeof ps.poll.expiresAt === 'number') {
if (ps.poll.expiresAt < Date.now()) {
throw new ApiError(meta.errors.cannotCreateAlreadyExpiredPoll);
throw new ApiError('EXPIRED_POLL');
}
} else if (typeof ps.poll.expiredAfter === 'number') {
ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter;
@ -267,9 +211,7 @@ export default define(meta, paramDef, async (ps, user) => {
if (ps.channelId != null) {
channel = await Channels.findOneBy({ id: ps.channelId });
if (channel == null) {
throw new ApiError(meta.errors.noSuchChannel);
}
if (channel == null) throw new ApiError('NO_SUCH_CHANNEL');
}
// 投稿を作成

View file

@ -18,19 +18,7 @@ export const meta = {
minInterval: SECOND,
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '490be23f-8c1f-4796-819f-94cb4f9d1630',
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: 'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9',
},
},
errors: ['ACCESS_DENIED', 'NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -44,12 +32,12 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
if ((!user.isAdmin && !user.isModerator) && (note.userId !== user.id)) {
throw new ApiError(meta.errors.accessDenied);
throw new ApiError('ACCESS_DENIED');
}
// この操作を行うのが投稿者とは限らない(例えばモデレーター)ため

View file

@ -11,19 +11,7 @@ export const meta = {
kind: 'write:favorites',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '6dd26674-e060-4816-909a-45ba3f4da458',
},
alreadyFavorited: {
message: 'The note has already been marked as a favorite.',
code: 'ALREADY_FAVORITED',
id: 'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6',
},
},
errors: ['NO_SUCH_NOTE', 'ALREADY_FAVORITED'],
} as const;
export const paramDef = {
@ -38,7 +26,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// Get favoritee
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
@ -48,9 +36,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (exist != null) {
throw new ApiError(meta.errors.alreadyFavorited);
}
if (exist != null) throw new ApiError('ALREADY_FAVORITED');
// Create favorite
await NoteFavorites.insert({

View file

@ -10,19 +10,7 @@ export const meta = {
kind: 'write:favorites',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '80848a2c-398f-4343-baa9-df1d57696c56',
},
notFavorited: {
message: 'You have not marked that note a favorite.',
code: 'NOT_FAVORITED',
id: 'b625fc69-635e-45e9-86f4-dbefbef35af5',
},
},
errors: ['NO_SUCH_NOTE', 'NOT_FAVORITED'],
} as const;
export const paramDef = {
@ -37,7 +25,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// Get favoritee
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
@ -47,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => {
userId: user.id,
});
if (exist == null) {
throw new ApiError(meta.errors.notFavorited);
}
if (exist == null) throw new ApiError('NOT_FAVORITED');
// Delete favorite
await NoteFavorites.delete(exist.id);

View file

@ -23,13 +23,7 @@ export const meta = {
},
},
errors: {
gtlDisabled: {
message: 'Global timeline has been disabled.',
code: 'GTL_DISABLED',
id: '0332fc13-6ab2-4427-ae80-a9fadffd1a6b',
},
},
errors: ['TIMELINE_DISABLED'],
} as const;
export const paramDef = {
@ -54,7 +48,7 @@ export default define(meta, paramDef, async (ps, user) => {
const m = await fetchMeta();
if (m.disableGlobalTimeline) {
if (user == null || (!user.isAdmin && !user.isModerator)) {
throw new ApiError(meta.errors.gtlDisabled);
throw new ApiError('TIMELINE_DISABLED');
}
}

View file

@ -28,13 +28,7 @@ export const meta = {
},
},
errors: {
stlDisabled: {
message: 'Hybrid timeline has been disabled.',
code: 'STL_DISABLED',
id: '620763f4-f621-4533-ab33-0577a1a3c342',
},
},
errors: ['TIMELINE_DISABLED'],
} as const;
export const paramDef = {
@ -61,7 +55,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const m = await fetchMeta();
if (m.disableLocalTimeline && (!user.isAdmin && !user.isModerator)) {
throw new ApiError(meta.errors.stlDisabled);
throw new ApiError('TIMELINE_DISABLED');
}
//#region Construct query

View file

@ -26,13 +26,7 @@ export const meta = {
},
},
errors: {
ltlDisabled: {
message: 'Local timeline has been disabled.',
code: 'LTL_DISABLED',
id: '45a6eb02-7695-4393-b023-dd3be9aaaefd',
},
},
errors: ['TIMELINE_DISABLED'],
} as const;
export const paramDef = {
@ -61,7 +55,7 @@ export default define(meta, paramDef, async (ps, user) => {
const m = await fetchMeta();
if (m.disableLocalTimeline) {
if (user == null || (!user.isAdmin && !user.isModerator)) {
throw new ApiError(meta.errors.ltlDisabled);
throw new ApiError('TIMELINE_DISABLED');
}
}

View file

@ -19,50 +19,14 @@ export const meta = {
kind: 'write:votes',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'ecafbd2e-c283-4d6d-aecb-1a0a33b75396',
},
noPoll: {
message: 'The note does not attach a poll.',
code: 'NO_POLL',
id: '5f979967-52d9-4314-a911-1c673727f92f',
},
invalidChoice: {
message: 'Choice ID is invalid.',
code: 'INVALID_CHOICE',
id: 'e0cc9a04-f2e8-41e4-a5f1-4127293260cc',
},
alreadyVoted: {
message: 'You have already voted.',
code: 'ALREADY_VOTED',
id: '0963fc77-efac-419b-9424-b391608dc6d8',
},
alreadyExpired: {
message: 'The poll is already expired.',
code: 'ALREADY_EXPIRED',
id: '1022a357-b085-4054-9083-8f8de358337e',
},
youHaveBeenBlocked: {
message: 'You cannot vote this poll because you have been blocked by this user.',
code: 'YOU_HAVE_BEEN_BLOCKED',
id: '85a5377e-b1e9-4617-b0b9-5bea73331e49',
},
},
errors: ['NO_SUCH_NOTE', 'INVALID_CHOICE', 'ALREADY_VOTED', 'EXPIRED_POLL', 'BLOCKED'],
} as const;
export const paramDef = {
type: 'object',
properties: {
noteId: { type: 'string', format: 'misskey:id' },
choice: { type: 'integer' },
choice: { type: 'integer', minimum: 0 },
},
required: ['noteId', 'choice'],
} as const;
@ -73,12 +37,12 @@ export default define(meta, paramDef, async (ps, user) => {
// Get votee
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
if (!note.hasPoll) {
throw new ApiError(meta.errors.noPoll);
throw new ApiError('NO_SUCH_NOTE', 'The note exists but does not have a poll attached.');
}
// Check blocking
@ -87,19 +51,17 @@ export default define(meta, paramDef, async (ps, user) => {
blockerId: note.userId,
blockeeId: user.id,
});
if (block) {
throw new ApiError(meta.errors.youHaveBeenBlocked);
}
if (block) throw new ApiError('BLOCKED');
}
const poll = await Polls.findOneByOrFail({ noteId: note.id });
if (poll.expiresAt && poll.expiresAt < createdAt) {
throw new ApiError(meta.errors.alreadyExpired);
throw new ApiError('EXPIRED_POLL');
}
if (poll.choices[ps.choice] == null) {
throw new ApiError(meta.errors.invalidChoice);
throw new ApiError('INVALID_CHOICE', `There are only ${poll.choices.length} choices.`);
}
// if already voted
@ -111,10 +73,10 @@ export default define(meta, paramDef, async (ps, user) => {
if (exist.length) {
if (poll.multiple) {
if (exist.some(x => x.choice === ps.choice)) {
throw new ApiError(meta.errors.alreadyVoted);
throw new ApiError('ALREADY_VOTED', 'This is a multiple choice poll, but you already voted for that option.');
}
} else {
throw new ApiError(meta.errors.alreadyVoted);
throw new ApiError('ALREADY_VOTED', 'This is a single choice poll.');
}
}

View file

@ -23,13 +23,7 @@ export const meta = {
},
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '263fff3d-d0e1-4af4-bea7-8408059b451a',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -53,7 +47,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
// check note visibility
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -10,25 +10,7 @@ export const meta = {
kind: 'write:reactions',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '033d0620-5bfe-4027-965d-980b0c85a3ea',
},
alreadyReacted: {
message: 'You are already reacting to that note.',
code: 'ALREADY_REACTED',
id: '71efcf98-86d6-4e2b-b2ad-9d032369366b',
},
youHaveBeenBlocked: {
message: 'You cannot react this note because you have been blocked by this user.',
code: 'YOU_HAVE_BEEN_BLOCKED',
id: '20ef5475-9f38-4e4c-bd33-de6d979498ec',
},
},
errors: ['NO_SUCH_NOTE', 'ALREADY_REACTED', 'BLOCKED'],
} as const;
export const paramDef = {
@ -43,12 +25,12 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
await createReaction(user, note, ps.reaction).catch(e => {
if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError(meta.errors.alreadyReacted);
if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError(meta.errors.youHaveBeenBlocked);
if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError('ALREADY_REACTED');
if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError('BLOCKED');
throw e;
});
return;

View file

@ -17,19 +17,7 @@ export const meta = {
minInterval: 3 * SECOND,
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37',
},
notReacted: {
message: 'You are not reacting to that note.',
code: 'NOT_REACTED',
id: '92f4426d-4196-4125-aa5b-02943e2ec8fc',
},
},
errors: ['NO_SUCH_NOTE', 'NOT_REACTED'],
} as const;
export const paramDef = {
@ -43,11 +31,11 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
await deleteReaction(user, note).catch(e => {
if (e.id === '60527ec9-b4cb-4a88-a6bd-32d3ad26817d') throw new ApiError(meta.errors.notReacted);
if (e.id === '60527ec9-b4cb-4a88-a6bd-32d3ad26817d') throw new ApiError('NOT_REACTED');
throw e;
});
});

View file

@ -22,13 +22,7 @@ export const meta = {
},
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '12908022-2e21-46cd-ba6a-3edaf6093f46',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -45,7 +39,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -22,9 +22,6 @@ export const meta = {
ref: 'Note',
},
},
errors: {
},
} as const;
export const paramDef = {

View file

@ -14,13 +14,7 @@ export const meta = {
ref: 'Note',
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '24fcbfc6-2e37-42b6-8388-c29b3861a08d',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -34,7 +28,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
@ -42,7 +36,7 @@ export default define(meta, paramDef, async (ps, user) => {
// FIXME: packing with detail may throw an error if the reply or renote is not visible (#8774)
detail: true,
}).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});
});

View file

@ -13,13 +13,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: '5ff67ada-ed3b-2e71-8e87-a1a421e177d2',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -41,7 +35,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -10,13 +10,7 @@ export const meta = {
kind: 'write:account',
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'bddd57ac-ceb3-b29d-4334-86ea5fae481a',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
export const paramDef = {
@ -30,7 +24,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

View file

@ -55,13 +55,7 @@ export const meta = {
},
},
errors: {
noSuchNote: {
message: 'No such note.',
code: 'NO_SUCH_NOTE',
id: 'bea9b03f-36e0-49c5-a4db-627a029f8971',
},
},
errors: ['NO_SUCH_NOTE'],
} as const;
// List of permitted languages from https://www.deepl.com/docs-api/translate-text/translate-text/
@ -116,7 +110,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const note = await getNote(ps.noteId, user).catch(err => {
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE');
throw err;
});

Some files were not shown because too many files have changed in this diff Show more