diff --git a/functions/src/create-notification.ts b/functions/src/create-notification.ts index c9f3ff8f..2815655f 100644 --- a/functions/src/create-notification.ts +++ b/functions/src/create-notification.ts @@ -188,6 +188,15 @@ export const createNotification = async ( } } +export type replied_users_info = { + [key: string]: { + repliedToType: 'comment' | 'answer' + repliedToAnswerText: string | undefined + repliedToId: string | undefined + bet: Bet | undefined + } +} + export const createCommentOrAnswerOrUpdatedContractNotification = async ( sourceId: string, sourceType: 'comment' | 'answer' | 'contract', @@ -197,11 +206,8 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async ( sourceText: string, sourceContract: Contract, miscData?: { - repliedToType?: 'comment' | 'answer' - repliedToId?: string - repliedToContent?: string - repliedUserId?: string - taggedUserIds?: string[] + repliedUsersInfo: replied_users_info + taggedUserIds: string[] }, resolutionData?: { bets: Bet[] @@ -215,13 +221,7 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async ( resolutions?: { [outcome: string]: number } } ) => { - const { - repliedToType, - repliedToContent, - repliedUserId, - taggedUserIds, - repliedToId, - } = miscData ?? {} + const { repliedUsersInfo, taggedUserIds } = miscData ?? {} const browserRecipientIdsList: string[] = [] const emailRecipientIdsList: string[] = [] @@ -289,6 +289,8 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async ( } if (sendToEmail && !emailRecipientIdsList.includes(userId)) { if (sourceType === 'comment') { + const { repliedToType, repliedToAnswerText, repliedToId, bet } = + repliedUsersInfo?.[userId] ?? {} // TODO: change subject of email title to be more specific, i.e.: replied to you on/tagged you on/comment await sendNewCommentEmail( reason, @@ -297,9 +299,8 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async ( sourceContract, sourceText, sourceId, - // TODO: Add any paired bets to the comment - undefined, - repliedToType === 'answer' ? repliedToContent : undefined, + bet, + repliedToAnswerText, repliedToType === 'answer' ? repliedToId : undefined ) } else if (sourceType === 'answer') @@ -437,12 +438,16 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async ( } const notifyRepliedUser = async () => { - if (sourceType === 'comment' && repliedUserId && repliedToType) - await sendNotificationsIfSettingsPermit( - repliedUserId, - repliedToType === 'answer' - ? 'reply_to_users_answer' - : 'reply_to_users_comment' + if (sourceType === 'comment' && repliedUsersInfo) + await Promise.all( + Object.keys(repliedUsersInfo).map((userId) => + sendNotificationsIfSettingsPermit( + userId, + repliedUsersInfo[userId].repliedToType === 'answer' + ? 'reply_to_users_answer' + : 'reply_to_users_comment' + ) + ) ) } diff --git a/functions/src/on-create-comment-on-contract.ts b/functions/src/on-create-comment-on-contract.ts index a46420bc..65e32dca 100644 --- a/functions/src/on-create-comment-on-contract.ts +++ b/functions/src/on-create-comment-on-contract.ts @@ -5,7 +5,10 @@ import { getContract, getUser, getValues } from './utils' import { ContractComment } from '../../common/comment' import { Bet } from '../../common/bet' import { Answer } from '../../common/answer' -import { createCommentOrAnswerOrUpdatedContractNotification } from './create-notification' +import { + createCommentOrAnswerOrUpdatedContractNotification, + replied_users_info, +} from './create-notification' import { parseMentions, richTextToString } from '../../common/util/parse' import { addUserToContractFollowers } from './follow-market' @@ -83,6 +86,36 @@ export const onCreateCommentOnContract = functions ? comments.find((c) => c.id === comment.replyToCommentId)?.userId : answer?.userId + const mentionedUsers = compact(parseMentions(comment.content)) + const repliedUsers: replied_users_info = {} + + // The parent of the reply chain could be a comment or an answer + if (repliedUserId && repliedToType) + repliedUsers[repliedUserId] = { + repliedToType, + repliedToAnswerText: answer ? answer.text : undefined, + repliedToId: comment.replyToCommentId || answer?.id, + bet: bet, + } + + const commentsInSameReplyChain = comments.filter((c) => + repliedToType === 'answer' + ? c.answerOutcome === answer?.id + : repliedToType === 'comment' + ? c.replyToCommentId === comment.replyToCommentId + : false + ) + // The rest of the children in the chain are always comments + commentsInSameReplyChain.forEach((c) => { + if (c.userId !== comment.userId && c.userId !== repliedUserId) { + repliedUsers[c.userId] = { + repliedToType: 'comment', + repliedToAnswerText: undefined, + repliedToId: c.id, + bet: undefined, + } + } + }) await createCommentOrAnswerOrUpdatedContractNotification( comment.id, 'comment', @@ -92,11 +125,8 @@ export const onCreateCommentOnContract = functions richTextToString(comment.content), contract, { - repliedToType, - repliedToId: comment.replyToCommentId || answer?.id, - repliedToContent: answer ? answer.text : undefined, - repliedUserId, - taggedUserIds: compact(parseMentions(comment.content)), + repliedUsersInfo: repliedUsers, + taggedUserIds: mentionedUsers, } ) })