Refactor API (#4770)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update description.ts

* wip
This commit is contained in:
syuilo 2019-04-23 22:35:26 +09:00 committed by GitHub
parent b0fce9b791
commit 493c83ef2d
105 changed files with 1622 additions and 808 deletions

View file

@ -29,7 +29,6 @@
"@fortawesome/free-solid-svg-icons": "5.7.2", "@fortawesome/free-solid-svg-icons": "5.7.2",
"@fortawesome/vue-fontawesome": "0.1.5", "@fortawesome/vue-fontawesome": "0.1.5",
"@koa/cors": "2.2.3", "@koa/cors": "2.2.3",
"@prezzemolo/rap": "0.1.2",
"@prezzemolo/zip": "0.0.3", "@prezzemolo/zip": "0.0.3",
"@types/bcryptjs": "2.4.2", "@types/bcryptjs": "2.4.2",
"@types/bull": "3.5.11", "@types/bull": "3.5.11",

View file

@ -77,11 +77,11 @@ export default Vue.extend({
input: { input: {
default: this.list.name default: this.list.name
} }
}).then(({ canceled, result: title }) => { }).then(({ canceled, result: name }) => {
if (canceled) return; if (canceled) return;
this.$root.api('users/lists/update', { this.$root.api('users/lists/update', {
listId: this.list.id, listId: this.list.id,
title: title name: name
}); });
}); });
}, },

View file

@ -28,10 +28,10 @@ export default Vue.extend({
this.$root.dialog({ this.$root.dialog({
title: this.$t('list-name'), title: this.$t('list-name'),
input: true input: true
}).then(async ({ canceled, result: title }) => { }).then(async ({ canceled, result: name }) => {
if (canceled) return; if (canceled) return;
const list = await this.$root.api('users/lists/create', { const list = await this.$root.api('users/lists/create', {
title name
}); });
this.lists.push(list) this.lists.push(list)

View file

@ -123,10 +123,10 @@ export default Vue.extend({
this.$root.dialog({ this.$root.dialog({
title: this.$t('list-name'), title: this.$t('list-name'),
input: true input: true
}).then(async ({ canceled, result: title }) => { }).then(async ({ canceled, result: name }) => {
if (canceled) return; if (canceled) return;
const list = await this.$root.api('users/lists/create', { const list = await this.$root.api('users/lists/create', {
title name
}); });
this.list = list; this.list = list;

View file

@ -1,14 +1,46 @@
export const types = {
boolean: 'boolean' as 'boolean',
string: 'string' as 'string',
number: 'number' as 'number',
array: 'array' as 'array',
object: 'object' as 'object',
any: 'any' as 'any',
};
export const bool = {
true: true as true,
false: false as false,
};
export type Schema = { export type Schema = {
type: 'number' | 'string' | 'array' | 'object' | any; type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any';
optional?: boolean; nullable: boolean;
optional: boolean;
items?: Schema; items?: Schema;
properties?: Obj; properties?: Obj;
description?: string; description?: string;
example?: any;
format?: string;
ref?: string;
enum?: string[];
}; };
type NonUndefinedPropertyNames<T extends Obj> = {
[K in keyof T]: T[K]['optional'] extends true ? never : K
}[keyof T];
type UndefinedPropertyNames<T extends Obj> = {
[K in keyof T]: T[K]['optional'] extends true ? K : never
}[keyof T];
type OnlyRequired<T extends Obj> = Pick<T, NonUndefinedPropertyNames<T>>;
type OnlyOptional<T extends Obj> = Pick<T, UndefinedPropertyNames<T>>;
export type Obj = { [key: string]: Schema }; export type Obj = { [key: string]: Schema };
export type ObjType<s extends Obj> = { [P in keyof s]: SchemaType<s[P]> }; export type ObjType<s extends Obj> =
{ [P in keyof OnlyOptional<s>]?: SchemaType<s[P]> } &
{ [P in keyof OnlyRequired<s>]: SchemaType<s[P]> };
// https://qiita.com/hrsh7th@github/items/84e8968c3601009cdcf2 // https://qiita.com/hrsh7th@github/items/84e8968c3601009cdcf2
type MyType<T extends Schema> = { type MyType<T extends Schema> = {
@ -16,26 +48,20 @@ type MyType<T extends Schema> = {
1: SchemaType<T>; 1: SchemaType<T>;
}[T extends Schema ? 1 : 0]; }[T extends Schema ? 1 : 0];
export type SchemaType<p extends Schema> = type NullOrUndefined<p extends Schema, T> =
p['type'] extends 'number' ? number : p['nullable'] extends true
p['type'] extends 'string' ? string : ? p['optional'] extends true
p['type'] extends 'array' ? MyType<NonNullable<p['items']>>[] : ? (T | null | undefined)
p['type'] extends 'object' ? ObjType<NonNullable<p['properties']>> : : (T | null)
any; : p['optional'] extends true
? (T | undefined)
: T;
export function convertOpenApiSchema(schema: Schema) { export type SchemaType<p extends Schema> =
const x = JSON.parse(JSON.stringify(schema)); // copy p['type'] extends 'number' ? NullOrUndefined<p, number> :
if (!['string', 'number', 'boolean', 'array', 'object'].includes(x.type)) { p['type'] extends 'string' ? NullOrUndefined<p, string> :
x['$ref'] = `#/components/schemas/${x.type}`; p['type'] extends 'boolean' ? NullOrUndefined<p, boolean> :
} p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> :
if (x.type === 'array' && x.items) { p['type'] extends 'object' ? NullOrUndefined<p, ObjType<NonNullable<p['properties']>>> :
x.items = convertOpenApiSchema(x.items); p['type'] extends 'any' ? NullOrUndefined<p, any> :
} any;
if (x.type === 'object' && x.properties) {
x.required = Object.entries(x.properties).filter(([k, v]: any) => !v.isOptional).map(([k, v]: any) => k);
for (const k of Object.keys(x.properties)) {
x.properties[k] = convertOpenApiSchema(x.properties[k]);
}
}
return x;
}

View file

@ -1,8 +1,8 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Users } from '..'; import { Users } from '..';
import rap from '@prezzemolo/rap';
import { AbuseUserReport } from '../entities/abuse-user-report'; import { AbuseUserReport } from '../entities/abuse-user-report';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
@EntityRepository(AbuseUserReport) @EntityRepository(AbuseUserReport)
export class AbuseUserReportRepository extends Repository<AbuseUserReport> { export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
@ -17,7 +17,7 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
) { ) {
const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: report.id, id: report.id,
createdAt: report.createdAt, createdAt: report.createdAt,
reporterId: report.reporterId, reporterId: report.reporterId,

View file

@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
import { App } from '../entities/app'; import { App } from '../entities/app';
import { AccessTokens } from '..'; import { AccessTokens } from '..';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedApp = SchemaType<typeof packedAppSchema>;
@EntityRepository(App) @EntityRepository(App)
export class AppRepository extends Repository<App> { export class AppRepository extends Repository<App> {
@ -13,7 +16,7 @@ export class AppRepository extends Repository<App> {
includeSecret?: boolean, includeSecret?: boolean,
includeProfileImageIds?: boolean includeProfileImageIds?: boolean
} }
) { ): Promise<PackedApp> {
const opts = Object.assign({ const opts = Object.assign({
detail: false, detail: false,
includeSecret: false, includeSecret: false,
@ -37,3 +40,40 @@ export class AppRepository extends Repository<App> {
}; };
} }
} }
export const packedAppSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this Note.',
example: 'xxxxxxxxxx',
},
name: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'アプリケーションの名前'
},
callbackUrl: {
type: types.string,
optional: bool.false, nullable: bool.true,
description: 'コールバックするURL'
},
permission: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
}
},
secret: {
type: types.string,
optional: bool.true, nullable: bool.false,
description: 'アプリケーションのシークレットキー'
}
},
};

View file

@ -1,8 +1,8 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Apps } from '..'; import { Apps } from '..';
import rap from '@prezzemolo/rap';
import { AuthSession } from '../entities/auth-session'; import { AuthSession } from '../entities/auth-session';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
@EntityRepository(AuthSession) @EntityRepository(AuthSession)
export class AuthSessionRepository extends Repository<AuthSession> { export class AuthSessionRepository extends Repository<AuthSession> {
@ -12,7 +12,7 @@ export class AuthSessionRepository extends Repository<AuthSession> {
) { ) {
const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: session.id, id: session.id,
app: Apps.pack(session.appId, me), app: Apps.pack(session.appId, me),
token: session.token token: session.token

View file

@ -1,8 +1,11 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Users } from '..'; import { Users } from '..';
import rap from '@prezzemolo/rap';
import { Blocking } from '../entities/blocking'; import { Blocking } from '../entities/blocking';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { SchemaType, types, bool } from '../../misc/schema';
export type PackedBlocking = SchemaType<typeof packedBlockingSchema>;
@EntityRepository(Blocking) @EntityRepository(Blocking)
export class BlockingRepository extends Repository<Blocking> { export class BlockingRepository extends Repository<Blocking> {
@ -16,14 +19,47 @@ export class BlockingRepository extends Repository<Blocking> {
public async pack( public async pack(
src: Blocking['id'] | Blocking, src: Blocking['id'] | Blocking,
me?: any me?: any
) { ): Promise<PackedBlocking> {
const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: blocking.id, id: blocking.id,
createdAt: blocking.createdAt.toISOString(),
blockeeId: blocking.blockeeId,
blockee: Users.pack(blocking.blockeeId, me, { blockee: Users.pack(blocking.blockeeId, me, {
detail: true detail: true
}) })
}); });
} }
} }
export const packedBlockingSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this blocking.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the blocking was created.'
},
blockeeId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
blockee: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
description: 'The blockee.'
},
}
};

View file

@ -1,10 +1,13 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { DriveFile } from '../entities/drive-file'; import { DriveFile } from '../entities/drive-file';
import { Users, DriveFolders } from '..'; import { Users, DriveFolders } from '..';
import rap from '@prezzemolo/rap';
import { User } from '../entities/user'; import { User } from '../entities/user';
import { toPuny } from '../../misc/convert-host'; import { toPuny } from '../../misc/convert-host';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedDriveFile = SchemaType<typeof packedDriveFileSchema>;
@EntityRepository(DriveFile) @EntityRepository(DriveFile)
export class DriveFileRepository extends Repository<DriveFile> { export class DriveFileRepository extends Repository<DriveFile> {
@ -82,7 +85,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
self?: boolean, self?: boolean,
withUser?: boolean, withUser?: boolean,
} }
) { ): Promise<PackedDriveFile> {
const opts = Object.assign({ const opts = Object.assign({
detail: false, detail: false,
self: false self: false
@ -90,9 +93,9 @@ export class DriveFileRepository extends Repository<DriveFile> {
const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: file.id, id: file.id,
createdAt: file.createdAt, createdAt: file.createdAt.toISOString(),
name: file.name, name: file.name,
type: file.type, type: file.type,
md5: file.md5, md5: file.md5,
@ -109,3 +112,66 @@ export class DriveFileRepository extends Repository<DriveFile> {
}); });
} }
} }
export const packedDriveFileSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this Drive file.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the Drive file was created on Misskey.'
},
name: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The file name with extension.',
example: 'lenna.jpg'
},
type: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The MIME type of this Drive file.',
example: 'image/jpeg'
},
md5: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'md5',
description: 'The MD5 hash of this Drive file.',
example: '15eca7fba0480996e2245f5185bf39f2'
},
size: {
type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The size of this Drive file. (bytes)',
example: 51469
},
url: {
type: types.string,
optional: bool.false, nullable: bool.true,
format: 'url',
description: 'The URL of this Drive file.',
},
folderId: {
type: types.string,
optional: bool.false, nullable: bool.true,
format: 'id',
description: 'The parent folder ID of this Drive file.',
example: 'xxxxxxxxxx',
},
isSensitive: {
type: types.boolean,
optional: bool.false, nullable: bool.false,
description: 'Whether this Drive file is sensitive.',
},
},
};

View file

@ -1,8 +1,11 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { DriveFolders, DriveFiles } from '..'; import { DriveFolders, DriveFiles } from '..';
import rap from '@prezzemolo/rap';
import { DriveFolder } from '../entities/drive-folder'; import { DriveFolder } from '../entities/drive-folder';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { SchemaType, types, bool } from '../../misc/schema';
export type PackedDriveFolder = SchemaType<typeof packedDriveFolderSchema>;
@EntityRepository(DriveFolder) @EntityRepository(DriveFolder)
export class DriveFolderRepository extends Repository<DriveFolder> { export class DriveFolderRepository extends Repository<DriveFolder> {
@ -18,16 +21,16 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
options?: { options?: {
detail: boolean detail: boolean
} }
): Promise<Record<string, any>> { ): Promise<PackedDriveFolder> {
const opts = Object.assign({ const opts = Object.assign({
detail: false detail: false
}, options); }, options);
const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: folder.id, id: folder.id,
createdAt: folder.createdAt, createdAt: folder.createdAt.toISOString(),
name: folder.name, name: folder.name,
parentId: folder.parentId, parentId: folder.parentId,
@ -48,3 +51,50 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
}); });
} }
} }
export const packedDriveFolderSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this Drive folder.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the Drive folder was created.'
},
name: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The folder name.',
},
foldersCount: {
type: types.number,
optional: bool.true, nullable: bool.false,
description: 'The count of child folders.',
},
filesCount: {
type: types.number,
optional: bool.true, nullable: bool.false,
description: 'The count of child files.',
},
parentId: {
type: types.string,
optional: bool.false, nullable: bool.true,
format: 'id',
description: 'The parent folder ID of this folder.',
example: 'xxxxxxxxxx',
},
parent: {
type: types.object,
optional: bool.true, nullable: bool.true,
ref: 'DriveFolder'
},
},
};

View file

@ -1,8 +1,9 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Users } from '..'; import { Users } from '..';
import rap from '@prezzemolo/rap';
import { Following } from '../entities/following'; import { Following } from '../entities/following';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { SchemaType, types, bool } from '../../misc/schema';
type LocalFollowerFollowing = Following & { type LocalFollowerFollowing = Following & {
followerHost: null; followerHost: null;
@ -28,6 +29,8 @@ type RemoteFolloweeFollowing = Following & {
followeeSharedInbox: string; followeeSharedInbox: string;
}; };
export type PackedFollowing = SchemaType<typeof packedFollowingSchema>;
@EntityRepository(Following) @EntityRepository(Following)
export class FollowingRepository extends Repository<Following> { export class FollowingRepository extends Repository<Following> {
public isLocalFollower(following: Following): following is LocalFollowerFollowing { public isLocalFollower(following: Following): following is LocalFollowerFollowing {
@ -64,22 +67,64 @@ export class FollowingRepository extends Repository<Following> {
populateFollowee?: boolean; populateFollowee?: boolean;
populateFollower?: boolean; populateFollower?: boolean;
} }
) { ): Promise<PackedFollowing> {
const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
if (opts == null) opts = {}; if (opts == null) opts = {};
return await rap({ return await awaitAll({
id: following.id, id: following.id,
createdAt: following.createdAt, createdAt: following.createdAt.toISOString(),
followeeId: following.followeeId, followeeId: following.followeeId,
followerId: following.followerId, followerId: following.followerId,
followee: opts.populateFollowee ? Users.pack(following.followee || following.followeeId, me, { followee: opts.populateFollowee ? Users.pack(following.followee || following.followeeId, me, {
detail: true detail: true
}) : null, }) : undefined,
follower: opts.populateFollower ? Users.pack(following.follower || following.followerId, me, { follower: opts.populateFollower ? Users.pack(following.follower || following.followerId, me, {
detail: true detail: true
}) : null, }) : undefined,
}); });
} }
} }
export const packedFollowingSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this following.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the following was created.'
},
followeeId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
followee: {
type: types.object,
optional: bool.true, nullable: bool.false,
ref: 'User',
description: 'The followee.'
},
followerId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
follower: {
type: types.object,
optional: bool.true, nullable: bool.false,
ref: 'User',
description: 'The follower.'
},
}
};

View file

@ -1,8 +1,8 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import rap from '@prezzemolo/rap';
import { ReversiMatching } from '../../../entities/games/reversi/matching'; import { ReversiMatching } from '../../../entities/games/reversi/matching';
import { Users } from '../../..'; import { Users } from '../../..';
import { ensure } from '../../../../prelude/ensure'; import { ensure } from '../../../../prelude/ensure';
import { awaitAll } from '../../../../prelude/await-all';
@EntityRepository(ReversiMatching) @EntityRepository(ReversiMatching)
export class ReversiMatchingRepository extends Repository<ReversiMatching> { export class ReversiMatchingRepository extends Repository<ReversiMatching> {
@ -12,7 +12,7 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> {
) { ) {
const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: matching.id, id: matching.id,
createdAt: matching.createdAt, createdAt: matching.createdAt,
parentId: matching.parentId, parentId: matching.parentId,

View file

@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
import { MessagingMessage } from '../entities/messaging-message'; import { MessagingMessage } from '../entities/messaging-message';
import { Users, DriveFiles } from '..'; import { Users, DriveFiles } from '..';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>;
@EntityRepository(MessagingMessage) @EntityRepository(MessagingMessage)
export class MessagingMessageRepository extends Repository<MessagingMessage> { export class MessagingMessageRepository extends Repository<MessagingMessage> {
@ -15,7 +18,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
options?: { options?: {
populateRecipient: boolean populateRecipient: boolean
} }
) { ): Promise<PackedMessagingMessage> {
const opts = options || { const opts = options || {
populateRecipient: true populateRecipient: true
}; };
@ -24,15 +27,73 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
return { return {
id: message.id, id: message.id,
createdAt: message.createdAt, createdAt: message.createdAt.toISOString(),
text: message.text, text: message.text,
userId: message.userId, userId: message.userId,
user: await Users.pack(message.user || message.userId, me), user: await Users.pack(message.user || message.userId, me),
recipientId: message.recipientId, recipientId: message.recipientId,
recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : null, recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined,
fileId: message.fileId, fileId: message.fileId,
file: message.fileId ? await DriveFiles.pack(message.fileId) : null, file: message.fileId ? await DriveFiles.pack(message.fileId) : null,
isRead: message.isRead isRead: message.isRead
}; };
} }
} }
export const packedMessagingMessageSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this MessagingMessage.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the MessagingMessage was created.'
},
userId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
user: {
type: types.object,
ref: 'User',
optional: bool.true, nullable: bool.false,
},
text: {
type: types.string,
optional: bool.false, nullable: bool.true,
},
fileId: {
type: types.string,
optional: bool.true, nullable: bool.true,
format: 'id',
},
file: {
type: types.object,
optional: bool.true, nullable: bool.true,
ref: 'DriveFile',
},
recipientId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
recipient: {
type: types.object,
optional: bool.true, nullable: bool.false,
ref: 'User'
},
isRead: {
type: types.boolean,
optional: bool.true, nullable: bool.false,
},
},
};

View file

@ -1,8 +1,11 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Users } from '..'; import { Users } from '..';
import rap from '@prezzemolo/rap';
import { Muting } from '../entities/muting'; import { Muting } from '../entities/muting';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedMuting = SchemaType<typeof packedMutingSchema>;
@EntityRepository(Muting) @EntityRepository(Muting)
export class MutingRepository extends Repository<Muting> { export class MutingRepository extends Repository<Muting> {
@ -16,14 +19,47 @@ export class MutingRepository extends Repository<Muting> {
public async pack( public async pack(
src: Muting['id'] | Muting, src: Muting['id'] | Muting,
me?: any me?: any
) { ): Promise<PackedMuting> {
const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: muting.id, id: muting.id,
createdAt: muting.createdAt.toISOString(),
muteeId: muting.muteeId,
mutee: Users.pack(muting.muteeId, me, { mutee: Users.pack(muting.muteeId, me, {
detail: true detail: true
}) })
}); });
} }
} }
export const packedMutingSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this muting.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the muting was created.'
},
muteeId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
mutee: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
description: 'The mutee.'
},
}
};

View file

@ -2,18 +2,54 @@ import { EntityRepository, Repository } from 'typeorm';
import { NoteReaction } from '../entities/note-reaction'; import { NoteReaction } from '../entities/note-reaction';
import { Users } from '..'; import { Users } from '..';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedNoteReaction = SchemaType<typeof packedNoteReactionSchema>;
@EntityRepository(NoteReaction) @EntityRepository(NoteReaction)
export class NoteReactionRepository extends Repository<NoteReaction> { export class NoteReactionRepository extends Repository<NoteReaction> {
public async pack( public async pack(
src: NoteReaction['id'] | NoteReaction, src: NoteReaction['id'] | NoteReaction,
me?: any me?: any
) { ): Promise<PackedNoteReaction> {
const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return { return {
id: reaction.id, id: reaction.id,
createdAt: reaction.createdAt.toISOString(),
user: await Users.pack(reaction.userId, me), user: await Users.pack(reaction.userId, me),
type: reaction.reaction,
}; };
} }
} }
export const packedNoteReactionSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this reaction.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the reaction was created.'
},
user: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
description: 'User who performed this reaction.'
},
type: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The reaction type.'
},
},
};

View file

@ -4,8 +4,11 @@ import { User } from '../entities/user';
import { unique, concat } from '../../prelude/array'; import { unique, concat } from '../../prelude/array';
import { nyaize } from '../../misc/nyaize'; import { nyaize } from '../../misc/nyaize';
import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..'; import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
import rap from '@prezzemolo/rap';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { SchemaType, types, bool } from '../../misc/schema';
import { awaitAll } from '../../prelude/await-all';
export type PackedNote = SchemaType<typeof packedNoteSchema>;
@EntityRepository(Note) @EntityRepository(Note)
export class NoteRepository extends Repository<Note> { export class NoteRepository extends Repository<Note> {
@ -13,18 +16,18 @@ export class NoteRepository extends Repository<Note> {
return x.trim().length <= 100; return x.trim().length <= 100;
} }
private async hideNote(packedNote: any, meId: User['id'] | null) { private async hideNote(packedNote: PackedNote, meId: User['id'] | null) {
let hide = false; let hide = false;
// visibility が specified かつ自分が指定されていなかったら非表示 // visibility が specified かつ自分が指定されていなかったら非表示
if (packedNote.visibility == 'specified') { if (packedNote.visibility === 'specified') {
if (meId == null) { if (meId == null) {
hide = true; hide = true;
} else if (meId === packedNote.userId) { } else if (meId === packedNote.userId) {
hide = false; hide = false;
} else { } else {
// 指定されているかどうか // 指定されているかどうか
const specified = packedNote.visibleUserIds.some((id: any) => meId === id); const specified = packedNote.visibleUserIds!.some((id: any) => meId === id);
if (specified) { if (specified) {
hide = false; hide = false;
@ -40,10 +43,10 @@ export class NoteRepository extends Repository<Note> {
hide = true; hide = true;
} else if (meId === packedNote.userId) { } else if (meId === packedNote.userId) {
hide = false; hide = false;
} else if (packedNote.reply && (meId === packedNote.reply.userId)) { } else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) {
// 自分の投稿に対するリプライ // 自分の投稿に対するリプライ
hide = false; hide = false;
} else if (packedNote.mentions && packedNote.mentions.some((id: any) => meId === id)) { } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
// 自分へのメンション // 自分へのメンション
hide = false; hide = false;
} else { } else {
@ -62,14 +65,13 @@ export class NoteRepository extends Repository<Note> {
} }
if (hide) { if (hide) {
packedNote.visibleUserIds = null; packedNote.visibleUserIds = undefined;
packedNote.fileIds = []; packedNote.fileIds = [];
packedNote.files = []; packedNote.files = [];
packedNote.text = null; packedNote.text = null;
packedNote.poll = null; packedNote.poll = undefined;
packedNote.cw = null; packedNote.cw = null;
packedNote.tags = []; packedNote.geo = undefined;
packedNote.geo = null;
packedNote.isHidden = true; packedNote.isHidden = true;
} }
} }
@ -92,7 +94,7 @@ export class NoteRepository extends Repository<Note> {
detail?: boolean; detail?: boolean;
skipHide?: boolean; skipHide?: boolean;
} }
): Promise<Record<string, any>> { ): Promise<PackedNote> {
const opts = Object.assign({ const opts = Object.assign({
detail: true, detail: true,
skipHide: false skipHide: false
@ -159,9 +161,9 @@ export class NoteRepository extends Repository<Note> {
const reactionEmojis = unique(concat([note.emojis, Object.keys(note.reactions)])); const reactionEmojis = unique(concat([note.emojis, Object.keys(note.reactions)]));
const packed = await rap({ const packed = await awaitAll({
id: note.id, id: note.id,
createdAt: note.createdAt, createdAt: note.createdAt.toISOString(),
app: note.appId ? Apps.pack(note.appId) : undefined, app: note.appId ? Apps.pack(note.appId) : undefined,
userId: note.userId, userId: note.userId,
user: Users.pack(note.user || note.userId, meId), user: Users.pack(note.user || note.userId, meId),
@ -213,3 +215,127 @@ export class NoteRepository extends Repository<Note> {
return packed; return packed;
} }
} }
export const packedNoteSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this Note.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the Note was created on Misskey.'
},
text: {
type: types.string,
optional: bool.false, nullable: bool.true,
},
cw: {
type: types.string,
optional: bool.true, nullable: bool.true,
},
userId: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
},
user: {
type: types.object,
ref: 'User',
optional: bool.false, nullable: bool.false,
},
replyId: {
type: types.string,
optional: bool.true, nullable: bool.true,
format: 'id',
example: 'xxxxxxxxxx',
},
renoteId: {
type: types.string,
optional: bool.true, nullable: bool.true,
format: 'id',
example: 'xxxxxxxxxx',
},
reply: {
type: types.object,
optional: bool.true, nullable: bool.true,
ref: 'Note'
},
renote: {
type: types.object,
optional: bool.true, nullable: bool.true,
ref: 'Note'
},
viaMobile: {
type: types.boolean,
optional: bool.true, nullable: bool.false,
},
isHidden: {
type: types.boolean,
optional: bool.true, nullable: bool.false,
},
visibility: {
type: types.string,
optional: bool.false, nullable: bool.false,
},
mentions: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id'
}
},
visibleUserIds: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id'
}
},
fileIds: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id'
}
},
files: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFile'
}
},
tags: {
type: types.array,
optional: bool.true, nullable: bool.false,
items: {
type: types.string,
optional: bool.false, nullable: bool.false,
}
},
poll: {
type: types.object,
optional: bool.true, nullable: bool.true,
},
geo: {
type: types.object,
optional: bool.true, nullable: bool.true,
},
},
};

View file

@ -1,8 +1,11 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { Users, Notes } from '..'; import { Users, Notes } from '..';
import rap from '@prezzemolo/rap';
import { Notification } from '../entities/notification'; import { Notification } from '../entities/notification';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { awaitAll } from '../../prelude/await-all';
import { types, bool, SchemaType } from '../../misc/schema';
export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
@EntityRepository(Notification) @EntityRepository(Notification)
export class NotificationRepository extends Repository<Notification> { export class NotificationRepository extends Repository<Notification> {
@ -14,12 +17,12 @@ export class NotificationRepository extends Repository<Notification> {
public async pack( public async pack(
src: Notification['id'] | Notification, src: Notification['id'] | Notification,
) { ): Promise<PackedNotification> {
const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
return await rap({ return await awaitAll({
id: notification.id, id: notification.id,
createdAt: notification.createdAt, createdAt: notification.createdAt.toISOString(),
type: notification.type, type: notification.type,
userId: notification.notifierId, userId: notification.notifierId,
user: Users.pack(notification.notifier || notification.notifierId), user: Users.pack(notification.notifier || notification.notifierId),
@ -46,3 +49,39 @@ export class NotificationRepository extends Repository<Notification> {
}); });
} }
} }
export const packedNotificationSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this notification.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the notification was created.'
},
type: {
type: types.string,
optional: bool.false, nullable: bool.false,
enum: ['follow', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'],
description: 'The type of the notification.'
},
userId: {
type: types.string,
optional: bool.true, nullable: bool.true,
format: 'id',
},
user: {
type: types.object,
ref: 'User',
optional: bool.true, nullable: bool.true,
},
}
};

View file

@ -2,12 +2,15 @@ import { EntityRepository, Repository } from 'typeorm';
import { UserList } from '../entities/user-list'; import { UserList } from '../entities/user-list';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import { UserListJoinings } from '..'; import { UserListJoinings } from '..';
import { bool, types, SchemaType } from '../../misc/schema';
export type PackedUserList = SchemaType<typeof packedUserListSchema>;
@EntityRepository(UserList) @EntityRepository(UserList)
export class UserListRepository extends Repository<UserList> { export class UserListRepository extends Repository<UserList> {
public async pack( public async pack(
src: UserList['id'] | UserList, src: UserList['id'] | UserList,
) { ): Promise<PackedUserList> {
const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
const users = await UserListJoinings.find({ const users = await UserListJoinings.find({
@ -16,8 +19,43 @@ export class UserListRepository extends Repository<UserList> {
return { return {
id: userList.id, id: userList.id,
createdAt: userList.createdAt.toISOString(),
name: userList.name, name: userList.name,
userIds: users.map(x => x.userId) userIds: users.map(x => x.userId)
}; };
} }
} }
export const packedUserListSchema = {
type: types.object,
optional: bool.false, nullable: bool.false,
properties: {
id: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'id',
description: 'The unique identifier for this UserList.',
example: 'xxxxxxxxxx',
},
createdAt: {
type: types.string,
optional: bool.false, nullable: bool.false,
format: 'date-time',
description: 'The date that the UserList was created.'
},
name: {
type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The name of the UserList.'
},
userIds: {
type: types.array,
nullable: bool.false, optional: bool.true,
items: {
type: types.string,
nullable: bool.false, optional: bool.false,
format: 'id',
}
},
},
};

View file

@ -1,9 +1,12 @@
import { EntityRepository, Repository, In } from 'typeorm'; import { EntityRepository, Repository, In } from 'typeorm';
import { User, ILocalUser, IRemoteUser } from '../entities/user'; import { User, ILocalUser, IRemoteUser } from '../entities/user';
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..'; import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..';
import rap from '@prezzemolo/rap';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
import config from '../../config'; import config from '../../config';
import { SchemaType, bool, types } from '../../misc/schema';
import { awaitAll } from '../../prelude/await-all';
export type PackedUser = SchemaType<typeof packedUserSchema>;
@EntityRepository(User) @EntityRepository(User)
export class UserRepository extends Repository<User> { export class UserRepository extends Repository<User> {
@ -71,7 +74,7 @@ export class UserRepository extends Repository<User> {
includeSecrets?: boolean, includeSecrets?: boolean,
includeHasUnreadNotes?: boolean includeHasUnreadNotes?: boolean
} }
): Promise<Record<string, any>> { ): Promise<PackedUser> {
const opts = Object.assign({ const opts = Object.assign({
detail: false, detail: false,
includeSecrets: false includeSecrets: false
@ -86,7 +89,7 @@ export class UserRepository extends Repository<User> {
const falsy = opts.detail ? false : undefined; const falsy = opts.detail ? false : undefined;
return await rap({ const packed = {
id: user.id, id: user.id,
name: user.name, name: user.name,
username: user.username, username: user.username,
@ -120,8 +123,8 @@ export class UserRepository extends Repository<User> {
...(opts.detail ? { ...(opts.detail ? {
url: profile!.url, url: profile!.url,
createdAt: user.createdAt, createdAt: user.createdAt.toISOString(),
updatedAt: user.updatedAt, updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
bannerUrl: user.bannerUrl, bannerUrl: user.bannerUrl,
bannerColor: user.bannerColor, bannerColor: user.bannerColor,
isLocked: user.isLocked, isLocked: user.isLocked,
@ -179,7 +182,9 @@ export class UserRepository extends Repository<User> {
isBlocked: relation.isBlocked, isBlocked: relation.isBlocked,
isMuted: relation.isMuted, isMuted: relation.isMuted,
} : {}) } : {})
}); };
return await awaitAll(packed);
} }
public isLocalUser(user: User): user is ILocalUser { public isLocalUser(user: User): user is ILocalUser {
@ -216,3 +221,156 @@ export class UserRepository extends Repository<User> {
} }
//#endregion //#endregion
} }
export const packedUserSchema = {
type: types.object,
nullable: bool.false, optional: bool.false,
properties: {
id: {
type: types.string,
nullable: bool.false, optional: bool.false,
format: 'id',
description: 'The unique identifier for this User.',
example: 'xxxxxxxxxx',
},
username: {
type: types.string,
nullable: bool.false, optional: bool.false,
description: 'The screen name, handle, or alias that this user identifies themselves with.',
example: 'ai'
},
name: {
type: types.string,
nullable: bool.true, optional: bool.false,
description: 'The name of the user, as theyve defined it.',
example: '藍'
},
url: {
type: types.string,
format: 'url',
nullable: bool.true, optional: bool.true,
},
avatarUrl: {
type: types.string,
format: 'url',
nullable: bool.true, optional: bool.false,
},
avatarColor: {
type: types.any,
nullable: bool.true, optional: bool.false,
},
bannerUrl: {
type: types.string,
format: 'url',
nullable: bool.true, optional: bool.true,
},
bannerColor: {
type: types.any,
nullable: bool.true, optional: bool.true,
},
emojis: {
type: types.any,
nullable: bool.true, optional: bool.false,
},
host: {
type: types.string,
nullable: bool.true, optional: bool.false,
example: 'misskey.example.com'
},
description: {
type: types.string,
nullable: bool.true, optional: bool.true,
description: 'The user-defined UTF-8 string describing their account.',
example: 'Hi masters, I am Ai!'
},
birthday: {
type: types.string,
nullable: bool.true, optional: bool.true,
example: '2018-03-12'
},
createdAt: {
type: types.string,
nullable: bool.false, optional: bool.true,
format: 'date-time',
description: 'The date that the user account was created on Misskey.'
},
updatedAt: {
type: types.string,
nullable: bool.true, optional: bool.true,
format: 'date-time',
},
location: {
type: types.string,
nullable: bool.true, optional: bool.true,
},
followersCount: {
type: types.number,
nullable: bool.false, optional: bool.true,
description: 'The number of followers this account currently has.'
},
followingCount: {
type: types.number,
nullable: bool.false, optional: bool.true,
description: 'The number of users this account is following.'
},
notesCount: {
type: types.number,
nullable: bool.false, optional: bool.true,
description: 'The number of Notes (including renotes) issued by the user.'
},
isBot: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
description: 'Whether this account is a bot.'
},
pinnedNoteIds: {
type: types.array,
nullable: bool.false, optional: bool.true,
items: {
type: types.string,
nullable: bool.false, optional: bool.false,
format: 'id',
}
},
pinnedNotes: {
type: types.array,
nullable: bool.false, optional: bool.true,
items: {
type: types.object,
nullable: bool.false, optional: bool.false,
ref: 'Note'
}
},
isCat: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
description: 'Whether this account is a cat.'
},
isAdmin: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
description: 'Whether this account is the admin.'
},
isModerator: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
description: 'Whether this account is a moderator.'
},
isVerified: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
},
isLocked: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
},
hasUnreadSpecifiedNotes: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
},
hasUnreadMentions: {
type: types.boolean,
nullable: bool.false, optional: bool.true,
},
},
};

22
src/prelude/await-all.ts Normal file
View file

@ -0,0 +1,22 @@
type Await<T> = T extends Promise<infer U> ? U : T;
type AwaitAll<T> = {
[P in keyof T]: Await<T[P]>;
};
export async function awaitAll<T>(obj: T): Promise<AwaitAll<T>> {
const target = {} as any;
const keys = Object.keys(obj);
const rawValues = Object.values(obj);
const retValues = ((values: any[]): any[] =>
values.map(value => {
if (!value || !value.constructor || value.constructor.name !== 'Object') return value;
return awaitAll(value);
})
)(rawValues);
const values = await Promise.all(retValues);
for (let i = 0; i < values.length; i++) {
target[keys[i]] = values[i];
}
return target;
}

View file

@ -3,6 +3,7 @@ import { ILocalUser } from '../../models/entities/user';
import { IEndpointMeta } from './endpoints'; import { IEndpointMeta } from './endpoints';
import { ApiError } from './error'; import { ApiError } from './error';
import { App } from '../../models/entities/app'; import { App } from '../../models/entities/app';
import { SchemaType } from '../../misc/schema';
type Params<T extends IEndpointMeta> = { type Params<T extends IEndpointMeta> = {
[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function [P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
@ -12,7 +13,11 @@ type Params<T extends IEndpointMeta> = {
export type Response = Record<string, any> | void; export type Response = Record<string, any> | void;
export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<Response>): (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> { type executor<T extends IEndpointMeta> =
(params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>)
: (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> {
return (params: any, user: ILocalUser, app: App, file?: any) => { return (params: any, user: ILocalUser, app: App, file?: any) => {
function cleanup() { function cleanup() {
fs.unlink(file.path, () => {}); fs.unlink(file.path, () => {});

View file

@ -4,6 +4,7 @@ import define from '../../define';
import { Apps } from '../../../../models'; import { Apps } from '../../../../models';
import { genId } from '../../../../misc/gen-id'; import { genId } from '../../../../misc/gen-id';
import { unique } from '../../../../prelude/array'; import { unique } from '../../../../prelude/array';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
tags: ['app'], tags: ['app'],
@ -52,27 +53,10 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
properties: { optional: bool.false, nullable: bool.false,
id: { ref: 'App',
type: 'string', },
description: 'アプリケーションのID'
},
name: {
type: 'string',
description: 'アプリケーションの名前'
},
callbackUrl: {
type: 'string',
nullable: true,
description: 'コールバックするURL'
},
secret: {
type: 'string',
description: 'アプリケーションのシークレットキー'
}
}
}
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error'; import { ApiError } from '../../error';
import { Apps } from '../../../../models'; import { Apps } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
tags: ['app'], tags: ['app'],
@ -13,6 +14,12 @@ export const meta = {
}, },
}, },
res: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'App',
},
errors: { errors: {
noSuchApp: { noSuchApp: {
message: 'No such app.', message: 'No such app.',

View file

@ -5,6 +5,7 @@ import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { Apps, AuthSessions } from '../../../../../models'; import { Apps, AuthSessions } from '../../../../../models';
import { genId } from '../../../../../misc/gen-id'; import { genId } from '../../../../../misc/gen-id';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
tags: ['auth'], tags: ['auth'],
@ -27,14 +28,18 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
token: { token: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'セッションのトークン' description: 'セッションのトークン'
}, },
url: { url: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
format: 'url',
description: 'セッションのURL' description: 'セッションのURL'
}, },
} }

View file

@ -3,6 +3,7 @@ import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models'; import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
import { ensure } from '../../../../../prelude/ensure'; import { ensure } from '../../../../../prelude/ensure';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
tags: ['auth'], tags: ['auth'],
@ -28,15 +29,19 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
accessToken: { accessToken: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'ユーザーのアクセストークン', description: 'ユーザーのアクセストークン',
}, },
user: { user: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
description: '認証したユーザー' description: '認証したユーザー'
}, },
} }

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { Blockings } from '../../../../models'; import { Blockings } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -32,9 +33,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Blocking', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Blocking',
} }
}, },
}; };

View file

@ -1,6 +1,7 @@
import define from '../define'; import define from '../define';
import fetchMeta from '../../../misc/fetch-meta'; import fetchMeta from '../../../misc/fetch-meta';
import { DriveFiles } from '../../../models'; import { DriveFiles } from '../../../models';
import { types, bool } from '../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -15,13 +16,16 @@ export const meta = {
kind: 'read:drive', kind: 'read:drive',
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
capacity: { capacity: {
type: 'number' type: types.number,
optional: bool.false, nullable: bool.false,
}, },
usage: { usage: {
type: 'number' type: types.number,
optional: bool.false, nullable: bool.false,
} }
} }
} }

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { DriveFiles } from '../../../../models'; import { DriveFiles } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -41,10 +42,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'DriveFile', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}
}, },
}; };

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { DriveFiles } from '../../../../../models'; import { DriveFiles } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -29,10 +30,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -1,6 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import define from '../../../define'; import define from '../../../define';
import { DriveFiles } from '../../../../../models'; import { DriveFiles } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -24,7 +25,13 @@ export const meta = {
}, },
res: { res: {
type: 'DriveFile', type: types.array,
optional: bool.false, nullable: bool.false,
items: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}
}, },
}; };

View file

@ -6,6 +6,7 @@ import define from '../../../define';
import { apiLogger } from '../../../logger'; import { apiLogger } from '../../../logger';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { DriveFiles } from '../../../../../models'; import { DriveFiles } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -56,7 +57,9 @@ export const meta = {
}, },
res: { res: {
type: 'DriveFile', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}, },
errors: { errors: {
@ -87,7 +90,7 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
try { try {
// Create file // Create file
const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive); const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
return DriveFiles.pack(driveFile, { self: true }); return await DriveFiles.pack(driveFile, { self: true });
} catch (e) { } catch (e) {
apiLogger.error(e); apiLogger.error(e);
throw new ApiError(); throw new ApiError();

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import { ID } from '../../../../../misc/cafy-id'; import { ID } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import { DriveFiles } from '../../../../../models'; import { DriveFiles } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -22,7 +23,17 @@ export const meta = {
'ja-JP': 'フォルダID' 'ja-JP': 'フォルダID'
} }
}, },
} },
res: {
type: types.array,
optional: bool.false, nullable: bool.false,
items: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}
},
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {

View file

@ -4,6 +4,7 @@ import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { DriveFile } from '../../../../../models/entities/drive-file'; import { DriveFile } from '../../../../../models/entities/drive-file';
import { DriveFiles } from '../../../../../models'; import { DriveFiles } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -38,7 +39,9 @@ export const meta = {
}, },
res: { res: {
type: 'DriveFile', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}, },
errors: { errors: {

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { DriveFolders } from '../../../../models'; import { DriveFolders } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -37,10 +38,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'DriveFolder', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'DriveFolder',
}
}, },
}; };

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import { ID } from '../../../../../misc/cafy-id'; import { ID } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import { DriveFolders } from '../../../../../models'; import { DriveFolders } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
tags: ['drive'], tags: ['drive'],
@ -25,10 +26,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'DriveFolder', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'DriveFolder',
}
}, },
}; };

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { DriveFolders } from '../../../../../models'; import { DriveFolders } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -29,7 +30,9 @@ export const meta = {
}, },
res: { res: {
type: 'DriveFolder', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'DriveFolder',
}, },
errors: { errors: {

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { DriveFiles } from '../../../../models'; import { DriveFiles } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
tags: ['drive'], tags: ['drive'],
@ -31,10 +32,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'DriveFile', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'DriveFile',
}
}, },
}; };

View file

@ -1,6 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Hashtags } from '../../../../models'; import { Hashtags } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
tags: ['hashtags'], tags: ['hashtags'],
@ -47,9 +48,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Hashtag' type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Hashtag',
} }
}, },
}; };

View file

@ -1,6 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Hashtags } from '../../../../models'; import { Hashtags } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -37,9 +38,11 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'string' type: types.string,
optional: bool.false, nullable: bool.false,
} }
}, },
}; };

View file

@ -1,6 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Users } from '../../../../models'; import { Users } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
requireCredential: false, requireCredential: false,
@ -47,9 +48,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'User' type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
} }
}, },
}; };

View file

@ -1,5 +1,6 @@
import define from '../define'; import define from '../define';
import { Users } from '../../../models'; import { Users } from '../../../models';
import { types, bool } from '../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -15,8 +16,10 @@ export const meta = {
params: {}, params: {},
res: { res: {
type: 'User', type: types.object,
} optional: bool.false, nullable: bool.false,
ref: 'User',
},
}; };
export default define(meta, async (ps, user, app) => { export default define(meta, async (ps, user, app) => {

View file

@ -4,6 +4,7 @@ import { readNotification } from '../../common/read-notification';
import define from '../../define'; import define from '../../define';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { Notifications, Followings, Mutings } from '../../../../models'; import { Notifications, Followings, Mutings } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -53,10 +54,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Notification', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Notification',
}
}, },
}; };

View file

@ -3,6 +3,7 @@ import define from '../../define';
import { MessagingMessage } from '../../../../models/entities/messaging-message'; import { MessagingMessage } from '../../../../models/entities/messaging-message';
import { MessagingMessages, Mutings } from '../../../../models'; import { MessagingMessages, Mutings } from '../../../../models';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -24,10 +25,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'MessagingMessage', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'MessagingMessage',
}
}, },
}; };

View file

@ -6,6 +6,7 @@ import { ApiError } from '../../error';
import { getUser } from '../../common/getters'; import { getUser } from '../../common/getters';
import { MessagingMessages } from '../../../../models'; import { MessagingMessages } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -48,10 +49,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'MessagingMessage', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'MessagingMessage',
}
}, },
errors: { errors: {

View file

@ -9,6 +9,7 @@ import { getUser } from '../../../common/getters';
import { MessagingMessages, DriveFiles, Mutings } from '../../../../../models'; import { MessagingMessages, DriveFiles, Mutings } from '../../../../../models';
import { MessagingMessage } from '../../../../../models/entities/messaging-message'; import { MessagingMessage } from '../../../../../models/entities/messaging-message';
import { genId } from '../../../../../misc/gen-id'; import { genId } from '../../../../../misc/gen-id';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -41,7 +42,9 @@ export const meta = {
}, },
res: { res: {
type: 'MessagingMessage', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'MessagingMessage',
}, },
errors: { errors: {

View file

@ -5,6 +5,7 @@ import define from '../define';
import fetchMeta from '../../../misc/fetch-meta'; import fetchMeta from '../../../misc/fetch-meta';
import * as pkg from '../../../../package.json'; import * as pkg from '../../../../package.json';
import { Emojis } from '../../../models'; import { Emojis } from '../../../models';
import { types, bool } from '../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -26,32 +27,40 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
version: { version: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The version of Misskey of this instance.', description: 'The version of Misskey of this instance.',
example: pkg.version example: pkg.version
}, },
name: { name: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The name of this instance.', description: 'The name of this instance.',
}, },
description: { description: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The description of this instance.', description: 'The description of this instance.',
}, },
announcements: { announcements: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
title: { title: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The title of the announcement.', description: 'The title of the announcement.',
}, },
text: { text: {
type: 'string', type: types.string,
optional: bool.false, nullable: bool.false,
description: 'The text of the announcement. (can be HTML)', description: 'The text of the announcement. (can be HTML)',
}, },
} }
@ -59,19 +68,23 @@ export const meta = {
description: 'The announcements of this instance.', description: 'The announcements of this instance.',
}, },
disableRegistration: { disableRegistration: {
type: 'boolean', type: types.boolean,
optional: bool.false, nullable: bool.false,
description: 'Whether disabled open registration.', description: 'Whether disabled open registration.',
}, },
disableLocalTimeline: { disableLocalTimeline: {
type: 'boolean', type: types.boolean,
optional: bool.false, nullable: bool.false,
description: 'Whether disabled LTL and STL.', description: 'Whether disabled LTL and STL.',
}, },
disableGlobalTimeline: { disableGlobalTimeline: {
type: 'boolean', type: types.boolean,
optional: bool.false, nullable: bool.false,
description: 'Whether disabled GTL.', description: 'Whether disabled GTL.',
}, },
enableEmojiReaction: { enableEmojiReaction: {
type: 'boolean', type: types.boolean,
optional: bool.false, nullable: bool.false,
description: 'Whether enabled emoji reaction.', description: 'Whether enabled emoji reaction.',
}, },
} }

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
import define from '../../define'; import define from '../../define';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { Mutings } from '../../../../models'; import { Mutings } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -32,9 +33,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Muting', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Muting',
} }
}, },
}; };

View file

@ -3,6 +3,7 @@ import { ID } from '../../../misc/cafy-id';
import define from '../define'; import define from '../define';
import { makePaginationQuery } from '../common/make-pagination-query'; import { makePaginationQuery } from '../common/make-pagination-query';
import { Notes } from '../../../models'; import { Notes } from '../../../models';
import { types, bool } from '../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -62,9 +63,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Note',
} }
}, },
}; };

View file

@ -6,6 +6,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -41,10 +42,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -5,6 +5,7 @@ import { ApiError } from '../../error';
import { getNote } from '../../common/getters'; import { getNote } from '../../common/getters';
import { Note } from '../../../../models/entities/note'; import { Note } from '../../../../models/entities/note';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -37,10 +38,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -10,6 +10,7 @@ import { User } from '../../../../models/entities/user';
import { Users, DriveFiles, Notes } from '../../../../models'; import { Users, DriveFiles, Notes } from '../../../../models';
import { DriveFile } from '../../../../models/entities/drive-file'; import { DriveFile } from '../../../../models/entities/drive-file';
import { Note } from '../../../../models/entities/note'; import { Note } from '../../../../models/entities/note';
import { types, bool } from '../../../../misc/schema';
let maxNoteTextLength = 1000; let maxNoteTextLength = 1000;
@ -174,10 +175,13 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
createdNote: { createdNote: {
type: 'Note', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Note',
description: '作成した投稿' description: '作成した投稿'
} }
} }

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -24,10 +25,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -7,6 +7,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { activeUsersChart } from '../../../../services/chart'; import { activeUsersChart } from '../../../../services/chart';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -46,10 +47,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -9,6 +9,7 @@ import { Brackets } from 'typeorm';
import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { activeUsersChart } from '../../../../services/chart'; import { activeUsersChart } from '../../../../services/chart';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -89,10 +90,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -9,6 +9,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query';
import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { activeUsersChart } from '../../../../services/chart'; import { activeUsersChart } from '../../../../services/chart';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -63,10 +64,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -43,10 +44,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -4,6 +4,7 @@ import define from '../../define';
import { getNote } from '../../common/getters'; import { getNote } from '../../common/getters';
import { ApiError } from '../../error'; import { ApiError } from '../../error';
import { NoteReactions } from '../../../../models'; import { NoteReactions } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -44,9 +45,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Reaction' type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'NoteReaction',
} }
}, },

View file

@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -42,10 +43,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -5,6 +5,7 @@ import { Notes } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -46,10 +47,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -6,6 +6,7 @@ import { Notes } from '../../../../models';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -81,10 +82,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -4,6 +4,7 @@ import define from '../../define';
import { ApiError } from '../../error'; import { ApiError } from '../../error';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { In } from 'typeorm'; import { In } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -32,10 +33,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -4,6 +4,7 @@ import define from '../../define';
import { getNote } from '../../common/getters'; import { getNote } from '../../common/getters';
import { ApiError } from '../../error'; import { ApiError } from '../../error';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -28,7 +29,9 @@ export const meta = {
}, },
res: { res: {
type: 'Note', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'Note',
}, },
errors: { errors: {

View file

@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { activeUsersChart } from '../../../../services/chart'; import { activeUsersChart } from '../../../../services/chart';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -88,10 +89,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
}; };

View file

@ -6,6 +6,7 @@ import { UserLists, UserListJoinings, Notes } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query';
import { activeUsersChart } from '../../../../services/chart'; import { activeUsersChart } from '../../../../services/chart';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -94,10 +95,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -1,6 +1,7 @@
import define from '../define'; import define from '../define';
import { Notes, Users } from '../../../models'; import { Notes, Users } from '../../../models';
import { federationChart, driveChart } from '../../../services/chart'; import { federationChart, driveChart } from '../../../services/chart';
import { bool, types } from '../../../misc/schema';
export const meta = { export const meta = {
requireCredential: false, requireCredential: false,
@ -15,26 +16,32 @@ export const meta = {
}, },
res: { res: {
type: 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
notesCount: { notesCount: {
type: 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The count of all (local/remote) notes of this instance.', description: 'The count of all (local/remote) notes of this instance.',
}, },
originalNotesCount: { originalNotesCount: {
type: 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The count of all local notes of this instance.', description: 'The count of all local notes of this instance.',
}, },
usersCount: { usersCount: {
type: 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The count of all (local/remote) accounts of this instance.', description: 'The count of all (local/remote) accounts of this instance.',
}, },
originalUsersCount: { originalUsersCount: {
type: 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The count of all local accounts of this instance.', description: 'The count of all local accounts of this instance.',
}, },
instances: { instances: {
type: 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'The count of federated instances.', description: 'The count of federated instances.',
}, },
} }
@ -42,7 +49,14 @@ export const meta = {
}; };
export default define(meta, async () => { export default define(meta, async () => {
const [notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote] = await Promise.all([ const [notesCount,
originalNotesCount,
usersCount,
originalUsersCount,
instances,
driveUsageLocal,
driveUsageRemote
] = await Promise.all([
Notes.count(), Notes.count(),
Notes.count({ userHost: null }), Notes.count({ userHost: null }),
Users.count(), Users.count(),
@ -53,6 +67,12 @@ export default define(meta, async () => {
]); ]);
return { return {
notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote notesCount,
originalNotesCount,
usersCount,
originalUsersCount,
instances,
driveUsageLocal,
driveUsageRemote
}; };
}); });

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../define'; import define from '../define';
import { Users } from '../../../models'; import { Users } from '../../../models';
import { generateMuteQueryForUsers } from '../common/generate-mute-query'; import { generateMuteQueryForUsers } from '../common/generate-mute-query';
import { types, bool } from '../../../misc/schema';
export const meta = { export const meta = {
tags: ['users'], tags: ['users'],
@ -53,9 +54,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
} }
}, },
}; };

View file

@ -5,6 +5,7 @@ import { ApiError } from '../../error';
import { Users, Followings } from '../../../../models'; import { Users, Followings } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { toPunyNullable } from '../../../../misc/convert-host'; import { toPunyNullable } from '../../../../misc/convert-host';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -48,10 +49,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Following', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Following',
}
}, },
errors: { errors: {

View file

@ -5,6 +5,7 @@ import { ApiError } from '../../error';
import { Users, Followings } from '../../../../models'; import { Users, Followings } from '../../../../models';
import { makePaginationQuery } from '../../common/make-pagination-query'; import { makePaginationQuery } from '../../common/make-pagination-query';
import { toPunyNullable } from '../../../../misc/convert-host'; import { toPunyNullable } from '../../../../misc/convert-host';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -48,10 +49,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Following', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Following',
}
}, },
errors: { errors: {

View file

@ -6,6 +6,7 @@ import { ApiError } from '../../error';
import { getUser } from '../../common/getters'; import { getUser } from '../../common/getters';
import { Not, In } from 'typeorm'; import { Not, In } from 'typeorm';
import { Notes, Users } from '../../../../models'; import { Notes, Users } from '../../../../models';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
tags: ['users'], tags: ['users'],
@ -28,9 +29,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
} }
}, },

View file

@ -3,6 +3,7 @@ import define from '../../../define';
import { UserLists } from '../../../../../models'; import { UserLists } from '../../../../../models';
import { genId } from '../../../../../misc/gen-id'; import { genId } from '../../../../../misc/gen-id';
import { UserList } from '../../../../../models/entities/user-list'; import { UserList } from '../../../../../models/entities/user-list';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -17,10 +18,16 @@ export const meta = {
kind: 'write:account', kind: 'write:account',
params: { params: {
title: { name: {
validator: $.str.range(1, 100) validator: $.str.range(1, 100)
} }
} },
res: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'UserList',
},
}; };
export default define(meta, async (ps, user) => { export default define(meta, async (ps, user) => {
@ -28,7 +35,7 @@ export default define(meta, async (ps, user) => {
id: genId(), id: genId(),
createdAt: new Date(), createdAt: new Date(),
userId: user.id, userId: user.id,
name: ps.title, name: ps.name,
} as UserList); } as UserList);
return await UserLists.pack(userList); return await UserLists.pack(userList);

View file

@ -1,5 +1,6 @@
import define from '../../../define'; import define from '../../../define';
import { UserLists } from '../../../../../models'; import { UserLists } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -13,10 +14,13 @@ export const meta = {
kind: 'read:account', kind: 'read:account',
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'UserList', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'UserList',
}
}, },
}; };

View file

@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error'; import { ApiError } from '../../../error';
import { UserLists } from '../../../../../models'; import { UserLists } from '../../../../../models';
import { types, bool } from '../../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -23,7 +24,9 @@ export const meta = {
}, },
res: { res: {
type: 'UserList' type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'UserList',
}, },
errors: { errors: {

View file

@ -8,6 +8,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { generateMuteQuery } from '../../common/generate-mute-query'; import { generateMuteQuery } from '../../common/generate-mute-query';
import { Brackets } from 'typeorm'; import { Brackets } from 'typeorm';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -119,10 +120,13 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'Note', type: types.object,
}, optional: bool.false, nullable: bool.false,
ref: 'Note',
}
}, },
errors: { errors: {

View file

@ -3,6 +3,7 @@ import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Users, Followings } from '../../../../models'; import { Users, Followings } from '../../../../models';
import { generateMuteQueryForUsers } from '../../common/generate-mute-query'; import { generateMuteQueryForUsers } from '../../common/generate-mute-query';
import { types, bool } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -28,9 +29,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
} }
}, },
}; };

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../../define'; import define from '../../define';
import { Users } from '../../../../models'; import { Users } from '../../../../models';
import { User } from '../../../../models/entities/user'; import { User } from '../../../../models/entities/user';
import { bool, types } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -54,9 +55,12 @@ export const meta = {
}, },
res: { res: {
type: 'array', type: types.array,
optional: bool.false, nullable: bool.false,
items: { items: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
} }
}, },
}; };

View file

@ -6,6 +6,7 @@ import { ApiError } from '../../error';
import { ID } from '../../../../misc/cafy-id'; import { ID } from '../../../../misc/cafy-id';
import { Users } from '../../../../models'; import { Users } from '../../../../models';
import { In } from 'typeorm'; import { In } from 'typeorm';
import { bool, types } from '../../../../misc/schema';
export const meta = { export const meta = {
desc: { desc: {
@ -42,7 +43,9 @@ export const meta = {
}, },
res: { res: {
type: 'User', type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
}, },
errors: { errors: {

View file

@ -44,20 +44,20 @@ export function getDescription(lang = 'ja-JP'): string {
const descriptions = { const descriptions = {
'ja-JP': `**Misskey is a decentralized microblogging platform.** 'ja-JP': `**Misskey is a decentralized microblogging platform.**
## Usage # Usage
**APIはすべてPOSTでリクエスト/JSON形式です** **APIはすべてPOSTでリクエスト/JSON形式です**
APIはリクエストに認証情報(APIキー)\`i\`というパラメータでAPIキーを添付してください。 APIはリクエストに認証情報(APIキー)\`i\`というパラメータでAPIキーを添付してください。
### APIキーを取得する ## APIキーを取得する
> APIAPIキーを取得できます > APIAPIキーを取得できます
> () > ()
### APIキーを取得する ## APIキーを取得する
APIキーをアプリケーションが扱うのはセキュリティ上のリスクがあるので APIキーをアプリケーションが扱うのはセキュリティ上のリスクがあるので
APIを利用する際にはAPIキーを発行します APIを利用する際にはAPIキーを発行します
#### 1. ### 1.
Webサービス()Misskeyに登録します Webサービス()Misskeyに登録します
[](/dev) > [](/dev) >
@ -65,7 +65,7 @@ export function getDescription(lang = 'ja-JP'): string {
> </p> > </p>
#### 2. ### 2.
使 使
[${config.apiUrl}/auth/session/generate](#operation/auth/session/generate) \`appSecret\`としてシークレットキーを含めたリクエストを送信します。 [${config.apiUrl}/auth/session/generate](#operation/auth/session/generate) \`appSecret\`としてシークレットキーを含めたリクエストを送信します。
@ -76,7 +76,7 @@ export function getDescription(lang = 'ja-JP'): string {
URLを設定していない場合(()) URLを設定していない場合(())
#### 3. ### 3.
[${config.apiUrl}/auth/session/userkey](#operation/auth/session/userkey) [${config.apiUrl}/auth/session/userkey](#operation/auth/session/userkey)
@ -88,7 +88,7 @@ APIキーの生成方法を擬似コードで表すと次のようになりま
const i = sha256(userToken + secretKey); const i = sha256(userToken + secretKey);
\`\`\` \`\`\`
## Permissions # Permissions
|Permisson (kind)|Description|Endpoints| |Permisson (kind)|Description|Endpoints|
|:--|:--|:--| |:--|:--|:--|
${permissionTable} ${permissionTable}

View file

@ -2,9 +2,8 @@ import endpoints from '../endpoints';
import { Context } from 'cafy'; import { Context } from 'cafy';
import config from '../../../config'; import config from '../../../config';
import { errors as basicErrors } from './errors'; import { errors as basicErrors } from './errors';
import { schemas } from './schemas'; import { schemas, convertSchemaToOpenApiSchema } from './schemas';
import { getDescription } from './description'; import { getDescription } from './description';
import { convertOpenApiSchema } from '../../../misc/schema';
export function genOpenapiSpec(lang = 'ja-JP') { export function genOpenapiSpec(lang = 'ja-JP') {
const spec = { const spec = {
@ -59,7 +58,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
deprecated: (param.data || {}).deprecated, deprecated: (param.data || {}).deprecated,
...((param.data || {}).default ? { default: (param.data || {}).default } : {}), ...((param.data || {}).default ? { default: (param.data || {}).default } : {}),
type: param.name === 'ID' ? 'string' : param.name.toLowerCase(), type: param.name === 'ID' ? 'string' : param.name.toLowerCase(),
...(param.name === 'ID' ? { example: 'xxxxxxxxxxxxxxxxxxxxxxxx', format: 'id' } : {}), ...(param.name === 'ID' ? { example: 'xxxxxxxxxx', format: 'id' } : {}),
nullable: param.isNullable, nullable: param.isNullable,
...(param.name === 'String' ? { ...(param.name === 'String' ? {
...((param as any).enum ? { enum: (param as any).enum } : {}), ...((param as any).enum ? { enum: (param as any).enum } : {}),
@ -106,7 +105,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : []; const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : [];
const resSchema = endpoint.meta.res ? convertOpenApiSchema(endpoint.meta.res) : {}; const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {};
let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n'; let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n';
desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`; desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;

View file

@ -1,3 +1,39 @@
import { packedUserSchema } from '../../../models/repositories/user';
import { Schema } from '../../../misc/schema';
import { packedNoteSchema } from '../../../models/repositories/note';
import { packedUserListSchema } from '../../../models/repositories/user-list';
import { packedAppSchema } from '../../../models/repositories/app';
import { packedMessagingMessageSchema } from '../../../models/repositories/messaging-message';
import { packedNotificationSchema } from '../../../models/repositories/notification';
import { packedDriveFileSchema } from '../../../models/repositories/drive-file';
import { packedDriveFolderSchema } from '../../../models/repositories/drive-folder';
import { packedFollowingSchema } from '../../../models/repositories/following';
import { packedMutingSchema } from '../../../models/repositories/muting';
import { packedBlockingSchema } from '../../../models/repositories/blocking';
import { packedNoteReactionSchema } from '../../../models/repositories/note-reaction';
export function convertSchemaToOpenApiSchema(schema: Schema) {
const res: any = schema;
if (schema.type === 'object' && schema.properties) {
res.required = Object.entries(schema.properties).filter(([k, v]) => v.optional !== true).map(([k]) => k);
for (const k of Object.keys(schema.properties)) {
res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
}
}
if (schema.type === 'array' && schema.items) {
res.items = convertSchemaToOpenApiSchema(schema.items);
}
if (schema.ref) {
res.$ref = `#/components/schemas/${schema.ref}`;
}
return res;
}
export const schemas = { export const schemas = {
Error: { Error: {
type: 'object', type: 'object',
@ -26,413 +62,18 @@ export const schemas = {
required: ['error'] required: ['error']
}, },
User: { User: convertSchemaToOpenApiSchema(packedUserSchema),
type: 'object', UserList: convertSchemaToOpenApiSchema(packedUserListSchema),
properties: { App: convertSchemaToOpenApiSchema(packedAppSchema),
id: { MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema),
type: 'string', Note: convertSchemaToOpenApiSchema(packedNoteSchema),
format: 'id', Notification: convertSchemaToOpenApiSchema(packedNotificationSchema),
description: 'The unique identifier for this User.', DriveFile: convertSchemaToOpenApiSchema(packedDriveFileSchema),
example: 'xxxxxxxxxxxxxxxxxxxxxxxx', DriveFolder: convertSchemaToOpenApiSchema(packedDriveFolderSchema),
}, Following: convertSchemaToOpenApiSchema(packedFollowingSchema),
username: { Muting: convertSchemaToOpenApiSchema(packedMutingSchema),
type: 'string', Blocking: convertSchemaToOpenApiSchema(packedBlockingSchema),
description: 'The screen name, handle, or alias that this user identifies themselves with.', NoteReaction: convertSchemaToOpenApiSchema(packedNoteReactionSchema),
example: 'ai'
},
name: {
type: 'string',
nullable: true,
description: 'The name of the user, as theyve defined it.',
example: '藍'
},
host: {
type: 'string',
nullable: true,
example: 'misskey.example.com'
},
description: {
type: 'string',
nullable: true,
description: 'The user-defined UTF-8 string describing their account.',
example: 'Hi masters, I am Ai!'
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the user account was created on Misskey.'
},
followersCount: {
type: 'number',
description: 'The number of followers this account currently has.'
},
followingCount: {
type: 'number',
description: 'The number of users this account is following.'
},
notesCount: {
type: 'number',
description: 'The number of Notes (including renotes) issued by the user.'
},
isBot: {
type: 'boolean',
description: 'Whether this account is a bot.'
},
isCat: {
type: 'boolean',
description: 'Whether this account is a cat.'
},
isAdmin: {
type: 'boolean',
description: 'Whether this account is the admin.'
},
isVerified: {
type: 'boolean'
},
isLocked: {
type: 'boolean'
},
},
required: ['id', 'name', 'username', 'createdAt']
},
UserList: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this UserList.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the UserList was created.'
},
title: {
type: 'string',
description: 'The name of the UserList.'
},
},
required: ['id', 'createdAt', 'title']
},
MessagingMessage: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this MessagingMessage.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the MessagingMessage was created.'
},
text: {
type: 'string',
nullable: true
},
file: {
type: 'DriveFile',
nullable: true
},
recipientId: {
type: 'string',
format: 'id',
},
recipient: {
$ref: '#/components/schemas/User'
},
},
required: ['id', 'createdAt']
},
Note: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this Note.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the Note was created on Misskey.'
},
text: {
type: 'string'
},
cw: {
type: 'string'
},
userId: {
type: 'string',
format: 'id',
},
user: {
$ref: '#/components/schemas/User'
},
replyId: {
type: 'string',
format: 'id',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
renoteId: {
type: 'string',
format: 'id',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
reply: {
$ref: '#/components/schemas/Note'
},
renote: {
$ref: '#/components/schemas/Note'
},
viaMobile: {
type: 'boolean'
},
visibility: {
type: 'string'
},
},
required: ['id', 'userId', 'createdAt']
},
Notification: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this notification.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the notification was created.'
},
type: {
type: 'string',
enum: ['follow', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'],
description: 'The type of the notification.'
},
},
required: ['id', 'createdAt', 'type']
},
DriveFile: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this Drive file.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the Drive file was created on Misskey.'
},
name: {
type: 'string',
description: 'The file name with extension.',
example: 'lenna.jpg'
},
type: {
type: 'string',
description: 'The MIME type of this Drive file.',
example: 'image/jpeg'
},
md5: {
type: 'string',
format: 'md5',
description: 'The MD5 hash of this Drive file.',
example: '15eca7fba0480996e2245f5185bf39f2'
},
size: {
type: 'number',
description: 'The size of this Drive file. (bytes)',
example: 51469
},
folderId: {
type: 'string',
format: 'id',
nullable: true,
description: 'The parent folder ID of this Drive file.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
isSensitive: {
type: 'boolean',
description: 'Whether this Drive file is sensitive.',
},
},
required: ['id', 'createdAt', 'name', 'type', 'size', 'md5']
},
DriveFolder: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this Drive folder.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the Drive folder was created.'
},
name: {
type: 'string',
description: 'The folder name.',
},
foldersCount: {
type: 'number',
description: 'The count of child folders.',
},
filesCount: {
type: 'number',
description: 'The count of child files.',
},
parentId: {
type: 'string',
format: 'id',
nullable: true,
description: 'The parent folder ID of this folder.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
parent: {
$ref: '#/components/schemas/DriveFolder'
},
},
required: ['id', 'createdAt', 'name']
},
Following: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this following.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the following was created.'
},
followeeId: {
type: 'string',
format: 'id',
},
followee: {
$ref: '#/components/schemas/User',
description: 'The followee.'
},
followerId: {
type: 'string',
format: 'id',
},
follower: {
$ref: '#/components/schemas/User',
description: 'The follower.'
},
},
required: ['id', 'createdAt', 'followeeId', 'followerId']
},
Muting: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this mute.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the mute was created.'
},
mutee: {
$ref: '#/components/schemas/User',
description: 'The mutee.'
},
},
required: ['id', 'createdAt', 'mutee']
},
Blocking: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this block.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the block was created.'
},
blockee: {
$ref: '#/components/schemas/User',
description: 'The blockee.'
},
},
required: ['id', 'createdAt', 'blockee']
},
Reaction: {
type: 'object',
properties: {
id: {
type: 'string',
format: 'id',
description: 'The unique identifier for this reaction.',
example: 'xxxxxxxxxxxxxxxxxxxxxxxx',
},
createdAt: {
type: 'string',
format: 'date-time',
description: 'The date that the reaction was created.'
},
user: {
$ref: '#/components/schemas/User',
description: 'User who performed this reaction.'
},
type: {
type: 'string',
enum: [
'like',
'love',
'laugh',
'hmm',
'surprise',
'congrats',
'angry',
'confused',
'rip',
'pudding',
'star'
],
description: 'The reaction type.'
},
},
required: ['id', 'createdAt', 'user', 'type']
},
Hashtag: { Hashtag: {
type: 'object', type: 'object',

View file

@ -135,7 +135,7 @@ export default async (ctx: Koa.BaseContext) => {
includeSecrets: true includeSecrets: true
}); });
res.token = secret; (res as any).token = secret;
ctx.body = res; ctx.body = res;
}; };

View file

@ -3,6 +3,7 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta'; import fetchMeta from '../../../../misc/fetch-meta';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'globalTimeline'; public readonly chName = 'globalTimeline';
@ -21,7 +22,7 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
if (note.visibility !== 'public') return; if (note.visibility !== 'public') return;
// リプライなら再pack // リプライなら再pack

View file

@ -2,6 +2,7 @@ import autobind from 'autobind-decorator';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'hashtag'; public readonly chName = 'hashtag';
@ -20,8 +21,8 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
const noteTags = note.tags.map((t: string) => t.toLowerCase()); const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : [];
const matched = this.q.some(tags => tags.every(tag => noteTags.includes(tag.toLowerCase()))); const matched = this.q.some(tags => tags.every(tag => noteTags.includes(tag.toLowerCase())));
if (!matched) return; if (!matched) return;

View file

@ -2,6 +2,7 @@ import autobind from 'autobind-decorator';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'homeTimeline'; public readonly chName = 'homeTimeline';
@ -15,7 +16,7 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
// その投稿のユーザーをフォローしていなかったら弾く // その投稿のユーザーをフォローしていなかったら弾く
if (this.user!.id !== note.userId && !this.following.includes(note.userId)) return; if (this.user!.id !== note.userId && !this.following.includes(note.userId)) return;

View file

@ -3,6 +3,8 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta'; import fetchMeta from '../../../../misc/fetch-meta';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
import { PackedUser } from '../../../../models/repositories/user';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'hybridTimeline'; public readonly chName = 'hybridTimeline';
@ -19,12 +21,12 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
// 自分自身の投稿 または その投稿のユーザーをフォローしている または 全体公開のローカルの投稿 の場合だけ // 自分自身の投稿 または その投稿のユーザーをフォローしている または 全体公開のローカルの投稿 の場合だけ
if (!( if (!(
this.user!.id === note.userId || this.user!.id === note.userId ||
this.following.includes(note.userId) || this.following.includes(note.userId) ||
(note.user.host == null && note.visibility === 'public') ((note.user as PackedUser).host == null && note.visibility === 'public')
)) return; )) return;
if (['followers', 'specified'].includes(note.visibility)) { if (['followers', 'specified'].includes(note.visibility)) {

View file

@ -3,6 +3,8 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta'; import fetchMeta from '../../../../misc/fetch-meta';
import { Notes } from '../../../../models'; import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
import { PackedUser } from '../../../../models/repositories/user';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'localTimeline'; public readonly chName = 'localTimeline';
@ -21,8 +23,8 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
if (note.user.host !== null) return; if ((note.user as PackedUser).host !== null) return;
if (note.visibility === 'home') return; if (note.visibility === 'home') return;
if (['followers', 'specified'].includes(note.visibility)) { if (['followers', 'specified'].includes(note.visibility)) {

View file

@ -3,6 +3,7 @@ import Channel from '../channel';
import { Notes, UserListJoinings } from '../../../../models'; import { Notes, UserListJoinings } from '../../../../models';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import { User } from '../../../../models/entities/user'; import { User } from '../../../../models/entities/user';
import { PackedNote } from '../../../../models/repositories/note';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'userList'; public readonly chName = 'userList';
@ -38,7 +39,7 @@ export default class extends Channel {
} }
@autobind @autobind
private async onNote(note: any) { private async onNote(note: PackedNote) {
if (!this.listUsers.includes(note.userId)) return; if (!this.listUsers.includes(note.userId)) return;
if (['followers', 'specified'].includes(note.visibility)) { if (['followers', 'specified'].includes(note.visibility)) {

View file

@ -1,9 +1,12 @@
import { types, bool } from '../../../../misc/schema';
export const logSchema = { export const logSchema = {
/** /**
* *
*/ */
count: { count: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'アクティブユーザー数', description: 'アクティブユーザー数',
}, },
}; };
@ -12,14 +15,17 @@ export const logSchema = {
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,9 +1,12 @@
import { types, bool } from '../../../../misc/schema';
const logSchema = { const logSchema = {
/** /**
* *
*/ */
totalCount: { totalCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイル数' description: '集計期間時点での、全ドライブファイル数'
}, },
@ -11,7 +14,8 @@ const logSchema = {
* *
*/ */
totalSize: { totalSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイルの合計サイズ' description: '集計期間時点での、全ドライブファイルの合計サイズ'
}, },
@ -19,7 +23,8 @@ const logSchema = {
* *
*/ */
incCount: { incCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブファイル数' description: '増加したドライブファイル数'
}, },
@ -27,7 +32,8 @@ const logSchema = {
* 使 * 使
*/ */
incSize: { incSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブ使用量' description: '増加したドライブ使用量'
}, },
@ -35,7 +41,8 @@ const logSchema = {
* *
*/ */
decCount: { decCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブファイル数' description: '減少したドライブファイル数'
}, },
@ -43,20 +50,24 @@ const logSchema = {
* 使 * 使
*/ */
decSize: { decSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブ使用量' description: '減少したドライブ使用量'
}, },
}; };
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,22 +1,29 @@
import { types, bool } from '../../../../misc/schema';
/** /**
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
instance: { instance: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'インスタンス数の合計' description: 'インスタンス数の合計'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加インスタンス数' description: '増加インスタンス数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少インスタンス数' description: '減少インスタンス数'
}, },
} }

View file

@ -1,9 +1,12 @@
import { types, bool } from '../../../../misc/schema';
export const logSchema = { export const logSchema = {
/** /**
* 稿 * 稿
*/ */
count: { count: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '投稿された数', description: '投稿された数',
}, },
}; };
@ -12,14 +15,17 @@ export const logSchema = {
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,58 +1,73 @@
import { types, bool } from '../../../../misc/schema';
/** /**
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
requests: { requests: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
failed: { failed: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '失敗したリクエスト数' description: '失敗したリクエスト数'
}, },
succeeded: { succeeded: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '成功したリクエスト数' description: '成功したリクエスト数'
}, },
received: { received: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '受信したリクエスト数' description: '受信したリクエスト数'
}, },
} }
}, },
notes: { notes: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全投稿数' description: '集計期間時点での、全投稿数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加した投稿数' description: '増加した投稿数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少した投稿数' description: '減少した投稿数'
}, },
diffs: { diffs: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
normal: { normal: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '通常の投稿数の差分' description: '通常の投稿数の差分'
}, },
reply: { reply: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'リプライの投稿数の差分' description: 'リプライの投稿数の差分'
}, },
renote: { renote: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'Renoteの投稿数の差分' description: 'Renoteの投稿数の差分'
}, },
} }
@ -61,84 +76,103 @@ export const schema = {
}, },
users: { users: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ユーザー数' description: '集計期間時点での、全ユーザー数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したユーザー数' description: '増加したユーザー数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したユーザー数' description: '減少したユーザー数'
}, },
} }
}, },
following: { following: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全フォロー数' description: '集計期間時点での、全フォロー数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したフォロー数' description: '増加したフォロー数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したフォロー数' description: '減少したフォロー数'
}, },
} }
}, },
followers: { followers: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全フォロワー数' description: '集計期間時点での、全フォロワー数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したフォロワー数' description: '増加したフォロワー数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したフォロワー数' description: '減少したフォロワー数'
}, },
} }
}, },
drive: { drive: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
totalFiles: { totalFiles: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイル数' description: '集計期間時点での、全ドライブファイル数'
}, },
totalUsage: { totalUsage: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイルの合計サイズ' description: '集計期間時点での、全ドライブファイルの合計サイズ'
}, },
incFiles: { incFiles: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブファイル数' description: '増加したドライブファイル数'
}, },
incUsage: { incUsage: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブ使用量' description: '増加したドライブ使用量'
}, },
decFiles: { decFiles: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブファイル数' description: '減少したドライブファイル数'
}, },
decUsage: { decUsage: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブ使用量' description: '減少したドライブ使用量'
}, },
} }

View file

@ -1,27 +1,35 @@
import { types, bool } from '../../../../misc/schema';
/** /**
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
incomingRequests: { incomingRequests: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '受信したリクエスト数' description: '受信したリクエスト数'
}, },
outgoingRequests: { outgoingRequests: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '送信したリクエスト数' description: '送信したリクエスト数'
}, },
totalTime: { totalTime: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '応答時間の合計' // TIP: (totalTime / incomingRequests) でひとつのリクエストに平均でどれくらいの時間がかかったか知れる description: '応答時間の合計' // TIP: (totalTime / incomingRequests) でひとつのリクエストに平均でどれくらいの時間がかかったか知れる
}, },
incomingBytes: { incomingBytes: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '合計受信データ量' description: '合計受信データ量'
}, },
outgoingBytes: { outgoingBytes: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '合計送信データ量' description: '合計送信データ量'
}, },
} }

View file

@ -1,34 +1,43 @@
import { types, bool } from '../../../../misc/schema';
const logSchema = { const logSchema = {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全投稿数' description: '集計期間時点での、全投稿数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加した投稿数' description: '増加した投稿数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少した投稿数' description: '減少した投稿数'
}, },
diffs: { diffs: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
normal: { normal: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '通常の投稿数の差分' description: '通常の投稿数の差分'
}, },
reply: { reply: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'リプライの投稿数の差分' description: 'リプライの投稿数の差分'
}, },
renote: { renote: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'Renoteの投稿数の差分' description: 'Renoteの投稿数の差分'
}, },
} }
@ -36,14 +45,17 @@ const logSchema = {
}; };
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,11 +1,15 @@
import { types, bool } from '../../../../misc/schema';
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
/** /**
* *
*/ */
totalCount: { totalCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイル数' description: '集計期間時点での、全ドライブファイル数'
}, },
@ -13,7 +17,8 @@ export const schema = {
* *
*/ */
totalSize: { totalSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全ドライブファイルの合計サイズ' description: '集計期間時点での、全ドライブファイルの合計サイズ'
}, },
@ -21,7 +26,8 @@ export const schema = {
* *
*/ */
incCount: { incCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブファイル数' description: '増加したドライブファイル数'
}, },
@ -29,7 +35,8 @@ export const schema = {
* 使 * 使
*/ */
incSize: { incSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加したドライブ使用量' description: '増加したドライブ使用量'
}, },
@ -37,7 +44,8 @@ export const schema = {
* *
*/ */
decCount: { decCount: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブファイル数' description: '減少したドライブファイル数'
}, },
@ -45,7 +53,8 @@ export const schema = {
* 使 * 使
*/ */
decSize: { decSize: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少したドライブ使用量' description: '減少したドライブ使用量'
}, },
} }

View file

@ -1,15 +1,19 @@
import { types, bool } from '../../../../misc/schema';
export const logSchema = { export const logSchema = {
/** /**
* *
*/ */
followings: { followings: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
/** /**
* *
*/ */
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォローしている合計', description: 'フォローしている合計',
}, },
@ -17,7 +21,8 @@ export const logSchema = {
* *
*/ */
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォローした数', description: 'フォローした数',
}, },
@ -25,7 +30,8 @@ export const logSchema = {
* *
*/ */
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォロー解除した数', description: 'フォロー解除した数',
}, },
} }
@ -35,13 +41,15 @@ export const logSchema = {
* *
*/ */
followers: { followers: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
/** /**
* *
*/ */
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォローされている合計', description: 'フォローされている合計',
}, },
@ -49,7 +57,8 @@ export const logSchema = {
* *
*/ */
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォローされた数', description: 'フォローされた数',
}, },
@ -57,7 +66,8 @@ export const logSchema = {
* *
*/ */
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'フォロー解除された数', description: 'フォロー解除された数',
}, },
} }
@ -65,14 +75,17 @@ export const logSchema = {
}; };
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,36 +1,46 @@
import { types, bool } from '../../../../misc/schema';
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '集計期間時点での、全投稿数' description: '集計期間時点での、全投稿数'
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '増加した投稿数' description: '増加した投稿数'
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '減少した投稿数' description: '減少した投稿数'
}, },
diffs: { diffs: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
normal: { normal: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '通常の投稿数の差分' description: '通常の投稿数の差分'
}, },
reply: { reply: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'リプライの投稿数の差分' description: 'リプライの投稿数の差分'
}, },
renote: { renote: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'Renoteの投稿数の差分' description: 'Renoteの投稿数の差分'
}, },
} }

View file

@ -1,9 +1,12 @@
import { types, bool } from '../../../../misc/schema';
export const logSchema = { export const logSchema = {
/** /**
* *
*/ */
count: { count: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: 'リアクションされた数', description: 'リアクションされた数',
}, },
}; };
@ -12,14 +15,17 @@ export const logSchema = {
* *
*/ */
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
local: { local: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
remote: { remote: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: logSchema properties: logSchema
}, },
} }

View file

@ -1,21 +1,28 @@
import { types, bool } from '../../../../misc/schema';
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
foo: { foo: {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
total: { total: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '' description: ''
}, },
inc: { inc: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '' description: ''
}, },
dec: { dec: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '' description: ''
}, },
} }

View file

@ -1,8 +1,12 @@
import { types, bool } from '../../../../misc/schema';
export const schema = { export const schema = {
type: 'object' as 'object', type: types.object,
optional: bool.false, nullable: bool.false,
properties: { properties: {
foo: { foo: {
type: 'number' as 'number', type: types.number,
optional: bool.false, nullable: bool.false,
description: '' description: ''
}, },
} }

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