feat: 凍結されたユーザーのコンテンツを見えないようにする (MisskeyIO#134)
ついでにEntityServiceの型定義、meのoptionalをやめる
This commit is contained in:
		| @@ -624,7 +624,7 @@ export class DriveService { | ||||
| 		this.registerLogger.succ(`drive file has been created ${file.id}`); | ||||
|  | ||||
| 		if (user) { | ||||
| 			this.driveFileEntityService.pack(file, { self: true }).then(packedFile => { | ||||
| 			this.driveFileEntityService.pack(file, user, { self: true }).then(packedFile => { | ||||
| 				// Publish driveFileCreated event | ||||
| 				this.globalEventService.publishMainStream(user.id, 'driveFileCreated', packedFile); | ||||
| 				this.globalEventService.publishDriveStream(user.id, 'fileCreated', packedFile); | ||||
|   | ||||
| @@ -54,7 +54,7 @@ const mutedWordsCache = new MemorySingleCache<{ userId: UserProfile['userId']; m | ||||
| type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; | ||||
|  | ||||
| class NotificationManager { | ||||
| 	private notifier: { id: User['id']; }; | ||||
| 	private notifier: { id: User['id'] }; | ||||
| 	private note: Note; | ||||
| 	private queue: { | ||||
| 		target: LocalUser['id']; | ||||
| @@ -64,7 +64,7 @@ class NotificationManager { | ||||
| 	constructor( | ||||
| 		private mutingsRepository: MutingsRepository, | ||||
| 		private notificationService: NotificationService, | ||||
| 		notifier: { id: User['id']; }, | ||||
| 		notifier: { id: User['id'] }, | ||||
| 		note: Note, | ||||
| 	) { | ||||
| 		this.notifier = notifier; | ||||
| @@ -547,7 +547,7 @@ export class NoteCreateService implements OnApplicationShutdown { | ||||
| 			} | ||||
|  | ||||
| 			// Pack the note | ||||
| 			const noteObj = await this.noteEntityService.pack(note); | ||||
| 			const noteObj = await this.noteEntityService.pack(note, user); | ||||
|  | ||||
| 			this.globalEventService.publishNotesStream(noteObj); | ||||
|  | ||||
| @@ -767,7 +767,7 @@ export class NoteCreateService implements OnApplicationShutdown { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	private incNotesCountOfUser(user: { id: User['id']; }) { | ||||
| 	private incNotesCountOfUser(user: { id: User['id'] }) { | ||||
| 		this.usersRepository.createQueryBuilder().update() | ||||
| 			.set({ | ||||
| 				updatedAt: new Date(), | ||||
|   | ||||
| @@ -104,7 +104,7 @@ export class QueryService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public generateChannelQuery(q: SelectQueryBuilder<any>, me?: { id: User['id'] } | null): void { | ||||
| 	public generateChannelQuery(q: SelectQueryBuilder<any>, me: { id: User['id'] } | null): void { | ||||
| 		if (me == null) { | ||||
| 			q.andWhere('note.channelId IS NULL'); | ||||
| 		} else { | ||||
| @@ -208,7 +208,7 @@ export class QueryService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public generateRepliesQuery(q: SelectQueryBuilder<any>, withReplies: boolean, me?: Pick<User, 'id'> | null): void { | ||||
| 	public generateRepliesQuery(q: SelectQueryBuilder<any>, withReplies: boolean, me: Pick<User, 'id'> | null): void { | ||||
| 		if (me == null) { | ||||
| 			q.andWhere(new Brackets(qb => { qb | ||||
| 				.where('note.replyId IS NULL') // 返信ではない | ||||
| @@ -234,7 +234,7 @@ export class QueryService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public generateVisibilityQuery(q: SelectQueryBuilder<any>, me?: { id: User['id'] } | null): void { | ||||
| 	public generateVisibilityQuery(q: SelectQueryBuilder<any>, me: { id: User['id'] } | null): void { | ||||
| 		// This code must always be synchronized with the checks in Notes.isVisibleForMe. | ||||
| 		if (me == null) { | ||||
| 			q.andWhere(new Brackets(qb => { qb | ||||
|   | ||||
| @@ -50,7 +50,7 @@ export class UserListService { | ||||
| 			userListId: list.id, | ||||
| 		} as UserListJoining); | ||||
|  | ||||
| 		this.globalEventService.publishUserListStream(list.id, 'userAdded', await this.userEntityService.pack(target)); | ||||
| 		this.globalEventService.publishUserListStream(list.id, 'userAdded', await this.userEntityService.pack(target, me)); | ||||
|  | ||||
| 		// このインスタンス内にこのリモートユーザーをフォローしているユーザーがいなくても投稿を受け取るためにダミーのユーザーがフォローしたということにする | ||||
| 		if (this.userEntityService.isRemoteUser(target)) { | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import type { AbuseUserReportsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { AbuseUserReport } from '@/models/entities/AbuseUserReport.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -19,7 +21,8 @@ export class AbuseUserReportEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: AbuseUserReport['id'] | AbuseUserReport, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'AbuseUserReport'>> { | ||||
| 		const report = typeof src === 'object' ? src : await this.abuseUserReportsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return await awaitAll({ | ||||
| @@ -30,13 +33,13 @@ export class AbuseUserReportEntityService { | ||||
| 			reporterId: report.reporterId, | ||||
| 			targetUserId: report.targetUserId, | ||||
| 			assigneeId: report.assigneeId, | ||||
| 			reporter: this.userEntityService.pack(report.reporter ?? report.reporterId, null, { | ||||
| 			reporter: this.userEntityService.pack(report.reporter ?? report.reporterId, me, { | ||||
| 				detail: true, | ||||
| 			}), | ||||
| 			targetUser: this.userEntityService.pack(report.targetUser ?? report.targetUserId, null, { | ||||
| 			targetUser: this.userEntityService.pack(report.targetUser ?? report.targetUserId, me, { | ||||
| 				detail: true, | ||||
| 			}), | ||||
| 			assignee: report.assigneeId ? this.userEntityService.pack(report.assignee ?? report.assigneeId, null, { | ||||
| 			assignee: report.assigneeId ? this.userEntityService.pack(report.assignee ?? report.assigneeId, me, { | ||||
| 				detail: true, | ||||
| 			}) : null, | ||||
| 			forwarded: report.forwarded, | ||||
| @@ -44,9 +47,12 @@ export class AbuseUserReportEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		reports: any[], | ||||
| 	) { | ||||
| 		return Promise.all(reports.map(x => this.pack(x))); | ||||
| 	public async packMany( | ||||
| 		reports: (AbuseUserReport['id'] | AbuseUserReport)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'AbuseUserReport'>[]> { | ||||
| 		return (await Promise.allSettled(reports.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'AbuseUserReport'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ export class AppEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: App['id'] | App, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			detail?: boolean, | ||||
| 			includeSecret?: boolean, | ||||
|   | ||||
| @@ -20,7 +20,7 @@ export class AuthSessionEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: AuthSession['id'] | AuthSession, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		const session = typeof src === 'object' ? src : await this.authSessionsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ export class BlockingEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Blocking['id'] | Blocking, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'Blocking'>> { | ||||
| 		const blocking = typeof src === 'object' ? src : await this.blockingsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| @@ -36,10 +36,12 @@ export class BlockingEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		blockings: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(blockings.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		blockings: (Blocking['id'] | Blocking)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Blocking'>[]> { | ||||
| 		return (await Promise.allSettled(blockings.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Blocking'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,14 +1,20 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { In } from 'typeorm'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NoteUnreadsRepository, NotesRepository } from '@/models/index.js'; | ||||
| import type { | ||||
| 	ChannelFavoritesRepository, | ||||
| 	ChannelFollowingsRepository, | ||||
| 	ChannelsRepository, | ||||
| 	DriveFilesRepository, | ||||
| 	NotesRepository, | ||||
| 	NoteUnreadsRepository, | ||||
| } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Channel } from '@/models/entities/Channel.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { DriveFileEntityService } from './DriveFileEntityService.js'; | ||||
| import { NoteEntityService } from './NoteEntityService.js'; | ||||
| import { In } from 'typeorm'; | ||||
|  | ||||
| @Injectable() | ||||
| export class ChannelEntityService { | ||||
| @@ -39,7 +45,7 @@ export class ChannelEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Channel['id'] | Channel, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		detailed?: boolean, | ||||
| 	): Promise<Packed<'Channel'>> { | ||||
| 		const channel = typeof src === 'object' ? src : await this.channelsRepository.findOneByOrFail({ id: src }); | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { ClipFavoritesRepository, ClipsRepository, User } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { Clip } from '@/models/entities/Clip.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| @@ -24,7 +23,7 @@ export class ClipEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Clip['id'] | Clip, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'Clip'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const clip = typeof src === 'object' ? src : await this.clipsRepository.findOneByOrFail({ id: src }); | ||||
| @@ -34,7 +33,7 @@ export class ClipEntityService { | ||||
| 			createdAt: clip.createdAt.toISOString(), | ||||
| 			lastClippedAt: clip.lastClippedAt ? clip.lastClippedAt.toISOString() : null, | ||||
| 			userId: clip.userId, | ||||
| 			user: this.userEntityService.pack(clip.user ?? clip.userId), | ||||
| 			user: this.userEntityService.pack(clip.user ?? clip.userId, me), | ||||
| 			name: clip.name, | ||||
| 			description: clip.description, | ||||
| 			isPublic: clip.isPublic, | ||||
| @@ -44,11 +43,13 @@ export class ClipEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		clips: Clip[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(clips.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		clips: (Clip['id'] | Clip)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Clip'>[]> { | ||||
| 		return (await Promise.allSettled(clips.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Clip'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { forwardRef, Inject, Injectable } from '@nestjs/common'; | ||||
| import { DataSource, In } from 'typeorm'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { NotesRepository, DriveFilesRepository } from '@/models/index.js'; | ||||
| import type { DriveFilesRepository, NotesRepository } from '@/models/index.js'; | ||||
| import type { Config } from '@/config.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| @@ -9,6 +9,9 @@ import type { User } from '@/models/entities/User.js'; | ||||
| import type { DriveFile } from '@/models/entities/DriveFile.js'; | ||||
| import { appendQuery, query } from '@/misc/prelude/url.js'; | ||||
| import { deepClone } from '@/misc/clone.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isMimeImage } from '@/misc/is-mime-image.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
| import { UtilityService } from '../UtilityService.js'; | ||||
| import { VideoProcessingService } from '../VideoProcessingService.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| @@ -19,9 +22,6 @@ type PackOptions = { | ||||
| 	self?: boolean, | ||||
| 	withUser?: boolean, | ||||
| }; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isMimeImage } from '@/misc/is-mime-image.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
|  | ||||
| @Injectable() | ||||
| export class DriveFileEntityService { | ||||
| @@ -186,6 +186,7 @@ export class DriveFileEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: DriveFile['id'] | DriveFile, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Packed<'DriveFile'>> { | ||||
| 		const opts = Object.assign({ | ||||
| @@ -213,13 +214,14 @@ export class DriveFileEntityService { | ||||
| 				detail: true, | ||||
| 			}) : null, | ||||
| 			userId: opts.withUser ? file.userId : null, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId) : null, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId, me) : null, | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async packNullable( | ||||
| 		src: DriveFile['id'] | DriveFile, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Packed<'DriveFile'> | null> { | ||||
| 		const opts = Object.assign({ | ||||
| @@ -248,27 +250,30 @@ export class DriveFileEntityService { | ||||
| 				detail: true, | ||||
| 			}) : null, | ||||
| 			userId: opts.withUser ? file.userId : null, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId) : null, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId, me) : null, | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async packMany( | ||||
| 		files: DriveFile[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Packed<'DriveFile'>[]> { | ||||
| 		const items = await Promise.all(files.map(f => this.packNullable(f, options))); | ||||
| 		return items.filter((x): x is Packed<'DriveFile'> => x != null); | ||||
| 		return (await Promise.allSettled(files.map(f => this.packNullable(f, me, options)))) | ||||
| 			.filter(result => result.status === 'fulfilled' && result.value != null) | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'DriveFile'>>).value); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async packManyByIdsMap( | ||||
| 		fileIds: DriveFile['id'][], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>> { | ||||
| 		if (fileIds.length === 0) return new Map(); | ||||
| 		const files = await this.driveFilesRepository.findBy({ id: In(fileIds) }); | ||||
| 		const packedFiles = await this.packMany(files, options); | ||||
| 		const packedFiles = await this.packMany(files, me, options); | ||||
| 		const map = new Map<Packed<'DriveFile'>['id'], Packed<'DriveFile'> | null>(packedFiles.map(f => [f.id, f])); | ||||
| 		for (const id of fileIds) { | ||||
| 			if (!map.has(id)) map.set(id, null); | ||||
| @@ -279,10 +284,11 @@ export class DriveFileEntityService { | ||||
| 	@bindThis | ||||
| 	public async packManyByIds( | ||||
| 		fileIds: DriveFile['id'][], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Packed<'DriveFile'>[]> { | ||||
| 		if (fileIds.length === 0) return []; | ||||
| 		const filesMap = await this.packManyByIdsMap(fileIds, options); | ||||
| 		const filesMap = await this.packManyByIdsMap(fileIds, me, options); | ||||
| 		return fileIds.map(id => filesMap.get(id)).filter(isNotNull); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { DriveFilesRepository, DriveFoldersRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { DriveFolder } from '@/models/entities/DriveFolder.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { EmojisRepository } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { Emoji } from '@/models/entities/Emoji.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
|  | ||||
| @@ -33,10 +32,12 @@ export class EmojiEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packSimpleMany( | ||||
| 		emojis: any[], | ||||
| 	) { | ||||
| 		return Promise.all(emojis.map(x => this.packSimple(x))); | ||||
| 	public async packSimpleMany( | ||||
| 		emojis: (Emoji['id'] | Emoji)[], | ||||
| 	) : Promise<Packed<'EmojiSimple'>[]> { | ||||
| 		return (await Promise.allSettled(emojis.map(x => this.packSimple(x)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'EmojiSimple'>>).value); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| @@ -62,10 +63,11 @@ export class EmojiEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packDetailedMany( | ||||
| 		emojis: any[], | ||||
| 	) { | ||||
| 		return Promise.all(emojis.map(x => this.packDetailed(x))); | ||||
| 	public async packDetailedMany( | ||||
| 		emojis: (Emoji['id'] | Emoji)[], | ||||
| 	) : Promise<Packed<'EmojiDetailed'>[]> { | ||||
| 		return (await Promise.allSettled(emojis.map(x => this.packDetailed(x)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'EmojiDetailed'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; | ||||
| import type { FlashLikesRepository, FlashsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Flash } from '@/models/entities/Flash.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -25,7 +24,7 @@ export class FlashEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Flash['id'] | Flash, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'Flash'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const flash = typeof src === 'object' ? src : await this.flashsRepository.findOneByOrFail({ id: src }); | ||||
| @@ -45,11 +44,12 @@ export class FlashEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		flashs: Flash[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(flashs.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		flashs: (Flash['id'] | Flash)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Flash'>[]> { | ||||
| 		return (await Promise.allSettled(flashs.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Flash'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { FlashLikesRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { FlashLike } from '@/models/entities/FlashLike.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { FlashEntityService } from './FlashEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -20,8 +20,8 @@ export class FlashLikeEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: FlashLike['id'] | FlashLike, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'FlashLike'>> { | ||||
| 		const like = typeof src === 'object' ? src : await this.flashLikesRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return { | ||||
| @@ -31,11 +31,12 @@ export class FlashLikeEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		likes: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(likes.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		likes: (FlashLike['id'] | FlashLike)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'FlashLike'>[]> { | ||||
| 		return (await Promise.allSettled(likes.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'FlashLike'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { FollowRequestsRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { FollowRequest } from '@/models/entities/FollowRequest.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -20,8 +20,8 @@ export class FollowRequestEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: FollowRequest['id'] | FollowRequest, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'FollowRequest'>> { | ||||
| 		const request = typeof src === 'object' ? src : await this.followRequestsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return { | ||||
| @@ -30,5 +30,14 @@ export class FollowRequestEntityService { | ||||
| 			followee: await this.userEntityService.pack(request.followeeId, me), | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async packMany( | ||||
| 		requests: (FollowRequest['id'] | FollowRequest)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'FollowRequest'>[]> { | ||||
| 		return (await Promise.allSettled(requests.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'FollowRequest'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { FollowingsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Following } from '@/models/entities/Following.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -66,7 +65,7 @@ export class FollowingEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Following['id'] | Following, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		opts?: { | ||||
| 			populateFollowee?: boolean; | ||||
| 			populateFollower?: boolean; | ||||
| @@ -91,15 +90,16 @@ export class FollowingEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		followings: any[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	public async packMany( | ||||
| 		followings: (Following['id'] | Following)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		opts?: { | ||||
| 			populateFollowee?: boolean; | ||||
| 			populateFollower?: boolean; | ||||
| 		}, | ||||
| 	) { | ||||
| 		return Promise.all(followings.map(x => this.pack(x, me, opts))); | ||||
| 	) : Promise<Packed<'Following'>[]> { | ||||
| 		return (await Promise.allSettled(followings.map(x => this.pack(x, me, opts)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Following'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { GalleryLikesRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { GalleryLike } from '@/models/entities/GalleryLike.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import { GalleryPostEntityService } from './GalleryPostEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -19,8 +20,8 @@ export class GalleryLikeEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: GalleryLike['id'] | GalleryLike, | ||||
| 		me?: any, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'GalleryLike'>> { | ||||
| 		const like = typeof src === 'object' ? src : await this.galleryLikesRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return { | ||||
| @@ -30,11 +31,13 @@ export class GalleryLikeEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		likes: any[], | ||||
| 		me: any, | ||||
| 	) { | ||||
| 		return Promise.all(likes.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		likes: (GalleryLike['id'] | GalleryLike)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'GalleryLike'>[]> { | ||||
| 		return (await Promise.allSettled(likes.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'GalleryLike'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { GalleryPost } from '@/models/entities/GalleryPost.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -27,7 +26,7 @@ export class GalleryPostEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: GalleryPost['id'] | GalleryPost, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'GalleryPost'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const post = typeof src === 'object' ? src : await this.galleryPostsRepository.findOneByOrFail({ id: src }); | ||||
| @@ -42,7 +41,7 @@ export class GalleryPostEntityService { | ||||
| 			description: post.description, | ||||
| 			fileIds: post.fileIds, | ||||
| 			// TODO: packMany causes N+1 queries | ||||
| 			files: this.driveFileEntityService.packManyByIds(post.fileIds), | ||||
| 			files: this.driveFileEntityService.packManyByIds(post.fileIds, me), | ||||
| 			tags: post.tags.length > 0 ? post.tags : undefined, | ||||
| 			isSensitive: post.isSensitive, | ||||
| 			likedCount: post.likedCount, | ||||
| @@ -51,11 +50,12 @@ export class GalleryPostEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		posts: GalleryPost[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(posts.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		posts: (GalleryPost['id'] | GalleryPost)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'GalleryPost'>[]> { | ||||
| 		return (await Promise.allSettled(posts.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'GalleryPost'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { HashtagsRepository } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { Hashtag } from '@/models/entities/Hashtag.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| @@ -33,10 +32,11 @@ export class HashtagEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 	public async packMany( | ||||
| 		hashtags: Hashtag[], | ||||
| 	) { | ||||
| 		return Promise.all(hashtags.map(x => this.pack(x))); | ||||
| 	) : Promise<Packed<'Hashtag'>[]> { | ||||
| 		return (await Promise.allSettled(hashtags.map(x => this.pack(x)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Hashtag'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { InstancesRepository } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { Instance } from '@/models/entities/Instance.js'; | ||||
| import { MetaService } from '@/core/MetaService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -51,10 +50,11 @@ export class InstanceEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 	public async packMany( | ||||
| 		instances: Instance[], | ||||
| 	) { | ||||
| 		return Promise.all(instances.map(x => this.pack(x))); | ||||
| 	) : Promise<Packed<'FederationInstance'>[]> { | ||||
| 		return (await Promise.allSettled(instances.map(x => this.pack(x)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'FederationInstance'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ export class InviteCodeEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: RegistrationTicket['id'] | RegistrationTicket, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'InviteCode'>> { | ||||
| 		const target = typeof src === 'object' ? src : await this.registrationTicketsRepository.findOneOrFail({ | ||||
| 			where: { | ||||
| @@ -43,10 +43,12 @@ export class InviteCodeEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		targets: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(targets.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		targets: (RegistrationTicket['id'] | RegistrationTicket)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'InviteCode'>[]> { | ||||
| 		return (await Promise.allSettled(targets.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'InviteCode'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,9 +2,10 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { ModerationLogsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { ModerationLog } from '@/models/entities/ModerationLog.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -20,7 +21,8 @@ export class ModerationLogEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: ModerationLog['id'] | ModerationLog, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'ModerationLog'>> { | ||||
| 		const log = typeof src === 'object' ? src : await this.moderationLogsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return await awaitAll({ | ||||
| @@ -29,17 +31,20 @@ export class ModerationLogEntityService { | ||||
| 			type: log.type, | ||||
| 			info: log.info, | ||||
| 			userId: log.userId, | ||||
| 			user: this.userEntityService.pack(log.user ?? log.userId, null, { | ||||
| 			user: this.userEntityService.pack(log.user ?? log.userId, me, { | ||||
| 				detail: true, | ||||
| 			}), | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		reports: any[], | ||||
| 	) { | ||||
| 		return Promise.all(reports.map(x => this.pack(x))); | ||||
| 	public async packMany( | ||||
| 		reports: (ModerationLog['id'] | ModerationLog)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'ModerationLog'>[]> { | ||||
| 		return (await Promise.allSettled(reports.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'ModerationLog'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { MutingsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Muting } from '@/models/entities/Muting.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -22,7 +21,7 @@ export class MutingEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Muting['id'] | Muting, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'Muting'>> { | ||||
| 		const muting = typeof src === 'object' ? src : await this.mutingsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| @@ -38,11 +37,12 @@ export class MutingEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		mutings: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(mutings.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		mutings: (Muting['id'] | Muting)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Muting'>[]> { | ||||
| 		return (await Promise.allSettled(mutings.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Muting'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,16 @@ import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Note } from '@/models/entities/Note.js'; | ||||
| import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | ||||
| import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository, DriveFilesRepository } from '@/models/index.js'; | ||||
| import type { | ||||
| 	ChannelsRepository, | ||||
| 	DriveFilesRepository, | ||||
| 	FollowingsRepository, | ||||
| 	NoteReactionsRepository, | ||||
| 	NotesRepository, | ||||
| 	PollsRepository, | ||||
| 	PollVotesRepository, | ||||
| 	UsersRepository, | ||||
| } from '@/models/index.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
| import type { OnModuleInit } from '@nestjs/common'; | ||||
| @@ -253,13 +262,17 @@ export class NoteEntityService implements OnModuleInit { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async packAttachedFiles(fileIds: Note['fileIds'], packedFiles: Map<Note['fileIds'][number], Packed<'DriveFile'> | null>): Promise<Packed<'DriveFile'>[]> { | ||||
| 	public async packAttachedFiles( | ||||
| 		fileIds: Note['fileIds'], | ||||
| 		packedFiles: Map<Note['fileIds'][number], Packed<'DriveFile'> | null>, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'DriveFile'>[]> { | ||||
| 		const missingIds = []; | ||||
| 		for (const id of fileIds) { | ||||
| 			if (!packedFiles.has(id)) missingIds.push(id); | ||||
| 		} | ||||
| 		if (missingIds.length) { | ||||
| 			const additionalMap = await this.driveFileEntityService.packManyByIdsMap(missingIds); | ||||
| 			const additionalMap = await this.driveFileEntityService.packManyByIdsMap(missingIds, me); | ||||
| 			for (const [k, v] of additionalMap) { | ||||
| 				packedFiles.set(k, v); | ||||
| 			} | ||||
| @@ -270,7 +283,7 @@ export class NoteEntityService implements OnModuleInit { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Note['id'] | Note, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			detail?: boolean; | ||||
| 			skipHide?: boolean; | ||||
| @@ -326,7 +339,7 @@ export class NoteEntityService implements OnModuleInit { | ||||
| 			emojis: host != null ? this.customEmojiService.populateEmojis(note.emojis, host) : undefined, | ||||
| 			tags: note.tags.length > 0 ? note.tags : undefined, | ||||
| 			fileIds: note.fileIds, | ||||
| 			files: packedFiles != null ? this.packAttachedFiles(note.fileIds, packedFiles) : this.driveFileEntityService.packManyByIds(note.fileIds), | ||||
| 			files: packedFiles != null ? this.packAttachedFiles(note.fileIds, packedFiles, me) : this.driveFileEntityService.packManyByIds(note.fileIds, me), | ||||
| 			replyId: note.replyId, | ||||
| 			renoteId: note.renoteId, | ||||
| 			channelId: note.channelId ?? undefined, | ||||
| @@ -387,12 +400,12 @@ export class NoteEntityService implements OnModuleInit { | ||||
| 	@bindThis | ||||
| 	public async packMany( | ||||
| 		notes: Note[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			detail?: boolean; | ||||
| 			skipHide?: boolean; | ||||
| 		}, | ||||
| 	) { | ||||
| 	) : Promise<Packed<'Note'>[]> { | ||||
| 		if (notes.length === 0) return []; | ||||
|  | ||||
| 		const meId = me ? me.id : null; | ||||
| @@ -414,15 +427,17 @@ export class NoteEntityService implements OnModuleInit { | ||||
| 		await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes)); | ||||
| 		// TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく | ||||
| 		const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(isNotNull); | ||||
| 		const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds) : new Map(); | ||||
| 		const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds, me) : new Map(); | ||||
|  | ||||
| 		return await Promise.all(notes.map(n => this.pack(n, me, { | ||||
| 		return (await Promise.allSettled(notes.map(n => this.pack(n, me, { | ||||
| 			...options, | ||||
| 			_hint_: { | ||||
| 				myReactions: myReactionsMap, | ||||
| 				packedFiles, | ||||
| 			}, | ||||
| 		}))); | ||||
| 		})))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Note'>>).value); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { NoteFavoritesRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { NoteFavorite } from '@/models/entities/NoteFavorite.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from './NoteEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -20,8 +20,8 @@ export class NoteFavoriteEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: NoteFavorite['id'] | NoteFavorite, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'NoteFavorite'>> { | ||||
| 		const favorite = typeof src === 'object' ? src : await this.noteFavoritesRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return { | ||||
| @@ -33,10 +33,12 @@ export class NoteFavoriteEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		favorites: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(favorites.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		favorites: (NoteFavorite['id'] | NoteFavorite)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'NoteFavorite'>[]> { | ||||
| 		return (await Promise.allSettled(favorites.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'NoteFavorite'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { ModuleRef } from '@nestjs/core'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { NoteReactionsRepository } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import type { OnModuleInit } from '@nestjs/common'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | ||||
| import type { OnModuleInit } from '@nestjs/common'; | ||||
| import type { ReactionService } from '../ReactionService.js'; | ||||
| import type { UserEntityService } from './UserEntityService.js'; | ||||
| import type { NoteEntityService } from './NoteEntityService.js'; | ||||
| import { ModuleRef } from '@nestjs/core'; | ||||
|  | ||||
| @Injectable() | ||||
| export class NoteReactionEntityService implements OnModuleInit { | ||||
| @@ -39,7 +38,7 @@ export class NoteReactionEntityService implements OnModuleInit { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: NoteReaction['id'] | NoteReaction, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			withNote: boolean; | ||||
| 		}, | ||||
|   | ||||
| @@ -2,7 +2,13 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { ModuleRef } from '@nestjs/core'; | ||||
| import { In } from 'typeorm'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { AccessTokensRepository, FollowRequestsRepository, NoteReactionsRepository, NotesRepository, User, UsersRepository } from '@/models/index.js'; | ||||
| import type { | ||||
| 	AccessTokensRepository, | ||||
| 	FollowRequestsRepository, | ||||
| 	NoteReactionsRepository, | ||||
| 	NotesRepository, | ||||
| 	UsersRepository, | ||||
| } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Notification } from '@/models/entities/Notification.js'; | ||||
| import type { Note } from '@/models/entities/Note.js'; | ||||
| @@ -10,6 +16,7 @@ import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
| import { notificationTypes } from '@/types.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { OnModuleInit } from '@nestjs/common'; | ||||
| import type { CustomEmojiService } from '../CustomEmojiService.js'; | ||||
| import type { UserEntityService } from './UserEntityService.js'; | ||||
| @@ -108,7 +115,7 @@ export class NotificationEntityService implements OnModuleInit { | ||||
| 	public async packMany( | ||||
| 		notifications: Notification[], | ||||
| 		meId: User['id'], | ||||
| 	) { | ||||
| 	): Promise<Packed<'Notification'>[]> { | ||||
| 		if (notifications.length === 0) return []; | ||||
|  | ||||
| 		let validNotifications = notifications; | ||||
| @@ -143,9 +150,8 @@ export class NotificationEntityService implements OnModuleInit { | ||||
| 			validNotifications = validNotifications.filter(x => (x.type !== 'receiveFollowRequest') || reqs.some(r => r.followerId === x.notifierId)); | ||||
| 		} | ||||
|  | ||||
| 		return await Promise.all(validNotifications.map(x => this.pack(x, meId, {}, { | ||||
| 			packedNotes, | ||||
| 			packedUsers, | ||||
| 		}))); | ||||
| 		return (await Promise.allSettled(validNotifications.map(x => this.pack(x, meId, {}, { packedNotes, packedUsers })))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Notification'>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { DriveFilesRepository, PagesRepository, PageLikesRepository } from '@/models/index.js'; | ||||
| import type { DriveFilesRepository, PageLikesRepository, PagesRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { Page } from '@/models/entities/Page.js'; | ||||
| import type { DriveFile } from '@/models/entities/DriveFile.js'; | ||||
| @@ -31,7 +30,7 @@ export class PageEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Page['id'] | Page, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'Page'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const page = typeof src === 'object' ? src : await this.pagesRepository.findOneByOrFail({ id: src }); | ||||
| @@ -94,19 +93,20 @@ export class PageEntityService { | ||||
| 			font: page.font, | ||||
| 			script: page.script, | ||||
| 			eyeCatchingImageId: page.eyeCatchingImageId, | ||||
| 			eyeCatchingImage: page.eyeCatchingImageId ? await this.driveFileEntityService.pack(page.eyeCatchingImageId) : null, | ||||
| 			attachedFiles: this.driveFileEntityService.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)), | ||||
| 			eyeCatchingImage: page.eyeCatchingImageId ? await this.driveFileEntityService.pack(page.eyeCatchingImageId, me) : null, | ||||
| 			attachedFiles: this.driveFileEntityService.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null), me), | ||||
| 			likedCount: page.likedCount, | ||||
| 			isLiked: meId ? await this.pageLikesRepository.exist({ where: { pageId: page.id, userId: meId } }) : undefined, | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		pages: Page[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(pages.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		pages: (Page['id'] | Page)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Page'>[]> { | ||||
| 		return (await Promise.allSettled(pages.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Page'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { PageLikesRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { PageLike } from '@/models/entities/PageLike.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { PageEntityService } from './PageEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -20,8 +20,8 @@ export class PageLikeEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: PageLike['id'] | PageLike, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'PageLike'>> { | ||||
| 		const like = typeof src === 'object' ? src : await this.pageLikesRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		return { | ||||
| @@ -31,11 +31,12 @@ export class PageLikeEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		likes: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(likes.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		likes: (PageLike['id'] | PageLike)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'PageLike'>[]> { | ||||
| 		return (await Promise.allSettled(likes.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'PageLike'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ import { DI } from '@/di-symbols.js'; | ||||
| import type { RenoteMutingsRepository } from '@/models/index.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { User } from '@/models/entities/User.js'; | ||||
| import type { RenoteMuting } from '@/models/entities/RenoteMuting.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| @@ -22,7 +21,7 @@ export class RenoteMutingEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: RenoteMuting['id'] | RenoteMuting, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	): Promise<Packed<'RenoteMuting'>> { | ||||
| 		const muting = typeof src === 'object' ? src : await this.renoteMutingsRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| @@ -37,11 +36,12 @@ export class RenoteMutingEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		mutings: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(mutings.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		mutings: (RenoteMuting['id'] | RenoteMuting)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'RenoteMuting'>[]> { | ||||
| 		return (await Promise.allSettled(mutings.map(u => this.pack(u, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'RenoteMuting'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import type { User } from '@/models/entities/User.js'; | ||||
| import type { Role } from '@/models/entities/Role.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { DEFAULT_POLICIES } from '@/core/RoleService.js'; | ||||
| import { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -25,8 +26,8 @@ export class RoleEntityService { | ||||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: Role['id'] | Role, | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Role'>> { | ||||
| 		const role = typeof src === 'object' ? src : await this.rolesRepository.findOneByOrFail({ id: src }); | ||||
|  | ||||
| 		const assignedCount = await this.roleAssignmentsRepository.createQueryBuilder('assign') | ||||
| @@ -69,11 +70,12 @@ export class RoleEntityService { | ||||
| 	} | ||||
|  | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		roles: any[], | ||||
| 		me: { id: User['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(roles.map(x => this.pack(x, me))); | ||||
| 	public async packMany( | ||||
| 		roles: (Role['id'] | Role)[], | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 	) : Promise<Packed<'Role'>[]> { | ||||
| 		return (await Promise.allSettled(roles.map(x => this.pack(x, me)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<Packed<'Role'>>).value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { SigninsRepository } from '@/models/index.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { Signin } from '@/models/entities/Signin.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|   | ||||
| @@ -10,12 +10,39 @@ import type { Promiseable } from '@/misc/prelude/await-all.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; | ||||
| import type { LocalUser, PartialLocalUser, PartialRemoteUser, RemoteUser, User } from '@/models/entities/User.js'; | ||||
| import { birthdaySchema, descriptionSchema, localUsernameSchema, locationSchema, nameSchema, passwordSchema } from '@/models/entities/User.js'; | ||||
| import type { UsersRepository, UserSecurityKeysRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, MutingsRepository, DriveFilesRepository, NoteUnreadsRepository, ChannelFollowingsRepository, UserNotePiningsRepository, UserProfilesRepository, InstancesRepository, AnnouncementReadsRepository, AnnouncementsRepository, PagesRepository, UserProfile, RenoteMutingsRepository, UserMemoRepository } from '@/models/index.js'; | ||||
| import { | ||||
| 	birthdaySchema, | ||||
| 	descriptionSchema, | ||||
| 	localUsernameSchema, | ||||
| 	locationSchema, | ||||
| 	nameSchema, | ||||
| 	passwordSchema, | ||||
| } from '@/models/entities/User.js'; | ||||
| import type { | ||||
| 	AnnouncementReadsRepository, | ||||
| 	AnnouncementsRepository, | ||||
| 	BlockingsRepository, | ||||
| 	ChannelFollowingsRepository, | ||||
| 	DriveFilesRepository, | ||||
| 	FollowingsRepository, | ||||
| 	FollowRequestsRepository, | ||||
| 	InstancesRepository, | ||||
| 	MutingsRepository, | ||||
| 	NoteUnreadsRepository, | ||||
| 	PagesRepository, | ||||
| 	RenoteMutingsRepository, | ||||
| 	UserMemoRepository, | ||||
| 	UserNotePiningsRepository, | ||||
| 	UserProfile, | ||||
| 	UserProfilesRepository, | ||||
| 	UserSecurityKeysRepository, | ||||
| 	UsersRepository, | ||||
| } from '@/models/index.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; | ||||
| import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; | ||||
| import { IdentifiableError } from '@/misc/identifiable-error.js'; | ||||
| import type { OnModuleInit } from '@nestjs/common'; | ||||
| import type { AntennaService } from '../AntennaService.js'; | ||||
| import type { CustomEmojiService } from '../CustomEmojiService.js'; | ||||
| @@ -297,7 +324,7 @@ export class UserEntityService implements OnModuleInit { | ||||
|  | ||||
| 	public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>( | ||||
| 		src: User['id'] | User, | ||||
| 		me?: { id: User['id']; } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			detail?: D, | ||||
| 			includeSecrets?: boolean, | ||||
| @@ -332,6 +359,7 @@ export class UserEntityService implements OnModuleInit { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const isMe = meId === user.id; | ||||
| 		const iAmModerator = me ? await this.roleService.isModerator(me as User) : false; | ||||
| 		if (user.isSuspended && !iAmModerator) throw new IdentifiableError('8ca4f428-b32e-4f83-ac43-406ed7cd0452', 'This user is suspended.'); | ||||
|  | ||||
| 		const relation = meId && !isMe && opts.detail ? await this.getRelation(meId, user.id) : null; | ||||
| 		const pins = opts.detail ? await this.userNotePiningsRepository.createQueryBuilder('pin') | ||||
| @@ -511,14 +539,16 @@ export class UserEntityService implements OnModuleInit { | ||||
| 		return await awaitAll(packed); | ||||
| 	} | ||||
|  | ||||
| 	public packMany<D extends boolean = false>( | ||||
| 	public async packMany<D extends boolean = false>( | ||||
| 		users: (User['id'] | User)[], | ||||
| 		me?: { id: User['id'] } | null | undefined, | ||||
| 		me: { id: User['id'] } | null | undefined, | ||||
| 		options?: { | ||||
| 			detail?: D, | ||||
| 			includeSecrets?: boolean, | ||||
| 		}, | ||||
| 	): Promise<IsUserDetailed<D>[]> { | ||||
| 		return Promise.all(users.map(u => this.pack(u, me, options))); | ||||
| 		return (await Promise.allSettled(users.map(u => this.pack(u, me, options)))) | ||||
| 			.filter(result => result.status === 'fulfilled') | ||||
| 			.map(result => (result as PromiseFulfilledResult<IsUserDetailed<D>>).value); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import type { UserListJoiningsRepository, UserListsRepository } from '@/models/index.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import type { } from '@/models/entities/Blocking.js'; | ||||
| import type { UserList } from '@/models/entities/UserList.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 まっちゃとーにゅ
					まっちゃとーにゅ