From cc5a1977857e05797786bd2d78aa87606394e184 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 30 Dec 2021 21:22:48 +0100 Subject: [PATCH] do not create muted notification types in respective threads --- .../server/api/endpoints/notes/polls/vote.ts | 24 +++++++++++++------ packages/backend/src/services/note/create.ts | 16 ++++++++----- .../backend/src/services/note/polls/vote.ts | 22 +++++++++++------ .../src/services/note/reaction/create.ts | 12 +++++++--- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 6dd5ddf9e..a6b86a7eb 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -1,11 +1,11 @@ -import { Not } from 'typeorm'; +import { ArrayOverlap, Not } from 'typeorm'; import { publishNoteStream } from '@/services/stream.js'; import { createNotification } from '@/services/create-notification.js'; import { deliver } from '@/queue/index.js'; import { renderActivity } from '@/remote/activitypub/renderer/index.js'; import renderVote from '@/remote/activitypub/renderer/vote.js'; import { deliverQuestionUpdate } from '@/services/note/polls/update.js'; -import { PollVotes, NoteWatchings, Users, Polls, Blockings } from '@/models/index.js'; +import { PollVotes, NoteWatchings, Users, Polls, Blockings, NoteThreadMutings } from '@/models/index.js'; import { IRemoteUser } from '@/models/entities/user.js'; import { genId } from '@/misc/gen-id.js'; import { getNote } from '../../../common/getters.js'; @@ -136,14 +136,24 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - // Notify - createNotification(note.userId, 'pollVote', { - notifierId: user.id, - noteId: note.id, - choice: ps.choice, + // check if this thread and notification type is muted + const threadMuted = await NoteThreadMutings.findOne({ + userId: note.userId, + threadId: note.threadId || note.id, + mutingNotificationTypes: ArrayOverlap(['pollVote']), }); + // Notify + if (!threadMuted) { + createNotification(note.userId, 'pollVote', { + notifierId: user.id, + noteId: note.id, + choice: ps.choice, + }); + } // Fetch watchers + // checking for mutes is not necessary here, as note watchings will be + // deleted when a thread is muted NoteWatchings.findBy({ noteId: note.id, userId: Not(user.id), diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 9761de0e5..1b987b5cc 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -1,4 +1,4 @@ -import { Not, In } from 'typeorm'; +import { ArrayOverlap, Not, In } from 'typeorm'; import * as mfm from 'mfm-js'; import { db } from '@/db/postgre.js'; import es from '@/db/elasticsearch.js'; @@ -80,15 +80,19 @@ class NotificationManager { public async deliver() { for (const x of this.queue) { - // ミュート情報を取得 - const mentioneeMutes = await Mutings.findBy({ + // check if the sender or thread are muted + const userMuted = await Mutings.findOneBy({ muterId: x.target, + muteeId: this.notifier.id, }); - const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId); + const threadMuted = await NoteThreadMutings.findOneBy({ + userId: x.target, + threadId: this.note.threadId || this.note.id, + mutingNotificationTypes: ArrayOverlap([x.reason]), + }); - // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する - if (!mentioneesMutedUserIds.includes(this.notifier.id)) { + if (!userMuted && !threadMuted) { createNotification(x.target, x.reason, { notifierId: this.notifier.id, noteId: this.note.id, diff --git a/packages/backend/src/services/note/polls/vote.ts b/packages/backend/src/services/note/polls/vote.ts index 2c902f3ed..057e29005 100644 --- a/packages/backend/src/services/note/polls/vote.ts +++ b/packages/backend/src/services/note/polls/vote.ts @@ -1,8 +1,8 @@ -import { Not } from 'typeorm'; +import { ArrayOverlap, Not } from 'typeorm'; import { publishNoteStream } from '@/services/stream.js'; import { CacheableUser } from '@/models/entities/user.js'; import { Note } from '@/models/entities/note.js'; -import { PollVotes, NoteWatchings, Polls, Blockings } from '@/models/index.js'; +import { PollVotes, NoteWatchings, Polls, Blockings, NoteThreadMutings } from '@/models/index.js'; import { genId } from '@/misc/gen-id.js'; import { createNotification } from '../../create-notification.js'; @@ -57,12 +57,20 @@ export default async function(user: CacheableUser, note: Note, choice: number) { userId: user.id, }); - // Notify - createNotification(note.userId, 'pollVote', { - notifierId: user.id, - noteId: note.id, - choice, + // check if this thread and notification type is muted + const muted = await NoteThreadMutings.findOne({ + userId: note.userId, + threadId: note.threadId || note.id, + mutingNotificationTypes: ArrayOverlap(['pollVote']), }); + // Notify + if (!muted) { + createNotification(note.userId, 'pollVote', { + notifierId: user.id, + noteId: note.id, + choice: choice, + }); + } // Fetch watchers NoteWatchings.findBy({ diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts index 0fa84d346..9d3882a0c 100644 --- a/packages/backend/src/services/note/reaction/create.ts +++ b/packages/backend/src/services/note/reaction/create.ts @@ -1,4 +1,4 @@ -import { IsNull, Not } from 'typeorm'; +import { ArrayOverlap, IsNull, Not } from 'typeorm'; import { publishNoteStream } from '@/services/stream.js'; import { renderLike } from '@/remote/activitypub/renderer/like.js'; import DeliverManager from '@/remote/activitypub/deliver-manager.js'; @@ -6,7 +6,7 @@ import { renderActivity } from '@/remote/activitypub/renderer/index.js'; import { toDbReaction, decodeReaction } from '@/misc/reaction-lib.js'; import { User, IRemoteUser } from '@/models/entities/user.js'; import { Note } from '@/models/entities/note.js'; -import { NoteReactions, Users, NoteWatchings, Notes, Emojis, Blockings } from '@/models/index.js'; +import { NoteReactions, Users, NoteWatchings, Notes, Emojis, Blockings, NoteThreadMutings } from '@/models/index.js'; import { perUserReactionsChart } from '@/services/chart/index.js'; import { genId } from '@/misc/gen-id.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; @@ -98,8 +98,14 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, userId: user.id, }); + // check if this thread is muted + const threadMuted = await NoteThreadMutings.findOne({ + userId: note.userId, + threadId: note.threadId || note.id, + mutingNotificationTypes: ArrayOverlap(['reaction']), + }); // リアクションされたユーザーがローカルユーザーなら通知を作成 - if (note.userHost === null) { + if (note.userHost === null && !threadMuted) { createNotification(note.userId, 'reaction', { notifierId: user.id, noteId: note.id,