refactor: PackedHoge型をPacked<'Hoge'>型に書き換える (#7792)
* packedNotificationSchemaを更新 * read:gallery, write:gallery, read:gallery-likes, write:gallery-likesに翻訳を追加 * fix * add header, choice, invitation * test * fix * yatta * remove no longer needed "as PackedUser/PackedNote" * clean up * add simple-schema * fix lint * define items in full Schema * revert https://github.com/misskey-dev/misskey/pull/7772#discussion_r706627736 * user packとnote packの型不整合を修正 * add prelude/types.ts * emoji * signin * game * matching * fix * add emoji schema * add reversiGame * add reversiMatching * remove signin schema (use Signin entity) * add Packed type * note-reaction * user * user-group * user-list * note * app, messaging-message * notification * drive-file * drive-folder * following * muting * blocking * hashtag * page * app (with modifying schema) * import user? * channel * antenna * clip * gallery-post * emoji * Packed * reversi-matching * add changelog * add changelog * revert fix
This commit is contained in:
		
							parent
							
								
									bea42f5804
								
							
						
					
					
						commit
						14795b68f2
					
				
					 35 changed files with 312 additions and 122 deletions
				
			
		|  | @ -21,6 +21,8 @@ | |||
| - UIの改善 | ||||
| - MFMにsparklesエフェクトを追加 | ||||
| - 非ログイン自は更新ダイアログを出さないように | ||||
| - refactor: PackedHoge型をPacked<'Hoge'>型に書き換える | ||||
| - refactor: スキーマのないpack関数にスキーマを定義 | ||||
| 
 | ||||
| ### Bugfixes | ||||
| - アカウントデータのエクスポート/インポート処理ができない問題を修正 | ||||
|  |  | |||
|  | @ -3,13 +3,13 @@ import { Note } from '@/models/entities/note'; | |||
| import { User } from '@/models/entities/user'; | ||||
| import { UserListJoinings, UserGroupJoinings } from '@/models/index'; | ||||
| import { getFullApAccount } from './convert-host'; | ||||
| import { PackedNote } from '../models/repositories/note'; | ||||
| import { parseAcct } from '@/misc/acct'; | ||||
| import { Packed } from './schema'; | ||||
| 
 | ||||
| /** | ||||
|  * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい | ||||
|  */ | ||||
| export async function checkHitAntenna(antenna: Antenna, note: (Note | PackedNote), noteUser: { username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise<boolean> { | ||||
| export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'Note'>), noteUser: { username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise<boolean> { | ||||
| 	if (note.visibility === 'specified') return false; | ||||
| 
 | ||||
| 	if (note.visibility === 'followers') { | ||||
|  |  | |||
|  | @ -21,6 +21,9 @@ import { packedClipSchema } from '@/models/repositories/clip'; | |||
| import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance'; | ||||
| import { packedQueueCountSchema } from '@/models/repositories/queue'; | ||||
| import { packedGalleryPostSchema } from '@/models/repositories/gallery-post'; | ||||
| import { packedEmojiSchema } from '@/models/repositories/emoji'; | ||||
| import { packedReversiGameSchema } from '@/models/repositories/games/reversi/game'; | ||||
| import { packedReversiMatchingSchema } from '@/models/repositories/games/reversi/matching'; | ||||
| 
 | ||||
| export const refs = { | ||||
| 	User: packedUserSchema, | ||||
|  | @ -45,8 +48,13 @@ export const refs = { | |||
| 	Clip: packedClipSchema, | ||||
| 	FederationInstance: packedFederationInstanceSchema, | ||||
| 	GalleryPost: packedGalleryPostSchema, | ||||
| 	Emoji: packedEmojiSchema, | ||||
| 	ReversiGame: packedReversiGameSchema, | ||||
| 	ReversiMatching: packedReversiMatchingSchema, | ||||
| }; | ||||
| 
 | ||||
| export type Packed<x extends keyof typeof refs> = ObjType<(typeof refs[x])['properties']>; | ||||
| 
 | ||||
| export interface Schema extends SimpleSchema { | ||||
| 	items?: Schema; | ||||
| 	properties?: Obj; | ||||
|  | @ -92,7 +100,7 @@ export type SchemaType<p extends Schema> = | |||
| 	p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> : | ||||
| 	p['type'] extends 'object' ? ( | ||||
| 		p['ref'] extends keyof typeof refs | ||||
| 			? NullOrUndefined<p, SchemaType<typeof refs[p['ref']]>> | ||||
| 			? NullOrUndefined<p, Packed<p['ref']>> | ||||
| 			: NullOrUndefined<p, ObjType<NonNullable<p['properties']>>> | ||||
| 	) : | ||||
| 	p['type'] extends 'any' ? NullOrUndefined<p, any> : | ||||
|  |  | |||
|  | @ -1,15 +1,13 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Antenna } from '@/models/entities/antenna'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { AntennaNotes, UserGroupJoinings } from '../index'; | ||||
| 
 | ||||
| export type PackedAntenna = SchemaType<typeof packedAntennaSchema>; | ||||
| 
 | ||||
| @EntityRepository(Antenna) | ||||
| export class AntennaRepository extends Repository<Antenna> { | ||||
| 	public async pack( | ||||
| 		src: Antenna['id'] | Antenna, | ||||
| 	): Promise<PackedAntenna> { | ||||
| 	): Promise<Packed<'Antenna'>> { | ||||
| 		const antenna = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		const hasUnreadNote = (await AntennaNotes.findOne({ antennaId: antenna.id, read: false })) != null; | ||||
|  |  | |||
|  | @ -1,9 +1,8 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { App } from '@/models/entities/app'; | ||||
| import { AccessTokens } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| 
 | ||||
| export type PackedApp = SchemaType<typeof packedAppSchema>; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { User } from '../entities/user'; | ||||
| 
 | ||||
| @EntityRepository(App) | ||||
| export class AppRepository extends Repository<App> { | ||||
|  | @ -15,7 +14,7 @@ export class AppRepository extends Repository<App> { | |||
| 			includeSecret?: boolean, | ||||
| 			includeProfileImageIds?: boolean | ||||
| 		} | ||||
| 	): Promise<PackedApp> { | ||||
| 	): Promise<Packed<'App'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: false, | ||||
| 			includeSecret: false, | ||||
|  | @ -52,13 +51,9 @@ export const packedAppSchema = { | |||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const | ||||
| 		}, | ||||
| 		createdAt: { | ||||
| 		callbackUrl: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const | ||||
| 		}, | ||||
| 		lastUsedAt: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const | ||||
| 			optional: false as const, nullable: true as const | ||||
| 		}, | ||||
| 		permission: { | ||||
| 			type: 'array' as const, | ||||
|  |  | |||
|  | @ -2,17 +2,15 @@ import { EntityRepository, Repository } from 'typeorm'; | |||
| import { Users } from '../index'; | ||||
| import { Blocking } from '@/models/entities/blocking'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedBlocking = SchemaType<typeof packedBlockingSchema>; | ||||
| 
 | ||||
| @EntityRepository(Blocking) | ||||
| export class BlockingRepository extends Repository<Blocking> { | ||||
| 	public async pack( | ||||
| 		src: Blocking['id'] | Blocking, | ||||
| 		me?: { id: User['id'] } | null | undefined | ||||
| 	): Promise<PackedBlocking> { | ||||
| 	): Promise<Packed<'Blocking'>> { | ||||
| 		const blocking = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
|  |  | |||
|  | @ -1,17 +1,15 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Channel } from '@/models/entities/channel'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedChannel = SchemaType<typeof packedChannelSchema>; | ||||
| 
 | ||||
| @EntityRepository(Channel) | ||||
| export class ChannelRepository extends Repository<Channel> { | ||||
| 	public async pack( | ||||
| 		src: Channel['id'] | Channel, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<PackedChannel> { | ||||
| 	): Promise<Packed<'Channel'>> { | ||||
| 		const channel = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 		const meId = me ? me.id : null; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,16 +1,14 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Clip } from '@/models/entities/clip'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { Users } from '../index'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| 
 | ||||
| export type PackedClip = SchemaType<typeof packedClipSchema>; | ||||
| 
 | ||||
| @EntityRepository(Clip) | ||||
| export class ClipRepository extends Repository<Clip> { | ||||
| 	public async pack( | ||||
| 		src: Clip['id'] | Clip, | ||||
| 	): Promise<PackedClip> { | ||||
| 	): Promise<Packed<'Clip'>> { | ||||
| 		const clip = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
|  |  | |||
|  | @ -4,14 +4,12 @@ import { Users, DriveFolders } from '../index'; | |||
| import { User } from '@/models/entities/user'; | ||||
| import { toPuny } from '@/misc/convert-host'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import config from '@/config/index'; | ||||
| import { query, appendQuery } from '@/prelude/url'; | ||||
| import { Meta } from '@/models/entities/meta'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta'; | ||||
| 
 | ||||
| export type PackedDriveFile = SchemaType<typeof packedDriveFileSchema>; | ||||
| 
 | ||||
| type PackOptions = { | ||||
| 	detail?: boolean, | ||||
| 	self?: boolean, | ||||
|  | @ -99,12 +97,12 @@ export class DriveFileRepository extends Repository<DriveFile> { | |||
| 		return parseInt(sum, 10) || 0; | ||||
| 	} | ||||
| 
 | ||||
| 	public async pack(src: DriveFile['id'], options?: PackOptions): Promise<PackedDriveFile | null>; | ||||
| 	public async pack(src: DriveFile, options?: PackOptions): Promise<PackedDriveFile>; | ||||
| 	public async pack(src: DriveFile['id'], options?: PackOptions): Promise<Packed<'DriveFile'> | null>; | ||||
| 	public async pack(src: DriveFile, options?: PackOptions): Promise<Packed<'DriveFile'>>; | ||||
| 	public async pack( | ||||
| 		src: DriveFile['id'] | DriveFile, | ||||
| 		options?: PackOptions | ||||
| 	): Promise<PackedDriveFile | null> { | ||||
| 	): Promise<Packed<'DriveFile'> | null> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: false, | ||||
| 			self: false | ||||
|  |  | |||
|  | @ -2,9 +2,7 @@ import { EntityRepository, Repository } from 'typeorm'; | |||
| import { DriveFolders, DriveFiles } from '../index'; | ||||
| import { DriveFolder } from '@/models/entities/drive-folder'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| 
 | ||||
| export type PackedDriveFolder = SchemaType<typeof packedDriveFolderSchema>; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(DriveFolder) | ||||
| export class DriveFolderRepository extends Repository<DriveFolder> { | ||||
|  | @ -20,7 +18,7 @@ export class DriveFolderRepository extends Repository<DriveFolder> { | |||
| 		options?: { | ||||
| 			detail: boolean | ||||
| 		} | ||||
| 	): Promise<PackedDriveFolder> { | ||||
| 	): Promise<Packed<'DriveFolder'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: false | ||||
| 		}, options); | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Emoji } from '@/models/entities/emoji'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(Emoji) | ||||
| export class EmojiRepository extends Repository<Emoji> { | ||||
| 	public async pack( | ||||
| 		src: Emoji['id'] | Emoji, | ||||
| 	) { | ||||
| 	): Promise<Packed<'Emoji'>> { | ||||
| 		const emoji = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return { | ||||
|  | @ -24,3 +25,41 @@ export class EmojiRepository extends Repository<Emoji> { | |||
| 		return Promise.all(emojis.map(x => this.pack(x))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export const packedEmojiSchema = { | ||||
| 	type: 'object' as const, | ||||
| 	optional: false as const, nullable: false as const, | ||||
| 	properties: { | ||||
| 		id: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		aliases: { | ||||
| 			type: 'array' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			items: { | ||||
| 				type: 'string' as const, | ||||
| 				optional: false as const, nullable: false as const, | ||||
| 				format: 'id', | ||||
| 			}, | ||||
| 		}, | ||||
| 		name: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		category: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 		}, | ||||
| 		host: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 		}, | ||||
| 		url: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import { EntityRepository, Repository } from 'typeorm'; | |||
| import { Users } from '../index'; | ||||
| import { Following } from '@/models/entities/following'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| type LocalFollowerFollowing = Following & { | ||||
|  | @ -29,8 +29,6 @@ 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 { | ||||
|  | @ -56,7 +54,7 @@ export class FollowingRepository extends Repository<Following> { | |||
| 			populateFollowee?: boolean; | ||||
| 			populateFollower?: boolean; | ||||
| 		} | ||||
| 	): Promise<PackedFollowing> { | ||||
| 	): Promise<Packed<'Following'>> { | ||||
| 		const following = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		if (opts == null) opts = {}; | ||||
|  |  | |||
|  | @ -1,18 +1,16 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { GalleryPost } from '@/models/entities/gallery-post'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { Users, DriveFiles, GalleryLikes } from '../index'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedGalleryPost = SchemaType<typeof packedGalleryPostSchema>; | ||||
| 
 | ||||
| @EntityRepository(GalleryPost) | ||||
| export class GalleryPostRepository extends Repository<GalleryPost> { | ||||
| 	public async pack( | ||||
| 		src: GalleryPost['id'] | GalleryPost, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<PackedGalleryPost> { | ||||
| 	): Promise<Packed<'GalleryPost'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const post = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import { User } from '@/models/entities/user'; | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Users } from '../../../index'; | ||||
| import { ReversiGame } from '@/models/entities/games/reversi/game'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(ReversiGame) | ||||
| export class ReversiGameRepository extends Repository<ReversiGame> { | ||||
|  | @ -11,7 +12,7 @@ export class ReversiGameRepository extends Repository<ReversiGame> { | |||
| 		options?: { | ||||
| 			detail?: boolean | ||||
| 		} | ||||
| 	) { | ||||
| 	): Promise<Packed<'ReversiGame'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: true | ||||
| 		}, options); | ||||
|  | @ -20,8 +21,8 @@ export class ReversiGameRepository extends Repository<ReversiGame> { | |||
| 
 | ||||
| 		return { | ||||
| 			id: game.id, | ||||
| 			createdAt: game.createdAt, | ||||
| 			startedAt: game.startedAt, | ||||
| 			createdAt: game.createdAt.toISOString(), | ||||
| 			startedAt: game.startedAt && game.startedAt.toISOString(), | ||||
| 			isStarted: game.isStarted, | ||||
| 			isEnded: game.isEnded, | ||||
| 			form1: game.form1, | ||||
|  | @ -41,9 +42,150 @@ export class ReversiGameRepository extends Repository<ReversiGame> { | |||
| 			canPutEverywhere: game.canPutEverywhere, | ||||
| 			loopedBoard: game.loopedBoard, | ||||
| 			...(opts.detail ? { | ||||
| 				logs: game.logs, | ||||
| 				logs: game.logs.map(log => ({ | ||||
| 					at: log.at.toISOString(), | ||||
| 					color: log.color, | ||||
| 					pos: log.pos | ||||
| 				})), | ||||
| 				map: game.map, | ||||
| 			} : {}) | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export const packedReversiGameSchema = { | ||||
| 	type: 'object' as const, | ||||
| 	optional: false as const, nullable: false as const, | ||||
| 	properties: { | ||||
| 		id: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		createdAt: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'date-time', | ||||
| 		}, | ||||
| 		startedAt: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 			format: 'date-time', | ||||
| 		}, | ||||
| 		isStarted: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		isEnded: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		form1: { | ||||
| 			type: 'any' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 		}, | ||||
| 		form2: { | ||||
| 			type: 'any' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 		}, | ||||
| 		user1Accepted: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		user2Accepted: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		user1Id: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		user2Id: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		user1: { | ||||
| 			type: 'object' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			ref: 'User' as const, | ||||
| 		}, | ||||
| 		user2: { | ||||
| 			type: 'object' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			ref: 'User' as const, | ||||
| 		}, | ||||
| 		winnerId: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		winner: { | ||||
| 			type: 'object' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 			ref: 'User' as const, | ||||
| 		}, | ||||
| 		surrendered: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		black: { | ||||
| 			type: 'number' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 		}, | ||||
| 		bw: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		isLlotheo: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		canPutEverywhere: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		loopedBoard: { | ||||
| 			type: 'boolean' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 		}, | ||||
| 		logs: { | ||||
| 			type: 'array' as const, | ||||
| 			optional: true as const, nullable: false as const, | ||||
| 			items: { | ||||
| 				type: 'object' as const, | ||||
| 				optional: true as const, nullable: false as const, | ||||
| 				properties: { | ||||
| 					at: { | ||||
| 						type: 'string' as const, | ||||
| 						optional: false as const, nullable: false as const, | ||||
| 						format: 'date-time', | ||||
| 					}, | ||||
| 					color: { | ||||
| 						type: 'boolean' as const, | ||||
| 						optional: false as const, nullable: false as const, | ||||
| 					}, | ||||
| 					pos: { | ||||
| 						type: 'number' as const, | ||||
| 						optional: false as const, nullable: false as const, | ||||
| 					}, | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		map: { | ||||
| 			type: 'array' as const, | ||||
| 			optional: true as const, nullable: false as const, | ||||
| 			items: { | ||||
| 				type: 'string' as const, | ||||
| 				optional: false as const, nullable: false as const, | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -3,18 +3,19 @@ import { ReversiMatching } from '@/models/entities/games/reversi/matching'; | |||
| import { Users } from '../../../index'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(ReversiMatching) | ||||
| export class ReversiMatchingRepository extends Repository<ReversiMatching> { | ||||
| 	public async pack( | ||||
| 		src: ReversiMatching['id'] | ReversiMatching, | ||||
| 		me: { id: User['id'] } | ||||
| 	) { | ||||
| 	): Promise<Packed<'ReversiMatching'>> { | ||||
| 		const matching = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
| 			id: matching.id, | ||||
| 			createdAt: matching.createdAt, | ||||
| 			createdAt: matching.createdAt.toISOString(), | ||||
| 			parentId: matching.parentId, | ||||
| 			parent: Users.pack(matching.parentId, me, { | ||||
| 				detail: true | ||||
|  | @ -26,3 +27,43 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> { | |||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export const packedReversiMatchingSchema = { | ||||
| 	type: 'object' as const, | ||||
| 	optional: false as const, nullable: false as const, | ||||
| 	properties: { | ||||
| 		id: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		createdAt: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'date-time', | ||||
| 		}, | ||||
| 		parentId: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		parent: { | ||||
| 			type: 'object' as const, | ||||
| 			optional: false as const, nullable: true as const, | ||||
| 			ref: 'User' as const, | ||||
| 		}, | ||||
| 		childId: { | ||||
| 			type: 'string' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			format: 'id', | ||||
| 			example: 'xxxxxxxxxx', | ||||
| 		}, | ||||
| 		child: { | ||||
| 			type: 'object' as const, | ||||
| 			optional: false as const, nullable: false as const, | ||||
| 			ref: 'User' as const, | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -1,14 +1,12 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Hashtag } from '@/models/entities/hashtag'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| 
 | ||||
| export type PackedHashtag = SchemaType<typeof packedHashtagSchema>; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(Hashtag) | ||||
| export class HashtagRepository extends Repository<Hashtag> { | ||||
| 	public async pack( | ||||
| 		src: Hashtag, | ||||
| 	): Promise<PackedHashtag> { | ||||
| 	): Promise<Packed<'Hashtag'>> { | ||||
| 		return { | ||||
| 			tag: src.name, | ||||
| 			mentionedUsersCount: src.mentionedUsersCount, | ||||
|  |  | |||
|  | @ -1,11 +1,9 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { MessagingMessage } from '@/models/entities/messaging-message'; | ||||
| import { Users, DriveFiles, UserGroups } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>; | ||||
| 
 | ||||
| @EntityRepository(MessagingMessage) | ||||
| export class MessagingMessageRepository extends Repository<MessagingMessage> { | ||||
| 	public validateText(text: string): boolean { | ||||
|  | @ -19,7 +17,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> { | |||
| 			populateRecipient?: boolean, | ||||
| 			populateGroup?: boolean, | ||||
| 		} | ||||
| 	): Promise<PackedMessagingMessage> { | ||||
| 	): Promise<Packed<'MessagingMessage'>> { | ||||
| 		const opts = options || { | ||||
| 			populateRecipient: true, | ||||
| 			populateGroup: true, | ||||
|  |  | |||
|  | @ -2,17 +2,15 @@ import { EntityRepository, Repository } from 'typeorm'; | |||
| import { Users } from '../index'; | ||||
| import { Muting } from '@/models/entities/muting'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedMuting = SchemaType<typeof packedMutingSchema>; | ||||
| 
 | ||||
| @EntityRepository(Muting) | ||||
| export class MutingRepository extends Repository<Muting> { | ||||
| 	public async pack( | ||||
| 		src: Muting['id'] | Muting, | ||||
| 		me?: { id: User['id'] } | null | undefined | ||||
| 	): Promise<PackedMuting> { | ||||
| 	): Promise<Packed<'Muting'>> { | ||||
| 		const muting = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
|  |  | |||
|  | @ -1,18 +1,16 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { NoteReaction } from '@/models/entities/note-reaction'; | ||||
| import { Users } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { convertLegacyReaction } from '@/misc/reaction-lib'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedNoteReaction = SchemaType<typeof packedNoteReactionSchema>; | ||||
| 
 | ||||
| @EntityRepository(NoteReaction) | ||||
| export class NoteReactionRepository extends Repository<NoteReaction> { | ||||
| 	public async pack( | ||||
| 		src: NoteReaction['id'] | NoteReaction, | ||||
| 		me?: { id: User['id'] } | null | undefined | ||||
| 	): Promise<PackedNoteReaction> { | ||||
| 	): Promise<Packed<'NoteReaction'>> { | ||||
| 		const reaction = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		return { | ||||
|  |  | |||
|  | @ -3,15 +3,13 @@ import * as mfm from 'mfm-js'; | |||
| import { Note } from '@/models/entities/note'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import { Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls, Channels } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { nyaize } from '@/misc/nyaize'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib'; | ||||
| import { NoteReaction } from '@/models/entities/note-reaction'; | ||||
| import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis'; | ||||
| 
 | ||||
| export type PackedNote = SchemaType<typeof packedNoteSchema>; | ||||
| 
 | ||||
| @EntityRepository(Note) | ||||
| export class NoteRepository extends Repository<Note> { | ||||
| 	public validateCw(x: string) { | ||||
|  | @ -67,7 +65,7 @@ export class NoteRepository extends Repository<Note> { | |||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	private async hideNote(packedNote: PackedNote, meId: User['id'] | null) { | ||||
| 	private async hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) { | ||||
| 		// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
 | ||||
| 		let hide = false; | ||||
| 
 | ||||
|  | @ -137,7 +135,7 @@ export class NoteRepository extends Repository<Note> { | |||
| 				myReactions: Map<Note['id'], NoteReaction | null>; | ||||
| 			}; | ||||
| 		} | ||||
| 	): Promise<PackedNote> { | ||||
| 	): Promise<Packed<'Note'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: true, | ||||
| 			skipHide: false | ||||
|  |  | |||
|  | @ -2,15 +2,13 @@ import { EntityRepository, In, Repository } from 'typeorm'; | |||
| import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index'; | ||||
| import { Notification } from '@/models/entities/notification'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { Note } from '@/models/entities/note'; | ||||
| import { NoteReaction } from '@/models/entities/note-reaction'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis'; | ||||
| import { notificationTypes } from '@/types'; | ||||
| 
 | ||||
| export type PackedNotification = SchemaType<typeof packedNotificationSchema>; | ||||
| 
 | ||||
| @EntityRepository(Notification) | ||||
| export class NotificationRepository extends Repository<Notification> { | ||||
| 	public async pack( | ||||
|  | @ -20,7 +18,7 @@ export class NotificationRepository extends Repository<Notification> { | |||
| 				myReactions: Map<Note['id'], NoteReaction | null>; | ||||
| 			}; | ||||
| 		} | ||||
| 	): Promise<PackedNotification> { | ||||
| 	): Promise<Packed<'Notification'>> { | ||||
| 		const notification = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 		const token = notification.appAccessTokenId ? await AccessTokens.findOneOrFail(notification.appAccessTokenId) : null; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,17 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { Page } from '@/models/entities/page'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { Users, DriveFiles, PageLikes } from '../index'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { DriveFile } from '@/models/entities/drive-file'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| 
 | ||||
| export type PackedPage = SchemaType<typeof packedPageSchema>; | ||||
| 
 | ||||
| @EntityRepository(Page) | ||||
| export class PageRepository extends Repository<Page> { | ||||
| 	public async pack( | ||||
| 		src: Page['id'] | Page, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<PackedPage> { | ||||
| 	): Promise<Packed<'Page'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const page = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,15 +1,13 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { UserGroup } from '@/models/entities/user-group'; | ||||
| import { UserGroupJoinings } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| 
 | ||||
| export type PackedUserGroup = SchemaType<typeof packedUserGroupSchema>; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(UserGroup) | ||||
| export class UserGroupRepository extends Repository<UserGroup> { | ||||
| 	public async pack( | ||||
| 		src: UserGroup['id'] | UserGroup, | ||||
| 	): Promise<PackedUserGroup> { | ||||
| 	): Promise<Packed<'UserGroup'>> { | ||||
| 		const userGroup = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		const users = await UserGroupJoinings.find({ | ||||
|  |  | |||
|  | @ -1,15 +1,13 @@ | |||
| import { EntityRepository, Repository } from 'typeorm'; | ||||
| import { UserList } from '@/models/entities/user-list'; | ||||
| import { UserListJoinings } from '../index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| 
 | ||||
| export type PackedUserList = SchemaType<typeof packedUserListSchema>; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| @EntityRepository(UserList) | ||||
| export class UserListRepository extends Repository<UserList> { | ||||
| 	public async pack( | ||||
| 		src: UserList['id'] | UserList, | ||||
| 	): Promise<PackedUserList> { | ||||
| 	): Promise<Packed<'UserList'>> { | ||||
| 		const userList = typeof src === 'object' ? src : await this.findOneOrFail(src); | ||||
| 
 | ||||
| 		const users = await UserListJoinings.find({ | ||||
|  |  | |||
|  | @ -3,14 +3,12 @@ import { EntityRepository, Repository, In, Not } from 'typeorm'; | |||
| import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; | ||||
| import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '../index'; | ||||
| import config from '@/config/index'; | ||||
| import { SchemaType } from '@/misc/schema'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| import { awaitAll } from '@/prelude/await-all'; | ||||
| import { populateEmojis } from '@/misc/populate-emojis'; | ||||
| import { getAntennas } from '@/misc/antenna-cache'; | ||||
| import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const'; | ||||
| 
 | ||||
| export type PackedUser = SchemaType<typeof packedUserSchema>; | ||||
| 
 | ||||
| @EntityRepository(User) | ||||
| export class UserRepository extends Repository<User> { | ||||
| 	public async getRelation(me: User['id'], target: User['id']) { | ||||
|  | @ -164,7 +162,7 @@ export class UserRepository extends Repository<User> { | |||
| 			detail?: boolean, | ||||
| 			includeSecrets?: boolean, | ||||
| 		} | ||||
| 	): Promise<PackedUser> { | ||||
| 	): Promise<Packed<'User'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: false, | ||||
| 			includeSecrets: false | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ import Channel from '../channel'; | |||
| import { Notes, Users } from '@/models/index'; | ||||
| import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'channel'; | ||||
|  | @ -25,7 +25,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (note.channelId !== this.channelId) return; | ||||
| 
 | ||||
| 		// リプライなら再pack
 | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | |||
| import Channel from '../channel'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta'; | ||||
| import { Notes } from '@/models/index'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'globalTimeline'; | ||||
|  | @ -24,7 +24,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (note.visibility !== 'public') return; | ||||
| 		if (note.channelId != null) return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,9 +2,9 @@ import autobind from 'autobind-decorator'; | |||
| import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | ||||
| import Channel from '../channel'; | ||||
| import { Notes } from '@/models/index'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { normalizeForSearch } from '@/misc/normalize-for-search'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'hashtag'; | ||||
|  | @ -23,7 +23,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : []; | ||||
| 		const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag)))); | ||||
| 		if (!matched) return; | ||||
|  |  | |||
|  | @ -2,9 +2,9 @@ import autobind from 'autobind-decorator'; | |||
| import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | ||||
| import Channel from '../channel'; | ||||
| import { Notes } from '@/models/index'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'homeTimeline'; | ||||
|  | @ -18,7 +18,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (note.channelId) { | ||||
| 			if (!this.followingChannels.has(note.channelId)) return; | ||||
| 		} else { | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | |||
| import Channel from '../channel'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta'; | ||||
| import { Notes } from '@/models/index'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'hybridTimeline'; | ||||
|  | @ -22,7 +22,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		// チャンネルの投稿ではなく、自分自身の投稿 または
 | ||||
| 		// チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または
 | ||||
| 		// チャンネルの投稿ではなく、全体公開のローカルの投稿 または
 | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | |||
| import Channel from '../channel'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta'; | ||||
| import { Notes } from '@/models/index'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { checkWordMute } from '@/misc/check-word-mute'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'localTimeline'; | ||||
|  | @ -24,7 +24,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (note.user.host !== null) return; | ||||
| 		if (note.visibility !== 'public') return; | ||||
| 		if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ import Channel from '../channel'; | |||
| import { Notes, UserListJoinings, UserLists } from '@/models/index'; | ||||
| import { isMutedUserRelated } from '@/misc/is-muted-user-related'; | ||||
| import { User } from '@/models/entities/user'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| export default class extends Channel { | ||||
| 	public readonly chName = 'userList'; | ||||
|  | @ -47,7 +47,7 @@ export default class extends Channel { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	private async onNote(note: PackedNote) { | ||||
| 	private async onNote(note: Packed<'Note'>) { | ||||
| 		if (!this.listUsers.includes(note.userId)) return; | ||||
| 
 | ||||
| 		if (['followers', 'specified'].includes(note.visibility)) { | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ import { AccessToken } from '@/models/entities/access-token'; | |||
| import { UserProfile } from '@/models/entities/user-profile'; | ||||
| import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '@/services/stream'; | ||||
| import { UserGroup } from '@/models/entities/user-group'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| /** | ||||
|  * Main stream connection | ||||
|  | @ -31,7 +31,7 @@ export default class Connection { | |||
| 	public subscriber: EventEmitter; | ||||
| 	private channels: Channel[] = []; | ||||
| 	private subscribingNotes: any = {}; | ||||
| 	private cachedNotes: PackedNote[] = []; | ||||
| 	private cachedNotes: Packed<'Note'>[] = []; | ||||
| 
 | ||||
| 	constructor( | ||||
| 		wsConnection: websocket.connection, | ||||
|  | @ -150,8 +150,8 @@ export default class Connection { | |||
| 	} | ||||
| 
 | ||||
| 	@autobind | ||||
| 	public cacheNote(note: PackedNote) { | ||||
| 		const add = (note: PackedNote) => { | ||||
| 	public cacheNote(note: Packed<'Note'>) { | ||||
| 		const add = (note: Packed<'Note'>) => { | ||||
| 			const existIndex = this.cachedNotes.findIndex(n => n.id === note.id); | ||||
| 			if (existIndex > -1) { | ||||
| 				this.cachedNotes[existIndex] = note; | ||||
|  |  | |||
|  | @ -6,15 +6,15 @@ import { Not, IsNull, In } from 'typeorm'; | |||
| import { Channel } from '@/models/entities/channel'; | ||||
| import { checkHitAntenna } from '@/misc/check-hit-antenna'; | ||||
| import { getAntennas } from '@/misc/antenna-cache'; | ||||
| import { PackedNote } from '@/models/repositories/note'; | ||||
| import { readNotificationByQuery } from '@/server/api/common/read-notification'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| /** | ||||
|  * Mark notes as read | ||||
|  */ | ||||
| export default async function( | ||||
| 	userId: User['id'], | ||||
| 	notes: (Note | PackedNote)[], | ||||
| 	notes: (Note | Packed<'Note'>)[], | ||||
| 	info?: { | ||||
| 		following: Set<User['id']>; | ||||
| 		followingChannels: Set<Channel['id']>; | ||||
|  | @ -34,10 +34,10 @@ export default async function( | |||
| 	})).map(x => x.followeeId)); | ||||
| 
 | ||||
| 	const myAntennas = (await getAntennas()).filter(a => a.userId === userId); | ||||
| 	const readMentions: (Note | PackedNote)[] = []; | ||||
| 	const readSpecifiedNotes: (Note | PackedNote)[] = []; | ||||
| 	const readChannelNotes: (Note | PackedNote)[] = []; | ||||
| 	const readAntennaNotes: (Note | PackedNote)[] = []; | ||||
| 	const readMentions: (Note | Packed<'Note'>)[] = []; | ||||
| 	const readSpecifiedNotes: (Note | Packed<'Note'>)[] = []; | ||||
| 	const readChannelNotes: (Note | Packed<'Note'>)[] = []; | ||||
| 	const readAntennaNotes: (Note | Packed<'Note'>)[] = []; | ||||
| 
 | ||||
| 	for (const note of notes) { | ||||
| 		if (note.mentions && note.mentions.includes(userId)) { | ||||
|  |  | |||
|  | @ -2,11 +2,10 @@ import * as push from 'web-push'; | |||
| import config from '@/config/index'; | ||||
| import { SwSubscriptions } from '@/models/index'; | ||||
| import { fetchMeta } from '@/misc/fetch-meta'; | ||||
| import { PackedNotification } from '../models/repositories/notification'; | ||||
| import { PackedMessagingMessage } from '../models/repositories/messaging-message'; | ||||
| import { Packed } from '@/misc/schema'; | ||||
| 
 | ||||
| type notificationType = 'notification' | 'unreadMessagingMessage'; | ||||
| type notificationBody = PackedNotification | PackedMessagingMessage; | ||||
| type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>; | ||||
| 
 | ||||
| export default async function(userId: string, type: notificationType, body: notificationBody) { | ||||
| 	const meta = await fetchMeta(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue