diff --git a/keyserver/src/creators/message-creator.js b/keyserver/src/creators/message-creator.js --- a/keyserver/src/creators/message-creator.js +++ b/keyserver/src/creators/message-creator.js @@ -38,7 +38,7 @@ } from '../fetchers/message-fetchers.js'; import { fetchOtherSessionsForViewer } from '../fetchers/session-fetchers.js'; import { fetchServerThreadInfos } from '../fetchers/thread-fetchers.js'; -import { sendPushNotifs } from '../push/send.js'; +import { sendPushNotifs, sendRescindNotifs } from '../push/send.js'; import { handleAsyncPromise } from '../responders/handlers.js'; import type { Viewer } from '../session/viewer.js'; import { earliestFocusedTimeConsideredExpired } from '../shared/focused-times.js'; @@ -393,6 +393,8 @@ const messageInfosPerUser = {}; const latestMessagesPerUser: LatestMessagesPerUser = new Map(); const userPushInfoPromises = {}; + const userRescindInfoPromises = {}; + for (const pair of perUserInfo) { const [userID, preUserPushInfo] = pair; @@ -473,20 +475,28 @@ }; const userPushInfoPromise = generateNotifUserInfoPromise(pushTypes.NOTIF); + const userRescindInfoPromise = generateNotifUserInfoPromise( + pushTypes.RESCIND, + ); userPushInfoPromises[userID] = userPushInfoPromise; + userRescindInfoPromises[userID] = userRescindInfoPromise; } const latestMessages = flattenLatestMessagesPerUser(latestMessagesPerUser); - const [pushInfo] = await Promise.all([ + const [pushInfo, rescindInfo] = await Promise.all([ promiseAll(userPushInfoPromises), + promiseAll(userRescindInfoPromises), createReadStatusUpdates(latestMessages), redisPublish(viewer, messageInfosPerUser, updatesForCurrentSession), updateLatestMessages(latestMessages), ]); - await sendPushNotifs(_pickBy(Boolean)(pushInfo)); + await Promise.all([ + sendPushNotifs(_pickBy(Boolean)(pushInfo)), + sendRescindNotifs(_pickBy(Boolean)(rescindInfo)), + ]); } async function redisPublish( diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js --- a/keyserver/src/push/send.js +++ b/keyserver/src/push/send.js @@ -33,6 +33,7 @@ import { promiseAll } from 'lib/utils/promises.js'; import { getAPNsNotificationTopic } from './providers.js'; +import { rescindPushNotifs } from './rescind.js'; import { apnPush, fcmPush, @@ -244,6 +245,31 @@ await saveNotifResults(deliveryResults, notifications, true); } +async function sendRescindNotifs(rescindInfo: PushInfo) { + if (Object.keys(rescindInfo).length === 0) { + return; + } + + const usersToCollapsableNotifInfo = await fetchCollapsableNotifs(rescindInfo); + + const promises = []; + for (const userID in usersToCollapsableNotifInfo) { + for (const notifInfo of usersToCollapsableNotifInfo[userID]) { + for (const existingMessageInfo of notifInfo.existingMessageInfos) { + const rescindCondition = SQL` + n.user = ${userID} AND + n.thread = ${existingMessageInfo.threadID} AND + n.message = ${existingMessageInfo.id} + `; + + promises.push(rescindPushNotifs(rescindCondition)); + } + } + } + + await Promise.all(promises); +} + // The results in deliveryResults will be combined with the rows // in rowsToSave and then written to the notifications table async function saveNotifResults( @@ -840,4 +866,4 @@ await saveNotifResults(deliveryResults, new Map(), false); } -export { sendPushNotifs, updateBadgeCount }; +export { sendPushNotifs, sendRescindNotifs, updateBadgeCount };