diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2019-04-23 22:35:26 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-23 22:35:26 +0900 |
| commit | 0463c6bb0f8fd32740ceb61ccce04c662272a618 (patch) | |
| tree | a28cbdf6c9cdc14648b8c0e46248665a3ad7e5af /src/models | |
| parent | Fix #4768 (diff) | |
| download | sharkey-0463c6bb0f8fd32740ceb61ccce04c662272a618.tar.gz sharkey-0463c6bb0f8fd32740ceb61ccce04c662272a618.tar.bz2 sharkey-0463c6bb0f8fd32740ceb61ccce04c662272a618.zip | |
Refactor API (#4770)
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* Update description.ts
* wip
Diffstat (limited to 'src/models')
| -rw-r--r-- | src/models/repositories/abuse-user-report.ts | 4 | ||||
| -rw-r--r-- | src/models/repositories/app.ts | 42 | ||||
| -rw-r--r-- | src/models/repositories/auth-session.ts | 4 | ||||
| -rw-r--r-- | src/models/repositories/blocking.ts | 42 | ||||
| -rw-r--r-- | src/models/repositories/drive-file.ts | 74 | ||||
| -rw-r--r-- | src/models/repositories/drive-folder.ts | 58 | ||||
| -rw-r--r-- | src/models/repositories/following.ts | 57 | ||||
| -rw-r--r-- | src/models/repositories/games/reversi/matching.ts | 4 | ||||
| -rw-r--r-- | src/models/repositories/messaging-message.ts | 67 | ||||
| -rw-r--r-- | src/models/repositories/muting.ts | 42 | ||||
| -rw-r--r-- | src/models/repositories/note-reaction.ts | 38 | ||||
| -rw-r--r-- | src/models/repositories/note.ts | 152 | ||||
| -rw-r--r-- | src/models/repositories/notification.ts | 47 | ||||
| -rw-r--r-- | src/models/repositories/user-list.ts | 40 | ||||
| -rw-r--r-- | src/models/repositories/user.ts | 170 |
15 files changed, 786 insertions, 55 deletions
diff --git a/src/models/repositories/abuse-user-report.ts b/src/models/repositories/abuse-user-report.ts index f619d6e37f..c708b265a6 100644 --- a/src/models/repositories/abuse-user-report.ts +++ b/src/models/repositories/abuse-user-report.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '..'; -import rap from '@prezzemolo/rap'; import { AbuseUserReport } from '../entities/abuse-user-report'; import { ensure } from '../../prelude/ensure'; +import { awaitAll } from '../../prelude/await-all'; @EntityRepository(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); - return await rap({ + return await awaitAll({ id: report.id, createdAt: report.createdAt, reporterId: report.reporterId, diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts index fa5ebf2ac7..6562a470be 100644 --- a/src/models/repositories/app.ts +++ b/src/models/repositories/app.ts @@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm'; import { App } from '../entities/app'; import { AccessTokens } from '..'; import { ensure } from '../../prelude/ensure'; +import { types, bool, SchemaType } from '../../misc/schema'; + +export type PackedApp = SchemaType<typeof packedAppSchema>; @EntityRepository(App) export class AppRepository extends Repository<App> { @@ -13,7 +16,7 @@ export class AppRepository extends Repository<App> { includeSecret?: boolean, includeProfileImageIds?: boolean } - ) { + ): Promise<PackedApp> { const opts = Object.assign({ detail: 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: 'アプリケーションのシークレットキー' + } + }, +}; diff --git a/src/models/repositories/auth-session.ts b/src/models/repositories/auth-session.ts index 32f7968233..a6a4d46de6 100644 --- a/src/models/repositories/auth-session.ts +++ b/src/models/repositories/auth-session.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Apps } from '..'; -import rap from '@prezzemolo/rap'; import { AuthSession } from '../entities/auth-session'; import { ensure } from '../../prelude/ensure'; +import { awaitAll } from '../../prelude/await-all'; @EntityRepository(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); - return await rap({ + return await awaitAll({ id: session.id, app: Apps.pack(session.appId, me), token: session.token diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts index e18aa591f3..fd209bce1c 100644 --- a/src/models/repositories/blocking.ts +++ b/src/models/repositories/blocking.ts @@ -1,8 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '..'; -import rap from '@prezzemolo/rap'; import { Blocking } from '../entities/blocking'; 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) export class BlockingRepository extends Repository<Blocking> { @@ -16,14 +19,47 @@ export class BlockingRepository extends Repository<Blocking> { public async pack( src: Blocking['id'] | Blocking, me?: any - ) { + ): Promise<PackedBlocking> { const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure); - return await rap({ + return await awaitAll({ id: blocking.id, + createdAt: blocking.createdAt.toISOString(), + blockeeId: blocking.blockeeId, blockee: Users.pack(blocking.blockeeId, me, { 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.' + }, + } +}; diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index f117b38b24..245db4b797 100644 --- a/src/models/repositories/drive-file.ts +++ b/src/models/repositories/drive-file.ts @@ -1,10 +1,13 @@ import { EntityRepository, Repository } from 'typeorm'; import { DriveFile } from '../entities/drive-file'; import { Users, DriveFolders } from '..'; -import rap from '@prezzemolo/rap'; import { User } from '../entities/user'; import { toPuny } from '../../misc/convert-host'; 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) export class DriveFileRepository extends Repository<DriveFile> { @@ -82,7 +85,7 @@ export class DriveFileRepository extends Repository<DriveFile> { self?: boolean, withUser?: boolean, } - ) { + ): Promise<PackedDriveFile> { const opts = Object.assign({ detail: 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); - return await rap({ + return await awaitAll({ id: file.id, - createdAt: file.createdAt, + createdAt: file.createdAt.toISOString(), name: file.name, type: file.type, 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.', + }, + }, +}; diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts index ce88adefa4..ef920c4326 100644 --- a/src/models/repositories/drive-folder.ts +++ b/src/models/repositories/drive-folder.ts @@ -1,8 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; import { DriveFolders, DriveFiles } from '..'; -import rap from '@prezzemolo/rap'; import { DriveFolder } from '../entities/drive-folder'; 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) export class DriveFolderRepository extends Repository<DriveFolder> { @@ -18,16 +21,16 @@ export class DriveFolderRepository extends Repository<DriveFolder> { options?: { detail: boolean } - ): Promise<Record<string, any>> { + ): Promise<PackedDriveFolder> { const opts = Object.assign({ detail: false }, options); const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure); - return await rap({ + return await awaitAll({ id: folder.id, - createdAt: folder.createdAt, + createdAt: folder.createdAt.toISOString(), name: folder.name, 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' + }, + }, +}; diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts index 3fff57866f..aba6527fac 100644 --- a/src/models/repositories/following.ts +++ b/src/models/repositories/following.ts @@ -1,8 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '..'; -import rap from '@prezzemolo/rap'; import { Following } from '../entities/following'; import { ensure } from '../../prelude/ensure'; +import { awaitAll } from '../../prelude/await-all'; +import { SchemaType, types, bool } from '../../misc/schema'; type LocalFollowerFollowing = Following & { followerHost: null; @@ -28,6 +29,8 @@ type RemoteFolloweeFollowing = Following & { followeeSharedInbox: string; }; +export type PackedFollowing = SchemaType<typeof packedFollowingSchema>; + @EntityRepository(Following) export class FollowingRepository extends Repository<Following> { public isLocalFollower(following: Following): following is LocalFollowerFollowing { @@ -64,22 +67,64 @@ export class FollowingRepository extends Repository<Following> { populateFollowee?: boolean; populateFollower?: boolean; } - ) { + ): Promise<PackedFollowing> { const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure); if (opts == null) opts = {}; - return await rap({ + return await awaitAll({ id: following.id, - createdAt: following.createdAt, + createdAt: following.createdAt.toISOString(), followeeId: following.followeeId, followerId: following.followerId, followee: opts.populateFollowee ? Users.pack(following.followee || following.followeeId, me, { detail: true - }) : null, + }) : undefined, follower: opts.populateFollower ? Users.pack(following.follower || following.followerId, me, { 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.' + }, + } +}; diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 4d99c6ef76..86c9204456 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; -import rap from '@prezzemolo/rap'; import { ReversiMatching } from '../../../entities/games/reversi/matching'; import { Users } from '../../..'; import { ensure } from '../../../../prelude/ensure'; +import { awaitAll } from '../../../../prelude/await-all'; @EntityRepository(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); - return await rap({ + return await awaitAll({ id: matching.id, createdAt: matching.createdAt, parentId: matching.parentId, diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index 6659273539..33f95bbd5f 100644 --- a/src/models/repositories/messaging-message.ts +++ b/src/models/repositories/messaging-message.ts @@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm'; import { MessagingMessage } from '../entities/messaging-message'; import { Users, DriveFiles } from '..'; import { ensure } from '../../prelude/ensure'; +import { types, bool, SchemaType } from '../../misc/schema'; + +export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>; @EntityRepository(MessagingMessage) export class MessagingMessageRepository extends Repository<MessagingMessage> { @@ -15,7 +18,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> { options?: { populateRecipient: boolean } - ) { + ): Promise<PackedMessagingMessage> { const opts = options || { populateRecipient: true }; @@ -24,15 +27,73 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> { return { id: message.id, - createdAt: message.createdAt, + createdAt: message.createdAt.toISOString(), text: message.text, userId: message.userId, user: await Users.pack(message.user || message.userId, me), 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, file: message.fileId ? await DriveFiles.pack(message.fileId) : null, 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, + }, + }, +}; diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts index 1812e2e713..1e8135a5c9 100644 --- a/src/models/repositories/muting.ts +++ b/src/models/repositories/muting.ts @@ -1,8 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '..'; -import rap from '@prezzemolo/rap'; import { Muting } from '../entities/muting'; 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) export class MutingRepository extends Repository<Muting> { @@ -16,14 +19,47 @@ export class MutingRepository extends Repository<Muting> { public async pack( src: Muting['id'] | Muting, me?: any - ) { + ): Promise<PackedMuting> { const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure); - return await rap({ + return await awaitAll({ id: muting.id, + createdAt: muting.createdAt.toISOString(), + muteeId: muting.muteeId, mutee: Users.pack(muting.muteeId, me, { 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.' + }, + } +}; diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts index 28191d4ab0..85e5b6b0a1 100644 --- a/src/models/repositories/note-reaction.ts +++ b/src/models/repositories/note-reaction.ts @@ -2,18 +2,54 @@ import { EntityRepository, Repository } from 'typeorm'; import { NoteReaction } from '../entities/note-reaction'; import { Users } from '..'; import { ensure } from '../../prelude/ensure'; +import { types, bool, SchemaType } from '../../misc/schema'; + +export type PackedNoteReaction = SchemaType<typeof packedNoteReactionSchema>; @EntityRepository(NoteReaction) export class NoteReactionRepository extends Repository<NoteReaction> { public async pack( src: NoteReaction['id'] | NoteReaction, me?: any - ) { + ): Promise<PackedNoteReaction> { const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure); return { id: reaction.id, + createdAt: reaction.createdAt.toISOString(), 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.' + }, + }, +}; diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 1d2ce7a9c9..1dbfabe88d 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -4,8 +4,11 @@ import { User } from '../entities/user'; import { unique, concat } from '../../prelude/array'; import { nyaize } from '../../misc/nyaize'; import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..'; -import rap from '@prezzemolo/rap'; 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) export class NoteRepository extends Repository<Note> { @@ -13,18 +16,18 @@ export class NoteRepository extends Repository<Note> { 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; // visibility が specified かつ自分が指定されていなかったら非表示 - if (packedNote.visibility == 'specified') { + if (packedNote.visibility === 'specified') { if (meId == null) { hide = true; } else if (meId === packedNote.userId) { hide = false; } else { // 指定されているかどうか - const specified = packedNote.visibleUserIds.some((id: any) => meId === id); + const specified = packedNote.visibleUserIds!.some((id: any) => meId === id); if (specified) { hide = false; @@ -40,10 +43,10 @@ export class NoteRepository extends Repository<Note> { hide = true; } else if (meId === packedNote.userId) { hide = false; - } else if (packedNote.reply && (meId === packedNote.reply.userId)) { + } else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) { // 自分の投稿に対するリプライ 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; } else { @@ -62,14 +65,13 @@ export class NoteRepository extends Repository<Note> { } if (hide) { - packedNote.visibleUserIds = null; + packedNote.visibleUserIds = undefined; packedNote.fileIds = []; packedNote.files = []; packedNote.text = null; - packedNote.poll = null; + packedNote.poll = undefined; packedNote.cw = null; - packedNote.tags = []; - packedNote.geo = null; + packedNote.geo = undefined; packedNote.isHidden = true; } } @@ -92,7 +94,7 @@ export class NoteRepository extends Repository<Note> { detail?: boolean; skipHide?: boolean; } - ): Promise<Record<string, any>> { + ): Promise<PackedNote> { const opts = Object.assign({ detail: true, skipHide: false @@ -159,9 +161,9 @@ export class NoteRepository extends Repository<Note> { const reactionEmojis = unique(concat([note.emojis, Object.keys(note.reactions)])); - const packed = await rap({ + const packed = await awaitAll({ id: note.id, - createdAt: note.createdAt, + createdAt: note.createdAt.toISOString(), app: note.appId ? Apps.pack(note.appId) : undefined, userId: note.userId, user: Users.pack(note.user || note.userId, meId), @@ -213,3 +215,127 @@ export class NoteRepository extends Repository<Note> { 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, + }, + }, +}; diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 4781d4c065..cf77b35a08 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -1,8 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users, Notes } from '..'; -import rap from '@prezzemolo/rap'; import { Notification } from '../entities/notification'; 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) export class NotificationRepository extends Repository<Notification> { @@ -14,12 +17,12 @@ export class NotificationRepository extends Repository<Notification> { public async pack( src: Notification['id'] | Notification, - ) { + ): Promise<PackedNotification> { const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure); - return await rap({ + return await awaitAll({ id: notification.id, - createdAt: notification.createdAt, + createdAt: notification.createdAt.toISOString(), type: notification.type, userId: 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, + }, + } +}; diff --git a/src/models/repositories/user-list.ts b/src/models/repositories/user-list.ts index e591794b8b..54231c7f85 100644 --- a/src/models/repositories/user-list.ts +++ b/src/models/repositories/user-list.ts @@ -2,12 +2,15 @@ import { EntityRepository, Repository } from 'typeorm'; import { UserList } from '../entities/user-list'; import { ensure } from '../../prelude/ensure'; import { UserListJoinings } from '..'; +import { bool, types, SchemaType } from '../../misc/schema'; + +export type PackedUserList = SchemaType<typeof packedUserListSchema>; @EntityRepository(UserList) export class UserListRepository extends Repository<UserList> { public async pack( src: UserList['id'] | UserList, - ) { + ): Promise<PackedUserList> { const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure); const users = await UserListJoinings.find({ @@ -16,8 +19,43 @@ export class UserListRepository extends Repository<UserList> { return { id: userList.id, + createdAt: userList.createdAt.toISOString(), name: userList.name, 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', + } + }, + }, +}; diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index afba15eb53..6b212203f9 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -1,9 +1,12 @@ import { EntityRepository, Repository, In } from 'typeorm'; import { User, ILocalUser, IRemoteUser } from '../entities/user'; import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..'; -import rap from '@prezzemolo/rap'; import { ensure } from '../../prelude/ensure'; 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) export class UserRepository extends Repository<User> { @@ -71,7 +74,7 @@ export class UserRepository extends Repository<User> { includeSecrets?: boolean, includeHasUnreadNotes?: boolean } - ): Promise<Record<string, any>> { + ): Promise<PackedUser> { const opts = Object.assign({ detail: false, includeSecrets: false @@ -86,7 +89,7 @@ export class UserRepository extends Repository<User> { const falsy = opts.detail ? false : undefined; - return await rap({ + const packed = { id: user.id, name: user.name, username: user.username, @@ -120,8 +123,8 @@ export class UserRepository extends Repository<User> { ...(opts.detail ? { url: profile!.url, - createdAt: user.createdAt, - updatedAt: user.updatedAt, + createdAt: user.createdAt.toISOString(), + updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, bannerUrl: user.bannerUrl, bannerColor: user.bannerColor, isLocked: user.isLocked, @@ -179,7 +182,9 @@ export class UserRepository extends Repository<User> { isBlocked: relation.isBlocked, isMuted: relation.isMuted, } : {}) - }); + }; + + return await awaitAll(packed); } public isLocalUser(user: User): user is ILocalUser { @@ -216,3 +221,156 @@ export class UserRepository extends Repository<User> { } //#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 they’ve 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, + }, + }, +}; |