diff --git a/src/server/api/common/generate-replies-query.ts b/src/server/api/common/generate-replies-query.ts new file mode 100644 index 000000000..c7ca742e2 --- /dev/null +++ b/src/server/api/common/generate-replies-query.ts @@ -0,0 +1,27 @@ +import { User } from '../../../models/entities/user'; +import { Brackets, SelectQueryBuilder } from 'typeorm'; + +export function generateRepliesQuery(q: SelectQueryBuilder, me?: User) { + if (me == null) { + q.andWhere(new Brackets(qb => { qb + .where(`note.replyId IS NULL`) // 返信ではない + .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 + .where(`note.replyId IS NOT NULL`) + .andWhere('note.replyUserId = note.userId'); + })); + })); + } else { + q.andWhere(new Brackets(qb => { qb + .where(`note.replyId IS NULL`) // 返信ではない + .orWhere('note.replyUserId = :meId', { meId: me.id }) // 返信だけど自分のノートへの返信 + .orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信 + .where(`note.replyId IS NOT NULL`) + .andWhere('note.userId = :meId', { meId: me.id }); + })) + .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 + .where(`note.replyId IS NOT NULL`) + .andWhere('note.replyUserId = note.userId'); + })); + })); + } +} diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 15f495576..7475c8f07 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -8,6 +8,7 @@ import { Notes } from '../../../../models'; import { generateMuteQuery } from '../../common/generate-mute-query'; import { activeUsersChart } from '../../../../services/chart'; import { Brackets } from 'typeorm'; +import { generateRepliesQuery } from '../../common/generate-replies-query'; export const meta = { desc: { @@ -77,21 +78,9 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('note.visibility = \'public\'') - .andWhere('note.replyId IS NULL') - .andWhere(new Brackets(qb => { qb - .where(`note.replyId IS NULL`) // 返信ではない - .orWhere('note.replyUserId = :meId', { meId: user.id }) // 返信だけど自分のノートへの返信 - .orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.userId = :meId', { meId: user.id }); - })) - .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.replyUserId = note.userId', { meId: user.id }); - })); - })) .leftJoinAndSelect('note.user', 'user'); + generateRepliesQuery(query, user); if (user) generateMuteQuery(query, user); if (ps.withFiles) { diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index a4f376f8e..5aa18b2e9 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -9,6 +9,7 @@ import { Brackets } from 'typeorm'; import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateMuteQuery } from '../../common/generate-mute-query'; import { activeUsersChart } from '../../../../services/chart'; +import { generateRepliesQuery } from '../../common/generate-replies-query'; export const meta = { desc: { @@ -124,21 +125,10 @@ export default define(meta, async (ps, user) => { qb.where(`((note.userId IN (${ followingQuery.getQuery() })) OR (note.userId = :meId))`, { meId: user.id }) .orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)'); })) - .andWhere(new Brackets(qb => { qb - .where(`note.replyId IS NULL`) // 返信ではない - .orWhere('note.replyUserId = :meId', { meId: user.id }) // 返信だけど自分のノートへの返信 - .orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.userId = :meId', { meId: user.id }); - })) - .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.replyUserId = note.userId', { meId: user.id }); - })); - })) .leftJoinAndSelect('note.user', 'user') .setParameters(followingQuery.getParameters()); + generateRepliesQuery(query, user); generateVisibilityQuery(query, user); generateMuteQuery(query, user); diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 71ebceb0e..06f00969a 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -9,6 +9,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { activeUsersChart } from '../../../../services/chart'; import { Brackets } from 'typeorm'; +import { generateRepliesQuery } from '../../common/generate-replies-query'; export const meta = { desc: { @@ -93,20 +94,9 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)') - .andWhere(new Brackets(qb => { qb - .where(`note.replyId IS NULL`) // 返信ではない - .orWhere('note.replyUserId = :meId', { meId: user.id }) // 返信だけど自分のノートへの返信 - .orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.userId = :meId', { meId: user.id }); - })) - .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.replyUserId = note.userId', { meId: user.id }); - })); - })) .leftJoinAndSelect('note.user', 'user'); + generateRepliesQuery(query, user); generateVisibilityQuery(query, user); if (user) generateMuteQuery(query, user); diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 68a5784d9..2c25fbc96 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query' import { generateMuteQuery } from '../../common/generate-mute-query'; import { activeUsersChart } from '../../../../services/chart'; import { Brackets } from 'typeorm'; +import { generateRepliesQuery } from '../../common/generate-replies-query'; export const meta = { desc: { @@ -110,21 +111,10 @@ export default define(meta, async (ps, user) => { .where(`note.userId IN (${ followingQuery.getQuery() })`) .orWhere('note.userId = :meId', { meId: user.id }); })) - .andWhere(new Brackets(qb => { qb - .where(`note.replyId IS NULL`) // 返信ではない - .orWhere('note.replyUserId = :meId', { meId: user.id }) // 返信だけど自分のノートへの返信 - .orWhere(new Brackets(qb => { qb // 返信だけど自分の行った返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.userId = :meId', { meId: user.id }); - })) - .orWhere(new Brackets(qb => { qb // 返信だけど投稿者自身への返信 - .where(`note.replyId IS NOT NULL`) - .andWhere('note.replyUserId = note.userId', { meId: user.id }); - })); - })) .leftJoinAndSelect('note.user', 'user') .setParameters(followingQuery.getParameters()); + generateRepliesQuery(query, user); generateVisibilityQuery(query, user); generateMuteQuery(query, user);