diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-all-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-all-timeline.ts deleted file mode 100644 index d3d9fa346a..0000000000 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-all-timeline.ts +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and other misskey contributors - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Brackets } from 'typeorm'; -import { Inject, Injectable } from '@nestjs/common'; -import type { NotesRepository } from '@/models/index.js'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { QueryService } from '@/core/QueryService.js'; -import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; -import ActiveUsersChart from '@/core/chart/charts/active-users.js'; -import { DI } from '@/di-symbols.js'; -import { RoleService } from '@/core/RoleService.js'; -import { IdService } from '@/core/IdService.js'; -import { ApiError } from '../../error.js'; - -export const meta = { - tags: ['notes'], - - res: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - ref: 'Note', - }, - }, - - errors: { - ltlDisabled: { - message: 'hybrid Local timeline has been disabled.', - code: 'LTL_DISABLED', - id: '45a6eb02-7695-4393-b023-dd3be9aaaefd', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - withFiles: { type: 'boolean', default: false }, - withReplies: { type: 'boolean', default: false }, - fileType: { type: 'array', items: { - type: 'string', - } }, - excludeNsfw: { type: 'boolean', default: false }, - limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, - sinceId: { type: 'string', format: 'misskey:id' }, - untilId: { type: 'string', format: 'misskey:id' }, - sinceDate: { type: 'integer' }, - untilDate: { type: 'integer' }, - }, - required: [], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - @Inject(DI.notesRepository) - private notesRepository: NotesRepository, - - private noteEntityService: NoteEntityService, - private queryService: QueryService, - private roleService: RoleService, - private activeUsersChart: ActiveUsersChart, - private idService: IdService, - ) { - super(meta, paramDef, async (ps, me) => { - const policies = await this.roleService.getUserPolicies(me ? me.id : null); - if (!policies.ltlAvailable) { - throw new ApiError(meta.errors.ltlDisabled); - } - - //#region Construct query - const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), - ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) - .andWhere('note.id > :minId', { minId: this.idService.genId(new Date(Date.now() - (1000 * 60 * 60 * 24 * 10))) }) // 10日前まで - .andWhere('(note.visibility = \'home\') AND (note.userHost IS NULL)') - .innerJoinAndSelect('note.user', 'user') - .leftJoinAndSelect('note.reply', 'reply') - .leftJoinAndSelect('note.renote', 'renote') - .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); - - this.queryService.generateChannelQuery(query, me); - this.queryService.generateRepliesQuery(query, ps.withReplies, me); - this.queryService.generateVisibilityQuery(query, me); - if (me) this.queryService.generateMutedUserQuery(query, me); - if (me) this.queryService.generateMutedNoteQuery(query, me); - if (me) this.queryService.generateBlockedUserQuery(query, me); - if (me) this.queryService.generateMutedUserRenotesQueryForNotes(query, me); - - if (ps.withFiles) { - query.andWhere('note.fileIds != \'{}\''); - } - - if (ps.fileType != null) { - query.andWhere('note.fileIds != \'{}\''); - query.andWhere(new Brackets(qb => { - for (const type of ps.fileType!) { - const i = ps.fileType!.indexOf(type); - qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type }); - } - })); - - if (ps.excludeNsfw) { - query.andWhere('note.cw IS NULL'); - query.andWhere('0 = (SELECT COUNT(*) FROM drive_file df WHERE df.id = ANY(note."fileIds") AND df."isSensitive" = TRUE)'); - } - } - //#endregion - - const timeline = await query.limit(ps.limit).getMany(); - - process.nextTick(() => { - if (me) { - this.activeUsersChart.read(me); - } - }); - - return await this.noteEntityService.packMany(timeline, me); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/roles/notes.ts b/packages/backend/src/server/api/endpoints/roles/notes.ts index 0db51abc55..8a1cc8dd59 100644 --- a/packages/backend/src/server/api/endpoints/roles/notes.ts +++ b/packages/backend/src/server/api/endpoints/roles/notes.ts @@ -13,6 +13,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { IdService } from '@/core/IdService.js'; import { RedisTimelineService } from '@/core/RedisTimelineService.js'; import { ApiError } from '../../error.js'; +import {RoleService} from "@/core/RoleService.js"; export const meta = { tags: ['role', 'notes'], @@ -62,7 +63,7 @@ export default class extends Endpoint { // eslint- @Inject(DI.rolesRepository) private rolesRepository: RolesRepository, - + private roleService: RoleService, private idService: IdService, private noteEntityService: NoteEntityService, private queryService: QueryService, @@ -71,7 +72,7 @@ export default class extends Endpoint { // eslint- super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null); - + const isModerator = await this.roleService.isModerator(me); const role = await this.rolesRepository.findOneBy({ id: ps.roleId, isPublic: true, @@ -90,15 +91,21 @@ export default class extends Endpoint { // eslint- if (noteIds.length === 0) { return []; } - - const query = this.notesRepository.createQueryBuilder('note') + const query = isModerator ? this.notesRepository.createQueryBuilder('note') .where('note.id IN (:...noteIds)', { noteIds: noteIds }) - .andWhere('(note.visibility = \'public\')') .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('renote.user', 'renoteUser') : + this.notesRepository.createQueryBuilder('note') + .where('note.id IN (:...noteIds)', { noteIds: noteIds }) + .andWhere('(note.visibility = \'public\')' ) + .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('note.reply', 'reply') + .leftJoinAndSelect('note.renote', 'renote') + .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('renote.user', 'renoteUser'); this.queryService.generateVisibilityQuery(query, me); this.queryService.generateMutedUserQuery(query, me); @@ -106,7 +113,6 @@ export default class extends Endpoint { // eslint- const notes = await query.getMany(); notes.sort((a, b) => a.id > b.id ? -1 : 1); - return await this.noteEntityService.packMany(notes, me); }); }