mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-10-31 21:44:12 +00:00 
			
		
		
		
	Merge branch 'develop' into release/2024.5.0
This commit is contained in:
		
						commit
						90ba1ca1f9
					
				
					 24 changed files with 268 additions and 87 deletions
				
			
		|  | @ -10,6 +10,8 @@ import { awaitAll } from '@/misc/prelude/await-all.js'; | |||
| import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -26,6 +28,11 @@ export class AbuseUserReportEntityService { | |||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: MiAbuseUserReport['id'] | MiAbuseUserReport, | ||||
| 		hint?: { | ||||
| 			packedReporter?: Packed<'UserDetailedNotMe'>, | ||||
| 			packedTargetUser?: Packed<'UserDetailedNotMe'>, | ||||
| 			packedAssignee?: Packed<'UserDetailedNotMe'>, | ||||
| 		}, | ||||
| 	) { | ||||
| 		const report = typeof src === 'object' ? src : await this.abuseUserReportsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -37,13 +44,13 @@ export class AbuseUserReportEntityService { | |||
| 			reporterId: report.reporterId, | ||||
| 			targetUserId: report.targetUserId, | ||||
| 			assigneeId: report.assigneeId, | ||||
| 			reporter: this.userEntityService.pack(report.reporter ?? report.reporterId, null, { | ||||
| 			reporter: hint?.packedReporter ?? this.userEntityService.pack(report.reporter ?? report.reporterId, null, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 			targetUser: this.userEntityService.pack(report.targetUser ?? report.targetUserId, null, { | ||||
| 			targetUser: hint?.packedTargetUser ?? this.userEntityService.pack(report.targetUser ?? report.targetUserId, null, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 			assignee: report.assigneeId ? this.userEntityService.pack(report.assignee ?? report.assigneeId, null, { | ||||
| 			assignee: report.assigneeId ? hint?.packedAssignee ?? this.userEntityService.pack(report.assignee ?? report.assigneeId, null, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}) : null, | ||||
| 			forwarded: report.forwarded, | ||||
|  | @ -51,9 +58,24 @@ export class AbuseUserReportEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		reports: any[], | ||||
| 	public async packMany( | ||||
| 		reports: MiAbuseUserReport[], | ||||
| 	) { | ||||
| 		return Promise.all(reports.map(x => this.pack(x))); | ||||
| 		const _reporters = reports.map(({ reporter, reporterId }) => reporter ?? reporterId); | ||||
| 		const _targetUsers = reports.map(({ targetUser, targetUserId }) => targetUser ?? targetUserId); | ||||
| 		const _assignees = reports.map(({ assignee, assigneeId }) => assignee ?? assigneeId).filter(isNotNull); | ||||
| 		const _userMap = await this.userEntityService.packMany( | ||||
| 			[..._reporters, ..._targetUsers, ..._assignees], | ||||
| 			null, | ||||
| 			{ schema: 'UserDetailedNotMe' }, | ||||
| 		).then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			reports.map(report => { | ||||
| 				const packedReporter = _userMap.get(report.reporterId); | ||||
| 				const packedTargetUser = _userMap.get(report.targetUserId); | ||||
| 				const packedAssignee = report.assigneeId != null ? _userMap.get(report.assigneeId) : undefined; | ||||
| 				return this.pack(report, { packedReporter, packedTargetUser, packedAssignee }); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ export class BlockingEntityService { | |||
| 	public async pack( | ||||
| 		src: MiBlocking['id'] | MiBlocking, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			blockee?: Packed<'UserDetailedNotMe'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'Blocking'>> { | ||||
| 		const blocking = typeof src === 'object' ? src : await this.blockingsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -36,17 +39,20 @@ export class BlockingEntityService { | |||
| 			id: blocking.id, | ||||
| 			createdAt: this.idService.parse(blocking.id).date.toISOString(), | ||||
| 			blockeeId: blocking.blockeeId, | ||||
| 			blockee: this.userEntityService.pack(blocking.blockeeId, me, { | ||||
| 			blockee: hint?.blockee ?? this.userEntityService.pack(blocking.blockeeId, me, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		blockings: any[], | ||||
| 	public async packMany( | ||||
| 		blockings: MiBlocking[], | ||||
| 		me: { id: MiUser['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(blockings.map(x => this.pack(x, me))); | ||||
| 		const _blockees = blockings.map(({ blockee, blockeeId }) => blockee ?? blockeeId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_blockees, me, { schema: 'UserDetailedNotMe' }) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(blockings.map(blocking => this.pack(blocking, me, { blockee: _userMap.get(blocking.blockeeId) }))); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -35,6 +35,9 @@ export class ClipEntityService { | |||
| 	public async pack( | ||||
| 		src: MiClip['id'] | MiClip, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'Clip'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const clip = typeof src === 'object' ? src : await this.clipsRepository.findOneByOrFail({ id: src }); | ||||
|  | @ -44,7 +47,7 @@ export class ClipEntityService { | |||
| 			createdAt: this.idService.parse(clip.id).date.toISOString(), | ||||
| 			lastClippedAt: clip.lastClippedAt ? clip.lastClippedAt.toISOString() : null, | ||||
| 			userId: clip.userId, | ||||
| 			user: this.userEntityService.pack(clip.user ?? clip.userId), | ||||
| 			user: hint?.packedUser ?? this.userEntityService.pack(clip.user ?? clip.userId), | ||||
| 			name: clip.name, | ||||
| 			description: clip.description, | ||||
| 			isPublic: clip.isPublic, | ||||
|  | @ -55,11 +58,14 @@ export class ClipEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 	public async packMany( | ||||
| 		clips: MiClip[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(clips.map(x => this.pack(x, me))); | ||||
| 		const _users = clips.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(clips.map(clip => this.pack(clip, me, { packedUser: _userMap.get(clip.userId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -222,6 +222,9 @@ export class DriveFileEntityService { | |||
| 	public async packNullable( | ||||
| 		src: MiDriveFile['id'] | MiDriveFile, | ||||
| 		options?: PackOptions, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'DriveFile'> | null> { | ||||
| 		const opts = Object.assign({ | ||||
| 			detail: false, | ||||
|  | @ -249,7 +252,7 @@ export class DriveFileEntityService { | |||
| 				detail: true, | ||||
| 			}) : null, | ||||
| 			userId: file.userId, | ||||
| 			user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId) : null, | ||||
| 			user: (opts.withUser && file.userId) ? hint?.packedUser ?? this.userEntityService.pack(file.userId) : null, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -258,7 +261,10 @@ export class DriveFileEntityService { | |||
| 		files: MiDriveFile[], | ||||
| 		options?: PackOptions, | ||||
| 	): Promise<Packed<'DriveFile'>[]> { | ||||
| 		const items = await Promise.all(files.map(f => this.packNullable(f, options))); | ||||
| 		const _user = files.map(({ user, userId }) => user ?? userId).filter(isNotNull); | ||||
| 		const _userMap = await this.userEntityService.packMany(_user) | ||||
| 			.then(users => new Map(users.map(user => [user.id, user]))); | ||||
| 		const items = await Promise.all(files.map(f => this.packNullable(f, options, f.userId ? { packedUser: _userMap.get(f.userId) } : {}))); | ||||
| 		return items.filter(isNotNull); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,6 +33,9 @@ export class FlashEntityService { | |||
| 	public async pack( | ||||
| 		src: MiFlash['id'] | MiFlash, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'Flash'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const flash = typeof src === 'object' ? src : await this.flashsRepository.findOneByOrFail({ id: src }); | ||||
|  | @ -42,7 +45,7 @@ export class FlashEntityService { | |||
| 			createdAt: this.idService.parse(flash.id).date.toISOString(), | ||||
| 			updatedAt: flash.updatedAt.toISOString(), | ||||
| 			userId: flash.userId, | ||||
| 			user: this.userEntityService.pack(flash.user ?? flash.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意
 | ||||
| 			user: hint?.packedUser ?? this.userEntityService.pack(flash.user ?? flash.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意
 | ||||
| 			title: flash.title, | ||||
| 			summary: flash.summary, | ||||
| 			script: flash.script, | ||||
|  | @ -52,11 +55,14 @@ export class FlashEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		flashs: MiFlash[], | ||||
| 	public async packMany( | ||||
| 		flashes: MiFlash[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(flashs.map(x => this.pack(x, me))); | ||||
| 		const _users = flashes.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(flashes.map(flash => this.pack(flash, me, { packedUser: _userMap.get(flash.userId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import type { } from '@/models/Blocking.js'; | |||
| import type { MiUser } from '@/models/User.js'; | ||||
| import type { MiFollowRequest } from '@/models/FollowRequest.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -26,14 +27,36 @@ export class FollowRequestEntityService { | |||
| 	public async pack( | ||||
| 		src: MiFollowRequest['id'] | MiFollowRequest, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			packedFollower?: Packed<'UserLite'>, | ||||
| 			packedFollowee?: Packed<'UserLite'>, | ||||
| 		}, | ||||
| 	) { | ||||
| 		const request = typeof src === 'object' ? src : await this.followRequestsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
| 		return { | ||||
| 			id: request.id, | ||||
| 			follower: await this.userEntityService.pack(request.followerId, me), | ||||
| 			followee: await this.userEntityService.pack(request.followeeId, me), | ||||
| 			follower: hint?.packedFollower ?? await this.userEntityService.pack(request.followerId, me), | ||||
| 			followee: hint?.packedFollowee ?? await this.userEntityService.pack(request.followeeId, me), | ||||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public async packMany( | ||||
| 		requests: MiFollowRequest[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		const _followers = requests.map(({ follower, followerId }) => follower ?? followerId); | ||||
| 		const _followees = requests.map(({ followee, followeeId }) => followee ?? followeeId); | ||||
| 		const _userMap = await this.userEntityService.packMany([..._followers, ..._followees], me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			requests.map(req => { | ||||
| 				const packedFollower = _userMap.get(req.followerId); | ||||
| 				const packedFollowee = _userMap.get(req.followeeId); | ||||
| 				return this.pack(req, me, { packedFollower, packedFollowee }); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -78,6 +78,10 @@ export class FollowingEntityService { | |||
| 			populateFollowee?: boolean; | ||||
| 			populateFollower?: boolean; | ||||
| 		}, | ||||
| 		hint?: { | ||||
| 			packedFollowee?: Packed<'UserDetailedNotMe'>, | ||||
| 			packedFollower?: Packed<'UserDetailedNotMe'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'Following'>> { | ||||
| 		const following = typeof src === 'object' ? src : await this.followingsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -88,25 +92,35 @@ export class FollowingEntityService { | |||
| 			createdAt: this.idService.parse(following.id).date.toISOString(), | ||||
| 			followeeId: following.followeeId, | ||||
| 			followerId: following.followerId, | ||||
| 			followee: opts.populateFollowee ? this.userEntityService.pack(following.followee ?? following.followeeId, me, { | ||||
| 			followee: opts.populateFollowee ? hint?.packedFollowee ?? this.userEntityService.pack(following.followee ?? following.followeeId, me, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}) : undefined, | ||||
| 			follower: opts.populateFollower ? this.userEntityService.pack(following.follower ?? following.followerId, me, { | ||||
| 			follower: opts.populateFollower ? hint?.packedFollower ?? this.userEntityService.pack(following.follower ?? following.followerId, me, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}) : undefined, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		followings: any[], | ||||
| 	public async packMany( | ||||
| 		followings: MiFollowing[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		opts?: { | ||||
| 			populateFollowee?: boolean; | ||||
| 			populateFollower?: boolean; | ||||
| 		}, | ||||
| 	) { | ||||
| 		return Promise.all(followings.map(x => this.pack(x, me, opts))); | ||||
| 		const _followees = opts?.populateFollowee ? followings.map(({ followee, followeeId }) => followee ?? followeeId) : []; | ||||
| 		const _followers = opts?.populateFollower ? followings.map(({ follower, followerId }) => follower ?? followerId) : []; | ||||
| 		const _userMap = await this.userEntityService.packMany([..._followees, ..._followers], me, { schema: 'UserDetailedNotMe' }) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			followings.map(following => { | ||||
| 				const packedFollowee = opts?.populateFollowee ? _userMap.get(following.followeeId) : undefined; | ||||
| 				const packedFollower = opts?.populateFollower ? _userMap.get(following.followerId) : undefined; | ||||
| 				return this.pack(following, me, opts, { packedFollowee, packedFollower }); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -35,6 +35,9 @@ export class GalleryPostEntityService { | |||
| 	public async pack( | ||||
| 		src: MiGalleryPost['id'] | MiGalleryPost, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'GalleryPost'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const post = typeof src === 'object' ? src : await this.galleryPostsRepository.findOneByOrFail({ id: src }); | ||||
|  | @ -44,7 +47,7 @@ export class GalleryPostEntityService { | |||
| 			createdAt: this.idService.parse(post.id).date.toISOString(), | ||||
| 			updatedAt: post.updatedAt.toISOString(), | ||||
| 			userId: post.userId, | ||||
| 			user: this.userEntityService.pack(post.user ?? post.userId, me), | ||||
| 			user: hint?.packedUser ?? this.userEntityService.pack(post.user ?? post.userId, me), | ||||
| 			title: post.title, | ||||
| 			description: post.description, | ||||
| 			fileIds: post.fileIds, | ||||
|  | @ -58,11 +61,14 @@ export class GalleryPostEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 	public async packMany( | ||||
| 		posts: MiGalleryPost[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(posts.map(x => this.pack(x, me))); | ||||
| 		const _users = posts.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(posts.map(post => this.pack(post, me, { packedUser: _userMap.get(post.userId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import type { MiUser } from '@/models/User.js'; | |||
| import type { MiRegistrationTicket } from '@/models/RegistrationTicket.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import { isNotNull } from '@/misc/is-not-null.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -29,6 +30,10 @@ export class InviteCodeEntityService { | |||
| 	public async pack( | ||||
| 		src: MiRegistrationTicket['id'] | MiRegistrationTicket, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hints?: { | ||||
| 			packedCreatedBy?: Packed<'UserLite'>, | ||||
| 			packedUsedBy?: Packed<'UserLite'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'InviteCode'>> { | ||||
| 		const target = typeof src === 'object' ? src : await this.registrationTicketsRepository.findOneOrFail({ | ||||
| 			where: { | ||||
|  | @ -42,18 +47,28 @@ export class InviteCodeEntityService { | |||
| 			code: target.code, | ||||
| 			expiresAt: target.expiresAt ? target.expiresAt.toISOString() : null, | ||||
| 			createdAt: this.idService.parse(target.id).date.toISOString(), | ||||
| 			createdBy: target.createdBy ? await this.userEntityService.pack(target.createdBy, me) : null, | ||||
| 			usedBy: target.usedBy ? await this.userEntityService.pack(target.usedBy, me) : null, | ||||
| 			createdBy: target.createdBy ? hints?.packedCreatedBy ?? await this.userEntityService.pack(target.createdBy, me) : null, | ||||
| 			usedBy: target.usedBy ? hints?.packedUsedBy ?? await this.userEntityService.pack(target.usedBy, me) : null, | ||||
| 			usedAt: target.usedAt ? target.usedAt.toISOString() : null, | ||||
| 			used: !!target.usedAt, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		targets: any[], | ||||
| 	public async packMany( | ||||
| 		tickets: MiRegistrationTicket[], | ||||
| 		me: { id: MiUser['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(targets.map(x => this.pack(x, me))); | ||||
| 		const _createdBys = tickets.map(({ createdBy, createdById }) => createdBy ?? createdById).filter(isNotNull); | ||||
| 		const _usedBys = tickets.map(({ usedBy, usedById }) => usedBy ?? usedById).filter(isNotNull); | ||||
| 		const _userMap = await this.userEntityService.packMany([..._createdBys, ..._usedBys], me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			tickets.map(ticket => { | ||||
| 				const packedCreatedBy = ticket.createdById != null ? _userMap.get(ticket.createdById) : undefined; | ||||
| 				const packedUsedBy = ticket.usedById != null ? _userMap.get(ticket.usedById) : undefined; | ||||
| 				return this.pack(ticket, me, { packedCreatedBy, packedUsedBy }); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -8,9 +8,10 @@ import { DI } from '@/di-symbols.js'; | |||
| import type { ModerationLogsRepository } from '@/models/_.js'; | ||||
| import { awaitAll } from '@/misc/prelude/await-all.js'; | ||||
| import type { } from '@/models/Blocking.js'; | ||||
| import type { MiModerationLog } from '@/models/ModerationLog.js'; | ||||
| import { MiModerationLog } from '@/models/ModerationLog.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { IdService } from '@/core/IdService.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { UserEntityService } from './UserEntityService.js'; | ||||
| 
 | ||||
| @Injectable() | ||||
|  | @ -27,6 +28,9 @@ export class ModerationLogEntityService { | |||
| 	@bindThis | ||||
| 	public async pack( | ||||
| 		src: MiModerationLog['id'] | MiModerationLog, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserDetailedNotMe'>, | ||||
| 		}, | ||||
| 	) { | ||||
| 		const log = typeof src === 'object' ? src : await this.moderationLogsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -36,17 +40,20 @@ export class ModerationLogEntityService { | |||
| 			type: log.type, | ||||
| 			info: log.info, | ||||
| 			userId: log.userId, | ||||
| 			user: this.userEntityService.pack(log.user ?? log.userId, null, { | ||||
| 			user: hint?.packedUser ?? this.userEntityService.pack(log.user ?? log.userId, null, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		reports: any[], | ||||
| 	public async packMany( | ||||
| 		reports: MiModerationLog[], | ||||
| 	) { | ||||
| 		return Promise.all(reports.map(x => this.pack(x))); | ||||
| 		const _users = reports.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, null, { schema: 'UserDetailedNotMe' }) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(reports.map(report => this.pack(report, { packedUser: _userMap.get(report.userId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,9 @@ export class MutingEntityService { | |||
| 	public async pack( | ||||
| 		src: MiMuting['id'] | MiMuting, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hints?: { | ||||
| 			packedMutee?: Packed<'UserDetailedNotMe'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'Muting'>> { | ||||
| 		const muting = typeof src === 'object' ? src : await this.mutingsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -38,18 +41,21 @@ export class MutingEntityService { | |||
| 			createdAt: this.idService.parse(muting.id).date.toISOString(), | ||||
| 			expiresAt: muting.expiresAt ? muting.expiresAt.toISOString() : null, | ||||
| 			muteeId: muting.muteeId, | ||||
| 			mutee: this.userEntityService.pack(muting.muteeId, me, { | ||||
| 			mutee: hints?.packedMutee ?? this.userEntityService.pack(muting.muteeId, me, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		mutings: any[], | ||||
| 	public async packMany( | ||||
| 		mutings: MiMuting[], | ||||
| 		me: { id: MiUser['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(mutings.map(x => this.pack(x, me))); | ||||
| 		const _mutees = mutings.map(({ mutee, muteeId }) => mutee ?? muteeId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_mutees, me, { schema: 'UserDetailedNotMe' }) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(mutings.map(muting => this.pack(muting, me, { packedMutee: _userMap.get(muting.muteeId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -290,6 +290,7 @@ export class NoteEntityService implements OnModuleInit { | |||
| 			_hint_?: { | ||||
| 				myReactions: Map<MiNote['id'], string | null>; | ||||
| 				packedFiles: Map<MiNote['fileIds'][number], Packed<'DriveFile'> | null>; | ||||
| 				packedUsers: Map<MiUser['id'], Packed<'UserLite'>> | ||||
| 			}; | ||||
| 		}, | ||||
| 	): Promise<Packed<'Note'>> { | ||||
|  | @ -319,12 +320,13 @@ export class NoteEntityService implements OnModuleInit { | |||
| 			.filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ
 | ||||
| 			.map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', '')); | ||||
| 		const packedFiles = options?._hint_?.packedFiles; | ||||
| 		const packedUsers = options?._hint_?.packedUsers; | ||||
| 
 | ||||
| 		const packed: Packed<'Note'> = await awaitAll({ | ||||
| 			id: note.id, | ||||
| 			createdAt: this.idService.parse(note.id).date.toISOString(), | ||||
| 			userId: note.userId, | ||||
| 			user: this.userEntityService.pack(note.user ?? note.userId, me), | ||||
| 			user: packedUsers?.get(note.userId) ?? this.userEntityService.pack(note.user ?? note.userId, me), | ||||
| 			text: text, | ||||
| 			cw: note.cw, | ||||
| 			visibility: note.visibility, | ||||
|  | @ -449,12 +451,20 @@ export class NoteEntityService implements OnModuleInit { | |||
| 		// 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 users = [ | ||||
| 			...notes.map(({ user, userId }) => user ?? userId), | ||||
| 			...notes.map(({ replyUserId }) => replyUserId).filter(isNotNull), | ||||
| 			...notes.map(({ renoteUserId }) => renoteUserId).filter(isNotNull), | ||||
| 		]; | ||||
| 		const packedUsers = await this.userEntityService.packMany(users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 
 | ||||
| 		return await Promise.all(notes.map(n => this.pack(n, me, { | ||||
| 			...options, | ||||
| 			_hint_: { | ||||
| 				myReactions: myReactionsMap, | ||||
| 				packedFiles, | ||||
| 				packedUsers, | ||||
| 			}, | ||||
| 		}))); | ||||
| 	} | ||||
|  |  | |||
|  | @ -52,6 +52,9 @@ export class NoteReactionEntityService implements OnModuleInit { | |||
| 		options?: { | ||||
| 			withNote: boolean; | ||||
| 		}, | ||||
| 		hints?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'NoteReaction'>> { | ||||
| 		const opts = Object.assign({ | ||||
| 			withNote: false, | ||||
|  | @ -62,7 +65,7 @@ export class NoteReactionEntityService implements OnModuleInit { | |||
| 		return { | ||||
| 			id: reaction.id, | ||||
| 			createdAt: this.idService.parse(reaction.id).date.toISOString(), | ||||
| 			user: await this.userEntityService.pack(reaction.user ?? reaction.userId, me), | ||||
| 			user: hints?.packedUser ?? await this.userEntityService.pack(reaction.user ?? reaction.userId, me), | ||||
| 			type: this.reactionService.convertLegacyReaction(reaction.reaction), | ||||
| 			...(opts.withNote ? { | ||||
| 				note: await this.noteEntityService.pack(reaction.note ?? reaction.noteId, me), | ||||
|  | @ -81,7 +84,9 @@ export class NoteReactionEntityService implements OnModuleInit { | |||
| 		const opts = Object.assign({ | ||||
| 			withNote: false, | ||||
| 		}, options); | ||||
| 
 | ||||
| 		return Promise.all(reactions.map(reaction => this.pack(reaction, me, opts))); | ||||
| 		const _users = reactions.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(reactions.map(reaction => this.pack(reaction, me, opts, { packedUser: _userMap.get(reaction.userId) }))); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -40,6 +40,9 @@ export class PageEntityService { | |||
| 	public async pack( | ||||
| 		src: MiPage['id'] | MiPage, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hint?: { | ||||
| 			packedUser?: Packed<'UserLite'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'Page'>> { | ||||
| 		const meId = me ? me.id : null; | ||||
| 		const page = typeof src === 'object' ? src : await this.pagesRepository.findOneByOrFail({ id: src }); | ||||
|  | @ -91,7 +94,7 @@ export class PageEntityService { | |||
| 			createdAt: this.idService.parse(page.id).date.toISOString(), | ||||
| 			updatedAt: page.updatedAt.toISOString(), | ||||
| 			userId: page.userId, | ||||
| 			user: this.userEntityService.pack(page.user ?? page.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意
 | ||||
| 			user: hint?.packedUser ?? this.userEntityService.pack(page.user ?? page.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意
 | ||||
| 			content: page.content, | ||||
| 			variables: page.variables, | ||||
| 			title: page.title, | ||||
|  | @ -110,11 +113,14 @@ export class PageEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 	public async packMany( | ||||
| 		pages: MiPage[], | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 	) { | ||||
| 		return Promise.all(pages.map(x => this.pack(x, me))); | ||||
| 		const _users = pages.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(pages.map(page => this.pack(page, me, { packedUser: _userMap.get(page.userId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,9 @@ export class RenoteMutingEntityService { | |||
| 	public async pack( | ||||
| 		src: MiRenoteMuting['id'] | MiRenoteMuting, | ||||
| 		me?: { id: MiUser['id'] } | null | undefined, | ||||
| 		hints?: { | ||||
| 			packedMutee?: Packed<'UserDetailedNotMe'> | ||||
| 		}, | ||||
| 	): Promise<Packed<'RenoteMuting'>> { | ||||
| 		const muting = typeof src === 'object' ? src : await this.renoteMutingsRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
|  | @ -37,18 +40,21 @@ export class RenoteMutingEntityService { | |||
| 			id: muting.id, | ||||
| 			createdAt: this.idService.parse(muting.id).date.toISOString(), | ||||
| 			muteeId: muting.muteeId, | ||||
| 			mutee: this.userEntityService.pack(muting.muteeId, me, { | ||||
| 			mutee: hints?.packedMutee ?? this.userEntityService.pack(muting.muteeId, me, { | ||||
| 				schema: 'UserDetailedNotMe', | ||||
| 			}), | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packMany( | ||||
| 		mutings: any[], | ||||
| 	public async packMany( | ||||
| 		mutings: MiRenoteMuting[], | ||||
| 		me: { id: MiUser['id'] }, | ||||
| 	) { | ||||
| 		return Promise.all(mutings.map(x => this.pack(x, me))); | ||||
| 		const _users = mutings.map(({ mutee, muteeId }) => mutee ?? muteeId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailedNotMe' }) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(mutings.map(muting => this.pack(muting, me, { packedMutee: _userMap.get(muting.muteeId) }))); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,13 +28,15 @@ export class ReversiGameEntityService { | |||
| 	@bindThis | ||||
| 	public async packDetail( | ||||
| 		src: MiReversiGame['id'] | MiReversiGame, | ||||
| 		hint?: { | ||||
| 			packedUser1?: Packed<'UserLite'>, | ||||
| 			packedUser2?: Packed<'UserLite'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'ReversiGameDetailed'>> { | ||||
| 		const game = typeof src === 'object' ? src : await this.reversiGamesRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
| 		const users = await Promise.all([ | ||||
| 			this.userEntityService.pack(game.user1 ?? game.user1Id), | ||||
| 			this.userEntityService.pack(game.user2 ?? game.user2Id), | ||||
| 		]); | ||||
| 		const user1 = hint?.packedUser1 ?? await this.userEntityService.pack(game.user1 ?? game.user1Id); | ||||
| 		const user2 = hint?.packedUser2 ?? await this.userEntityService.pack(game.user2 ?? game.user2Id); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
| 			id: game.id, | ||||
|  | @ -49,10 +51,10 @@ export class ReversiGameEntityService { | |||
| 			user2Ready: game.user2Ready, | ||||
| 			user1Id: game.user1Id, | ||||
| 			user2Id: game.user2Id, | ||||
| 			user1: users[0], | ||||
| 			user2: users[1], | ||||
| 			user1, | ||||
| 			user2, | ||||
| 			winnerId: game.winnerId, | ||||
| 			winner: game.winnerId ? users.find(u => u.id === game.winnerId)! : null, | ||||
| 			winner: game.winnerId ? [user1, user2].find(u => u.id === game.winnerId)! : null, | ||||
| 			surrenderedUserId: game.surrenderedUserId, | ||||
| 			timeoutUserId: game.timeoutUserId, | ||||
| 			black: game.black, | ||||
|  | @ -68,22 +70,35 @@ export class ReversiGameEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packDetailMany( | ||||
| 		xs: MiReversiGame[], | ||||
| 	public async packDetailMany( | ||||
| 		games: MiReversiGame[], | ||||
| 	) { | ||||
| 		return Promise.all(xs.map(x => this.packDetail(x))); | ||||
| 		const _user1s = games.map(({ user1, user1Id }) => user1 ?? user1Id); | ||||
| 		const _user2s = games.map(({ user2, user2Id }) => user2 ?? user2Id); | ||||
| 		const _userMap = await this.userEntityService.packMany([..._user1s, ..._user2s]) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			games.map(game => { | ||||
| 				return this.packDetail(game, { | ||||
| 					packedUser1: _userMap.get(game.user1Id), | ||||
| 					packedUser2: _userMap.get(game.user2Id), | ||||
| 				}); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public async packLite( | ||||
| 		src: MiReversiGame['id'] | MiReversiGame, | ||||
| 		hint?: { | ||||
| 			packedUser1?: Packed<'UserLite'>, | ||||
| 			packedUser2?: Packed<'UserLite'>, | ||||
| 		}, | ||||
| 	): Promise<Packed<'ReversiGameLite'>> { | ||||
| 		const game = typeof src === 'object' ? src : await this.reversiGamesRepository.findOneByOrFail({ id: src }); | ||||
| 
 | ||||
| 		const users = await Promise.all([ | ||||
| 			this.userEntityService.pack(game.user1 ?? game.user1Id), | ||||
| 			this.userEntityService.pack(game.user2 ?? game.user2Id), | ||||
| 		]); | ||||
| 		const user1 = hint?.packedUser1 ?? await this.userEntityService.pack(game.user1 ?? game.user1Id); | ||||
| 		const user2 = hint?.packedUser2 ?? await this.userEntityService.pack(game.user2 ?? game.user2Id); | ||||
| 
 | ||||
| 		return await awaitAll({ | ||||
| 			id: game.id, | ||||
|  | @ -94,10 +109,10 @@ export class ReversiGameEntityService { | |||
| 			isEnded: game.isEnded, | ||||
| 			user1Id: game.user1Id, | ||||
| 			user2Id: game.user2Id, | ||||
| 			user1: users[0], | ||||
| 			user2: users[1], | ||||
| 			user1, | ||||
| 			user2, | ||||
| 			winnerId: game.winnerId, | ||||
| 			winner: game.winnerId ? users.find(u => u.id === game.winnerId)! : null, | ||||
| 			winner: game.winnerId ? [user1, user2].find(u => u.id === game.winnerId)! : null, | ||||
| 			surrenderedUserId: game.surrenderedUserId, | ||||
| 			timeoutUserId: game.timeoutUserId, | ||||
| 			black: game.black, | ||||
|  | @ -111,10 +126,21 @@ export class ReversiGameEntityService { | |||
| 	} | ||||
| 
 | ||||
| 	@bindThis | ||||
| 	public packLiteMany( | ||||
| 		xs: MiReversiGame[], | ||||
| 	public async packLiteMany( | ||||
| 		games: MiReversiGame[], | ||||
| 	) { | ||||
| 		return Promise.all(xs.map(x => this.packLite(x))); | ||||
| 		const _user1s = games.map(({ user1, user1Id }) => user1 ?? user1Id); | ||||
| 		const _user2s = games.map(({ user2, user2Id }) => user2 ?? user2Id); | ||||
| 		const _userMap = await this.userEntityService.packMany([..._user1s, ..._user2s]) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all( | ||||
| 			games.map(game => { | ||||
| 				return this.packLite(game, { | ||||
| 					packedUser1: _userMap.get(game.user1Id), | ||||
| 					packedUser2: _userMap.get(game.user2Id), | ||||
| 				}); | ||||
| 			}), | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,11 +50,14 @@ export class UserListEntityService { | |||
| 	public async packMembershipsMany( | ||||
| 		memberships: MiUserListMembership[], | ||||
| 	) { | ||||
| 		const _users = memberships.map(({ user, userId }) => user ?? userId); | ||||
| 		const _userMap = await this.userEntityService.packMany(_users) | ||||
| 			.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 		return Promise.all(memberships.map(async x => ({ | ||||
| 			id: x.id, | ||||
| 			createdAt: this.idService.parse(x.id).date.toISOString(), | ||||
| 			userId: x.userId, | ||||
| 			user: await this.userEntityService.pack(x.userId), | ||||
| 			user: _userMap.get(x.userId) ?? await this.userEntityService.pack(x.userId), | ||||
| 			withReplies: x.withReplies, | ||||
| 		}))); | ||||
| 	} | ||||
|  |  | |||
|  | @ -89,10 +89,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				.limit(ps.limit) | ||||
| 				.getMany(); | ||||
| 
 | ||||
| 			const _users = assigns.map(({ user, userId }) => user ?? userId); | ||||
| 			const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailed' }) | ||||
| 				.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 			return await Promise.all(assigns.map(async assign => ({ | ||||
| 				id: assign.id, | ||||
| 				createdAt: this.idService.parse(assign.id).date.toISOString(), | ||||
| 				user: await this.userEntityService.pack(assign.user!, me, { schema: 'UserDetailed' }), | ||||
| 				user: _userMap.get(assign.userId) ?? await this.userEntityService.pack(assign.user!, me, { schema: 'UserDetailed' }), | ||||
| 				expiresAt: assign.expiresAt?.toISOString() ?? null, | ||||
| 			}))); | ||||
| 		}); | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				folderId: ps.folderId ?? IsNull(), | ||||
| 			}); | ||||
| 
 | ||||
| 			return await Promise.all(files.map(file => this.driveFileEntityService.pack(file, { self: true }))); | ||||
| 			return await this.driveFileEntityService.packMany(files, { self: true }); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				.limit(ps.limit) | ||||
| 				.getMany(); | ||||
| 
 | ||||
| 			return await Promise.all(requests.map(req => this.followRequestEntityService.pack(req))); | ||||
| 			return await this.followRequestEntityService.packMany(requests, me); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 
 | ||||
| 			const reactions = await query.limit(ps.limit).getMany(); | ||||
| 
 | ||||
| 			return await Promise.all(reactions.map(reaction => this.noteReactionEntityService.pack(reaction, me))); | ||||
| 			return await this.noteReactionEntityService.packMany(reactions, me); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -92,9 +92,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				.limit(ps.limit) | ||||
| 				.getMany(); | ||||
| 
 | ||||
| 			const _users = assigns.map(({ user, userId }) => user ?? userId); | ||||
| 			const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailed' }) | ||||
| 				.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 			return await Promise.all(assigns.map(async assign => ({ | ||||
| 				id: assign.id, | ||||
| 				user: await this.userEntityService.pack(assign.user!, me, { schema: 'UserDetailed' }), | ||||
| 				user: _userMap.get(assign.userId) ?? await this.userEntityService.pack(assign.user!, me, { schema: 'UserDetailed' }), | ||||
| 			}))); | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
|  | @ -118,12 +118,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 			const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]); | ||||
| 
 | ||||
| 			// Extract top replied users
 | ||||
| 			const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit); | ||||
| 			const topRepliedUserIds = repliedUsersSorted.slice(0, ps.limit); | ||||
| 
 | ||||
| 			// Make replies object (includes weights)
 | ||||
| 			const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({ | ||||
| 				user: await this.userEntityService.pack(user, me, { schema: 'UserDetailed' }), | ||||
| 				weight: repliedUsers[user] / peak, | ||||
| 			const _userMap = await this.userEntityService.packMany(topRepliedUserIds, me, { schema: 'UserDetailed' }) | ||||
| 				.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 			const repliesObj = await Promise.all(topRepliedUserIds.map(async (userId) => ({ | ||||
| 				user: _userMap.get(userId) ?? await this.userEntityService.pack(userId, me, { schema: 'UserDetailed' }), | ||||
| 				weight: repliedUsers[userId] / peak, | ||||
| 			}))); | ||||
| 
 | ||||
| 			return repliesObj; | ||||
|  |  | |||
|  | @ -117,9 +117,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 					if (user != null) _users.push(user); | ||||
| 				} | ||||
| 
 | ||||
| 				return await Promise.all(_users.map(u => this.userEntityService.pack(u, me, { | ||||
| 					schema: 'UserDetailed', | ||||
| 				}))); | ||||
| 				const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailed' }) | ||||
| 					.then(users => new Map(users.map(u => [u.id, u]))); | ||||
| 				return _users.map(u => _userMap.get(u.id)!); | ||||
| 			} else { | ||||
| 				// Lookup user
 | ||||
| 				if (typeof ps.host === 'string' && typeof ps.username === 'string') { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue