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 f31f986d66
commit 0463c6bb0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
105 changed files with 1622 additions and 808 deletions

View file

@ -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,

View file

@ -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: 'アプリケーションのシークレットキー'
}
},
};

View file

@ -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

View file

@ -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.'
},
}
};

View file

@ -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.',
},
},
};

View file

@ -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'
},
},
};

View file

@ -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.'
},
}
};

View file

@ -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,

View file

@ -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,
},
},
};

View file

@ -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.'
},
}
};

View file

@ -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.'
},
},
};

View file

@ -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,
},
},
};

View file

@ -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,
},
}
};

View file

@ -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',
}
},
},
};

View file

@ -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 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,
},
},
};