refactor: use ajv instead of cafy (#8324)
* wip * wip * Update abuse-user-reports.ts * Update files.ts * Update list-remote.ts * Update list.ts * Update show-users.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update update.ts * Update search.ts * Update reactions.ts * Update search.ts * wip * wip * wip * wip * Update update.ts * Update relation.ts * Update available.ts * wip * wip * wip * Update packages/backend/src/server/api/define.ts Co-authored-by: Johann150 <johann.galle@protonmail.com> * Update define.ts * Update define.ts * typo * wip * wip * wip * wip * wip * wip * wip * wip * Update update.ts * wip * Update signup.ts * Update call.ts * minimum for limit * type * remove needless annotation * wip * Update signup.ts * wip * wip * fix * Update create.ts Co-authored-by: Johann150 <johann.galle@protonmail.com>
This commit is contained in:
		
							parent
							
								
									59785ea04c
								
							
						
					
					
						commit
						510de87607
					
				
					 320 changed files with 4395 additions and 5939 deletions
				
			
		|  | @ -70,6 +70,7 @@ | |||
| 		"@typescript-eslint/eslint-plugin": "5.12.0", | ||||
| 		"@typescript-eslint/parser": "5.12.0", | ||||
| 		"abort-controller": "3.0.0", | ||||
| 		"ajv": "8.10.0", | ||||
| 		"archiver": "5.3.0", | ||||
| 		"autobind-decorator": "2.4.0", | ||||
| 		"autwh": "0.1.0", | ||||
|  |  | |||
|  | @ -65,16 +65,18 @@ export const refs = { | |||
| 
 | ||||
| // Packed = SchemaTypeDef<typeof refs[x]>; とすると展開されてマウスホバー時に型表示が使い物にならなくなる
 | ||||
| // ObjType<r['properties']>を指定すると(なぜか)展開されずにPacked<'Hoge'>と表示される
 | ||||
| type PackedDef<r extends { properties?: Obj; oneOf?: ReadonlyArray<MinimumSchema>; allOf?: ReadonlyArray<MinimumSchema> }> = | ||||
| 	r['allOf'] extends ReadonlyArray<MinimumSchema> ? UnionToIntersection<UnionSchemaType<r['allOf']>> : | ||||
| 	r['oneOf'] extends ReadonlyArray<MinimumSchema> ? UnionSchemaType<r['oneOf']> : | ||||
| 	r['properties'] extends Obj ? ObjType<r['properties']> : | ||||
| type PackedDef<r extends { properties?: Obj; oneOf?: ReadonlyArray<Schema>; allOf?: ReadonlyArray<Schema> }> = | ||||
| 	r['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<r['allOf']>> : | ||||
| 	r['oneOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<r['oneOf']> : | ||||
| 	r['properties'] extends Obj ? ObjType<r['properties'], any> : | ||||
| 	never; | ||||
| export type Packed<x extends keyof typeof refs> = PackedDef<typeof refs[x]>; | ||||
| 
 | ||||
| type TypeStringef = 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; | ||||
| type TypeStringef = 'null' | 'boolean' | 'integer' | 'number' | 'string' | 'array' | 'object' | 'any'; | ||||
| type StringDefToType<T extends TypeStringef> = | ||||
| 	T extends 'null' ? null : | ||||
| 	T extends 'boolean' ? boolean : | ||||
| 	T extends 'integer' ? number : | ||||
| 	T extends 'number' ? number : | ||||
| 	T extends 'string' ? string | Date : | ||||
| 	T extends 'array' ? ReadonlyArray<any> : | ||||
|  | @ -83,17 +85,18 @@ type StringDefToType<T extends TypeStringef> = | |||
| 
 | ||||
| // https://swagger.io/specification/?sbsearch=optional#schema-object
 | ||||
| type OfSchema = { | ||||
| 	readonly anyOf?: ReadonlyArray<MinimumSchema>; | ||||
| 	readonly oneOf?: ReadonlyArray<MinimumSchema>; | ||||
| 	readonly allOf?: ReadonlyArray<MinimumSchema>; | ||||
| 	readonly anyOf?: ReadonlyArray<Schema>; | ||||
| 	readonly oneOf?: ReadonlyArray<Schema>; | ||||
| 	readonly allOf?: ReadonlyArray<Schema>; | ||||
| } | ||||
| 
 | ||||
| export interface MinimumSchema extends OfSchema { | ||||
| export interface Schema extends OfSchema { | ||||
| 	readonly type?: TypeStringef; | ||||
| 	readonly nullable?: boolean; | ||||
| 	readonly optional?: boolean; | ||||
| 	readonly items?: MinimumSchema; | ||||
| 	readonly items?: Schema; | ||||
| 	readonly properties?: Obj; | ||||
| 	readonly required?: ReadonlyArray<keyof NonNullable<this['properties']>>; | ||||
| 	readonly description?: string; | ||||
| 	readonly example?: any; | ||||
| 	readonly format?: string; | ||||
|  | @ -104,26 +107,33 @@ export interface MinimumSchema extends OfSchema { | |||
| 	readonly minLength?: number; | ||||
| } | ||||
| 
 | ||||
| export interface Schema extends MinimumSchema { | ||||
| 	readonly nullable: boolean; | ||||
| 	readonly optional: boolean; | ||||
| } | ||||
| 
 | ||||
| type NonUndefinedPropertyNames<T extends Obj> = { | ||||
| 	[K in keyof T]: T[K]['optional'] extends true ? never : K | ||||
| type OptionalPropertyNames<T extends Obj> = { | ||||
| 	[K in keyof T]: T[K]['optional'] extends true ? K : never | ||||
| }[keyof T]; | ||||
| 
 | ||||
| type UndefinedPropertyNames<T extends Obj> = { | ||||
| 	[K in keyof T]: T[K]['optional'] extends true ? K : never | ||||
| type NonOptionalPropertyNames<T extends Obj> = { | ||||
| 	[K in keyof T]: T[K]['optional'] extends false ? K : never | ||||
| }[keyof T]; | ||||
| 
 | ||||
| type DefaultPropertyNames<T extends Obj> = { | ||||
| 	[K in keyof T]: T[K]['default'] extends null ? K : | ||||
| 		T[K]['default'] extends string ? K : | ||||
| 		T[K]['default'] extends number ? K : | ||||
| 		T[K]['default'] extends boolean ? K : | ||||
| 		T[K]['default'] extends Record<string, unknown> ? K : | ||||
| 		never | ||||
| }[keyof T]; | ||||
| 
 | ||||
| export interface Obj { [key: string]: Schema; } | ||||
| 
 | ||||
| export type ObjType<s extends Obj> = | ||||
| 	{ -readonly [P in UndefinedPropertyNames<s>]?: SchemaType<s[P]> } & | ||||
| 	{ -readonly [P in NonUndefinedPropertyNames<s>]: SchemaType<s[P]> }; | ||||
| export type ObjType<s extends Obj, RequiredProps extends ReadonlyArray<keyof s>> = | ||||
| 	{ -readonly [P in keyof s]?: SchemaType<s[P]> } & | ||||
| 	{ -readonly [P in RequiredProps[number]]: SchemaType<s[P]> } & | ||||
| 	{ -readonly [P in OptionalPropertyNames<s>]?: SchemaType<s[P]> } & | ||||
| 	{ -readonly [P in NonOptionalPropertyNames<s>]: SchemaType<s[P]> } & | ||||
| 	{ -readonly [P in DefaultPropertyNames<s>]: SchemaType<s[P]> }; | ||||
| 
 | ||||
| type NullOrUndefined<p extends MinimumSchema, T> = | ||||
| type NullOrUndefined<p extends Schema, T> = | ||||
| 	p['nullable'] extends true | ||||
| 		?	p['optional'] extends true | ||||
| 			? (T | null | undefined) | ||||
|  | @ -137,10 +147,12 @@ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ( | |||
| 
 | ||||
| // https://github.com/misskey-dev/misskey/pull/8144#discussion_r785287552
 | ||||
| // 単純にSchemaTypeDef<X>で判定するだけではダメ
 | ||||
| type UnionSchemaType<a extends readonly any[], X extends MinimumSchema = a[number]> = X extends any ? SchemaType<X> : never; | ||||
| type UnionSchemaType<a extends readonly any[], X extends Schema = a[number]> = X extends any ? SchemaType<X> : never; | ||||
| type ArrayUnion<T> = T extends any ? Array<T> : never;  | ||||
| 
 | ||||
| export type SchemaTypeDef<p extends MinimumSchema> = | ||||
| export type SchemaTypeDef<p extends Schema> = | ||||
| 	p['type'] extends 'null' ? null : | ||||
| 	p['type'] extends 'integer' ? number : | ||||
| 	p['type'] extends 'number' ? number : | ||||
| 	p['type'] extends 'string' ? ( | ||||
| 		p['enum'] extends readonly string[] ? | ||||
|  | @ -151,22 +163,22 @@ export type SchemaTypeDef<p extends MinimumSchema> = | |||
| 	p['type'] extends 'boolean' ? boolean : | ||||
| 	p['type'] extends 'object' ? ( | ||||
| 		p['ref'] extends keyof typeof refs ? Packed<p['ref']> : | ||||
| 		p['properties'] extends NonNullable<Obj> ? ObjType<p['properties']> : | ||||
| 		p['anyOf'] extends ReadonlyArray<MinimumSchema> ? UnionSchemaType<p['anyOf']> & Partial<UnionToIntersection<UnionSchemaType<p['anyOf']>>> : | ||||
| 		p['allOf'] extends ReadonlyArray<MinimumSchema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> : | ||||
| 		p['properties'] extends NonNullable<Obj> ? ObjType<p['properties'], NonNullable<p['required']>> : | ||||
| 		p['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['anyOf']> & Partial<UnionToIntersection<UnionSchemaType<p['anyOf']>>> : | ||||
| 		p['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> : | ||||
| 		any | ||||
| 	) : | ||||
| 	p['type'] extends 'array' ? ( | ||||
| 		p['items'] extends OfSchema ? ( | ||||
| 			p['items']['anyOf'] extends ReadonlyArray<MinimumSchema> ? UnionSchemaType<NonNullable<p['items']['anyOf']>>[] : | ||||
| 			p['items']['oneOf'] extends ReadonlyArray<MinimumSchema> ? ArrayUnion<UnionSchemaType<NonNullable<p['items']['oneOf']>>> : | ||||
| 			p['items']['allOf'] extends ReadonlyArray<MinimumSchema> ? UnionToIntersection<UnionSchemaType<NonNullable<p['items']['allOf']>>>[] : | ||||
| 			p['items']['anyOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<NonNullable<p['items']['anyOf']>>[] : | ||||
| 			p['items']['oneOf'] extends ReadonlyArray<Schema> ? ArrayUnion<UnionSchemaType<NonNullable<p['items']['oneOf']>>> : | ||||
| 			p['items']['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<NonNullable<p['items']['allOf']>>>[] : | ||||
| 			never | ||||
| 		) : | ||||
| 		p['items'] extends NonNullable<MinimumSchema> ? SchemaTypeDef<p['items']>[] : | ||||
| 		p['items'] extends NonNullable<Schema> ? SchemaTypeDef<p['items']>[] : | ||||
| 		any[] | ||||
| 	) : | ||||
| 	p['oneOf'] extends ReadonlyArray<MinimumSchema> ? UnionSchemaType<p['oneOf']> : | ||||
| 	p['oneOf'] extends ReadonlyArray<Schema> ? UnionSchemaType<p['oneOf']> : | ||||
| 	any; | ||||
| 
 | ||||
| export type SchemaType<p extends MinimumSchema> = NullOrUndefined<p, SchemaTypeDef<p>>; | ||||
| export type SchemaType<p extends Schema> = NullOrUndefined<p, SchemaTypeDef<p>>; | ||||
|  |  | |||
|  | @ -6,13 +6,6 @@ import { Packed } from '@/misc/schema'; | |||
| 
 | ||||
| @EntityRepository(DriveFolder) | ||||
| export class DriveFolderRepository extends Repository<DriveFolder> { | ||||
| 	public validateFolderName(name: string): boolean { | ||||
| 		return ( | ||||
| 			(name.trim().length > 0) && | ||||
| 			(name.length <= 200) | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	public async pack( | ||||
| 		src: DriveFolder['id'] | DriveFolder, | ||||
| 		options?: { | ||||
|  |  | |||
|  | @ -6,10 +6,6 @@ import { User } from '@/models/entities/user'; | |||
| 
 | ||||
| @EntityRepository(MessagingMessage) | ||||
| export class MessagingMessageRepository extends Repository<MessagingMessage> { | ||||
| 	public validateText(text: string): boolean { | ||||
| 		return text.trim().length <= 1000 && text.trim() != ''; | ||||
| 	} | ||||
| 
 | ||||
| 	public async pack( | ||||
| 		src: MessagingMessage['id'] | MessagingMessage, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
|  |  | |||
|  | @ -12,10 +12,6 @@ import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/popu | |||
| 
 | ||||
| @EntityRepository(Note) | ||||
| export class NoteRepository extends Repository<Note> { | ||||
| 	public validateCw(x: string) { | ||||
| 		return x.trim().length <= 100; | ||||
| 	} | ||||
| 
 | ||||
| 	public async isVisibleForMe(note: Note, meId: User['id'] | null): Promise<boolean> { | ||||
| 		// visibility が specified かつ自分が指定されていなかったら非表示
 | ||||
| 		if (note.visibility === 'specified') { | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import $ from 'cafy'; | ||||
| import { EntityRepository, Repository, In, Not } from 'typeorm'; | ||||
| import * as Ajv from 'ajv'; | ||||
| import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; | ||||
| import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '../index'; | ||||
| import config from '@/config/index'; | ||||
|  | @ -17,8 +17,26 @@ type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends bo | |||
| 		Packed<'UserDetailed'> : | ||||
| 	Packed<'UserLite'>; | ||||
| 
 | ||||
| const ajv = new Ajv(); | ||||
| 
 | ||||
| @EntityRepository(User) | ||||
| export class UserRepository extends Repository<User> { | ||||
| 	public localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; | ||||
| 	public passwordSchema = { type: 'string', minLength: 1 } as const; | ||||
| 	public nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||
| 	public descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; | ||||
| 	public locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; | ||||
| 	public birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; | ||||
| 
 | ||||
| 	//#region Validators
 | ||||
| 	public validateLocalUsername = ajv.compile(this.localUsernameSchema); | ||||
| 	public validatePassword = ajv.compile(this.passwordSchema); | ||||
| 	public validateName = ajv.compile(this.nameSchema); | ||||
| 	public validateDescription = ajv.compile(this.descriptionSchema); | ||||
| 	public validateLocation = ajv.compile(this.locationSchema); | ||||
| 	public validateBirthday = ajv.compile(this.birthdaySchema); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	public async getRelation(me: User['id'], target: User['id']) { | ||||
| 		const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([ | ||||
| 			Followings.findOne({ | ||||
|  | @ -351,13 +369,4 @@ export class UserRepository extends Repository<User> { | |||
| 	public isRemoteUser(user: User | { host: User['host'] }): boolean { | ||||
| 		return !this.isLocalUser(user); | ||||
| 	} | ||||
| 
 | ||||
| 	//#region Validators
 | ||||
| 	public validateLocalUsername = $.str.match(/^\w{1,20}$/); | ||||
| 	public validatePassword = $.str.min(1); | ||||
| 	public validateName = $.str.min(1).max(50); | ||||
| 	public validateDescription = $.str.min(1).max(500); | ||||
| 	public validateLocation = $.str.min(1).max(50); | ||||
| 	public validateBirthday = $.str.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/); | ||||
| 	//#endregion
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import authenticate, { AuthenticationError } from './authenticate'; | |||
| import call from './call'; | ||||
| import { ApiError } from './error'; | ||||
| 
 | ||||
| export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => { | ||||
| export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise<void>((res) => { | ||||
| 	const body = ctx.request.body; | ||||
| 
 | ||||
| 	const reply = (x?: any, y?: ApiError) => { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import * as Koa from 'koa'; | |||
| import { performance } from 'perf_hooks'; | ||||
| import { limiter } from './limiter'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import endpoints from './endpoints'; | ||||
| import endpoints, { IEndpoint } from './endpoints'; | ||||
| import { ApiError } from './error'; | ||||
| import { apiLogger } from './logger'; | ||||
| import { AccessToken } from '@/models/entities/access-token'; | ||||
|  | @ -67,7 +67,7 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac | |||
| 
 | ||||
| 	if (ep.meta.requireCredential && ep.meta.limit && !user!.isAdmin && !user!.isModerator) { | ||||
| 		// Rate limit
 | ||||
| 		await limiter(ep, user!).catch(e => { | ||||
| 		await limiter(ep as IEndpoint & { meta: { limit: NonNullable<IEndpoint['meta']['limit']> } }, user!).catch(e => { | ||||
| 			throw new ApiError({ | ||||
| 				message: 'Rate limit exceeded. Please try again later.', | ||||
| 				code: 'RATE_LIMIT_EXCEEDED', | ||||
|  | @ -78,10 +78,10 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac | |||
| 	} | ||||
| 
 | ||||
| 	// Cast non JSON input
 | ||||
| 	if (ep.meta.requireFile && ep.meta.params) { | ||||
| 		for (const k of Object.keys(ep.meta.params)) { | ||||
| 			const param = ep.meta.params[k]; | ||||
| 			if (['Boolean', 'Number'].includes(param.validator.name) && typeof data[k] === 'string') { | ||||
| 	if (ep.meta.requireFile) { | ||||
| 		for (const k of Object.keys(ep.params)) { | ||||
| 			const param = ep.params.properties![k]; | ||||
| 			if (['boolean', 'number', 'integer'].includes(param.type ?? '') && typeof data[k] === 'string') { | ||||
| 				try { | ||||
| 					data[k] = JSON.parse(data[k]); | ||||
| 				} catch (e) { | ||||
|  | @ -91,8 +91,8 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac | |||
| 						id: '0b5f1631-7c1a-41a6-b399-cce335f34d85', | ||||
| 					}, { | ||||
| 						param: k, | ||||
| 						reason: `cannot cast to ${param.validator.name}`, | ||||
| 					}) | ||||
| 						reason: `cannot cast to ${param.type}`, | ||||
| 					}); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -21,13 +21,13 @@ export async function signup(opts: { | |||
| 	let hash = passwordHash; | ||||
| 
 | ||||
| 	// Validate username
 | ||||
| 	if (!Users.validateLocalUsername.ok(username)) { | ||||
| 	if (!Users.validateLocalUsername(username)) { | ||||
| 		throw new Error('INVALID_USERNAME'); | ||||
| 	} | ||||
| 
 | ||||
| 	if (password != null && passwordHash == null) { | ||||
| 		// Validate password
 | ||||
| 		if (!Users.validatePassword.ok(password)) { | ||||
| 		if (!Users.validatePassword(password)) { | ||||
| 			throw new Error('INVALID_PASSWORD'); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| import * as fs from 'fs'; | ||||
| import * as Ajv from 'ajv'; | ||||
| import { ILocalUser } from '@/models/entities/user'; | ||||
| import { IEndpointMeta } from './endpoints'; | ||||
| import { ApiError } from './error'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Schema, SchemaType } from '@/misc/schema'; | ||||
| import { AccessToken } from '@/models/entities/access-token'; | ||||
| 
 | ||||
| type NonOptional<T> = T extends undefined ? never : T; | ||||
| 
 | ||||
| type SimpleUserInfo = { | ||||
| 	id: ILocalUser['id']; | ||||
| 	createdAt: ILocalUser['createdAt']; | ||||
|  | @ -21,22 +20,24 @@ type SimpleUserInfo = { | |||
| 	showTimelineReplies: ILocalUser['showTimelineReplies']; | ||||
| }; | ||||
| 
 | ||||
| type Params<T extends IEndpointMeta> = { | ||||
| 	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends () => any | ||||
| 		? ReturnType<NonNullable<T['params']>[P]['transform']> | ||||
| 		: NonNullable<T['params']>[P]['default'] extends null | number | string | ||||
| 			? NonOptional<ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0]> | ||||
| 			: ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0]; | ||||
| }; | ||||
| 
 | ||||
| export type Response = Record<string, any> | void; | ||||
| 
 | ||||
| type executor<T extends IEndpointMeta> = | ||||
| 	(params: Params<T>, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: () => any) => | ||||
| // TODO: paramsの型をT['params']のスキーマ定義から推論する
 | ||||
| type executor<T extends IEndpointMeta, Ps extends Schema> = | ||||
| 	(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: () => any) => | ||||
| 		Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>; | ||||
| 
 | ||||
| export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>) | ||||
| const ajv = new Ajv({ | ||||
| 	useDefaults: true, | ||||
| }); | ||||
| 
 | ||||
| ajv.addFormat('misskey:id', /^[a-z0-9]+$/); | ||||
| 
 | ||||
| export default function <T extends IEndpointMeta, Ps extends Schema>(meta: T, paramDef: Ps, cb: executor<T, Ps>) | ||||
| 		: (params: any, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any) => Promise<any> { | ||||
| 
 | ||||
| 	const validate = ajv.compile(paramDef); | ||||
| 
 | ||||
| 	return (params: any, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any) => { | ||||
| 		function cleanup() { | ||||
| 			fs.unlink(file.path, () => {}); | ||||
|  | @ -48,42 +49,22 @@ export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>) | |||
| 			id: '4267801e-70d1-416a-b011-4ee502885d8b', | ||||
| 		})); | ||||
| 
 | ||||
| 		const [ps, pserr] = getParams(meta, params); | ||||
| 		if (pserr) { | ||||
| 		const valid = validate(params); | ||||
| 		if (!valid) { | ||||
| 			if (file) cleanup(); | ||||
| 			return Promise.reject(pserr); | ||||
| 		} | ||||
| 
 | ||||
| 		return cb(ps, user, token, file, cleanup); | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| 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 = null; | ||||
| 	Object.entries(defs.params).some(([k, def]) => { | ||||
| 		const [v, e] = def.validator.get(params[k]); | ||||
| 		if (e) { | ||||
| 			err = new ApiError({ | ||||
| 			const errors = validate.errors!; | ||||
| 			const err = new ApiError({ | ||||
| 				message: 'Invalid param.', | ||||
| 				code: 'INVALID_PARAM', | ||||
| 				id: '3d81ceae-475f-4600-b2a8-2bc116157532', | ||||
| 			}, { | ||||
| 				param: k, | ||||
| 				reason: e.message, | ||||
| 				param: errors[0].schemaPath, | ||||
| 				reason: errors[0].message, | ||||
| 			}); | ||||
| 			return true; | ||||
| 		} else { | ||||
| 			if (v === undefined && Object.prototype.hasOwnProperty.call(def, 'default')) { | ||||
| 				x[k] = def.default; | ||||
| 			} else { | ||||
| 				x[k] = v; | ||||
| 			} | ||||
| 			if (def.transform) x[k] = def.transform(x[k]); | ||||
| 			return false; | ||||
| 			return Promise.reject(err); | ||||
| 		} | ||||
| 	}); | ||||
| 	return [x, err]; | ||||
| 
 | ||||
| 		return cb(params, user, token, file, cleanup); | ||||
| 	}; | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import { fileURLToPath } from 'url'; | ||||
| import { dirname } from 'path'; | ||||
| import { Context } from 'cafy'; | ||||
| import * as path from 'path'; | ||||
| import * as glob from 'glob'; | ||||
| import { Schema } from '@/misc/schema'; | ||||
|  | @ -9,23 +7,11 @@ import { Schema } from '@/misc/schema'; | |||
| const _filename = __filename; | ||||
| const _dirname = dirname(_filename); | ||||
| 
 | ||||
| export type Param = { | ||||
| 	validator: Context<any>; | ||||
| 	transform?: any; | ||||
| 	default?: any; | ||||
| 	deprecated?: boolean; | ||||
| 	ref?: string; | ||||
| }; | ||||
| 
 | ||||
| export interface IEndpointMeta { | ||||
| 	readonly stability?: 'deprecated' | 'experimental' | 'stable'; | ||||
| 
 | ||||
| 	readonly tags?: ReadonlyArray<string>; | ||||
| 
 | ||||
| 	readonly params?: { | ||||
| 		readonly [key: string]: Param; | ||||
| 	}; | ||||
| 
 | ||||
| 	readonly errors?: { | ||||
| 		readonly [key: string]: { | ||||
| 			readonly message: string; | ||||
|  | @ -99,12 +85,15 @@ export interface IEndpointMeta { | |||
| 	 * パーミッションの実現に利用されます。 | ||||
| 	 */ | ||||
| 	readonly kind?: string; | ||||
| 
 | ||||
| 	readonly description?: string; | ||||
| } | ||||
| 
 | ||||
| export interface IEndpoint { | ||||
| 	name: string; | ||||
| 	exec: any; | ||||
| 	meta: IEndpointMeta; | ||||
| 	params: Schema; | ||||
| } | ||||
| 
 | ||||
| const files = glob.sync('**/*.js', { | ||||
|  | @ -118,6 +107,7 @@ const endpoints: IEndpoint[] = files.map(f => { | |||
| 		name: f.replace('.js', ''), | ||||
| 		exec: ep.default, | ||||
| 		meta: ep.meta || {}, | ||||
| 		params: ep.paramDef, | ||||
| 	}; | ||||
| }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { AbuseUserReports } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
|  | @ -10,49 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		state: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 
 | ||||
| 		reporterOrigin: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'combined', | ||||
| 				'local', | ||||
| 				'remote', | ||||
| 			]), | ||||
| 			default: 'combined', | ||||
| 		}, | ||||
| 
 | ||||
| 		targetUserOrigin: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'combined', | ||||
| 				'local', | ||||
| 				'remote', | ||||
| 			]), | ||||
| 			default: 'combined', | ||||
| 		}, | ||||
| 
 | ||||
| 		forwarded: { | ||||
| 			validator: $.optional.bool, | ||||
| 			default: false, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -115,8 +70,22 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		state: { type: 'string', nullable: true, default: null }, | ||||
| 		reporterOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "combined" }, | ||||
| 		targetUserOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "combined" }, | ||||
| 		forwarded: { type: 'boolean', default: false }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	switch (ps.state) { | ||||
|  | @ -134,7 +103,7 @@ export default define(meta, async (ps) => { | |||
| 		case 'remote': query.andWhere('report.targetUserHost IS NOT NULL'); break; | ||||
| 	} | ||||
| 
 | ||||
| 	const reports = await query.take(ps.limit!).getMany(); | ||||
| 	const reports = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	return await AbuseUserReports.packMany(reports); | ||||
| }); | ||||
|  |  | |||
|  | @ -5,16 +5,6 @@ import { signup } from '../../../common/signup'; | |||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		username: { | ||||
| 			validator: Users.validateLocalUsername, | ||||
| 		}, | ||||
| 
 | ||||
| 		password: { | ||||
| 			validator: Users.validatePassword, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -28,8 +18,17 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		username: Users.localUsernameSchema, | ||||
| 		password: Users.passwordSchema, | ||||
| 	}, | ||||
| 	required: ['username', 'password'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, _me) => { | ||||
| export default define(meta, paramDef, async (ps, _me) => { | ||||
| 	const me = _me ? await Users.findOneOrFail(_me.id) : null; | ||||
| 	const noUsers = (await Users.count({ | ||||
| 		host: null, | ||||
|  |  | |||
|  | @ -1,26 +1,26 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| import { doPostSuspend } from '@/services/suspend-user'; | ||||
| import { publishUserEvent } from '@/services/stream'; | ||||
| import { createDeleteAccountJob } from '@/queue'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Ads } from '@/models/index'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
|  | @ -8,34 +7,24 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		url: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		memo: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		place: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		priority: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		ratio: { | ||||
| 			validator: $.num.int().min(0), | ||||
| 		}, | ||||
| 		expiresAt: { | ||||
| 			validator: $.num.int(), | ||||
| 		}, | ||||
| 		imageUrl: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		url: { type: 'string', minLength: 1 }, | ||||
| 		memo: { type: 'string' }, | ||||
| 		place: { type: 'string' }, | ||||
| 		priority: { type: 'string' }, | ||||
| 		ratio: { type: 'integer' }, | ||||
| 		expiresAt: { type: 'integer' }, | ||||
| 		imageUrl: { type: 'string', minLength: 1 }, | ||||
| 	}, | ||||
| 	required: ['url', 'memo', 'place', 'priority', 'ratio', 'expiresAt', 'imageUrl'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	await Ads.insert({ | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Ads } from '@/models/index'; | ||||
| import { ApiError } from '../../../error'; | ||||
| 
 | ||||
|  | @ -10,12 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAd: { | ||||
| 			message: 'No such ad.', | ||||
|  | @ -25,8 +17,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['id'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const ad = await Ads.findOne(ps.id); | ||||
| 
 | ||||
| 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { Ads } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../../common/make-pagination-query'; | ||||
|  | @ -9,29 +7,24 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId) | ||||
| 		.andWhere('ad.expiresAt > :now', { now: new Date() }); | ||||
| 
 | ||||
| 	const ads = await query.take(ps.limit!).getMany(); | ||||
| 	const ads = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	return ads; | ||||
| }); | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Ads } from '@/models/index'; | ||||
| import { ApiError } from '../../../error'; | ||||
| 
 | ||||
|  | @ -10,33 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 		memo: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		url: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		imageUrl: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		place: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		priority: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		ratio: { | ||||
| 			validator: $.num.int().min(0), | ||||
| 		}, | ||||
| 		expiresAt: { | ||||
| 			validator: $.num.int(), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAd: { | ||||
| 			message: 'No such ad.', | ||||
|  | @ -46,8 +17,23 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 		memo: { type: 'string' }, | ||||
| 		url: { type: 'string', minLength: 1 }, | ||||
| 		imageUrl: { type: 'string', minLength: 1 }, | ||||
| 		place: { type: 'string' }, | ||||
| 		priority: { type: 'string' }, | ||||
| 		ratio: { type: 'integer' }, | ||||
| 		expiresAt: { type: 'integer' }, | ||||
| 	}, | ||||
| 	required: ['id', 'memo', 'url', 'imageUrl', 'place', 'priority', 'ratio', 'expiresAt'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const ad = await Ads.findOne(ps.id); | ||||
| 
 | ||||
| 	if (ad == null) throw new ApiError(meta.errors.noSuchAd); | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Announcements } from '@/models/index'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
|  | @ -9,18 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		title: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		text: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		imageUrl: { | ||||
| 			validator: $.nullable.str.min(1), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -57,8 +44,18 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		title: { type: 'string', minLength: 1 }, | ||||
| 		text: { type: 'string', minLength: 1 }, | ||||
| 		imageUrl: { type: 'string', nullable: true, minLength: 1 }, | ||||
| 	}, | ||||
| 	required: ['title', 'text', 'imageUrl'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const announcement = await Announcements.insert({ | ||||
| 		id: genId(), | ||||
| 		createdAt: new Date(), | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Announcements } from '@/models/index'; | ||||
| import { ApiError } from '../../../error'; | ||||
| 
 | ||||
|  | @ -10,12 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAnnouncement: { | ||||
| 			message: 'No such announcement.', | ||||
|  | @ -25,8 +17,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['id'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const announcement = await Announcements.findOne(ps.id); | ||||
| 
 | ||||
| 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { Announcements, AnnouncementReads } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../../common/make-pagination-query'; | ||||
|  | @ -10,21 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -69,11 +52,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	const announcements = await query.take(ps.limit!).getMany(); | ||||
| 	const announcements = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	for (const announcement of announcements) { | ||||
| 		(announcement as any).reads = await AnnouncementReads.count({ | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Announcements } from '@/models/index'; | ||||
| import { ApiError } from '../../../error'; | ||||
| 
 | ||||
|  | @ -10,21 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 		title: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		text: { | ||||
| 			validator: $.str.min(1), | ||||
| 		}, | ||||
| 		imageUrl: { | ||||
| 			validator: $.nullable.str.min(1), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAnnouncement: { | ||||
| 			message: 'No such announcement.', | ||||
|  | @ -34,8 +17,19 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 		title: { type: 'string', minLength: 1 }, | ||||
| 		text: { type: 'string', minLength: 1 }, | ||||
| 		imageUrl: { type: 'string', nullable: true, minLength: 1 }, | ||||
| 	}, | ||||
| 	required: ['id', 'title', 'text', 'imageUrl'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const announcement = await Announcements.findOne(ps.id); | ||||
| 
 | ||||
| 	if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); | ||||
|  |  | |||
|  | @ -1,24 +1,24 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { deleteFile } from '@/services/drive/delete-file'; | ||||
| import { DriveFiles } from '@/models/index'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const files = await DriveFiles.find({ | ||||
| 		userId: ps.userId, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -8,7 +8,13 @@ export const meta = { | |||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	createCleanRemoteFilesJob(); | ||||
| }); | ||||
|  |  | |||
|  | @ -10,8 +10,14 @@ export const meta = { | |||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const files = await DriveFiles.find({ | ||||
| 		userId: IsNull(), | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { DriveFiles } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../../common/make-pagination-query'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -10,39 +8,6 @@ export const meta = { | |||
| 	requireCredential: false, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		type: { | ||||
| 			validator: $.optional.nullable.str.match(/^[a-zA-Z0-9\/\-*]+$/), | ||||
| 		}, | ||||
| 
 | ||||
| 		origin: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'combined', | ||||
| 				'local', | ||||
| 				'remote', | ||||
| 			]), | ||||
| 			default: 'local', | ||||
| 		}, | ||||
| 
 | ||||
| 		hostname: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -54,8 +19,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) }, | ||||
| 		origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, | ||||
| 		hostname: { type: 'string', nullable: true, default: null }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	if (ps.origin === 'local') { | ||||
|  | @ -76,7 +54,7 @@ export default define(meta, async (ps, me) => { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	const files = await query.take(ps.limit!).getMany(); | ||||
| 	const files = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	return await DriveFiles.packMany(files, { detail: true, withUser: true, self: true }); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { DriveFiles } from '@/models/index'; | ||||
|  | @ -10,16 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		fileId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		url: { | ||||
| 			validator: $.optional.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchFile: { | ||||
| 			message: 'No such file.', | ||||
|  | @ -161,8 +149,17 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		fileId: { type: 'string', format: 'misskey:id' }, | ||||
| 		url: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const file = ps.fileId ? await DriveFiles.findOne(ps.fileId) : await DriveFiles.findOne({ | ||||
| 		where: [{ | ||||
| 			url: ps.url, | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection, In } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -10,20 +8,23 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		ids: { | ||||
| 			validator: $.arr($.type(ID)), | ||||
| 		}, | ||||
| 
 | ||||
| 		aliases: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		ids: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 		aliases: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['ids', 'aliases'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const emojis = await Emojis.find({ | ||||
| 		id: In(ps.ids), | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,11 +1,9 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Emojis, DriveFiles } from '@/models/index'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import rndstr from 'rndstr'; | ||||
| import { publishBroadcastStream } from '@/services/stream'; | ||||
| 
 | ||||
|  | @ -15,12 +13,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		fileId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchFile: { | ||||
| 			message: 'No such file.', | ||||
|  | @ -30,8 +22,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		fileId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['fileId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const file = await DriveFiles.findOne(ps.fileId); | ||||
| 
 | ||||
| 	if (file == null) throw new ApiError(meta.errors.noSuchFile); | ||||
|  |  | |||
|  | @ -1,11 +1,9 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { DriveFile } from '@/models/entities/drive-file'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { uploadFromUrl } from '@/services/drive/upload-from-url'; | ||||
| import { publishBroadcastStream } from '@/services/stream'; | ||||
| 
 | ||||
|  | @ -15,12 +13,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		emojiId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchEmoji: { | ||||
| 			message: 'No such emoji.', | ||||
|  | @ -42,8 +34,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		emojiId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['emojiId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const emoji = await Emojis.findOne(ps.emojiId); | ||||
| 
 | ||||
| 	if (emoji == null) { | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection, In } from 'typeorm'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -11,16 +9,20 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		ids: { | ||||
| 			validator: $.arr($.type(ID)), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		ids: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['ids'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const emojis = await Emojis.find({ | ||||
| 		id: In(ps.ids), | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -12,12 +10,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchEmoji: { | ||||
| 			message: 'No such emoji.', | ||||
|  | @ -27,8 +19,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['id'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const emoji = await Emojis.findOne(ps.id); | ||||
| 
 | ||||
| 	if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); | ||||
|  |  | |||
|  | @ -1,21 +1,22 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { createImportCustomEmojisJob } from '@/queue/index'; | ||||
| import ms from 'ms'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	secure: true, | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 	params: { | ||||
| 		fileId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		fileId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['fileId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	createImportCustomEmojisJob(user, ps.fileId); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { toPuny } from '@/misc/convert-host'; | ||||
| import { makePaginationQuery } from '../../../common/make-pagination-query'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
|  | @ -11,31 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		query: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 
 | ||||
| 		host: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -77,8 +50,20 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		query: { type: 'string', nullable: true, default: null }, | ||||
| 		host: { type: 'string', nullable: true, default: null }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	if (ps.host == null) { | ||||
|  | @ -93,7 +78,7 @@ export default define(meta, async (ps) => { | |||
| 
 | ||||
| 	const emojis = await q | ||||
| 		.orderBy('emoji.id', 'DESC') | ||||
| 		.take(ps.limit!) | ||||
| 		.take(ps.limit) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	return Emojis.packMany(emojis); | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../../common/make-pagination-query'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emoji } from '@/models/entities/emoji'; | ||||
| 
 | ||||
| export const meta = { | ||||
|  | @ -11,26 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		query: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -72,8 +50,19 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		query: { type: 'string', nullable: true, default: null }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId) | ||||
| 		.andWhere(`emoji.host IS NULL`); | ||||
| 
 | ||||
|  | @ -81,7 +70,7 @@ export default define(meta, async (ps) => { | |||
| 
 | ||||
| 	if (ps.query) { | ||||
| 		//q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` });
 | ||||
| 		//const emojis = await q.take(ps.limit!).getMany();
 | ||||
| 		//const emojis = await q.take(ps.limit).getMany();
 | ||||
| 
 | ||||
| 		emojis = await q.getMany(); | ||||
| 
 | ||||
|  | @ -90,9 +79,9 @@ export default define(meta, async (ps) => { | |||
| 			emoji.aliases.some(a => a.includes(ps.query!)) || | ||||
| 			emoji.category?.includes(ps.query!)); | ||||
| 
 | ||||
| 		emojis.splice(ps.limit! + 1); | ||||
| 		emojis.splice(ps.limit + 1); | ||||
| 	} else { | ||||
| 		emojis = await q.take(ps.limit!).getMany(); | ||||
| 		emojis = await q.take(ps.limit).getMany(); | ||||
| 	} | ||||
| 
 | ||||
| 	return Emojis.packMany(emojis); | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection, In } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -10,20 +8,23 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		ids: { | ||||
| 			validator: $.arr($.type(ID)), | ||||
| 		}, | ||||
| 
 | ||||
| 		aliases: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		ids: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 		aliases: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['ids', 'aliases'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const emojis = await Emojis.find({ | ||||
| 		id: In(ps.ids), | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection, In } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -10,20 +8,23 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		ids: { | ||||
| 			validator: $.arr($.type(ID)), | ||||
| 		}, | ||||
| 
 | ||||
| 		aliases: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		ids: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 		aliases: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['ids', 'aliases'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	await Emojis.update({ | ||||
| 		id: In(ps.ids), | ||||
| 	}, { | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection, In } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -10,20 +8,21 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		ids: { | ||||
| 			validator: $.arr($.type(ID)), | ||||
| 		}, | ||||
| 
 | ||||
| 		category: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		ids: { type: 'array', items: { | ||||
| 			type: 'string', format: 'misskey:id', | ||||
| 		} }, | ||||
| 		category: { type: 'string', nullable: true }, | ||||
| 	}, | ||||
| 	required: ['ids'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	await Emojis.update({ | ||||
| 		id: In(ps.ids), | ||||
| 	}, { | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { Emojis } from '@/models/index'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -11,24 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		id: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		name: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		category: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		aliases: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchEmoji: { | ||||
| 			message: 'No such emoji.', | ||||
|  | @ -38,8 +18,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		id: { type: 'string', format: 'misskey:id' }, | ||||
| 		name: { type: 'string' }, | ||||
| 		category: { type: 'string', nullable: true }, | ||||
| 		aliases: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 	}, | ||||
| 	required: ['id', 'name', 'aliases'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const emoji = await Emojis.findOne(ps.id); | ||||
| 
 | ||||
| 	if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { deleteFile } from '@/services/drive/delete-file'; | ||||
| import { DriveFiles } from '@/models/index'; | ||||
|  | @ -8,16 +7,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		host: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		host: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['host'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const files = await DriveFiles.find({ | ||||
| 		userHost: ps.host, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Instances } from '@/models/index'; | ||||
| import { toPuny } from '@/misc/convert-host'; | ||||
|  | @ -9,16 +8,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		host: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		host: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['host'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const instance = await Instances.findOne({ host: toPuny(ps.host) }); | ||||
| 
 | ||||
| 	if (instance == null) { | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import deleteFollowing from '@/services/following/delete'; | ||||
| import { Followings, Users } from '@/models/index'; | ||||
|  | @ -8,16 +7,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		host: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		host: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['host'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const followings = await Followings.find({ | ||||
| 		followerHost: ps.host, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { Instances } from '@/models/index'; | ||||
| import { toPuny } from '@/misc/convert-host'; | ||||
|  | @ -8,20 +7,19 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		host: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		isSuspended: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		host: { type: 'string' }, | ||||
| 		isSuspended: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: ['host', 'isSuspended'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const instance = await Instances.findOne({ host: toPuny(ps.host) }); | ||||
| 
 | ||||
| 	if (instance == null) { | ||||
|  |  | |||
|  | @ -6,13 +6,16 @@ export const meta = { | |||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	tags: ['admin'], | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async () => { | ||||
| export default define(meta, paramDef, async () => { | ||||
| 	const stats = await | ||||
| 		getConnection().query(`SELECT * FROM pg_indexes;`) | ||||
| 		.then(recs => { | ||||
|  |  | |||
|  | @ -7,9 +7,6 @@ export const meta = { | |||
| 
 | ||||
| 	tags: ['admin'], | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -22,8 +19,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async () => { | ||||
| export default define(meta, paramDef, async () => { | ||||
| 	const sizes = await | ||||
| 		getConnection().query(` | ||||
| 			SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size" | ||||
|  |  | |||
|  | @ -9,8 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: {}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -26,8 +24,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async () => { | ||||
| export default define(meta, paramDef, async () => { | ||||
| 	const code = rndstr({ | ||||
| 		length: 8, | ||||
| 		chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns)
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| 
 | ||||
|  | @ -8,16 +6,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireAdmin: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| 
 | ||||
|  | @ -8,16 +6,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireAdmin: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { getNote } from '../../../common/getters'; | ||||
|  | @ -11,16 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		noteId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		expiresAt: { | ||||
| 			validator: $.num.int(), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchNote: { | ||||
| 			message: 'No such note.', | ||||
|  | @ -36,8 +24,17 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		noteId: { type: 'string', format: 'misskey:id' }, | ||||
| 		expiresAt: { type: 'integer' }, | ||||
| 	}, | ||||
| 	required: ['noteId', 'expiresAt'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const note = await getNote(ps.noteId).catch(e => { | ||||
| 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); | ||||
| 		throw e; | ||||
|  |  | |||
|  | @ -7,12 +7,16 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: {}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	destroy(); | ||||
| 
 | ||||
| 	insertModerationLog(me, 'clearQueue'); | ||||
|  |  | |||
|  | @ -8,9 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -35,8 +32,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const jobs = await deliverQueue.getJobs(['delayed']); | ||||
| 
 | ||||
| 	const res = [] as [string, number][]; | ||||
|  |  | |||
|  | @ -8,9 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -35,8 +32,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const jobs = await inboxQueue.getJobs(['delayed']); | ||||
| 
 | ||||
| 	const res = [] as [string, number][]; | ||||
|  |  | |||
|  | @ -7,8 +7,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: {}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -33,8 +31,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const deliverJobCounts = await deliverQueue.getJobCounts(); | ||||
| 	const inboxJobCounts = await inboxQueue.getJobCounts(); | ||||
| 	const dbJobCounts = await dbQueue.getJobCounts(); | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| import { URL } from 'url'; | ||||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { addRelay } from '@/services/relay'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -10,12 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		inbox: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		invalidUrl: { | ||||
| 			message: 'Invalid URL', | ||||
|  | @ -52,8 +45,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		inbox: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['inbox'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	try { | ||||
| 		if (new URL(ps.inbox).protocol !== 'https:') throw 'https only'; | ||||
| 	} catch { | ||||
|  |  | |||
|  | @ -7,9 +7,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -42,7 +39,13 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	return await listRelay(); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { removeRelay } from '@/services/relay'; | ||||
| 
 | ||||
|  | @ -7,15 +6,17 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		inbox: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		inbox: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['inbox'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	return await removeRelay(ps.inbox); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import * as bcrypt from 'bcryptjs'; | ||||
| import rndstr from 'rndstr'; | ||||
|  | @ -11,12 +9,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -31,8 +23,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { AbuseUserReports, Users } from '@/models/index'; | ||||
| import { getInstanceActor } from '@/services/instance-actor'; | ||||
|  | @ -12,22 +10,19 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		reportId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		forward: { | ||||
| 			validator: $.optional.boolean, | ||||
| 			required: false, | ||||
| 			default: false, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		reportId: { type: 'string', format: 'misskey:id' }, | ||||
| 		forward: { type: 'boolean', default: false }, | ||||
| 	}, | ||||
| 	required: ['reportId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const report = await AbuseUserReports.findOne(ps.reportId); | ||||
| 
 | ||||
| 	if (report == null) { | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { sendEmail } from '@/services/send-email'; | ||||
| 
 | ||||
|  | @ -7,21 +6,19 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		to: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		subject: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 		text: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		to: { type: 'string' }, | ||||
| 		subject: { type: 'string' }, | ||||
| 		text: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['to', 'subject', 'text'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	await sendEmail(ps.to, ps.subject, ps.text, ps.text); | ||||
| }); | ||||
|  |  | |||
|  | @ -10,9 +10,6 @@ export const meta = { | |||
| 
 | ||||
| 	tags: ['admin', 'meta'], | ||||
| 
 | ||||
| 	params: { | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -90,8 +87,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async () => { | ||||
| export default define(meta, paramDef, async () => { | ||||
| 	const memStats = await si.mem(); | ||||
| 	const fsStats = await si.fsSize(); | ||||
| 	const netInterface = await si.networkInterfaceDefault(); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ModerationLogs } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
|  | @ -10,21 +8,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -65,11 +48,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const query = makePaginationQuery(ModerationLogs.createQueryBuilder('report'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	const reports = await query.take(ps.limit!).getMany(); | ||||
| 	const reports = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	return await ModerationLogs.packMany(reports); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| 
 | ||||
|  | @ -9,20 +7,22 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		nullable: false, optional: false, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| 
 | ||||
|  | @ -8,61 +7,6 @@ export const meta = { | |||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		offset: { | ||||
| 			validator: $.optional.num.min(0), | ||||
| 			default: 0, | ||||
| 		}, | ||||
| 
 | ||||
| 		sort: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'+follower', | ||||
| 				'-follower', | ||||
| 				'+createdAt', | ||||
| 				'-createdAt', | ||||
| 				'+updatedAt', | ||||
| 				'-updatedAt', | ||||
| 			]), | ||||
| 		}, | ||||
| 
 | ||||
| 		state: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'all', | ||||
| 				'available', | ||||
| 				'admin', | ||||
| 				'moderator', | ||||
| 				'adminOrModerator', | ||||
| 				'silenced', | ||||
| 				'suspended', | ||||
| 			]), | ||||
| 			default: 'all', | ||||
| 		}, | ||||
| 
 | ||||
| 		origin: { | ||||
| 			validator: $.optional.str.or([ | ||||
| 				'combined', | ||||
| 				'local', | ||||
| 				'remote', | ||||
| 			]), | ||||
| 			default: 'local', | ||||
| 		}, | ||||
| 
 | ||||
| 		username: { | ||||
| 			validator: $.optional.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 
 | ||||
| 		hostname: { | ||||
| 			validator: $.optional.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		nullable: false, optional: false, | ||||
|  | @ -74,8 +18,22 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		offset: { type: 'integer', default: 0 }, | ||||
| 		sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, | ||||
| 		state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" }, | ||||
| 		origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, | ||||
| 		username: { type: 'string', default: null }, | ||||
| 		hostname: { type: 'string', default: null }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = Users.createQueryBuilder('user'); | ||||
| 
 | ||||
| 	switch (ps.state) { | ||||
|  | @ -111,7 +69,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(); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -9,16 +7,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import deleteFollowing from '@/services/following/delete'; | ||||
| import { Users, Followings, Notifications } from '@/models/index'; | ||||
|  | @ -13,16 +11,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -9,16 +7,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Users } from '@/models/index'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -10,16 +8,18 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const user = await Users.findOne(ps.userId as string); | ||||
| 
 | ||||
| 	if (user == null) { | ||||
|  |  | |||
|  | @ -1,310 +1,107 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { Meta } from '@/models/entities/meta'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
| import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['admin'], | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireAdmin: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		disableRegistration: { | ||||
| 			validator: $.optional.nullable.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		disableLocalTimeline: { | ||||
| 			validator: $.optional.nullable.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		disableGlobalTimeline: { | ||||
| 			validator: $.optional.nullable.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		useStarForReactionFallback: { | ||||
| 			validator: $.optional.nullable.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		pinnedUsers: { | ||||
| 			validator: $.optional.nullable.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		hiddenTags: { | ||||
| 			validator: $.optional.nullable.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		blockedHosts: { | ||||
| 			validator: $.optional.nullable.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		themeColor: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		mascotImageUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		bannerUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		errorImageUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		iconUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		backgroundImageUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		logoImageUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		name: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		description: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		maxNoteTextLength: { | ||||
| 			validator: $.optional.num.min(0).max(DB_MAX_NOTE_TEXT_LENGTH), | ||||
| 		}, | ||||
| 
 | ||||
| 		localDriveCapacityMb: { | ||||
| 			validator: $.optional.num.min(0), | ||||
| 		}, | ||||
| 
 | ||||
| 		remoteDriveCapacityMb: { | ||||
| 			validator: $.optional.num.min(0), | ||||
| 		}, | ||||
| 
 | ||||
| 		cacheRemoteFiles: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		proxyRemoteFiles: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		emailRequiredForSignup: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableHcaptcha: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		hcaptchaSiteKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		hcaptchaSecretKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableRecaptcha: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		recaptchaSiteKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		recaptchaSecretKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		proxyAccountId: { | ||||
| 			validator: $.optional.nullable.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		maintainerName: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		maintainerEmail: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		pinnedPages: { | ||||
| 			validator: $.optional.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		pinnedClipId: { | ||||
| 			validator: $.optional.nullable.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		langs: { | ||||
| 			validator: $.optional.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		summalyProxy: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		deeplAuthKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		deeplIsPro: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableTwitterIntegration: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		twitterConsumerKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		twitterConsumerSecret: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableGithubIntegration: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		githubClientId: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		githubClientSecret: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableDiscordIntegration: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		discordClientId: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		discordClientSecret: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableEmail: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		email: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		smtpSecure: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		smtpHost: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		smtpPort: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 		}, | ||||
| 
 | ||||
| 		smtpUser: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		smtpPass: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		enableServiceWorker: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		swPublicKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		swPrivateKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		tosUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		repositoryUrl: { | ||||
| 			validator: $.optional.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		feedbackUrl: { | ||||
| 			validator: $.optional.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		useObjectStorage: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageBaseUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageBucket: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStoragePrefix: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageEndpoint: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageRegion: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStoragePort: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageAccessKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageSecretKey: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageUseSSL: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageUseProxy: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageSetPublicRead: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		objectStorageS3ForcePathStyle: { | ||||
| 			validator: $.optional.bool, | ||||
| 		}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		disableRegistration: { type: 'boolean', nullable: true }, | ||||
| 		disableLocalTimeline: { type: 'boolean', nullable: true }, | ||||
| 		disableGlobalTimeline: { type: 'boolean', nullable: true }, | ||||
| 		useStarForReactionFallback: { type: 'boolean', nullable: true }, | ||||
| 		pinnedUsers: { type: 'array', nullable: true, items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		hiddenTags: { type: 'array', nullable: true, items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		blockedHosts: { type: 'array', nullable: true, items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		themeColor: { type: 'string', nullable: true }, | ||||
| 		mascotImageUrl: { type: 'string', nullable: true }, | ||||
| 		bannerUrl: { type: 'string', nullable: true }, | ||||
| 		errorImageUrl: { type: 'string', nullable: true }, | ||||
| 		iconUrl: { type: 'string', nullable: true }, | ||||
| 		backgroundImageUrl: { type: 'string', nullable: true }, | ||||
| 		logoImageUrl: { type: 'string', nullable: true }, | ||||
| 		name: { type: 'string', nullable: true }, | ||||
| 		description: { type: 'string', nullable: true }, | ||||
| 		maxNoteTextLength: { type: 'integer', maximum: 8192 }, | ||||
| 		localDriveCapacityMb: { type: 'integer' }, | ||||
| 		remoteDriveCapacityMb: { type: 'integer' }, | ||||
| 		cacheRemoteFiles: { type: 'boolean' }, | ||||
| 		proxyRemoteFiles: { type: 'boolean' }, | ||||
| 		emailRequiredForSignup: { type: 'boolean' }, | ||||
| 		enableHcaptcha: { type: 'boolean' }, | ||||
| 		hcaptchaSiteKey: { type: 'string', nullable: true }, | ||||
| 		hcaptchaSecretKey: { type: 'string', nullable: true }, | ||||
| 		enableRecaptcha: { type: 'boolean' }, | ||||
| 		recaptchaSiteKey: { type: 'string', nullable: true }, | ||||
| 		recaptchaSecretKey: { type: 'string', nullable: true }, | ||||
| 		proxyAccountId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		maintainerName: { type: 'string', nullable: true }, | ||||
| 		maintainerEmail: { type: 'string', nullable: true }, | ||||
| 		pinnedPages: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		pinnedClipId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		langs: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		summalyProxy: { type: 'string', nullable: true }, | ||||
| 		deeplAuthKey: { type: 'string', nullable: true }, | ||||
| 		deeplIsPro: { type: 'boolean' }, | ||||
| 		enableTwitterIntegration: { type: 'boolean' }, | ||||
| 		twitterConsumerKey: { type: 'string', nullable: true }, | ||||
| 		twitterConsumerSecret: { type: 'string', nullable: true }, | ||||
| 		enableGithubIntegration: { type: 'boolean' }, | ||||
| 		githubClientId: { type: 'string', nullable: true }, | ||||
| 		githubClientSecret: { type: 'string', nullable: true }, | ||||
| 		enableDiscordIntegration: { type: 'boolean' }, | ||||
| 		discordClientId: { type: 'string', nullable: true }, | ||||
| 		discordClientSecret: { type: 'string', nullable: true }, | ||||
| 		enableEmail: { type: 'boolean' }, | ||||
| 		email: { type: 'string', nullable: true }, | ||||
| 		smtpSecure: { type: 'boolean' }, | ||||
| 		smtpHost: { type: 'string', nullable: true }, | ||||
| 		smtpPort: { type: 'integer', nullable: true }, | ||||
| 		smtpUser: { type: 'string', nullable: true }, | ||||
| 		smtpPass: { type: 'string', nullable: true }, | ||||
| 		enableServiceWorker: { type: 'boolean' }, | ||||
| 		swPublicKey: { type: 'string', nullable: true }, | ||||
| 		swPrivateKey: { type: 'string', nullable: true }, | ||||
| 		tosUrl: { type: 'string', nullable: true }, | ||||
| 		repositoryUrl: { type: 'string' }, | ||||
| 		feedbackUrl: { type: 'string' }, | ||||
| 		useObjectStorage: { type: 'boolean' }, | ||||
| 		objectStorageBaseUrl: { type: 'string', nullable: true }, | ||||
| 		objectStorageBucket: { type: 'string', nullable: true }, | ||||
| 		objectStoragePrefix: { type: 'string', nullable: true }, | ||||
| 		objectStorageEndpoint: { type: 'string', nullable: true }, | ||||
| 		objectStorageRegion: { type: 'string', nullable: true }, | ||||
| 		objectStoragePort: { type: 'integer', nullable: true }, | ||||
| 		objectStorageAccessKey: { type: 'string', nullable: true }, | ||||
| 		objectStorageSecretKey: { type: 'string', nullable: true }, | ||||
| 		objectStorageUseSSL: { type: 'boolean' }, | ||||
| 		objectStorageUseProxy: { type: 'boolean' }, | ||||
| 		objectStorageSetPublicRead: { type: 'boolean' }, | ||||
| 		objectStorageS3ForcePathStyle: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const set = {} as Partial<Meta>; | ||||
| 
 | ||||
| 	if (typeof ps.disableRegistration === 'boolean') { | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { getConnection } from 'typeorm'; | ||||
| import { insertModerationLog } from '@/services/insert-moderation-log'; | ||||
|  | @ -8,19 +7,19 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: true, | ||||
| 	requireModerator: true, | ||||
| } as const; | ||||
| 
 | ||||
| 	params: { | ||||
| 		full: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 		analyze: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		full: { type: 'boolean' }, | ||||
| 		analyze: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: ['full', 'analyze'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const params: string[] = []; | ||||
| 
 | ||||
| 	if (ps.full) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../define'; | ||||
| import { Announcements, AnnouncementReads } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../common/make-pagination-query'; | ||||
|  | @ -9,26 +7,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		withUnreads: { | ||||
| 			validator: $.optional.boolean, | ||||
| 			default: false, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -73,11 +51,22 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		withUnreads: { type: 'boolean', default: false }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); | ||||
| 
 | ||||
| 	const announcements = await query.take(ps.limit!).getMany(); | ||||
| 	const announcements = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	if (user) { | ||||
| 		const reads = (await AnnouncementReads.find({ | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
| import { Antennas, UserLists, UserGroupJoinings } from '@/models/index'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { publishInternalEvent } from '@/services/stream'; | ||||
| 
 | ||||
|  | @ -13,52 +11,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	params: { | ||||
| 		name: { | ||||
| 			validator: $.str.range(1, 100), | ||||
| 		}, | ||||
| 
 | ||||
| 		src: { | ||||
| 			validator: $.str.or(['home', 'all', 'users', 'list', 'group']), | ||||
| 		}, | ||||
| 
 | ||||
| 		userListId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		userGroupId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		keywords: { | ||||
| 			validator: $.arr($.arr($.str)), | ||||
| 		}, | ||||
| 
 | ||||
| 		excludeKeywords: { | ||||
| 			validator: $.arr($.arr($.str)), | ||||
| 		}, | ||||
| 
 | ||||
| 		users: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		caseSensitive: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		withReplies: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		withFile: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		notify: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchUserList: { | ||||
| 			message: 'No such user list.', | ||||
|  | @ -80,8 +32,36 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		name: { type: 'string', minLength: 1, maxLength: 100 }, | ||||
| 		src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'group'] }, | ||||
| 		userListId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		userGroupId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		keywords: { type: 'array', items: { | ||||
| 			type: 'array', items: { | ||||
| 				type: 'string', | ||||
| 			}, | ||||
| 		} }, | ||||
| 		excludeKeywords: { type: 'array', items: { | ||||
| 			type: 'array', items: { | ||||
| 				type: 'string', | ||||
| 			}, | ||||
| 		} }, | ||||
| 		users: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		caseSensitive: { type: 'boolean' }, | ||||
| 		withReplies: { type: 'boolean' }, | ||||
| 		withFile: { type: 'boolean' }, | ||||
| 		notify: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: ['name', 'src', 'keywords', 'excludeKeywords', 'users', 'caseSensitive', 'withReplies', 'withFile', 'notify'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	let userList; | ||||
| 	let userGroupJoining; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Antennas } from '@/models/index'; | ||||
|  | @ -12,12 +10,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	params: { | ||||
| 		antennaId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAntenna: { | ||||
| 			message: 'No such antenna.', | ||||
|  | @ -27,8 +19,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		antennaId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['antennaId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const antenna = await Antennas.findOne({ | ||||
| 		id: ps.antennaId, | ||||
| 		userId: user.id, | ||||
|  |  | |||
|  | @ -19,8 +19,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const antennas = await Antennas.find({ | ||||
| 		userId: me.id, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import readNote from '@/services/note/read'; | ||||
| import { Antennas, Notes, AntennaNotes } from '@/models/index'; | ||||
|  | @ -16,33 +14,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:account', | ||||
| 
 | ||||
| 	params: { | ||||
| 		antennaId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceDate: { | ||||
| 			validator: $.optional.num, | ||||
| 		}, | ||||
| 
 | ||||
| 		untilDate: { | ||||
| 			validator: $.optional.num, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAntenna: { | ||||
| 			message: 'No such antenna.', | ||||
|  | @ -62,8 +33,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		antennaId: { type: 'string', format: 'misskey:id' }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		sinceDate: { type: 'integer' }, | ||||
| 		untilDate: { type: 'integer' }, | ||||
| 	}, | ||||
| 	required: ['antennaId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const antenna = await Antennas.findOne({ | ||||
| 		id: ps.antennaId, | ||||
| 		userId: user.id, | ||||
|  | @ -92,7 +76,7 @@ export default define(meta, async (ps, user) => { | |||
| 	generateBlockedUserQuery(query, user); | ||||
| 
 | ||||
| 	const notes = await query | ||||
| 		.take(ps.limit!) | ||||
| 		.take(ps.limit) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	if (notes.length > 0) { | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Antennas } from '@/models/index'; | ||||
|  | @ -11,12 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:account', | ||||
| 
 | ||||
| 	params: { | ||||
| 		antennaId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAntenna: { | ||||
| 			message: 'No such antenna.', | ||||
|  | @ -32,8 +24,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		antennaId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['antennaId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	// Fetch the antenna
 | ||||
| 	const antenna = await Antennas.findOne({ | ||||
| 		id: ps.antennaId, | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Antennas, UserLists, UserGroupJoinings } from '@/models/index'; | ||||
|  | @ -12,56 +10,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:account', | ||||
| 
 | ||||
| 	params: { | ||||
| 		antennaId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		name: { | ||||
| 			validator: $.str.range(1, 100), | ||||
| 		}, | ||||
| 
 | ||||
| 		src: { | ||||
| 			validator: $.str.or(['home', 'all', 'users', 'list', 'group']), | ||||
| 		}, | ||||
| 
 | ||||
| 		userListId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		userGroupId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		keywords: { | ||||
| 			validator: $.arr($.arr($.str)), | ||||
| 		}, | ||||
| 
 | ||||
| 		excludeKeywords: { | ||||
| 			validator: $.arr($.arr($.str)), | ||||
| 		}, | ||||
| 
 | ||||
| 		users: { | ||||
| 			validator: $.arr($.str), | ||||
| 		}, | ||||
| 
 | ||||
| 		caseSensitive: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		withReplies: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		withFile: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 
 | ||||
| 		notify: { | ||||
| 			validator: $.bool, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchAntenna: { | ||||
| 			message: 'No such antenna.', | ||||
|  | @ -89,8 +37,37 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		antennaId: { type: 'string', format: 'misskey:id' }, | ||||
| 		name: { type: 'string', minLength: 1, maxLength: 100 }, | ||||
| 		src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'group'] }, | ||||
| 		userListId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		userGroupId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 		keywords: { type: 'array', items: { | ||||
| 			type: 'array', items: { | ||||
| 				type: 'string', | ||||
| 			}, | ||||
| 		} }, | ||||
| 		excludeKeywords: { type: 'array', items: { | ||||
| 			type: 'array', items: { | ||||
| 				type: 'string', | ||||
| 			}, | ||||
| 		} }, | ||||
| 		users: { type: 'array', items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		caseSensitive: { type: 'boolean' }, | ||||
| 		withReplies: { type: 'boolean' }, | ||||
| 		withFile: { type: 'boolean' }, | ||||
| 		notify: { type: 'boolean' }, | ||||
| 	}, | ||||
| 	required: ['antennaId', 'name', 'src', 'keywords', 'excludeKeywords', 'users', 'caseSensitive', 'withReplies', 'withFile', 'notify'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	// Fetch the antenna
 | ||||
| 	const antenna = await Antennas.findOne({ | ||||
| 		id: ps.antennaId, | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import Resolver from '@/remote/activitypub/resolver'; | ||||
| import { ApiError } from '../../error'; | ||||
|  | @ -14,12 +13,6 @@ export const meta = { | |||
| 		max: 30, | ||||
| 	}, | ||||
| 
 | ||||
| 	params: { | ||||
| 		uri: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -29,8 +22,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		uri: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['uri'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const resolver = new Resolver(); | ||||
| 	const object = await resolver.resolve(ps.uri); | ||||
| 	return object; | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import config from '@/config/index'; | ||||
| import { createPerson } from '@/remote/activitypub/models/person'; | ||||
|  | @ -24,12 +23,6 @@ export const meta = { | |||
| 		max: 30, | ||||
| 	}, | ||||
| 
 | ||||
| 	params: { | ||||
| 		uri: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchObject: { | ||||
| 			message: 'No such object.', | ||||
|  | @ -75,8 +68,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		uri: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['uri'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	const object = await fetchAny(ps.uri); | ||||
| 	if (object) { | ||||
| 		return object; | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { Apps } from '@/models/index'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
|  | @ -10,26 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		name: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		description: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		permission: { | ||||
| 			validator: $.arr($.str).unique(), | ||||
| 		}, | ||||
| 
 | ||||
| 		// TODO: Check it is valid url
 | ||||
| 		callbackUrl: { | ||||
| 			validator: $.optional.nullable.str, | ||||
| 			default: null, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -37,8 +16,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		name: { type: 'string' }, | ||||
| 		description: { type: 'string' }, | ||||
| 		permission: { type: 'array', uniqueItems: true, items: { | ||||
| 			type: 'string', | ||||
| 		} }, | ||||
| 		callbackUrl: { type: 'string', nullable: true }, | ||||
| 	}, | ||||
| 	required: ['name', 'description', 'permission'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	// Generate secret
 | ||||
| 	const secret = secureRndstr(32, true); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Apps } from '@/models/index'; | ||||
|  | @ -7,12 +5,6 @@ import { Apps } from '@/models/index'; | |||
| export const meta = { | ||||
| 	tags: ['app'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		appId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchApp: { | ||||
| 			message: 'No such app.', | ||||
|  | @ -28,8 +20,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		appId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['appId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user, token) => { | ||||
| export default define(meta, paramDef, async (ps, user, token) => { | ||||
| 	const isSecure = user != null && token == null; | ||||
| 
 | ||||
| 	// Lookup app
 | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| import * as crypto from 'crypto'; | ||||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { AuthSessions, AccessTokens, Apps } from '@/models/index'; | ||||
|  | @ -13,12 +12,6 @@ export const meta = { | |||
| 
 | ||||
| 	secure: true, | ||||
| 
 | ||||
| 	params: { | ||||
| 		token: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchSession: { | ||||
| 			message: 'No such session.', | ||||
|  | @ -28,8 +21,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		token: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['token'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	// Fetch token
 | ||||
| 	const session = await AuthSessions | ||||
| 		.findOne({ token: ps.token }); | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| import { v4 as uuid } from 'uuid'; | ||||
| import $ from 'cafy'; | ||||
| import config from '@/config/index'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
|  | @ -11,12 +10,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		appSecret: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -42,8 +35,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		appSecret: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['appSecret'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	// Lookup app
 | ||||
| 	const app = await Apps.findOne({ | ||||
| 		secret: ps.appSecret, | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { AuthSessions } from '@/models/index'; | ||||
|  | @ -8,12 +7,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		token: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchSession: { | ||||
| 			message: 'No such session.', | ||||
|  | @ -44,8 +37,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		token: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['token'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	// Lookup session
 | ||||
| 	const session = await AuthSessions.findOne({ | ||||
| 		token: ps.token, | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../../define'; | ||||
| import { ApiError } from '../../../error'; | ||||
| import { Apps, AuthSessions, AccessTokens, Users } from '@/models/index'; | ||||
|  | @ -8,16 +7,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		appSecret: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 
 | ||||
| 		token: { | ||||
| 			validator: $.str, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -56,8 +45,17 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		appSecret: { type: 'string' }, | ||||
| 		token: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['appSecret', 'token'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	// Lookup app
 | ||||
| 	const app = await Apps.findOne({ | ||||
| 		secret: ps.appSecret, | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import ms from 'ms'; | ||||
| import create from '@/services/blocking/create'; | ||||
| import define from '../../define'; | ||||
|  | @ -19,12 +17,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:blocks', | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
|  | @ -52,8 +44,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const blocker = await Users.findOneOrFail(user.id); | ||||
| 
 | ||||
| 	// 自分自身
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import ms from 'ms'; | ||||
| import deleteBlocking from '@/services/blocking/delete'; | ||||
| import define from '../../define'; | ||||
|  | @ -19,12 +17,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:blocks', | ||||
| 
 | ||||
| 	params: { | ||||
| 		userId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchUser: { | ||||
| 			message: 'No such user.', | ||||
|  | @ -52,8 +44,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		userId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['userId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const blocker = await Users.findOneOrFail(user.id); | ||||
| 
 | ||||
| 	// Check if the blockee is yourself
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Blockings } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
|  | @ -11,21 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:blocks', | ||||
| 
 | ||||
| 	params: { | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 30, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -37,13 +20,23 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = makePaginationQuery(Blockings.createQueryBuilder('blocking'), ps.sinceId, ps.untilId) | ||||
| 		.andWhere(`blocking.blockerId = :meId`, { meId: me.id }); | ||||
| 
 | ||||
| 	const blockings = await query | ||||
| 		.take(ps.limit!) | ||||
| 		.take(ps.limit) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	return await Blockings.packMany(blockings, me); | ||||
|  |  | |||
|  | @ -1,10 +1,8 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Channels, DriveFiles } from '@/models/index'; | ||||
| import { Channel } from '@/models/entities/channel'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['channels'], | ||||
|  | @ -13,20 +11,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		name: { | ||||
| 			validator: $.str.range(1, 128), | ||||
| 		}, | ||||
| 
 | ||||
| 		description: { | ||||
| 			validator: $.nullable.optional.str.range(1, 2048), | ||||
| 		}, | ||||
| 
 | ||||
| 		bannerId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -42,8 +26,18 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		name: { type: 'string', minLength: 1, maxLength: 128 }, | ||||
| 		description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, | ||||
| 		bannerId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 	}, | ||||
| 	required: ['name'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	let banner = null; | ||||
| 	if (ps.bannerId != null) { | ||||
| 		banner = await DriveFiles.findOne({ | ||||
|  |  | |||
|  | @ -17,8 +17,14 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: {}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = Channels.createQueryBuilder('channel') | ||||
| 		.where('channel.lastNotedAt IS NOT NULL') | ||||
| 		.orderBy('channel.lastNotedAt', 'DESC'); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Channels, ChannelFollowings } from '@/models/index'; | ||||
|  | @ -13,12 +11,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		channelId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchChannel: { | ||||
| 			message: 'No such channel.', | ||||
|  | @ -28,8 +20,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		channelId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['channelId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const channel = await Channels.findOne({ | ||||
| 		id: ps.channelId, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Channels, ChannelFollowings } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
|  | @ -11,21 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 5, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -37,13 +20,23 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 5 }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = makePaginationQuery(ChannelFollowings.createQueryBuilder(), ps.sinceId, ps.untilId) | ||||
| 		.andWhere({ followerId: me.id }); | ||||
| 
 | ||||
| 	const followings = await query | ||||
| 		.take(ps.limit!) | ||||
| 		.take(ps.limit) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	return await Promise.all(followings.map(x => Channels.pack(x.followeeId, me))); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { Channels } from '@/models/index'; | ||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||
|  | @ -11,21 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'read:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 5, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -37,13 +20,23 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 5 }, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const query = makePaginationQuery(Channels.createQueryBuilder(), ps.sinceId, ps.untilId) | ||||
| 		.andWhere({ userId: me.id }); | ||||
| 
 | ||||
| 	const channels = await query | ||||
| 		.take(ps.limit!) | ||||
| 		.take(ps.limit) | ||||
| 		.getMany(); | ||||
| 
 | ||||
| 	return await Promise.all(channels.map(x => Channels.pack(x, me))); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Channels } from '@/models/index'; | ||||
|  | @ -9,12 +7,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		channelId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -30,8 +22,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		channelId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['channelId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const channel = await Channels.findOne({ | ||||
| 		id: ps.channelId, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Notes, Channels } from '@/models/index'; | ||||
|  | @ -11,33 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	requireCredential: false, | ||||
| 
 | ||||
| 	params: { | ||||
| 		channelId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 100), | ||||
| 			default: 10, | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		untilId: { | ||||
| 			validator: $.optional.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		sinceDate: { | ||||
| 			validator: $.optional.num, | ||||
| 		}, | ||||
| 
 | ||||
| 		untilDate: { | ||||
| 			validator: $.optional.num, | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'array', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -57,8 +28,21 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		channelId: { type: 'string', format: 'misskey:id' }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, | ||||
| 		sinceId: { type: 'string', format: 'misskey:id' }, | ||||
| 		untilId: { type: 'string', format: 'misskey:id' }, | ||||
| 		sinceDate: { type: 'integer' }, | ||||
| 		untilDate: { type: 'integer' }, | ||||
| 	}, | ||||
| 	required: ['channelId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const channel = await Channels.findOne({ | ||||
| 		id: ps.channelId, | ||||
| 	}); | ||||
|  | @ -78,7 +62,7 @@ export default define(meta, async (ps, user) => { | |||
| 		.leftJoinAndSelect('note.channel', 'channel'); | ||||
| 	//#endregion
 | ||||
| 
 | ||||
| 	const timeline = await query.take(ps.limit!).getMany(); | ||||
| 	const timeline = await query.take(ps.limit).getMany(); | ||||
| 
 | ||||
| 	if (user) activeUsersChart.read(user); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Channels, ChannelFollowings } from '@/models/index'; | ||||
|  | @ -12,12 +10,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		channelId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	errors: { | ||||
| 		noSuchChannel: { | ||||
| 			message: 'No such channel.', | ||||
|  | @ -27,8 +19,16 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		channelId: { type: 'string', format: 'misskey:id' }, | ||||
| 	}, | ||||
| 	required: ['channelId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, user) => { | ||||
| export default define(meta, paramDef, async (ps, user) => { | ||||
| 	const channel = await Channels.findOne({ | ||||
| 		id: ps.channelId, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,5 +1,3 @@ | |||
| import $ from 'cafy'; | ||||
| import { ID } from '@/misc/cafy-id'; | ||||
| import define from '../../define'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { Channels, DriveFiles } from '@/models/index'; | ||||
|  | @ -11,24 +9,6 @@ export const meta = { | |||
| 
 | ||||
| 	kind: 'write:channels', | ||||
| 
 | ||||
| 	params: { | ||||
| 		channelId: { | ||||
| 			validator: $.type(ID), | ||||
| 		}, | ||||
| 
 | ||||
| 		name: { | ||||
| 			validator: $.optional.str.range(1, 128), | ||||
| 		}, | ||||
| 
 | ||||
| 		description: { | ||||
| 			validator: $.nullable.optional.str.range(1, 2048), | ||||
| 		}, | ||||
| 
 | ||||
| 		bannerId: { | ||||
| 			validator: $.nullable.optional.type(ID), | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	res: { | ||||
| 		type: 'object', | ||||
| 		optional: false, nullable: false, | ||||
|  | @ -56,8 +36,19 @@ export const meta = { | |||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		channelId: { type: 'string', format: 'misskey:id' }, | ||||
| 		name: { type: 'string', minLength: 1, maxLength: 128 }, | ||||
| 		description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, | ||||
| 		bannerId: { type: 'string', format: 'misskey:id', nullable: true }, | ||||
| 	}, | ||||
| 	required: ['channelId'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps, me) => { | ||||
| export default define(meta, paramDef, async (ps, me) => { | ||||
| 	const channel = await Channels.findOne({ | ||||
| 		id: ps.channelId, | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,31 +1,24 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { convertLog } from '@/services/chart/core'; | ||||
| import { getJsonSchema } from '@/services/chart/core'; | ||||
| import { activeUsersChart } from '@/services/chart/index'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['charts', 'users'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		span: { | ||||
| 			validator: $.str.or(['day', 'hour']), | ||||
| 		}, | ||||
| 	res: getJsonSchema(activeUsersChart.schema), | ||||
| } as const; | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 500), | ||||
| 			default: 30, | ||||
| 		}, | ||||
| 
 | ||||
| 		offset: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 			default: null, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		span: { type: 'string', enum: ['day', 'hour'] }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, | ||||
| 		offset: { type: 'integer', nullable: true, default: null }, | ||||
| 	}, | ||||
| 
 | ||||
| 	// TODO: response definition
 | ||||
| 	required: ['span'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| 	return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	return await activeUsersChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,31 +1,24 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { convertLog } from '@/services/chart/core'; | ||||
| import { getJsonSchema } from '@/services/chart/core'; | ||||
| import { apRequestChart } from '@/services/chart/index'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['charts'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		span: { | ||||
| 			validator: $.str.or(['day', 'hour']), | ||||
| 		}, | ||||
| 	res: getJsonSchema(apRequestChart.schema), | ||||
| } as const; | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 500), | ||||
| 			default: 30, | ||||
| 		}, | ||||
| 
 | ||||
| 		offset: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 			default: null, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		span: { type: 'string', enum: ['day', 'hour'] }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, | ||||
| 		offset: { type: 'integer', nullable: true, default: null }, | ||||
| 	}, | ||||
| 
 | ||||
| 	// TODO: response definition
 | ||||
| 	required: ['span'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| 	return await apRequestChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	return await apRequestChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,31 +1,24 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { convertLog } from '@/services/chart/core'; | ||||
| import { getJsonSchema } from '@/services/chart/core'; | ||||
| import { driveChart } from '@/services/chart/index'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['charts', 'drive'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		span: { | ||||
| 			validator: $.str.or(['day', 'hour']), | ||||
| 		}, | ||||
| 	res: getJsonSchema(driveChart.schema), | ||||
| } as const; | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 500), | ||||
| 			default: 30, | ||||
| 		}, | ||||
| 
 | ||||
| 		offset: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 			default: null, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		span: { type: 'string', enum: ['day', 'hour'] }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, | ||||
| 		offset: { type: 'integer', nullable: true, default: null }, | ||||
| 	}, | ||||
| 
 | ||||
| 	// TODO: response definition
 | ||||
| 	required: ['span'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| 	return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	return await driveChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); | ||||
| }); | ||||
|  |  | |||
|  | @ -1,31 +1,24 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { convertLog } from '@/services/chart/core'; | ||||
| import { getJsonSchema } from '@/services/chart/core'; | ||||
| import { federationChart } from '@/services/chart/index'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['charts'], | ||||
| 
 | ||||
| 	params: { | ||||
| 		span: { | ||||
| 			validator: $.str.or(['day', 'hour']), | ||||
| 		}, | ||||
| 	res: getJsonSchema(federationChart.schema), | ||||
| } as const; | ||||
| 
 | ||||
| 		limit: { | ||||
| 			validator: $.optional.num.range(1, 500), | ||||
| 			default: 30, | ||||
| 		}, | ||||
| 
 | ||||
| 		offset: { | ||||
| 			validator: $.optional.nullable.num, | ||||
| 			default: null, | ||||
| 		}, | ||||
| const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		span: { type: 'string', enum: ['day', 'hour'] }, | ||||
| 		limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, | ||||
| 		offset: { type: 'integer', nullable: true, default: null }, | ||||
| 	}, | ||||
| 
 | ||||
| 	// TODO: response definition
 | ||||
| 	required: ['span'], | ||||
| } as const; | ||||
| 
 | ||||
| // eslint-disable-next-line import/no-default-export
 | ||||
| export default define(meta, async (ps) => { | ||||
| 	return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); | ||||
| export default define(meta, paramDef, async (ps) => { | ||||
| 	return await federationChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); | ||||
| }); | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue