Move private user out of getDestinationsForUser
This commit is contained in:
parent
deb0d4a2d2
commit
f18d5825c2
|
@ -1,4 +1,5 @@
|
|||
import { notification_subscription_types } from 'common/user'
|
||||
import { notification_subscription_types, PrivateUser } from './user'
|
||||
import { DOMAIN } from './envs/constants'
|
||||
|
||||
export type Notification = {
|
||||
id: string
|
||||
|
@ -53,6 +54,7 @@ export type notification_source_update_types =
|
|||
| 'deleted'
|
||||
| 'closed'
|
||||
|
||||
/* Optional - if possible use a keyof notification_subscription_types */
|
||||
export type notification_reason_types =
|
||||
| 'tagged_user'
|
||||
| 'on_new_follow'
|
||||
|
@ -90,7 +92,11 @@ export type notification_reason_types =
|
|||
| 'your_contract_closed'
|
||||
| 'subsidized_your_market'
|
||||
|
||||
// Adding a new key:value here is optional, you can also just use a key of notification_subscription_types
|
||||
// Adding a new key:value here is optional, you can just use a key of notification_subscription_types
|
||||
// You might want to add a key:value here if there will be multiple notification reasons that map to the same
|
||||
// subscription type, i.e. 'comment_on_contract_you_follow' and 'comment_on_contract_with_users_answer' both map to
|
||||
// 'all_comments_on_watched_markets' subscription type
|
||||
// TODO: perhaps better would be to map notification_subscription_types to arrays of notification_reason_types
|
||||
export const notificationReasonToSubscriptionType: Partial<
|
||||
Record<notification_reason_types, keyof notification_subscription_types>
|
||||
> = {
|
||||
|
@ -127,3 +133,27 @@ export const notificationReasonToSubscriptionType: Partial<
|
|||
reply_to_users_answer: 'all_replies_to_my_answers_on_watched_markets',
|
||||
reply_to_users_comment: 'all_replies_to_my_comments_on_watched_markets',
|
||||
}
|
||||
|
||||
export const getDestinationsForUser = async (
|
||||
privateUser: PrivateUser,
|
||||
reason: notification_reason_types | keyof notification_subscription_types
|
||||
) => {
|
||||
const notificationSettings = privateUser.notificationSubscriptionTypes
|
||||
let destinations
|
||||
let subscriptionType: keyof notification_subscription_types | undefined
|
||||
if (Object.keys(notificationSettings).includes(reason)) {
|
||||
subscriptionType = reason as keyof notification_subscription_types
|
||||
destinations = notificationSettings[subscriptionType]
|
||||
} else {
|
||||
const key = reason as notification_reason_types
|
||||
subscriptionType = notificationReasonToSubscriptionType[key]
|
||||
destinations = subscriptionType
|
||||
? notificationSettings[subscriptionType]
|
||||
: []
|
||||
}
|
||||
return {
|
||||
sendToEmail: destinations.includes('email'),
|
||||
sendToBrowser: destinations.includes('browser'),
|
||||
urlToManageThisNotification: `${DOMAIN}/notifications?section=${subscriptionType}`,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import {
|
||||
getDestinationsForUser,
|
||||
Notification,
|
||||
notification_reason_types,
|
||||
notificationReasonToSubscriptionType,
|
||||
} from '../../common/notification'
|
||||
import { notification_subscription_types, User } from '../../common/user'
|
||||
import { User } from '../../common/user'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { getPrivateUser, getValues } from './utils'
|
||||
import { Comment } from '../../common/comment'
|
||||
|
@ -23,7 +23,6 @@ import {
|
|||
sendNewAnswerEmail,
|
||||
sendNewCommentEmail,
|
||||
} from './emails'
|
||||
import { DOMAIN } from 'common/lib/envs/constants'
|
||||
const firestore = admin.firestore()
|
||||
|
||||
type recipients_to_reason_texts = {
|
||||
|
@ -61,8 +60,12 @@ export const createNotification = async (
|
|||
) => {
|
||||
for (const userId in userToReasonTexts) {
|
||||
const { reason } = userToReasonTexts[userId]
|
||||
const { sendToBrowser, sendToEmail, privateUser } =
|
||||
await getDestinationsForUser(userId, reason)
|
||||
const privateUser = await getPrivateUser(userId)
|
||||
if (!privateUser) continue
|
||||
const { sendToBrowser, sendToEmail } = await getDestinationsForUser(
|
||||
privateUser,
|
||||
reason
|
||||
)
|
||||
if (sendToBrowser) {
|
||||
const notificationRef = firestore
|
||||
.collection(`/users/${userId}/notifications`)
|
||||
|
@ -93,7 +96,12 @@ export const createNotification = async (
|
|||
if (!sendToEmail) continue
|
||||
|
||||
if (reason === 'your_contract_closed' && privateUser && sourceContract) {
|
||||
await sendMarketCloseEmail(reason, sourceUser, sourceContract)
|
||||
await sendMarketCloseEmail(
|
||||
reason,
|
||||
sourceUser,
|
||||
privateUser,
|
||||
sourceContract
|
||||
)
|
||||
} else if (reason === 'tagged_user') {
|
||||
// TODO: send email to tagged user in new contract
|
||||
} else if (reason === 'subsidized_your_market') {
|
||||
|
@ -197,35 +205,6 @@ export const createNotification = async (
|
|||
await sendNotificationsIfSettingsPermit(userToReasonTexts)
|
||||
}
|
||||
|
||||
export const getDestinationsForUser = async (
|
||||
userId: string,
|
||||
reason: notification_reason_types | keyof notification_subscription_types
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(userId)
|
||||
if (!privateUser)
|
||||
return { sendToEmail: false, sendToBrowser: false, privateUser: null }
|
||||
|
||||
const notificationSettings = privateUser.notificationSubscriptionTypes
|
||||
let destinations
|
||||
let subscriptionType: keyof notification_subscription_types | undefined
|
||||
if (Object.keys(notificationSettings).includes(reason)) {
|
||||
subscriptionType = reason as keyof notification_subscription_types
|
||||
destinations = notificationSettings[subscriptionType]
|
||||
} else {
|
||||
const key = reason as notification_reason_types
|
||||
subscriptionType = notificationReasonToSubscriptionType[key]
|
||||
destinations = subscriptionType
|
||||
? notificationSettings[subscriptionType]
|
||||
: []
|
||||
}
|
||||
return {
|
||||
sendToEmail: destinations.includes('email'),
|
||||
sendToBrowser: destinations.includes('browser'),
|
||||
privateUser,
|
||||
urlToManageThisNotification: `${DOMAIN}/notifications?section=${subscriptionType}`,
|
||||
}
|
||||
}
|
||||
|
||||
export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||
sourceId: string,
|
||||
sourceType: 'comment' | 'answer' | 'contract',
|
||||
|
@ -314,9 +293,10 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
|||
recipientIdsList.includes(userId)
|
||||
)
|
||||
return
|
||||
|
||||
const privateUser = await getPrivateUser(userId)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser, sendToEmail } = await getDestinationsForUser(
|
||||
userId,
|
||||
privateUser,
|
||||
reason
|
||||
)
|
||||
|
||||
|
@ -328,7 +308,7 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
|||
if (sourceType === 'comment') {
|
||||
await sendNewCommentEmail(
|
||||
reason,
|
||||
userId,
|
||||
privateUser,
|
||||
sourceUser,
|
||||
sourceContract,
|
||||
sourceText,
|
||||
|
@ -341,7 +321,7 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
|||
} else if (sourceType === 'answer')
|
||||
await sendNewAnswerEmail(
|
||||
reason,
|
||||
userId,
|
||||
privateUser,
|
||||
sourceUser.name,
|
||||
sourceText,
|
||||
sourceContract,
|
||||
|
@ -354,7 +334,7 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
|||
)
|
||||
await sendMarketResolutionEmail(
|
||||
reason,
|
||||
userId,
|
||||
privateUser,
|
||||
resolutionData.userInvestments[userId],
|
||||
resolutionData.userPayouts[userId],
|
||||
sourceUser,
|
||||
|
@ -534,8 +514,10 @@ export const createTipNotification = async (
|
|||
contract?: Contract,
|
||||
group?: Group
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(toUser.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
toUser.id,
|
||||
privateUser,
|
||||
'tip_received'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -565,6 +547,7 @@ export const createTipNotification = async (
|
|||
}
|
||||
return await notificationRef.set(removeUndefinedProps(notification))
|
||||
|
||||
// TODO: send notification to users that are watching the contract and want highly tipped comments only
|
||||
// maybe TODO: send email notification to bet creator
|
||||
}
|
||||
|
||||
|
@ -576,7 +559,12 @@ export const createBetFillNotification = async (
|
|||
contract: Contract,
|
||||
idempotencyKey: string
|
||||
) => {
|
||||
const { sendToBrowser } = await getDestinationsForUser(toUser.id, 'bet_fill')
|
||||
const privateUser = await getPrivateUser(toUser.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
privateUser,
|
||||
'bet_fill'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
||||
const fill = userBet.fills.find((fill) => fill.matchedBetId === bet.id)
|
||||
|
@ -616,8 +604,10 @@ export const createReferralNotification = async (
|
|||
referredByContract?: Contract,
|
||||
referredByGroup?: Group
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(toUser.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
toUser.id,
|
||||
privateUser,
|
||||
'you_referred_user'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -668,8 +658,10 @@ export const createLoanIncomeNotification = async (
|
|||
idempotencyKey: string,
|
||||
income: number
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(toUser.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
toUser.id,
|
||||
privateUser,
|
||||
'loan_income'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -704,8 +696,10 @@ export const createChallengeAcceptedNotification = async (
|
|||
acceptedAmount: number,
|
||||
contract: Contract
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(challengeCreator.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
challengeCreator.id,
|
||||
privateUser,
|
||||
'challenge_accepted'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -743,8 +737,10 @@ export const createBettingStreakBonusNotification = async (
|
|||
amount: number,
|
||||
idempotencyKey: string
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(user.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
user.id,
|
||||
privateUser,
|
||||
'betting_streak_incremented'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -784,8 +780,10 @@ export const createLikeNotification = async (
|
|||
contract: Contract,
|
||||
tip?: TipTxn
|
||||
) => {
|
||||
const privateUser = await getPrivateUser(toUser.id)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
toUser.id,
|
||||
privateUser,
|
||||
'liked_and_tipped_your_contract'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
@ -828,8 +826,11 @@ export const createUniqueBettorBonusNotification = async (
|
|||
amount: number,
|
||||
idempotencyKey: string
|
||||
) => {
|
||||
console.log('createUniqueBettorBonusNotification')
|
||||
const privateUser = await getPrivateUser(contractCreatorId)
|
||||
if (!privateUser) return
|
||||
const { sendToBrowser } = await getDestinationsForUser(
|
||||
contractCreatorId,
|
||||
privateUser,
|
||||
'unique_bettors_on_your_contract'
|
||||
)
|
||||
if (!sendToBrowser) return
|
||||
|
|
|
@ -18,12 +18,14 @@ import { formatNumericProbability } from '../../common/pseudo-numeric'
|
|||
import { sendTemplateEmail, sendTextEmail } from './send-email'
|
||||
import { getUser } from './utils'
|
||||
import { buildCardUrl, getOpenGraphProps } from '../../common/contract-details'
|
||||
import { notification_reason_types } from '../../common/notification'
|
||||
import { getDestinationsForUser } from './create-notification'
|
||||
import {
|
||||
notification_reason_types,
|
||||
getDestinationsForUser,
|
||||
} from '../../common/notification'
|
||||
|
||||
export const sendMarketResolutionEmail = async (
|
||||
reason: notification_reason_types,
|
||||
userId: string,
|
||||
privateUser: PrivateUser,
|
||||
investment: number,
|
||||
payout: number,
|
||||
creator: User,
|
||||
|
@ -33,14 +35,11 @@ export const sendMarketResolutionEmail = async (
|
|||
resolutionProbability?: number,
|
||||
resolutions?: { [outcome: string]: number }
|
||||
) => {
|
||||
const {
|
||||
privateUser,
|
||||
sendToEmail,
|
||||
urlToManageThisNotification: unsubscribeUrl,
|
||||
} = await getDestinationsForUser(userId, reason)
|
||||
const { sendToEmail, urlToManageThisNotification: unsubscribeUrl } =
|
||||
await getDestinationsForUser(privateUser, reason)
|
||||
if (!privateUser || !privateUser.email || !sendToEmail) return
|
||||
|
||||
const user = await getUser(userId)
|
||||
const user = await getUser(privateUser.id)
|
||||
if (!user) return
|
||||
|
||||
const outcome = toDisplayResolution(
|
||||
|
@ -53,7 +52,7 @@ export const sendMarketResolutionEmail = async (
|
|||
const subject = `Resolved ${outcome}: ${contract.question}`
|
||||
|
||||
const creatorPayoutText =
|
||||
creatorPayout >= 1 && userId === creator.id
|
||||
creatorPayout >= 1 && privateUser.id === creator.id
|
||||
? ` (plus ${formatMoney(creatorPayout)} in commissions)`
|
||||
: ''
|
||||
|
||||
|
@ -310,15 +309,13 @@ export const sendThankYouEmail = async (
|
|||
export const sendMarketCloseEmail = async (
|
||||
reason: notification_reason_types,
|
||||
user: User,
|
||||
privateUser: PrivateUser,
|
||||
contract: Contract
|
||||
) => {
|
||||
const {
|
||||
privateUser,
|
||||
sendToEmail,
|
||||
urlToManageThisNotification: unsubscribeUrl,
|
||||
} = await getDestinationsForUser(user.id, reason)
|
||||
const { sendToEmail, urlToManageThisNotification: unsubscribeUrl } =
|
||||
await getDestinationsForUser(privateUser, reason)
|
||||
|
||||
if (!privateUser || !privateUser.email || !sendToEmail) return
|
||||
if (!privateUser.email || !sendToEmail) return
|
||||
|
||||
const { username, name, id: userId } = user
|
||||
const firstName = name.split(' ')[0]
|
||||
|
@ -344,7 +341,7 @@ export const sendMarketCloseEmail = async (
|
|||
|
||||
export const sendNewCommentEmail = async (
|
||||
reason: notification_reason_types,
|
||||
userId: string,
|
||||
privateUser: PrivateUser,
|
||||
commentCreator: User,
|
||||
contract: Contract,
|
||||
commentText: string,
|
||||
|
@ -353,11 +350,8 @@ export const sendNewCommentEmail = async (
|
|||
answerText?: string,
|
||||
answerId?: string
|
||||
) => {
|
||||
const {
|
||||
privateUser,
|
||||
sendToEmail,
|
||||
urlToManageThisNotification: unsubscribeUrl,
|
||||
} = await getDestinationsForUser(userId, reason)
|
||||
const { sendToEmail, urlToManageThisNotification: unsubscribeUrl } =
|
||||
await getDestinationsForUser(privateUser, reason)
|
||||
if (!privateUser || !privateUser.email || !sendToEmail) return
|
||||
|
||||
const { question } = contract
|
||||
|
@ -421,7 +415,7 @@ export const sendNewCommentEmail = async (
|
|||
|
||||
export const sendNewAnswerEmail = async (
|
||||
reason: notification_reason_types,
|
||||
userId: string,
|
||||
privateUser: PrivateUser,
|
||||
name: string,
|
||||
text: string,
|
||||
contract: Contract,
|
||||
|
@ -429,14 +423,11 @@ export const sendNewAnswerEmail = async (
|
|||
) => {
|
||||
const { creatorId } = contract
|
||||
// Don't send the creator's own answers.
|
||||
if (userId === creatorId) return
|
||||
if (privateUser.id === creatorId) return
|
||||
|
||||
const {
|
||||
privateUser,
|
||||
sendToEmail,
|
||||
urlToManageThisNotification: unsubscribeUrl,
|
||||
} = await getDestinationsForUser(userId, reason)
|
||||
if (!privateUser || !privateUser.email || !sendToEmail) return
|
||||
const { sendToEmail, urlToManageThisNotification: unsubscribeUrl } =
|
||||
await getDestinationsForUser(privateUser, reason)
|
||||
if (!privateUser.email || !sendToEmail) return
|
||||
|
||||
const { question, creatorUsername, slug } = contract
|
||||
|
||||
|
|
|
@ -1006,6 +1006,7 @@ function getReasonForShowingNotification(
|
|||
) {
|
||||
const { sourceType, sourceUpdateType, reason, sourceSlug } = notification
|
||||
let reasonText: string
|
||||
// TODO: we could leave out this switch and just use the reason field now that they have more information
|
||||
switch (sourceType) {
|
||||
case 'comment':
|
||||
if (reason === 'reply_to_users_answer')
|
||||
|
|
Loading…
Reference in New Issue
Block a user