feat: 凍結されたユーザーのコンテンツを見えないようにする (MisskeyIO#134)
ついでにEntityServiceの型定義、meのoptionalをやめる
This commit is contained in:
parent
3b73874196
commit
7f0acd3ea4
|
@ -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';
|
||||
|
|
|
@ -7,29 +7,32 @@ import {
|
|||
packedUserDetailedSchema,
|
||||
packedUserSchema,
|
||||
} from '@/models/json-schema/user.js';
|
||||
import { packedNoteSchema } from '@/models/json-schema/note.js';
|
||||
import { packedUserListSchema } from '@/models/json-schema/user-list.js';
|
||||
import { packedAbuseUserReportSchema } from '@/models/json-schema/abuse-user-report.js';
|
||||
import { packedAntennaSchema } from '@/models/json-schema/antenna.js';
|
||||
import { packedAppSchema } from '@/models/json-schema/app.js';
|
||||
import { packedNotificationSchema } from '@/models/json-schema/notification.js';
|
||||
import { packedBlockingSchema } from '@/models/json-schema/blocking.js';
|
||||
import { packedChannelSchema } from '@/models/json-schema/channel.js';
|
||||
import { packedClipSchema } from '@/models/json-schema/clip.js';
|
||||
import { packedDriveFileSchema } from '@/models/json-schema/drive-file.js';
|
||||
import { packedDriveFolderSchema } from '@/models/json-schema/drive-folder.js';
|
||||
import { packedFollowingSchema } from '@/models/json-schema/following.js';
|
||||
import { packedMutingSchema } from '@/models/json-schema/muting.js';
|
||||
import { packedRenoteMutingSchema } from '@/models/json-schema/renote-muting.js';
|
||||
import { packedBlockingSchema } from '@/models/json-schema/blocking.js';
|
||||
import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js';
|
||||
import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
|
||||
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
|
||||
import { packedFlashLikeSchema, packedFlashSchema } from '@/models/json-schema/flash.js';
|
||||
import { packedFollowRequestSchema, packedFollowingSchema } from '@/models/json-schema/following.js';
|
||||
import { packedGalleryLikeSchema, packedGalleryPostSchema } from '@/models/json-schema/gallery.js';
|
||||
import { packedHashtagSchema } from '@/models/json-schema/hashtag.js';
|
||||
import { packedInviteCodeSchema } from '@/models/json-schema/invite-code.js';
|
||||
import { packedPageSchema } from '@/models/json-schema/page.js';
|
||||
import { packedModerationLogSchema } from '@/models/json-schema/moderation-log.js';
|
||||
import { packedMutingSchema } from '@/models/json-schema/muting.js';
|
||||
import { packedNoteFavoriteSchema } from '@/models/json-schema/note-favorite.js';
|
||||
import { packedChannelSchema } from '@/models/json-schema/channel.js';
|
||||
import { packedAntennaSchema } from '@/models/json-schema/antenna.js';
|
||||
import { packedClipSchema } from '@/models/json-schema/clip.js';
|
||||
import { packedFederationInstanceSchema } from '@/models/json-schema/federation-instance.js';
|
||||
import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js';
|
||||
import { packedNoteSchema } from '@/models/json-schema/note.js';
|
||||
import { packedNotificationSchema } from '@/models/json-schema/notification.js';
|
||||
import { packedPageLikeSchema, packedPageSchema } from '@/models/json-schema/page.js';
|
||||
import { packedQueueCountSchema } from '@/models/json-schema/queue.js';
|
||||
import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js';
|
||||
import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
|
||||
import { packedFlashSchema } from '@/models/json-schema/flash.js';
|
||||
import { packedRenoteMutingSchema } from '@/models/json-schema/renote-muting.js';
|
||||
import { packedRoleSchema } from '@/models/json-schema/role.js';
|
||||
import { packedUserListSchema } from '@/models/json-schema/user-list.js';
|
||||
|
||||
export const refs = {
|
||||
UserLite: packedUserLiteSchema,
|
||||
|
@ -49,21 +52,29 @@ export const refs = {
|
|||
DriveFile: packedDriveFileSchema,
|
||||
DriveFolder: packedDriveFolderSchema,
|
||||
Following: packedFollowingSchema,
|
||||
FollowRequest: packedFollowRequestSchema,
|
||||
Muting: packedMutingSchema,
|
||||
RenoteMuting: packedRenoteMutingSchema,
|
||||
Blocking: packedBlockingSchema,
|
||||
Hashtag: packedHashtagSchema,
|
||||
InviteCode: packedInviteCodeSchema,
|
||||
Page: packedPageSchema,
|
||||
PageLike: packedPageLikeSchema,
|
||||
Channel: packedChannelSchema,
|
||||
QueueCount: packedQueueCountSchema,
|
||||
Antenna: packedAntennaSchema,
|
||||
Clip: packedClipSchema,
|
||||
FederationInstance: packedFederationInstanceSchema,
|
||||
GalleryPost: packedGalleryPostSchema,
|
||||
GalleryLike: packedGalleryLikeSchema,
|
||||
EmojiSimple: packedEmojiSimpleSchema,
|
||||
EmojiDetailed: packedEmojiDetailedSchema,
|
||||
Flash: packedFlashSchema,
|
||||
FlashLike: packedFlashLikeSchema,
|
||||
|
||||
Role: packedRoleSchema,
|
||||
AbuseUserReport: packedAbuseUserReportSchema,
|
||||
ModerationLog: packedModerationLogSchema,
|
||||
};
|
||||
|
||||
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
|
||||
|
|
58
packages/backend/src/models/json-schema/abuse-user-report.ts
Normal file
58
packages/backend/src/models/json-schema/abuse-user-report.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
export const packedAbuseUserReportSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
comment: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
resolved: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
reporterId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
reporter: {
|
||||
type: 'object',
|
||||
ref: 'UserDetailed',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
targetUserId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
targetUser: {
|
||||
type: 'object',
|
||||
ref: 'UserDetailed',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
assigneeId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
format: 'id',
|
||||
},
|
||||
assignee: {
|
||||
type: 'object',
|
||||
ref: 'UserDetailed',
|
||||
optional: true, nullable: true,
|
||||
},
|
||||
forwarded: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
|
@ -49,3 +49,20 @@ export const packedFlashSchema = {
|
|||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const packedFlashLikeSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
flash: {
|
||||
type: 'object',
|
||||
ref: 'Flash',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
|
@ -34,3 +34,25 @@ export const packedFollowingSchema = {
|
|||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const packedFollowRequestSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
follower: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'UserLite',
|
||||
},
|
||||
followee: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'UserLite',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
|
@ -67,3 +67,20 @@ export const packedGalleryPostSchema = {
|
|||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const packedGalleryLikeSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
post: {
|
||||
type: 'object',
|
||||
ref: 'GalleryPost',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
41
packages/backend/src/models/json-schema/moderation-log.ts
Normal file
41
packages/backend/src/models/json-schema/moderation-log.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
export const packedModerationLogSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
info: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
patternProperties: {
|
||||
'^': {
|
||||
type: 'object',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
user: {
|
||||
type: 'object',
|
||||
ref: 'UserDetailed',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
|
@ -49,3 +49,20 @@ export const packedPageSchema = {
|
|||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const packedPageLikeSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
page: {
|
||||
type: 'object',
|
||||
ref: 'Page',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
103
packages/backend/src/models/json-schema/role.ts
Normal file
103
packages/backend/src/models/json-schema/role.ts
Normal file
|
@ -0,0 +1,103 @@
|
|||
export const packedRoleSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'date-time',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
color: {
|
||||
type: 'string',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
iconUrl: {
|
||||
type: 'string',
|
||||
format: 'url',
|
||||
optional: false, nullable: true,
|
||||
},
|
||||
target: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
enum: ['manual', 'conditional'],
|
||||
},
|
||||
condFormula: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
isPublic: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
isAdministrator: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
isModerator: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
isExplorable: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
asBadge: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
canEditMembersByModerator: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
displayOrder: {
|
||||
type: 'number',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
policies: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
patternProperties: {
|
||||
'^': {
|
||||
type: 'object',
|
||||
nullable: false, optional: false,
|
||||
properties: {
|
||||
useDefault: {
|
||||
type: 'boolean',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
priority: {
|
||||
type: 'number',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
value: {
|
||||
type: 'object',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
usersCount: {
|
||||
type: 'number',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
|
@ -101,7 +101,7 @@ export class ExportNotesProcessorService {
|
|||
if (note.hasPoll) {
|
||||
poll = await this.pollsRepository.findOneByOrFail({ noteId: note.id });
|
||||
}
|
||||
const files = await this.driveFileEntityService.packManyByIds(note.fileIds);
|
||||
const files = await this.driveFileEntityService.packManyByIds(note.fileIds, user);
|
||||
const content = JSON.stringify(serialize(note, poll, files));
|
||||
const isFirst = exportedNotesCount === 0;
|
||||
await write(isFirst ? content : ',\n' + content);
|
||||
|
|
|
@ -71,7 +71,7 @@ export class NodeinfoServerService {
|
|||
const activeHalfyear = null;
|
||||
const activeMonth = null;
|
||||
|
||||
const proxyAccount = meta.proxyAccountId ? await this.userEntityService.pack(meta.proxyAccountId).catch(() => null) : null;
|
||||
const proxyAccount = meta.proxyAccountId ? await this.userEntityService.pack(meta.proxyAccountId, null).catch(() => null) : null;
|
||||
|
||||
const basePolicies = { ...DEFAULT_POLICIES, ...meta.policies };
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import { MetaService } from '@/core/MetaService.js';
|
|||
import { createTemp } from '@/misc/create-temp.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { ApiError } from './error.js';
|
||||
import { RateLimiterService } from './RateLimiterService.js';
|
||||
import { ApiLoggerService } from './ApiLoggerService.js';
|
||||
|
@ -356,7 +357,7 @@ export class ApiCallService implements OnApplicationShutdown {
|
|||
|
||||
// API invoking
|
||||
return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => {
|
||||
if (err instanceof ApiError || err instanceof AuthenticationError) {
|
||||
if (err instanceof ApiError || err instanceof IdentifiableError || err instanceof AuthenticationError) {
|
||||
throw err;
|
||||
} else {
|
||||
const errId = randomUUID();
|
||||
|
|
|
@ -155,7 +155,7 @@ export class ApiServerService {
|
|||
return {
|
||||
ok: true,
|
||||
token: token.token,
|
||||
user: await this.userEntityService.pack(token.userId, null, { detail: true }),
|
||||
user: await this.userEntityService.pack(token.userId, { id: token.userId }, { detail: true }),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
|
|
|
@ -117,7 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const reports = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.abuseUserReportEntityService.packMany(reports);
|
||||
return await this.abuseUserReportEntityService.packMany(reports, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const files = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.driveFileEntityService.packMany(files, { detail: true, withUser: true, self: true });
|
||||
return await this.driveFileEntityService.packMany(files, me, { detail: true, withUser: true, self: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const reports = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.moderationLogEntityService.packMany(reports);
|
||||
return await this.moderationLogEntityService.packMany(reports, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
secret: secret,
|
||||
}).then(x => this.appsRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
return await this.appEntityService.pack(app, null, {
|
||||
return await this.appEntityService.pack(app, me, {
|
||||
detail: true,
|
||||
includeSecret: true,
|
||||
});
|
||||
|
|
|
@ -110,7 +110,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
return {
|
||||
accessToken: accessToken.token,
|
||||
user: await this.userEntityService.pack(session.userId, null, {
|
||||
user: await this.userEntityService.pack(session.userId, me, {
|
||||
detail: true,
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -75,7 +75,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const files = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.driveFileEntityService.packMany(files, { detail: false, self: true });
|
||||
return await this.driveFileEntityService.packMany(files, me, { detail: false, self: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
requestIp: instance.enableIpLogging ? ip : null,
|
||||
requestHeaders: instance.enableIpLogging ? headers : null,
|
||||
});
|
||||
return await this.driveFileEntityService.pack(driveFile, { self: true });
|
||||
return await this.driveFileEntityService.pack(driveFile, me, { self: true });
|
||||
} catch (err) {
|
||||
if (err instanceof Error || typeof err === 'string') {
|
||||
console.error(err);
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
userId: me.id,
|
||||
});
|
||||
|
||||
return await this.driveFileEntityService.packMany(files, { self: true });
|
||||
return await this.driveFileEntityService.packMany(files, me, { self: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
folderId: ps.folderId ?? IsNull(),
|
||||
});
|
||||
|
||||
return await Promise.all(files.map(file => this.driveFileEntityService.pack(file, { self: true })));
|
||||
return await Promise.all(files.map(file => this.driveFileEntityService.pack(file, me, { self: true })));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
return await this.driveFileEntityService.pack(file, {
|
||||
return await this.driveFileEntityService.pack(file, me, {
|
||||
detail: true,
|
||||
withUser: true,
|
||||
self: true,
|
||||
|
|
|
@ -129,7 +129,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
isSensitive: file.isSensitive,
|
||||
});
|
||||
|
||||
const fileObj = await this.driveFileEntityService.pack(file, { self: true });
|
||||
const fileObj = await this.driveFileEntityService.pack(file, me, { self: true });
|
||||
|
||||
// Publish fileUpdated event
|
||||
this.globalEventService.publishDriveStream(me.id, 'fileUpdated', fileObj);
|
||||
|
|
|
@ -51,7 +51,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
) {
|
||||
super(meta, paramDef, async (ps, user, _1, _2, _3, ip, headers) => {
|
||||
this.driveService.uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment, requestIp: ip, requestHeaders: headers }).then(file => {
|
||||
this.driveFileEntityService.pack(file, { self: true }).then(packedFile => {
|
||||
this.driveFileEntityService.pack(file, user, { self: true }).then(packedFile => {
|
||||
this.globalEventService.publishMainStream(user.id, 'urlUploadFinished', {
|
||||
marker: ps.marker,
|
||||
file: packedFile,
|
||||
|
|
|
@ -58,7 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const files = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.driveFileEntityService.packMany(files, { detail: false, self: true });
|
||||
return await this.driveFileEntityService.packMany(files, me, { detail: false, self: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
permissions: ps.permissions,
|
||||
}).then(x => this.flashsRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
return await this.flashEntityService.pack(flash);
|
||||
return await this.flashEntityService.pack(flash, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return await this.flashEntityService.packMany(flashs);
|
||||
return await this.flashEntityService.packMany(flashs, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return await Promise.all(requests.map(req => this.followRequestEntityService.pack(req)));
|
||||
return await this.followRequestEntityService.packMany(requests, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return await this.pageEntityService.packMany(pages);
|
||||
return await this.pageEntityService.packMany(pages, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,7 +341,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
};
|
||||
|
||||
if (ps.detail) {
|
||||
const proxyAccount = instance.proxyAccountId ? await this.userEntityService.pack(instance.proxyAccountId).catch(() => null) : null;
|
||||
const proxyAccount = instance.proxyAccountId ? await this.userEntityService.pack(instance.proxyAccountId, null).catch(() => null) : null;
|
||||
|
||||
response.proxyAccountName = proxyAccount ? proxyAccount.username : null;
|
||||
response.features = {
|
||||
|
|
|
@ -81,7 +81,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
const notes = await query.limit(ps.limit).getMany();
|
||||
|
||||
return await this.noteEntityService.packMany(notes);
|
||||
return await this.noteEntityService.packMany(notes, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
font: ps.font,
|
||||
})).then(x => this.pagesRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
return await this.pageEntityService.pack(page);
|
||||
return await this.pageEntityService.pack(page, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
// Pull the user
|
||||
await this.userListJoiningsRepository.delete({ userListId: userList.id, userId: user.id });
|
||||
|
||||
this.globalEventService.publishUserListStream(userList.id, 'userRemoved', await this.userEntityService.pack(user));
|
||||
this.globalEventService.publishUserListStream(userList.id, 'userRemoved', await this.userEntityService.pack(user, me));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
.limit(ps.limit)
|
||||
.getMany();
|
||||
|
||||
return await this.pageEntityService.packMany(pages);
|
||||
return await this.pageEntityService.packMany(pages, me);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { randomUUID } from 'node:crypto';
|
||||
import { randomUUID, randomBytes } from 'node:crypto';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { randomBytes } from 'node:crypto';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { createBullBoard } from '@bull-board/api';
|
||||
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter.js';
|
||||
|
@ -33,6 +32,7 @@ import { deepClone } from '@/misc/clone.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import manifest from './manifest.json' assert { type: 'json' };
|
||||
import { FeedService } from './FeedService.js';
|
||||
import { UrlPreviewService } from './UrlPreviewService.js';
|
||||
|
@ -201,7 +201,7 @@ export class ClientServerService {
|
|||
const csp = this.config.contentSecurityPolicy
|
||||
?? 'script-src \'self\' ' +
|
||||
'https://challenges.cloudflare.com https://hcaptcha.com https://*.hcaptcha.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://www.recaptcha.net/recaptcha/ {scriptNonce}; ' +
|
||||
'worker-src blob: \'self\'; ' +
|
||||
'worker-src blob: \'self\'; ' +
|
||||
'base-uri \'self\'; object-src \'self\'; report-uri /csp-error';
|
||||
reply.header('Content-Security-Policy-Report-Only', csp.replace('{scriptNonce}', `'nonce-${scriptNonce}'`));
|
||||
done();
|
||||
|
@ -489,22 +489,29 @@ export class ClientServerService {
|
|||
});
|
||||
|
||||
if (note) {
|
||||
const _note = await this.noteEntityService.pack(note);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
try {
|
||||
const _note = await this.noteEntityService.pack(note, null);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('note', {
|
||||
note: _note,
|
||||
profile,
|
||||
avatarUrl: _note.user.avatarUrl,
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(_note),
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} catch (err) {
|
||||
if ((err as IdentifiableError).id === '8ca4f428-b32e-4f83-ac43-406ed7cd0452') {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return await reply.view('note', {
|
||||
note: _note,
|
||||
profile,
|
||||
avatarUrl: _note.user.avatarUrl,
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(_note),
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} else {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
|
@ -526,24 +533,31 @@ export class ClientServerService {
|
|||
});
|
||||
|
||||
if (page) {
|
||||
const _page = await this.pageEntityService.pack(page);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: page.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
if (['public'].includes(page.visibility)) {
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
} else {
|
||||
reply.header('Cache-Control', 'private, max-age=0, must-revalidate');
|
||||
try {
|
||||
const _page = await this.pageEntityService.pack(page, null);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: page.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
if (['public'].includes(page.visibility)) {
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
} else {
|
||||
reply.header('Cache-Control', 'private, max-age=0, must-revalidate');
|
||||
}
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('page', {
|
||||
page: _page,
|
||||
profile,
|
||||
avatarUrl: _page.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} catch (err) {
|
||||
if ((err as IdentifiableError).id === '8ca4f428-b32e-4f83-ac43-406ed7cd0452') {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('page', {
|
||||
page: _page,
|
||||
profile,
|
||||
avatarUrl: _page.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} else {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
|
@ -556,20 +570,27 @@ export class ClientServerService {
|
|||
});
|
||||
|
||||
if (flash) {
|
||||
const _flash = await this.flashEntityService.pack(flash);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: flash.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
try {
|
||||
const _flash = await this.flashEntityService.pack(flash, null);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: flash.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('flash', {
|
||||
flash: _flash,
|
||||
profile,
|
||||
avatarUrl: _flash.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} catch (err) {
|
||||
if ((err as IdentifiableError).id === '8ca4f428-b32e-4f83-ac43-406ed7cd0452') {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return await reply.view('flash', {
|
||||
flash: _flash,
|
||||
profile,
|
||||
avatarUrl: _flash.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} else {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
|
@ -582,20 +603,27 @@ export class ClientServerService {
|
|||
});
|
||||
|
||||
if (clip && clip.isPublic) {
|
||||
const _clip = await this.clipEntityService.pack(clip);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: clip.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
try {
|
||||
const _clip = await this.clipEntityService.pack(clip, null);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: clip.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('clip', {
|
||||
clip: _clip,
|
||||
profile,
|
||||
avatarUrl: _clip.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} catch (err) {
|
||||
if ((err as IdentifiableError).id === '8ca4f428-b32e-4f83-ac43-406ed7cd0452') {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return await reply.view('clip', {
|
||||
clip: _clip,
|
||||
profile,
|
||||
avatarUrl: _clip.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} else {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
|
@ -606,20 +634,27 @@ export class ClientServerService {
|
|||
const post = await this.galleryPostsRepository.findOneBy({ id: request.params.post });
|
||||
|
||||
if (post) {
|
||||
const _post = await this.galleryPostEntityService.pack(post);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: post.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
try {
|
||||
const _post = await this.galleryPostEntityService.pack(post, null);
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: post.userId });
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
if (profile.preventAiLearning) {
|
||||
reply.header('X-Robots-Tag', 'noimageai');
|
||||
reply.header('X-Robots-Tag', 'noai');
|
||||
}
|
||||
return await reply.view('gallery-post', {
|
||||
post: _post,
|
||||
profile,
|
||||
avatarUrl: _post.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} catch (err) {
|
||||
if ((err as IdentifiableError).id === '8ca4f428-b32e-4f83-ac43-406ed7cd0452') {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return await reply.view('gallery-post', {
|
||||
post: _post,
|
||||
profile,
|
||||
avatarUrl: _post.user.avatarUrl,
|
||||
...this.generateCommonPugData(meta),
|
||||
});
|
||||
} else {
|
||||
return await renderBase(reply);
|
||||
}
|
||||
|
@ -632,7 +667,7 @@ export class ClientServerService {
|
|||
});
|
||||
|
||||
if (channel) {
|
||||
const _channel = await this.channelEntityService.pack(channel);
|
||||
const _channel = await this.channelEntityService.pack(channel, null);
|
||||
const meta = await this.metaService.fetch();
|
||||
reply.header('Cache-Control', 'public, max-age=15');
|
||||
return await reply.view('channel', {
|
||||
|
|
Loading…
Reference in a new issue