strictNullChecks (#4666)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
This commit is contained in:
@ -15,11 +15,11 @@ export default (endpoint: IEndpoint, ctx: Koa.BaseContext) => new Promise((res)
|
||||
ctx.status = x;
|
||||
ctx.body = {
|
||||
error: {
|
||||
message: y.message,
|
||||
code: y.code,
|
||||
id: y.id,
|
||||
kind: y.kind,
|
||||
...(y.info ? { info: y.info } : {})
|
||||
message: y!.message,
|
||||
code: y!.code,
|
||||
id: y!.id,
|
||||
kind: y!.kind,
|
||||
...(y!.info ? { info: y!.info } : {})
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@ -31,9 +31,9 @@ export default (endpoint: IEndpoint, ctx: Koa.BaseContext) => new Promise((res)
|
||||
// Authentication
|
||||
authenticate(body['i']).then(([user, app]) => {
|
||||
// API invoking
|
||||
call(endpoint.name, user, app, body, (ctx.req as any).file).then(res => {
|
||||
call(endpoint.name, user, app, body, (ctx.req as any).file).then((res: any) => {
|
||||
reply(res);
|
||||
}).catch(e => {
|
||||
}).catch((e: ApiError) => {
|
||||
reply(e.httpStatusCode ? e.httpStatusCode : e.kind == 'client' ? 400 : 500, e);
|
||||
});
|
||||
}).catch(() => {
|
||||
|
@ -3,7 +3,7 @@ import { User } from '../../models/entities/user';
|
||||
import { App } from '../../models/entities/app';
|
||||
import { Users, AccessTokens, Apps } from '../../models';
|
||||
|
||||
export default async (token: string): Promise<[User, App]> => {
|
||||
export default async (token: string): Promise<[User | null | undefined, App | null | undefined]> => {
|
||||
if (token == null) {
|
||||
return [null, null];
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ const accessDenied = {
|
||||
id: '56f35758-7dd5-468b-8439-5d6fb8ec9b8e'
|
||||
};
|
||||
|
||||
export default async (endpoint: string, user: User, app: App, data: any, file?: any) => {
|
||||
export default async (endpoint: string, user: User | null | undefined, app: App | null | undefined, data: any, file?: any) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
const ep = endpoints.find(e => e.name === endpoint);
|
||||
@ -39,15 +39,15 @@ export default async (endpoint: string, user: User, app: App, data: any, file?:
|
||||
});
|
||||
}
|
||||
|
||||
if (ep.meta.requireCredential && user.isSuspended) {
|
||||
if (ep.meta.requireCredential && user!.isSuspended) {
|
||||
throw new ApiError(accessDenied, { reason: 'Your account has been suspended.' });
|
||||
}
|
||||
|
||||
if (ep.meta.requireAdmin && !user.isAdmin) {
|
||||
if (ep.meta.requireAdmin && !user!.isAdmin) {
|
||||
throw new ApiError(accessDenied, { reason: 'You are not the admin.' });
|
||||
}
|
||||
|
||||
if (ep.meta.requireModerator && !user.isAdmin && !user.isModerator) {
|
||||
if (ep.meta.requireModerator && !user!.isAdmin && !user!.isModerator) {
|
||||
throw new ApiError(accessDenied, { reason: 'You are not a moderator.' });
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ export default async (endpoint: string, user: User, app: App, data: any, file?:
|
||||
|
||||
if (ep.meta.requireCredential && ep.meta.limit) {
|
||||
// Rate limit
|
||||
await limiter(ep, user).catch(e => {
|
||||
await limiter(ep, user!).catch(e => {
|
||||
throw new ApiError({
|
||||
message: 'Rate limit exceeded. Please try again later.',
|
||||
code: 'RATE_LIMIT_EXCEEDED',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SelectQueryBuilder } from 'typeorm';
|
||||
|
||||
export function makePaginationQuery<T>(q: SelectQueryBuilder<T>, sinceId: string, untilId: string, sinceDate?: number, untilDate?: number) {
|
||||
export function makePaginationQuery<T>(q: SelectQueryBuilder<T>, sinceId?: string, untilId?: string, sinceDate?: number, untilDate?: number) {
|
||||
if (sinceId && untilId) {
|
||||
q.andWhere(`${q.alias}.id > :sinceId`, { sinceId: sinceId });
|
||||
q.andWhere(`${q.alias}.id < :untilId`, { untilId: untilId });
|
||||
|
@ -5,9 +5,9 @@ import { ApiError } from './error';
|
||||
import { App } from '../../models/entities/app';
|
||||
|
||||
type Params<T extends IEndpointMeta> = {
|
||||
[P in keyof T['params']]: T['params'][P]['transform'] extends Function
|
||||
? ReturnType<T['params'][P]['transform']>
|
||||
: ReturnType<T['params'][P]['validator']['get']>[0];
|
||||
[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
|
||||
? ReturnType<NonNullable<T['params']>[P]['transform']>
|
||||
: ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0];
|
||||
};
|
||||
|
||||
export type Response = Record<string, any> | void;
|
||||
@ -34,11 +34,11 @@ export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T
|
||||
};
|
||||
}
|
||||
|
||||
function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, ApiError] {
|
||||
function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, ApiError | null] {
|
||||
if (defs.params == null) return [params, null];
|
||||
|
||||
const x: any = {};
|
||||
let err: ApiError = null;
|
||||
let err: ApiError | null = null;
|
||||
Object.entries(defs.params).some(([k, def]) => {
|
||||
const [v, e] = def.validator.get(params[k]);
|
||||
if (e) {
|
||||
|
@ -29,7 +29,7 @@ export const meta = {
|
||||
export default define(meta, async (ps) => {
|
||||
const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId);
|
||||
|
||||
const reports = await query.take(ps.limit).getMany();
|
||||
const reports = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await AbuseUserReports.packMany(reports);
|
||||
});
|
||||
|
@ -56,8 +56,8 @@ export default define(meta, async (ps, me) => {
|
||||
|
||||
const files = await DriveFiles.find({
|
||||
where: q,
|
||||
take: ps.limit,
|
||||
order: sort[ps.sort] || sort[fallback],
|
||||
take: ps.limit!,
|
||||
order: sort[ps.sort!] || sort[fallback],
|
||||
skip: ps.offset
|
||||
});
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const emojis = await Emojis.find({
|
||||
host: toPuny(ps.host)
|
||||
host: ps.host ? toPuny(ps.host) : null
|
||||
});
|
||||
|
||||
return emojis.map(e => ({
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import deleteFollowing from '../../../../../services/following/delete';
|
||||
import { Followings, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -22,13 +23,11 @@ export default define(meta, async (ps, me) => {
|
||||
});
|
||||
|
||||
const pairs = await Promise.all(followings.map(f => Promise.all([
|
||||
Users.findOne(f.followerId),
|
||||
Users.findOne(f.followeeId)
|
||||
Users.findOne(f.followerId).then(ensure),
|
||||
Users.findOne(f.followeeId).then(ensure)
|
||||
])));
|
||||
|
||||
for (const pair of pairs) {
|
||||
deleteFollowing(pair[0], pair[1]);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -65,7 +65,7 @@ export default define(meta, async (ps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const logs = await query.orderBy('log.createdAt', 'DESC').take(ps.limit).getMany();
|
||||
const logs = await query.orderBy('log.createdAt', 'DESC').take(ps.limit!).getMany();
|
||||
|
||||
return logs;
|
||||
});
|
||||
|
@ -28,9 +28,9 @@ export default define(meta, async (ps) => {
|
||||
const queue =
|
||||
ps.domain === 'deliver' ? deliverQueue :
|
||||
ps.domain === 'inbox' ? inboxQueue :
|
||||
null;
|
||||
null as never;
|
||||
|
||||
const jobs = await queue.getJobs([ps.state], 0, ps.limit);
|
||||
const jobs = await queue.getJobs([ps.state], 0, ps.limit!);
|
||||
|
||||
return jobs.map(job => ({
|
||||
id: job.id,
|
||||
|
@ -82,7 +82,7 @@ export default define(meta, async (ps, me) => {
|
||||
default: query.orderBy('user.id', 'ASC'); break;
|
||||
}
|
||||
|
||||
query.take(ps.limit);
|
||||
query.take(ps.limit!);
|
||||
query.skip(ps.offset);
|
||||
|
||||
const users = await query.getMany();
|
||||
|
@ -28,5 +28,5 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await getRemoteUser(ps.userId);
|
||||
await updatePerson(user.uri);
|
||||
await updatePerson(user.uri!);
|
||||
});
|
||||
|
@ -123,14 +123,14 @@ async function fetchAny(uri: string) {
|
||||
const note = await createNote(object.id);
|
||||
return {
|
||||
type: 'Note',
|
||||
object: await Notes.pack(note, null, { detail: true })
|
||||
object: await Notes.pack(note!, null, { detail: true })
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function mergePack(user: User, note: Note) {
|
||||
async function mergePack(user: User | null | undefined, note: Note | null | undefined) {
|
||||
if (user != null) {
|
||||
return {
|
||||
type: 'User',
|
||||
|
@ -5,6 +5,7 @@ import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { AuthSessions, AccessTokens, Apps } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -48,7 +49,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
if (exist == null) {
|
||||
// Lookup app
|
||||
const app = await Apps.findOne(session.appId);
|
||||
const app = await Apps.findOne(session.appId).then(ensure);
|
||||
|
||||
// Generate Hash
|
||||
const sha256 = crypto.createHash('sha256');
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -90,7 +91,7 @@ export default define(meta, async (ps) => {
|
||||
const accessToken = await AccessTokens.findOne({
|
||||
appId: app.id,
|
||||
userId: session.userId
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
// Delete session
|
||||
AuthSessions.delete(session.id);
|
||||
|
@ -44,7 +44,7 @@ export default define(meta, async (ps, me) => {
|
||||
.andWhere(`blocking.blockerId = :meId`, { meId: me.id });
|
||||
|
||||
const blockings = await query
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.getMany();
|
||||
|
||||
return await Blockings.packMany(blockings, me);
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await activeUsersChart.getChart(ps.span as any, ps.limit);
|
||||
return await activeUsersChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await driveChart.getChart(ps.span as any, ps.limit);
|
||||
return await driveChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await federationChart.getChart(ps.span as any, ps.limit);
|
||||
return await federationChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -40,5 +40,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await hashtagChart.getChart(ps.span as any, ps.limit, ps.tag);
|
||||
return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.tag);
|
||||
});
|
||||
|
@ -41,5 +41,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await instanceChart.getChart(ps.span as any, ps.limit, ps.host);
|
||||
return await instanceChart.getChart(ps.span as any, ps.limit!, ps.host);
|
||||
});
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await networkChart.getChart(ps.span as any, ps.limit);
|
||||
return await networkChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await notesChart.getChart(ps.span as any, ps.limit);
|
||||
return await notesChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -42,5 +42,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await perUserDriveChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.userId);
|
||||
});
|
||||
|
@ -42,5 +42,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.userId);
|
||||
});
|
||||
|
@ -42,5 +42,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await perUserNotesChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.userId);
|
||||
});
|
||||
|
@ -42,5 +42,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await perUserReactionsChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.userId);
|
||||
});
|
||||
|
@ -33,5 +33,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await usersChart.getChart(ps.span as any, ps.limit);
|
||||
return await usersChart.getChart(ps.span as any, ps.limit!);
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
}
|
||||
|
||||
const files = await query.take(ps.limit).getMany();
|
||||
const files = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await DriveFiles.packMany(files, { detail: false, self: true });
|
||||
});
|
||||
|
@ -92,6 +92,6 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
|
||||
apiLogger.error(e);
|
||||
throw new ApiError();
|
||||
} finally {
|
||||
cleanup();
|
||||
cleanup!();
|
||||
}
|
||||
});
|
||||
|
@ -63,7 +63,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
let file: DriveFile;
|
||||
let file: DriveFile | undefined;
|
||||
|
||||
if (ps.fileId) {
|
||||
file = await DriveFiles.findOne(ps.fileId);
|
||||
@ -81,14 +81,14 @@ export default define(meta, async (ps, user) => {
|
||||
throw new ApiError(meta.errors.fileIdOrUrlRequired);
|
||||
}
|
||||
|
||||
if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
return await DriveFiles.pack(file, {
|
||||
detail: true,
|
||||
self: true
|
||||
|
@ -54,7 +54,7 @@ export default define(meta, async (ps, user) => {
|
||||
query.andWhere('folder.parentId IS NULL');
|
||||
}
|
||||
|
||||
const folders = await query.take(ps.limit).getMany();
|
||||
const folders = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
|
||||
});
|
||||
|
@ -102,10 +102,10 @@ export default define(meta, async (ps, user) => {
|
||||
id: folderId
|
||||
});
|
||||
|
||||
if (folder2.id === folder.id) {
|
||||
if (folder2!.id === folder!.id) {
|
||||
return true;
|
||||
} else if (folder2.parentId) {
|
||||
return await checkCircle(folder2.parentId);
|
||||
} else if (folder2!.parentId) {
|
||||
return await checkCircle(folder2!.parentId);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
}
|
||||
|
||||
const files = await query.take(ps.limit).getMany();
|
||||
const files = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await DriveFiles.packMany(files, { detail: false, self: true });
|
||||
});
|
||||
|
@ -86,7 +86,7 @@ export default define(meta, async (ps, me) => {
|
||||
}
|
||||
}
|
||||
|
||||
const instances = await query.take(ps.limit).skip(ps.offset).getMany();
|
||||
const instances = await query.take(ps.limit!).skip(ps.offset).getMany();
|
||||
|
||||
return instances;
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
|
||||
// Fetch games
|
||||
const games = await query.take(ps.limit).getMany();
|
||||
const games = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Promise.all(games.map((g) => ReversiGames.pack(g, user, {
|
||||
detail: false
|
||||
|
@ -70,7 +70,7 @@ export default define(meta, async (ps, user) => {
|
||||
map: eighteight.data,
|
||||
bw: 'random',
|
||||
isLlotheo: false
|
||||
} as ReversiGame);
|
||||
} as Partial<ReversiGame>);
|
||||
|
||||
publishReversiStream(exist.parentId, 'matched', await ReversiGames.pack(game, exist.parentId));
|
||||
|
||||
@ -107,6 +107,6 @@ export default define(meta, async (ps, user) => {
|
||||
publishReversiStream(child.id, 'invited', packed);
|
||||
publishMainStream(child.id, 'reversiInvited', packed);
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -86,7 +86,7 @@ export default define(meta, async (ps, me) => {
|
||||
'tag.attachedRemoteUsersCount',
|
||||
]);
|
||||
|
||||
const tags = await query.take(ps.limit).getMany();
|
||||
const tags = await query.take(ps.limit!).getMany();
|
||||
|
||||
return tags;
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ export default define(meta, async (ps) => {
|
||||
const hashtags = await Hashtags.createQueryBuilder('tag')
|
||||
.where('tag.name like :q', { q: ps.query.toLowerCase() + '%' })
|
||||
.orderBy('tag.count', 'DESC')
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.skip(ps.offset)
|
||||
.getMany();
|
||||
|
||||
|
@ -79,7 +79,7 @@ export default define(meta, async (ps, me) => {
|
||||
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
|
||||
}
|
||||
|
||||
const users = await query.take(ps.limit).getMany();
|
||||
const users = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Users.packMany(users, me, { detail: true });
|
||||
});
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -18,7 +19,7 @@ export const meta = {
|
||||
export default define(meta, async (ps, user) => {
|
||||
const token = ps.token.replace(/\s/g, '');
|
||||
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
if (profile.twoFactorTempSecret == null) {
|
||||
throw new Error('二段階認証の設定が開始されていません');
|
||||
|
@ -5,6 +5,7 @@ import * as QRCode from 'qrcode';
|
||||
import config from '../../../../../config';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -19,10 +20,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password);
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -16,10 +17,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password);
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -31,7 +31,7 @@ export default define(meta, async (ps, user) => {
|
||||
where: {
|
||||
userId: user.id
|
||||
},
|
||||
take: ps.limit,
|
||||
take: ps.limit!,
|
||||
skip: ps.offset,
|
||||
order: {
|
||||
id: ps.sort == 'asc' ? 1 : -1
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../define';
|
||||
import { UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -20,10 +21,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.currentPassword, profile.password);
|
||||
const same = await bcrypt.compare(ps.currentPassword, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../define';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -16,10 +17,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password);
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -38,7 +38,7 @@ export default define(meta, async (ps, user) => {
|
||||
.leftJoinAndSelect('favorite.note', 'note');
|
||||
|
||||
const favorites = await query
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.getMany();
|
||||
|
||||
return await NoteFavorites.packMany(favorites, user);
|
||||
|
@ -81,13 +81,13 @@ export default define(meta, async (ps, user) => {
|
||||
query.setParameters(followingQuery.getParameters());
|
||||
}
|
||||
|
||||
if (ps.includeTypes.length > 0) {
|
||||
if (ps.includeTypes!.length > 0) {
|
||||
query.andWhere(`notification.type IN (:...includeTypes)`, { includeTypes: ps.includeTypes });
|
||||
} else if (ps.excludeTypes.length > 0) {
|
||||
} else if (ps.excludeTypes!.length > 0) {
|
||||
query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes });
|
||||
}
|
||||
|
||||
const notifications = await query.take(ps.limit).getMany();
|
||||
const notifications = await query.take(ps.limit!).getMany();
|
||||
|
||||
// Mark all as read
|
||||
if (notifications.length > 0 && ps.markAsRead) {
|
||||
|
@ -4,6 +4,7 @@ import { publishMainStream } from '../../../../services/stream';
|
||||
import generateUserToken from '../../common/generate-native-user-token';
|
||||
import define from '../../define';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -18,10 +19,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password);
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -29,7 +29,7 @@ export default define(meta, async (ps, user) => {
|
||||
const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId)
|
||||
.andWhere(`signin.userId = :meId`, { meId: user.id });
|
||||
|
||||
const history = await query.take(ps.limit).getMany();
|
||||
const history = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Promise.all(history.map(record => Signins.pack(record)));
|
||||
});
|
||||
|
@ -9,6 +9,7 @@ import * as ms from 'ms';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { apiLogger } from '../../logger';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -32,10 +33,10 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password);
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
|
@ -206,13 +206,13 @@ export default define(meta, async (ps, user, app) => {
|
||||
|
||||
if (updates.name != null) {
|
||||
const tokens = parsePlain(updates.name);
|
||||
emojis = emojis.concat(extractEmojis(tokens));
|
||||
emojis = emojis.concat(extractEmojis(tokens!));
|
||||
}
|
||||
|
||||
if (profile.description != null) {
|
||||
const tokens = parse(profile.description);
|
||||
emojis = emojis.concat(extractEmojis(tokens));
|
||||
tags = extractHashtags(tokens).map(tag => tag.toLowerCase());
|
||||
emojis = emojis.concat(extractEmojis(tokens!));
|
||||
tags = extractHashtags(tokens!).map(tag => tag.toLowerCase());
|
||||
}
|
||||
|
||||
updates.emojis = emojis;
|
||||
|
@ -38,7 +38,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
const history: MessagingMessage[] = [];
|
||||
|
||||
for (let i = 0; i < ps.limit; i++) {
|
||||
for (let i = 0; i < ps.limit!; i++) {
|
||||
const found = history.map(m => (m.userId === user.id) ? m.recipientId : m.userId);
|
||||
|
||||
const query = MessagingMessages.createQueryBuilder('message')
|
||||
|
@ -44,7 +44,7 @@ export default define(meta, async (ps, me) => {
|
||||
.andWhere(`muting.muterId = :meId`, { meId: me.id });
|
||||
|
||||
const mutings = await query
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.getMany();
|
||||
|
||||
return await Mutings.packMany(mutings, me);
|
||||
|
@ -32,7 +32,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
const apps = await Apps.find({
|
||||
where: query,
|
||||
take: ps.limit,
|
||||
take: ps.limit!,
|
||||
skip: ps.offset,
|
||||
});
|
||||
|
||||
|
@ -100,7 +100,7 @@ export default define(meta, async (ps) => {
|
||||
// query.isBot = bot;
|
||||
//}
|
||||
|
||||
const notes = await query.take(ps.limit).getMany();
|
||||
const notes = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(notes);
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ export default define(meta, async (ps, user) => {
|
||||
if (user) generateVisibilityQuery(query, user);
|
||||
if (user) generateMuteQuery(query, user);
|
||||
|
||||
const notes = await query.take(ps.limit).getMany();
|
||||
const notes = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(notes, user);
|
||||
});
|
||||
|
@ -64,12 +64,13 @@ export default define(meta, async (ps, user) => {
|
||||
async function get(id: any) {
|
||||
i++;
|
||||
const p = await Notes.findOne(id);
|
||||
if (p == null) return;
|
||||
|
||||
if (i > ps.offset) {
|
||||
if (i > ps.offset!) {
|
||||
conversation.push(p);
|
||||
}
|
||||
|
||||
if (conversation.length == ps.limit) {
|
||||
if (conversation.length == ps.limit!) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -225,23 +225,24 @@ export const meta = {
|
||||
export default define(meta, async (ps, user, app) => {
|
||||
let visibleUsers: User[] = [];
|
||||
if (ps.visibleUserIds) {
|
||||
visibleUsers = await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id)));
|
||||
visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id))))
|
||||
.filter(x => x != null) as User[];
|
||||
}
|
||||
|
||||
let files: DriveFile[] = [];
|
||||
const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null;
|
||||
if (fileIds != null) {
|
||||
files = await Promise.all(fileIds.map(fileId => {
|
||||
return DriveFiles.findOne({
|
||||
files = (await Promise.all(fileIds.map(fileId =>
|
||||
DriveFiles.findOne({
|
||||
id: fileId,
|
||||
userId: user.id
|
||||
});
|
||||
}));
|
||||
})
|
||||
))).filter(file => file != null) as DriveFile[];
|
||||
|
||||
files = files.filter(file => file != null);
|
||||
files = files;
|
||||
}
|
||||
|
||||
let renote: Note = null;
|
||||
let renote: Note | undefined;
|
||||
if (ps.renoteId != null) {
|
||||
// Fetch renote to note
|
||||
renote = await Notes.findOne(ps.renoteId);
|
||||
@ -253,7 +254,7 @@ export default define(meta, async (ps, user, app) => {
|
||||
}
|
||||
}
|
||||
|
||||
let reply: Note = null;
|
||||
let reply: Note | undefined;
|
||||
if (ps.replyId != null) {
|
||||
// Fetch reply
|
||||
reply = await Notes.findOne(ps.replyId);
|
||||
@ -290,8 +291,8 @@ export default define(meta, async (ps, user, app) => {
|
||||
choices: ps.poll.choices,
|
||||
multiple: ps.poll.multiple || false,
|
||||
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null
|
||||
} : null,
|
||||
text: ps.text,
|
||||
} : undefined,
|
||||
text: ps.text || undefined,
|
||||
reply,
|
||||
renote,
|
||||
cw: ps.cw,
|
||||
@ -300,9 +301,9 @@ export default define(meta, async (ps, user, app) => {
|
||||
localOnly: ps.localOnly,
|
||||
visibility: ps.visibility,
|
||||
visibleUsers,
|
||||
apMentions: ps.noExtractMentions ? [] : null,
|
||||
apHashtags: ps.noExtractHashtags ? [] : null,
|
||||
apEmojis: ps.noExtractEmojis ? [] : null,
|
||||
apMentions: ps.noExtractMentions ? [] : undefined,
|
||||
apHashtags: ps.noExtractHashtags ? [] : undefined,
|
||||
apEmojis: ps.noExtractEmojis ? [] : undefined,
|
||||
geo: ps.geo
|
||||
});
|
||||
|
||||
|
@ -6,6 +6,7 @@ import * as ms from 'ms';
|
||||
import { getNote } from '../../common/getters';
|
||||
import { ApiError } from '../../error';
|
||||
import { Users } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -63,5 +64,5 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
|
||||
// この操作を行うのが投稿者とは限らない(例えばモデレーター)ため
|
||||
await deleteNote(await Users.findOne(note.userId), note);
|
||||
await deleteNote(await Users.findOne(note.userId).then(ensure), note);
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
if (user) generateMuteQuery(query, user);
|
||||
|
||||
const notes = await query.orderBy('note.score', 'DESC').take(ps.limit).getMany();
|
||||
const notes = await query.orderBy('note.score', 'DESC').take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(notes, user);
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
if (user) {
|
||||
activeUsersChart.update(user);
|
||||
|
@ -185,7 +185,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
if (user) {
|
||||
activeUsersChart.update(user);
|
||||
|
@ -100,11 +100,11 @@ export default define(meta, async (ps, user) => {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
}
|
||||
|
||||
if (ps.fileType) {
|
||||
if (ps.fileType != null) {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const type of ps.fileType) {
|
||||
const i = ps.fileType.indexOf(type);
|
||||
for (const type of ps.fileType!) {
|
||||
const i = ps.fileType!.indexOf(type);
|
||||
qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
|
||||
}
|
||||
}));
|
||||
@ -120,7 +120,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
if (user) {
|
||||
activeUsersChart.update(user);
|
||||
|
@ -74,7 +74,7 @@ export default define(meta, async (ps, user) => {
|
||||
query.setParameters(followingQuery.getParameters());
|
||||
}
|
||||
|
||||
const mentions = await query.take(ps.limit).getMany();
|
||||
const mentions = await query.take(ps.limit!).getMany();
|
||||
|
||||
for (const note of mentions) {
|
||||
read(user.id, note.id);
|
||||
|
@ -58,7 +58,7 @@ export default define(meta, async (ps, user) => {
|
||||
query.setParameters(mutingQuery.getParameters());
|
||||
//#endregion
|
||||
|
||||
const polls = await query.take(ps.limit).skip(ps.offset).getMany();
|
||||
const polls = await query.take(ps.limit!).skip(ps.offset).getMany();
|
||||
|
||||
if (polls.length === 0) return [];
|
||||
|
||||
|
@ -14,6 +14,7 @@ import { PollVotes, NoteWatchings, Users, Polls, UserProfiles } from '../../../.
|
||||
import { Not } from 'typeorm';
|
||||
import { IRemoteUser } from '../../../../../models/entities/user';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -87,7 +88,7 @@ export default define(meta, async (ps, user) => {
|
||||
throw new ApiError(meta.errors.noPoll);
|
||||
}
|
||||
|
||||
const poll = await Polls.findOne({ noteId: note.id });
|
||||
const poll = await Polls.findOne({ noteId: note.id }).then(ensure);
|
||||
|
||||
if (poll.expiresAt && poll.expiresAt < createdAt) {
|
||||
throw new ApiError(meta.errors.alreadyExpired);
|
||||
@ -149,7 +150,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// この投稿をWatchする
|
||||
if (profile.autoWatch !== false) {
|
||||
@ -158,7 +159,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
// リモート投票の場合リプライ送信
|
||||
if (note.userHost != null) {
|
||||
const pollOwner: IRemoteUser = await Users.findOne(note.userId);
|
||||
const pollOwner = await Users.findOne(note.userId).then(ensure) as IRemoteUser;
|
||||
|
||||
deliver(user, renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
const reactions = await NoteReactions.find({
|
||||
where: query,
|
||||
take: ps.limit,
|
||||
take: ps.limit!,
|
||||
skip: ps.offset,
|
||||
order: {
|
||||
id: -1
|
||||
|
@ -70,7 +70,7 @@ export default define(meta, async (ps, user) => {
|
||||
if (user) generateVisibilityQuery(query, user);
|
||||
if (user) generateMuteQuery(query, user);
|
||||
|
||||
const renotes = await query.take(ps.limit).getMany();
|
||||
const renotes = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(renotes, user);
|
||||
});
|
||||
|
@ -61,7 +61,7 @@ export default define(meta, async (ps, user) => {
|
||||
if (user) generateVisibilityQuery(query, user);
|
||||
if (user) generateMuteQuery(query, user);
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(timeline, user);
|
||||
});
|
||||
|
@ -100,7 +100,7 @@ export default define(meta, async (ps, me) => {
|
||||
} else {
|
||||
let i = 0;
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const tags of ps.query) {
|
||||
for (const tags of ps.query!) {
|
||||
qb.orWhere(new Brackets(qb => {
|
||||
for (const tag of tags) {
|
||||
qb.andWhere(`:tag${i} = ANY(note.tags)`, { [`tag${i}`]: tag });
|
||||
@ -140,7 +140,7 @@ export default define(meta, async (ps, me) => {
|
||||
}
|
||||
|
||||
// Search notes
|
||||
const notes = await query.take(ps.limit).getMany();
|
||||
const notes = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(notes, me);
|
||||
});
|
||||
|
@ -54,7 +54,7 @@ export default define(meta, async (ps, me) => {
|
||||
index: 'misskey',
|
||||
type: 'note',
|
||||
body: {
|
||||
size: ps.limit,
|
||||
size: ps.limit!,
|
||||
from: ps.offset,
|
||||
query: {
|
||||
simple_query_string: {
|
||||
|
@ -171,7 +171,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
activeUsersChart.update(user);
|
||||
|
||||
|
@ -189,7 +189,7 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
activeUsersChart.update(user);
|
||||
|
||||
|
@ -88,7 +88,7 @@ export default define(meta, async (ps, me) => {
|
||||
|
||||
if (me) generateMuteQueryForUsers(query, me);
|
||||
|
||||
query.take(ps.limit);
|
||||
query.take(ps.limit!);
|
||||
query.skip(ps.offset);
|
||||
|
||||
const users = await query.getMany();
|
||||
|
@ -66,7 +66,7 @@ export const meta = {
|
||||
export default define(meta, async (ps, me) => {
|
||||
const user = await Users.findOne(ps.userId != null
|
||||
? { id: ps.userId }
|
||||
: { usernameLower: ps.username.toLowerCase(), host: toPuny(ps.host) });
|
||||
: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
|
||||
|
||||
if (user == null) {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
@ -76,7 +76,7 @@ export default define(meta, async (ps, me) => {
|
||||
.andWhere(`following.followeeId = :userId`, { userId: user.id });
|
||||
|
||||
const followings = await query
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.getMany();
|
||||
|
||||
return await Followings.packMany(followings, me, { populateFollower: true });
|
||||
|
@ -66,7 +66,7 @@ export const meta = {
|
||||
export default define(meta, async (ps, me) => {
|
||||
const user = await Users.findOne(ps.userId != null
|
||||
? { id: ps.userId }
|
||||
: { usernameLower: ps.username.toLowerCase(), host: toPuny(ps.host) });
|
||||
: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
|
||||
|
||||
if (user == null) {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
@ -76,7 +76,7 @@ export default define(meta, async (ps, me) => {
|
||||
.andWhere(`following.followerId = :userId`, { userId: user.id });
|
||||
|
||||
const followings = await query
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.getMany();
|
||||
|
||||
return await Followings.packMany(followings, me, { populateFollowee: true });
|
||||
|
@ -94,7 +94,7 @@ export default define(meta, async (ps, me) => {
|
||||
const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
|
||||
|
||||
// Extract top replied users
|
||||
const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit);
|
||||
const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit!);
|
||||
|
||||
// Make replies object (includes weights)
|
||||
const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
|
||||
|
@ -153,11 +153,11 @@ export default define(meta, async (ps, me) => {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
}
|
||||
|
||||
if (ps.fileType) {
|
||||
if (ps.fileType != null) {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const type of ps.fileType) {
|
||||
const i = ps.fileType.indexOf(type);
|
||||
for (const type of ps.fileType!) {
|
||||
const i = ps.fileType!.indexOf(type);
|
||||
qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
|
||||
}
|
||||
}));
|
||||
@ -194,7 +194,7 @@ export default define(meta, async (ps, me) => {
|
||||
|
||||
//#endregion
|
||||
|
||||
const timeline = await query.take(ps.limit).getMany();
|
||||
const timeline = await query.take(ps.limit!).getMany();
|
||||
|
||||
return await Notes.packMany(timeline, user);
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ export default define(meta, async (ps, me) => {
|
||||
|
||||
query.setParameters(followingQuery.getParameters());
|
||||
|
||||
const users = await query.take(ps.limit).skip(ps.offset).getMany();
|
||||
const users = await query.take(ps.limit!).skip(ps.offset).getMany();
|
||||
|
||||
return await Users.packMany(users, me, { detail: true });
|
||||
});
|
||||
|
@ -71,16 +71,16 @@ export default define(meta, async (ps, me) => {
|
||||
.where('user.host IS NULL')
|
||||
.andWhere('user.isSuspended = FALSE')
|
||||
.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
|
||||
.take(ps.limit)
|
||||
.take(ps.limit!)
|
||||
.skip(ps.offset)
|
||||
.getMany();
|
||||
|
||||
if (users.length < ps.limit && !ps.localOnly) {
|
||||
if (users.length < ps.limit! && !ps.localOnly) {
|
||||
const otherUsers = await Users.createQueryBuilder('user')
|
||||
.where('user.host IS NOT NULL')
|
||||
.andWhere('user.isSuspended = FALSE')
|
||||
.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
|
||||
.take(ps.limit - users.length)
|
||||
.take(ps.limit! - users.length)
|
||||
.getMany();
|
||||
|
||||
users = users.concat(otherUsers);
|
||||
|
@ -74,7 +74,7 @@ export default define(meta, async (ps, me) => {
|
||||
})));
|
||||
} else {
|
||||
// Lookup user
|
||||
if (typeof ps.host === 'string') {
|
||||
if (typeof ps.host === 'string' && typeof ps.username === 'string') {
|
||||
user = await resolveUser(ps.username, ps.host).catch(e => {
|
||||
apiLogger.warn(`failed to resolve remote user: ${e}`);
|
||||
throw new ApiError(meta.errors.failedToResolveRemoteUser);
|
||||
@ -82,7 +82,7 @@ export default define(meta, async (ps, me) => {
|
||||
} else {
|
||||
const q: any = ps.userId != null
|
||||
? { id: ps.userId }
|
||||
: { usernameLower: ps.username.toLowerCase(), host: null };
|
||||
: { usernameLower: ps.username!.toLowerCase(), host: null };
|
||||
|
||||
user = await Users.findOne(q);
|
||||
}
|
||||
@ -94,7 +94,7 @@ export default define(meta, async (ps, me) => {
|
||||
// ユーザー情報更新
|
||||
if (Users.isRemoteUser(user)) {
|
||||
if (user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
|
||||
resolveUser(ps.username, ps.host, { }, true);
|
||||
resolveUser(user.username, user.host, { }, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
type E = { message: string, code: string, id: string, kind?: 'client' | 'server', httpStatusCode?: number };
|
||||
|
||||
export class ApiError extends Error {
|
||||
public message: string;
|
||||
public code: string;
|
||||
@ -6,7 +8,7 @@ export class ApiError extends Error {
|
||||
public httpStatusCode?: number;
|
||||
public info?: any;
|
||||
|
||||
constructor(e?: { message: string, code: string, id: string, kind?: 'client' | 'server', httpStatusCode?: number }, info?: any) {
|
||||
constructor(e?: E | null | undefined, info?: any | null | undefined) {
|
||||
if (e == null) e = {
|
||||
message: 'Internal error occurred. Please contact us if the error persists.',
|
||||
code: 'INTERNAL_ERROR',
|
||||
|
@ -14,7 +14,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
|
||||
return;
|
||||
}
|
||||
|
||||
const limitation = endpoint.meta.limit;
|
||||
const limitation = endpoint.meta.limit!;
|
||||
|
||||
const key = limitation.hasOwnProperty('key')
|
||||
? limitation.key
|
||||
@ -41,7 +41,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
|
||||
id: `${user.id}:${key}:min`,
|
||||
duration: limitation.minInterval,
|
||||
max: 1,
|
||||
db: limiterDB
|
||||
db: limiterDB!
|
||||
});
|
||||
|
||||
minIntervalLimiter.get((err, info) => {
|
||||
@ -69,7 +69,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
|
||||
id: `${user.id}:${key}`,
|
||||
duration: limitation.duration,
|
||||
max: limitation.max,
|
||||
db: limiterDB
|
||||
db: limiterDB!
|
||||
});
|
||||
|
||||
limiter.get((err, info) => {
|
||||
|
@ -7,6 +7,7 @@ import config from '../../../config';
|
||||
import { Users, Signins, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
export default async (ctx: Koa.BaseContext) => {
|
||||
ctx.set('Access-Control-Allow-Origin', config.url);
|
||||
@ -45,10 +46,10 @@ export default async (ctx: Koa.BaseContext) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await UserProfiles.findOne({ userId: user.id });
|
||||
const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(password, profile.password);
|
||||
const same = await bcrypt.compare(password, profile.password!);
|
||||
|
||||
if (same) {
|
||||
if (profile.twoFactorEnabled) {
|
||||
|
@ -21,7 +21,7 @@ export default async (ctx: Koa.BaseContext) => {
|
||||
|
||||
// Verify recaptcha
|
||||
// ただしテスト時はこの機構は障害となるため無効にする
|
||||
if (process.env.NODE_ENV !== 'test' && instance.enableRecaptcha) {
|
||||
if (process.env.NODE_ENV !== 'test' && instance.enableRecaptcha && instance.recaptchaSecretKey) {
|
||||
recaptcha.init({
|
||||
secret_key: instance.recaptchaSecretKey
|
||||
});
|
||||
@ -100,7 +100,7 @@ export default async (ctx: Koa.BaseContext) => {
|
||||
e ? j(e) : s([publicKey, privateKey])
|
||||
));
|
||||
|
||||
let account: User;
|
||||
let account!: User;
|
||||
|
||||
// Start transaction
|
||||
await getConnection().transaction(async transactionalEntityManager => {
|
||||
|
@ -10,6 +10,7 @@ import signin from '../common/signin';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.BaseContext) {
|
||||
return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
|
||||
@ -43,7 +44,7 @@ router.get('/disconnect/discord', async ctx => {
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({
|
||||
userId: user.id
|
||||
@ -71,8 +72,8 @@ async function getOAuth2() {
|
||||
|
||||
if (meta.enableDiscordIntegration) {
|
||||
return new OAuth2(
|
||||
meta.discordClientId,
|
||||
meta.discordClientSecret,
|
||||
meta.discordClientId!,
|
||||
meta.discordClientSecret!,
|
||||
'https://discordapp.com/',
|
||||
'api/oauth2/authorize',
|
||||
'api/oauth2/token');
|
||||
@ -82,6 +83,8 @@ async function getOAuth2() {
|
||||
}
|
||||
|
||||
router.get('/connect/discord', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
if (!compareOrigin(ctx)) {
|
||||
ctx.throw(400, 'invalid origin');
|
||||
return;
|
||||
@ -103,10 +106,12 @@ router.get('/connect/discord', async ctx => {
|
||||
redis.set(userToken, JSON.stringify(params));
|
||||
|
||||
const oauth2 = await getOAuth2();
|
||||
ctx.redirect(oauth2.getAuthorizeUrl(params));
|
||||
ctx.redirect(oauth2!.getAuthorizeUrl(params));
|
||||
});
|
||||
|
||||
router.get('/signin/discord', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const sessid = uuid();
|
||||
|
||||
const params = {
|
||||
@ -129,10 +134,12 @@ router.get('/signin/discord', async ctx => {
|
||||
redis.set(sessid, JSON.stringify(params));
|
||||
|
||||
const oauth2 = await getOAuth2();
|
||||
ctx.redirect(oauth2.getAuthorizeUrl(params));
|
||||
ctx.redirect(oauth2!.getAuthorizeUrl(params));
|
||||
});
|
||||
|
||||
router.get('/dc/cb', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const userToken = getUserToken(ctx);
|
||||
|
||||
const oauth2 = await getOAuth2();
|
||||
@ -153,7 +160,7 @@ router.get('/dc/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||
redis.get(sessid, async (_, state) => {
|
||||
redis!.get(sessid, async (_, state) => {
|
||||
res(JSON.parse(state));
|
||||
});
|
||||
});
|
||||
@ -164,24 +171,22 @@ router.get('/dc/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { accessToken, refreshToken, expiresDate } = await new Promise<any>((res, rej) =>
|
||||
oauth2.getOAuthAccessToken(
|
||||
code,
|
||||
{
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri
|
||||
},
|
||||
(err, accessToken, refreshToken, result) => {
|
||||
if (err)
|
||||
rej(err);
|
||||
else if (result.error)
|
||||
rej(result.error);
|
||||
else
|
||||
oauth2!.getOAuthAccessToken(code, {
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri
|
||||
}, (err, accessToken, refreshToken, result) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
} else if (result.error) {
|
||||
rej(result.error);
|
||||
} else {
|
||||
res({
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresDate: Date.now() + Number(result.expires_in) * 1000
|
||||
});
|
||||
}));
|
||||
}
|
||||
}));
|
||||
|
||||
const { id, username, discriminator } = await new Promise<any>((res, rej) =>
|
||||
request({
|
||||
@ -191,10 +196,11 @@ router.get('/dc/cb', async ctx => {
|
||||
'User-Agent': config.userAgent
|
||||
}
|
||||
}, (err, response, body) => {
|
||||
if (err)
|
||||
if (err) {
|
||||
rej(err);
|
||||
else
|
||||
} else {
|
||||
res(JSON.parse(body));
|
||||
}
|
||||
}));
|
||||
|
||||
if (!id || !username || !discriminator) {
|
||||
@ -235,7 +241,7 @@ router.get('/dc/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||
redis.get(userToken, async (_, state) => {
|
||||
redis!.get(userToken, async (_, state) => {
|
||||
res(JSON.parse(state));
|
||||
});
|
||||
});
|
||||
@ -246,24 +252,22 @@ router.get('/dc/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { accessToken, refreshToken, expiresDate } = await new Promise<any>((res, rej) =>
|
||||
oauth2.getOAuthAccessToken(
|
||||
code,
|
||||
{
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri
|
||||
},
|
||||
(err, accessToken, refreshToken, result) => {
|
||||
if (err)
|
||||
rej(err);
|
||||
else if (result.error)
|
||||
rej(result.error);
|
||||
else
|
||||
res({
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresDate: Date.now() + Number(result.expires_in) * 1000
|
||||
});
|
||||
}));
|
||||
oauth2!.getOAuthAccessToken(code, {
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri
|
||||
}, (err, accessToken, refreshToken, result) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
} else if (result.error) {
|
||||
rej(result.error);
|
||||
} else {
|
||||
res({
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresDate: Date.now() + Number(result.expires_in) * 1000
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
const { id, username, discriminator } = await new Promise<any>((res, rej) =>
|
||||
request({
|
||||
@ -273,10 +277,11 @@ router.get('/dc/cb', async ctx => {
|
||||
'User-Agent': config.userAgent
|
||||
}
|
||||
}, (err, response, body) => {
|
||||
if (err)
|
||||
if (err) {
|
||||
rej(err);
|
||||
else
|
||||
} else {
|
||||
res(JSON.parse(body));
|
||||
}
|
||||
}));
|
||||
|
||||
if (!id || !username || !discriminator) {
|
||||
@ -287,7 +292,7 @@ router.get('/dc/cb', async ctx => {
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({ userId: user.id }, {
|
||||
discord: true,
|
||||
|
@ -10,6 +10,7 @@ import signin from '../common/signin';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.BaseContext) {
|
||||
return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
|
||||
@ -43,7 +44,7 @@ router.get('/disconnect/github', async ctx => {
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({
|
||||
userId: user.id
|
||||
@ -66,7 +67,7 @@ router.get('/disconnect/github', async ctx => {
|
||||
async function getOath2() {
|
||||
const meta = await fetchMeta();
|
||||
|
||||
if (meta.enableGithubIntegration) {
|
||||
if (meta.enableGithubIntegration && meta.githubClientId && meta.githubClientSecret) {
|
||||
return new OAuth2(
|
||||
meta.githubClientId,
|
||||
meta.githubClientSecret,
|
||||
@ -79,6 +80,8 @@ async function getOath2() {
|
||||
}
|
||||
|
||||
router.get('/connect/github', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
if (!compareOrigin(ctx)) {
|
||||
ctx.throw(400, 'invalid origin');
|
||||
return;
|
||||
@ -99,10 +102,12 @@ router.get('/connect/github', async ctx => {
|
||||
redis.set(userToken, JSON.stringify(params));
|
||||
|
||||
const oauth2 = await getOath2();
|
||||
ctx.redirect(oauth2.getAuthorizeUrl(params));
|
||||
ctx.redirect(oauth2!.getAuthorizeUrl(params));
|
||||
});
|
||||
|
||||
router.get('/signin/github', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const sessid = uuid();
|
||||
|
||||
const params = {
|
||||
@ -124,10 +129,12 @@ router.get('/signin/github', async ctx => {
|
||||
redis.set(sessid, JSON.stringify(params));
|
||||
|
||||
const oauth2 = await getOath2();
|
||||
ctx.redirect(oauth2.getAuthorizeUrl(params));
|
||||
ctx.redirect(oauth2!.getAuthorizeUrl(params));
|
||||
});
|
||||
|
||||
router.get('/gh/cb', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const userToken = getUserToken(ctx);
|
||||
|
||||
const oauth2 = await getOath2();
|
||||
@ -148,7 +155,7 @@ router.get('/gh/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||
redis.get(sessid, async (_, state) => {
|
||||
redis!.get(sessid, async (_, state) => {
|
||||
res(JSON.parse(state));
|
||||
});
|
||||
});
|
||||
@ -159,17 +166,17 @@ router.get('/gh/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { accessToken } = await new Promise<any>((res, rej) =>
|
||||
oauth2.getOAuthAccessToken(
|
||||
code,
|
||||
{ redirect_uri },
|
||||
(err, accessToken, refresh, result) => {
|
||||
if (err)
|
||||
rej(err);
|
||||
else if (result.error)
|
||||
rej(result.error);
|
||||
else
|
||||
res({ accessToken });
|
||||
}));
|
||||
oauth2!.getOAuthAccessToken(code, {
|
||||
redirect_uri
|
||||
}, (err, accessToken, refresh, result) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
} else if (result.error) {
|
||||
rej(result.error);
|
||||
} else {
|
||||
res({ accessToken });
|
||||
}
|
||||
}));
|
||||
|
||||
const { login, id } = await new Promise<any>((res, rej) =>
|
||||
request({
|
||||
@ -215,7 +222,7 @@ router.get('/gh/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||
redis.get(userToken, async (_, state) => {
|
||||
redis!.get(userToken, async (_, state) => {
|
||||
res(JSON.parse(state));
|
||||
});
|
||||
});
|
||||
@ -226,7 +233,7 @@ router.get('/gh/cb', async ctx => {
|
||||
}
|
||||
|
||||
const { accessToken } = await new Promise<any>((res, rej) =>
|
||||
oauth2.getOAuthAccessToken(
|
||||
oauth2!.getOAuthAccessToken(
|
||||
code,
|
||||
{ redirect_uri },
|
||||
(err, accessToken, refresh, result) => {
|
||||
@ -261,7 +268,7 @@ router.get('/gh/cb', async ctx => {
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({ userId: user.id }, {
|
||||
github: true,
|
||||
|
@ -9,6 +9,7 @@ import signin from '../common/signin';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.BaseContext) {
|
||||
return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
|
||||
@ -42,7 +43,7 @@ router.get('/disconnect/twitter', async ctx => {
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({
|
||||
userId: user.id
|
||||
@ -66,7 +67,7 @@ router.get('/disconnect/twitter', async ctx => {
|
||||
async function getTwAuth() {
|
||||
const meta = await fetchMeta();
|
||||
|
||||
if (meta.enableTwitterIntegration) {
|
||||
if (meta.enableTwitterIntegration && meta.twitterConsumerKey && meta.twitterConsumerSecret) {
|
||||
return autwh({
|
||||
consumerKey: meta.twitterConsumerKey,
|
||||
consumerSecret: meta.twitterConsumerSecret,
|
||||
@ -78,6 +79,8 @@ async function getTwAuth() {
|
||||
}
|
||||
|
||||
router.get('/connect/twitter', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
if (!compareOrigin(ctx)) {
|
||||
ctx.throw(400, 'invalid origin');
|
||||
return;
|
||||
@ -90,14 +93,16 @@ router.get('/connect/twitter', async ctx => {
|
||||
}
|
||||
|
||||
const twAuth = await getTwAuth();
|
||||
const twCtx = await twAuth.begin();
|
||||
const twCtx = await twAuth!.begin();
|
||||
redis.set(userToken, JSON.stringify(twCtx));
|
||||
ctx.redirect(twCtx.url);
|
||||
});
|
||||
|
||||
router.get('/signin/twitter', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const twAuth = await getTwAuth();
|
||||
const twCtx = await twAuth.begin();
|
||||
const twCtx = await twAuth!.begin();
|
||||
|
||||
const sessid = uuid();
|
||||
|
||||
@ -117,6 +122,8 @@ router.get('/signin/twitter', async ctx => {
|
||||
});
|
||||
|
||||
router.get('/tw/cb', async ctx => {
|
||||
if (redis == null) return;
|
||||
|
||||
const userToken = getUserToken(ctx);
|
||||
|
||||
const twAuth = await getTwAuth();
|
||||
@ -130,14 +137,14 @@ router.get('/tw/cb', async ctx => {
|
||||
}
|
||||
|
||||
const get = new Promise<any>((res, rej) => {
|
||||
redis.get(sessid, async (_, twCtx) => {
|
||||
redis!.get(sessid, async (_, twCtx) => {
|
||||
res(twCtx);
|
||||
});
|
||||
});
|
||||
|
||||
const twCtx = await get;
|
||||
|
||||
const result = await twAuth.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
|
||||
const result = await twAuth!.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
|
||||
|
||||
const link = await UserProfiles.createQueryBuilder()
|
||||
.where('twitter @> :twitter', {
|
||||
@ -163,19 +170,19 @@ router.get('/tw/cb', async ctx => {
|
||||
}
|
||||
|
||||
const get = new Promise<any>((res, rej) => {
|
||||
redis.get(userToken, async (_, twCtx) => {
|
||||
redis!.get(userToken, async (_, twCtx) => {
|
||||
res(twCtx);
|
||||
});
|
||||
});
|
||||
|
||||
const twCtx = await get;
|
||||
|
||||
const result = await twAuth.done(JSON.parse(twCtx), verifier);
|
||||
const result = await twAuth!.done(JSON.parse(twCtx), verifier);
|
||||
|
||||
const user = await Users.findOne({
|
||||
host: null,
|
||||
token: userToken
|
||||
});
|
||||
}).then(ensure);
|
||||
|
||||
await UserProfiles.update({ userId: user.id }, {
|
||||
twitter: true,
|
||||
|
@ -9,7 +9,7 @@ export default class extends Channel {
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
// Subscribe admin stream
|
||||
this.subscriber.on(`adminStream:${this.user.id}`, data => {
|
||||
this.subscriber.on(`adminStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
});
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ export default class extends Channel {
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
// Subscribe drive stream
|
||||
this.subscriber.on(`driveStream:${this.user.id}`, data => {
|
||||
this.subscriber.on(`driveStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
});
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export default class extends Channel {
|
||||
public static shouldShare = false;
|
||||
public static requireCredential = false;
|
||||
|
||||
private gameId: ReversiGame['id'];
|
||||
private gameId: ReversiGame['id'] | null = null;
|
||||
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
@ -40,7 +40,10 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
private async updateSettings(key: string, value: any) {
|
||||
const game = await ReversiGames.findOne(this.gameId);
|
||||
if (this.user == null) return;
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (game.isStarted) return;
|
||||
if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
|
||||
@ -49,11 +52,11 @@ export default class extends Channel {
|
||||
|
||||
if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard'].includes(key)) return;
|
||||
|
||||
await ReversiGames.update({ id: this.gameId }, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
[key]: value
|
||||
});
|
||||
|
||||
publishReversiGameStream(this.gameId, 'updateSettings', {
|
||||
publishReversiGameStream(this.gameId!, 'updateSettings', {
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
@ -61,7 +64,10 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
private async initForm(form: any) {
|
||||
const game = await ReversiGames.findOne(this.gameId);
|
||||
if (this.user == null) return;
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (game.isStarted) return;
|
||||
if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
|
||||
@ -72,9 +78,9 @@ export default class extends Channel {
|
||||
form2: form
|
||||
};
|
||||
|
||||
await ReversiGames.update({ id: this.gameId }, set);
|
||||
await ReversiGames.update(this.gameId!, set);
|
||||
|
||||
publishReversiGameStream(this.gameId, 'initForm', {
|
||||
publishReversiGameStream(this.gameId!, 'initForm', {
|
||||
userId: this.user.id,
|
||||
form
|
||||
});
|
||||
@ -82,7 +88,10 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
private async updateForm(id: string, value: any) {
|
||||
const game = await ReversiGames.findOne({ id: this.gameId });
|
||||
if (this.user == null) return;
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (game.isStarted) return;
|
||||
if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
|
||||
@ -101,9 +110,9 @@ export default class extends Channel {
|
||||
form1: form
|
||||
};
|
||||
|
||||
await ReversiGames.update({ id: this.gameId }, set);
|
||||
await ReversiGames.update(this.gameId!, set);
|
||||
|
||||
publishReversiGameStream(this.gameId, 'updateForm', {
|
||||
publishReversiGameStream(this.gameId!, 'updateForm', {
|
||||
userId: this.user.id,
|
||||
id,
|
||||
value
|
||||
@ -112,8 +121,10 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
private async message(message: any) {
|
||||
if (this.user == null) return;
|
||||
|
||||
message.id = Math.random();
|
||||
publishReversiGameStream(this.gameId, 'message', {
|
||||
publishReversiGameStream(this.gameId!, 'message', {
|
||||
userId: this.user.id,
|
||||
message
|
||||
});
|
||||
@ -121,29 +132,32 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
private async accept(accept: boolean) {
|
||||
const game = await ReversiGames.findOne(this.gameId);
|
||||
if (this.user == null) return;
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (game.isStarted) return;
|
||||
|
||||
let bothAccepted = false;
|
||||
|
||||
if (game.user1Id === this.user.id) {
|
||||
await ReversiGames.update({ id: this.gameId }, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
user1Accepted: accept
|
||||
});
|
||||
|
||||
publishReversiGameStream(this.gameId, 'changeAccepts', {
|
||||
publishReversiGameStream(this.gameId!, 'changeAccepts', {
|
||||
user1: accept,
|
||||
user2: game.user2Accepted
|
||||
});
|
||||
|
||||
if (accept && game.user2Accepted) bothAccepted = true;
|
||||
} else if (game.user2Id === this.user.id) {
|
||||
await ReversiGames.update({ id: this.gameId }, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
user2Accepted: accept
|
||||
});
|
||||
|
||||
publishReversiGameStream(this.gameId, 'changeAccepts', {
|
||||
publishReversiGameStream(this.gameId!, 'changeAccepts', {
|
||||
user1: game.user1Accepted,
|
||||
user2: accept
|
||||
});
|
||||
@ -156,7 +170,7 @@ export default class extends Channel {
|
||||
if (bothAccepted) {
|
||||
// 3秒後、まだacceptされていたらゲーム開始
|
||||
setTimeout(async () => {
|
||||
const freshGame = await ReversiGames.findOne(this.gameId);
|
||||
const freshGame = await ReversiGames.findOne(this.gameId!);
|
||||
if (freshGame == null || freshGame.isStarted || freshGame.isEnded) return;
|
||||
if (!freshGame.user1Accepted || !freshGame.user2Accepted) return;
|
||||
|
||||
@ -175,7 +189,7 @@ export default class extends Channel {
|
||||
|
||||
const map = freshGame.map != null ? freshGame.map : getRandomMap();
|
||||
|
||||
await ReversiGames.update({ id: this.gameId }, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
startedAt: new Date(),
|
||||
isStarted: true,
|
||||
black: bw,
|
||||
@ -199,22 +213,20 @@ export default class extends Channel {
|
||||
winner = null;
|
||||
}
|
||||
|
||||
await ReversiGames.update({
|
||||
id: this.gameId
|
||||
}, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
isEnded: true,
|
||||
winnerId: winner
|
||||
});
|
||||
|
||||
publishReversiGameStream(this.gameId, 'ended', {
|
||||
publishReversiGameStream(this.gameId!, 'ended', {
|
||||
winnerId: winner,
|
||||
game: await ReversiGames.pack(this.gameId, this.user)
|
||||
game: await ReversiGames.pack(this.gameId!, this.user)
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
|
||||
publishReversiGameStream(this.gameId, 'started',
|
||||
await ReversiGames.pack(this.gameId, this.user));
|
||||
publishReversiGameStream(this.gameId!, 'started',
|
||||
await ReversiGames.pack(this.gameId!, this.user));
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
@ -222,7 +234,10 @@ export default class extends Channel {
|
||||
// 石を打つ
|
||||
@autobind
|
||||
private async set(pos: number) {
|
||||
const game = await ReversiGames.findOne(this.gameId);
|
||||
if (this.user == null) return;
|
||||
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (!game.isStarted) return;
|
||||
if (game.isEnded) return;
|
||||
@ -267,30 +282,29 @@ export default class extends Channel {
|
||||
|
||||
game.logs.push(log);
|
||||
|
||||
await ReversiGames.update({
|
||||
id: this.gameId
|
||||
}, {
|
||||
await ReversiGames.update(this.gameId!, {
|
||||
crc32,
|
||||
isEnded: o.isEnded,
|
||||
winnerId: winner,
|
||||
logs: game.logs
|
||||
});
|
||||
|
||||
publishReversiGameStream(this.gameId, 'set', Object.assign(log, {
|
||||
publishReversiGameStream(this.gameId!, 'set', Object.assign(log, {
|
||||
next: o.turn
|
||||
}));
|
||||
|
||||
if (o.isEnded) {
|
||||
publishReversiGameStream(this.gameId, 'ended', {
|
||||
publishReversiGameStream(this.gameId!, 'ended', {
|
||||
winnerId: winner,
|
||||
game: await ReversiGames.pack(this.gameId, this.user)
|
||||
game: await ReversiGames.pack(this.gameId!, this.user)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async check(crc32: string) {
|
||||
const game = await ReversiGames.findOne(this.gameId);
|
||||
const game = await ReversiGames.findOne(this.gameId!);
|
||||
if (game == null) throw 'game not found';
|
||||
|
||||
if (!game.isStarted) return;
|
||||
|
||||
|
@ -11,7 +11,7 @@ export default class extends Channel {
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
// Subscribe reversi stream
|
||||
this.subscriber.on(`reversiStream:${this.user.id}`, data => {
|
||||
this.subscriber.on(`reversiStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
});
|
||||
}
|
||||
@ -22,7 +22,7 @@ export default class extends Channel {
|
||||
case 'ping':
|
||||
if (body.id == null) return;
|
||||
const matching = await ReversiMatchings.findOne({
|
||||
parentId: this.user.id,
|
||||
parentId: this.user!.id,
|
||||
childId: body.id
|
||||
});
|
||||
if (matching == null) return;
|
||||
|
@ -17,10 +17,10 @@ export default class extends Channel {
|
||||
@autobind
|
||||
private async onNote(note: any) {
|
||||
// その投稿のユーザーをフォローしていなかったら弾く
|
||||
if (this.user.id !== note.userId && !this.following.includes(note.userId)) return;
|
||||
if (this.user!.id !== note.userId && !this.following.includes(note.userId)) return;
|
||||
|
||||
if (['followers', 'specified'].includes(note.visibility)) {
|
||||
note = await Notes.pack(note.id, this.user, {
|
||||
note = await Notes.pack(note.id, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
|
||||
@ -30,13 +30,13 @@ export default class extends Channel {
|
||||
} else {
|
||||
// リプライなら再pack
|
||||
if (note.replyId != null) {
|
||||
note.reply = await Notes.pack(note.replyId, this.user, {
|
||||
note.reply = await Notes.pack(note.replyId, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
}
|
||||
// Renoteなら再pack
|
||||
if (note.renoteId != null) {
|
||||
note.renote = await Notes.pack(note.renoteId, this.user, {
|
||||
note.renote = await Notes.pack(note.renoteId, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export default class extends Channel {
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
const meta = await fetchMeta();
|
||||
if (meta.disableLocalTimeline && !this.user.isAdmin && !this.user.isModerator) return;
|
||||
if (meta.disableLocalTimeline && !this.user!.isAdmin && !this.user!.isModerator) return;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
@ -22,13 +22,13 @@ export default class extends Channel {
|
||||
private async onNote(note: any) {
|
||||
// 自分自身の投稿 または その投稿のユーザーをフォローしている または ローカルの投稿 の場合だけ
|
||||
if (!(
|
||||
this.user.id === note.userId ||
|
||||
this.user!.id === note.userId ||
|
||||
this.following.includes(note.userId) ||
|
||||
note.user.host == null
|
||||
)) return;
|
||||
|
||||
if (['followers', 'specified'].includes(note.visibility)) {
|
||||
note = await Notes.pack(note.id, this.user, {
|
||||
note = await Notes.pack(note.id, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
|
||||
@ -38,13 +38,13 @@ export default class extends Channel {
|
||||
} else {
|
||||
// リプライなら再pack
|
||||
if (note.replyId != null) {
|
||||
note.reply = await Notes.pack(note.replyId, this.user, {
|
||||
note.reply = await Notes.pack(note.replyId, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
}
|
||||
// Renoteなら再pack
|
||||
if (note.renoteId != null) {
|
||||
note.renote = await Notes.pack(note.renoteId, this.user, {
|
||||
note.renote = await Notes.pack(note.renoteId, this.user!, {
|
||||
detail: true
|
||||
});
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ export default class extends Channel {
|
||||
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
const mute = await Mutings.find({ muterId: this.user.id });
|
||||
const mute = await Mutings.find({ muterId: this.user!.id });
|
||||
|
||||
// Subscribe main stream channel
|
||||
this.subscriber.on(`mainStream:${this.user.id}`, async data => {
|
||||
this.subscriber.on(`mainStream:${this.user!.id}`, async data => {
|
||||
const { type, body } = data;
|
||||
|
||||
switch (type) {
|
||||
|
@ -9,7 +9,7 @@ export default class extends Channel {
|
||||
@autobind
|
||||
public async init(params: any) {
|
||||
// Subscribe messaging index stream
|
||||
this.subscriber.on(`messagingIndexStream:${this.user.id}`, data => {
|
||||
this.subscriber.on(`messagingIndexStream:${this.user!.id}`, data => {
|
||||
this.send(data);
|
||||
});
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ export default class extends Channel {
|
||||
this.otherpartyId = params.otherparty as string;
|
||||
|
||||
// Subscribe messaging stream
|
||||
this.subscriber.on(`messagingStream:${this.user.id}-${this.otherpartyId}`, data => {
|
||||
this.subscriber.on(`messagingStream:${this.user!.id}-${this.otherpartyId}`, data => {
|
||||
this.send(data);
|
||||
});
|
||||
}
|
||||
@ -23,7 +23,7 @@ export default class extends Channel {
|
||||
public onMessage(type: string, body: any) {
|
||||
switch (type) {
|
||||
case 'read':
|
||||
read(this.user.id, this.otherpartyId, body.id);
|
||||
read(this.user!.id, this.otherpartyId, body.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ export default class Connection {
|
||||
constructor(
|
||||
wsConnection: websocket.connection,
|
||||
subscriber: EventEmitter,
|
||||
user: User,
|
||||
app: App
|
||||
user: User | null | undefined,
|
||||
app: App | null | undefined
|
||||
) {
|
||||
this.wsConnection = wsConnection;
|
||||
this.user = user;
|
||||
this.app = app;
|
||||
this.subscriber = subscriber;
|
||||
if (user) this.user = user;
|
||||
if (app) this.app = app;
|
||||
|
||||
this.wsConnection.on('message', this.onWsConnectionMessage);
|
||||
|
||||
@ -52,6 +52,8 @@ export default class Connection {
|
||||
*/
|
||||
@autobind
|
||||
private async onWsConnectionMessage(data: websocket.IMessage) {
|
||||
if (data.utf8Data == null) return;
|
||||
|
||||
const { type, body } = JSON.parse(data.utf8Data);
|
||||
|
||||
switch (type) {
|
||||
@ -89,7 +91,7 @@ export default class Connection {
|
||||
@autobind
|
||||
private onReadNotification(payload: any) {
|
||||
if (!payload.id) return;
|
||||
readNotification(this.user.id, [payload.id]);
|
||||
readNotification(this.user!.id, [payload.id]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +111,7 @@ export default class Connection {
|
||||
this.subscriber.on(`noteStream:${payload.id}`, this.onNoteStreamMessage);
|
||||
}
|
||||
|
||||
if (payload.read) {
|
||||
if (payload.read && this.user) {
|
||||
readNote(this.user.id, payload.id);
|
||||
}
|
||||
}
|
||||
@ -221,7 +223,7 @@ export default class Connection {
|
||||
private async updateFollowing() {
|
||||
const followings = await Followings.find({
|
||||
where: {
|
||||
followerId: this.user.id
|
||||
followerId: this.user!.id
|
||||
},
|
||||
select: ['followeeId']
|
||||
});
|
||||
@ -233,7 +235,7 @@ export default class Connection {
|
||||
private async updateMuting() {
|
||||
const mutings = await Mutings.find({
|
||||
where: {
|
||||
muterId: this.user.id
|
||||
muterId: this.user!.id
|
||||
},
|
||||
select: ['muteeId']
|
||||
});
|
||||
@ -247,7 +249,7 @@ export default class Connection {
|
||||
@autobind
|
||||
public dispose() {
|
||||
for (const c of this.channels.filter(c => c.dispose)) {
|
||||
c.dispose();
|
||||
if (c.dispose) c.dispose();
|
||||
}
|
||||
|
||||
if (this.followingClock) clearInterval(this.followingClock);
|
||||
|
Reference in New Issue
Block a user