From ae1942ada7c99853d362d8caf6a527709455bfeb Mon Sep 17 00:00:00 2001 From: soxa <6390896+Soxasora@users.noreply.github.com> Date: Wed, 22 Jan 2025 23:12:41 +0100 Subject: [PATCH] fix: duplicate push notification on subscribed user and territory (#1820) * fix: duplicate notification on subscribed user and territory * fix comments not showing up, adjust query * use and tagged template helpers --------- Co-authored-by: k00b --- lib/webPush.js | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/lib/webPush.js b/lib/webPush.js index 88b20047..9e78ad2d 100644 --- a/lib/webPush.js +++ b/lib/webPush.js @@ -4,6 +4,7 @@ import { COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants' import { msatsToSats, numWithUnits } from './format' import models from '@/api/models' import { isMuted } from '@/lib/user' +import { Prisma } from '@prisma/client' const webPushEnabled = process.env.NODE_ENV === 'production' || (process.env.VAPID_MAILTO && process.env.NEXT_PUBLIC_VAPID_PUBKEY && process.env.VAPID_PRIVKEY) @@ -123,21 +124,36 @@ export async function replyToSubscription (subscriptionId, notification) { export const notifyUserSubscribers = async ({ models, item }) => { try { const isPost = !!item.title - const userSubsExcludingMutes = await models.$queryRawUnsafe(` - SELECT "UserSubscription"."followerId", "UserSubscription"."followeeId", users.name as "followeeName" - FROM "UserSubscription" - INNER JOIN users ON users.id = "UserSubscription"."followeeId" - WHERE "followeeId" = $1 AND ${isPost ? '"postsSubscribedAt"' : '"commentsSubscribedAt"'} IS NOT NULL - AND NOT EXISTS (SELECT 1 FROM "Mute" WHERE "Mute"."muterId" = "UserSubscription"."followerId" AND "Mute"."mutedId" = $1) - -- ignore subscription if user was already notified of item as a reply - AND NOT EXISTS ( - SELECT 1 FROM "Reply" - INNER JOIN users follower ON follower.id = "UserSubscription"."followerId" - WHERE "Reply"."itemId" = $2 - AND "Reply"."ancestorUserId" = follower.id - AND follower."noteAllDescendants" - ) - `, Number(item.userId), Number(item.id)) + + const userSubsExcludingMutes = await models.$queryRaw` + SELECT "UserSubscription"."followerId", "UserSubscription"."followeeId", users.name as "followeeName" + FROM "UserSubscription" + INNER JOIN users ON users.id = "UserSubscription"."followeeId" + WHERE "followeeId" = ${Number(item.userId)}::INTEGER + AND ${isPost ? Prisma.sql`"postsSubscribedAt"` : Prisma.sql`"commentsSubscribedAt"`} IS NOT NULL + -- ignore muted users + AND NOT EXISTS ( + SELECT 1 + FROM "Mute" + WHERE "Mute"."muterId" = "UserSubscription"."followerId" + AND "Mute"."mutedId" = ${Number(item.userId)}::INTEGER) + -- ignore subscription if user was already notified of item as a reply + AND NOT EXISTS ( + SELECT 1 FROM "Reply" + INNER JOIN users follower ON follower.id = "UserSubscription"."followerId" + WHERE "Reply"."itemId" = ${Number(item.id)}::INTEGER + AND "Reply"."ancestorUserId" = follower.id + AND follower."noteAllDescendants" + ) + -- ignore subscription if user has posted to a territory the recipient is subscribed to + ${isPost + ? Prisma.sql`AND NOT EXISTS ( + SELECT 1 + FROM "SubSubscription" + WHERE "SubSubscription"."userId" = "UserSubscription"."followerId" + AND "SubSubscription"."subName" = ${item.subName} + )` + : Prisma.empty}` const subType = isPost ? 'POST' : 'COMMENT' const tag = `FOLLOW-${item.userId}-${subType}` await Promise.allSettled(userSubsExcludingMutes.map(({ followerId, followeeName }) => sendUserNotification(followerId, {