Close emails (#50)

* script init for stephen dev

* market close emails

* order of operations

* template email

* sendMarketCloseEmail: handle unsubscribe

* remove debugging

* marketCloseEmails: every hour
This commit is contained in:
mantikoros 2022-02-17 12:18:02 -06:00 committed by GitHub
parent d6f15deff4
commit dcbdc66df5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 2 deletions

View File

@ -28,6 +28,7 @@ export type Contract = {
resolutionTime?: number // When the contract creator resolved the market
resolution?: outcome // Chosen by creator; must be one of outcomes
resolutionProbability?: number
closeEmailsSent?: number
volume24Hours: number
volume7Days: number

View File

@ -1,7 +1,9 @@
import _ = require('lodash')
import { getProbability } from '../../common/calculate'
import { Contract } from '../../common/contract'
import { CREATOR_FEE } from '../../common/fees'
import { PrivateUser, User } from '../../common/user'
import { formatPercent } from '../../common/util/format'
import { formatMoney, formatPercent } from '../../common/util/format'
import { sendTemplateEmail, sendTextEmail } from './send-email'
import { getPrivateUser, getUser } from './utils'
@ -88,3 +90,37 @@ Austin from Manifold
https://manifold.markets/`
)
}
export const sendMarketCloseEmail = async (
user: User,
privateUser: PrivateUser,
contract: Contract
) => {
if (
!privateUser ||
privateUser.unsubscribedFromResolutionEmails ||
!privateUser.email
)
return
const { username, name, id: userId } = user
const firstName = name.split(' ')[0]
const { question, pool: pools, slug } = contract
const pool = formatMoney(_.sum(_.values(pools)))
const url = `https://manifold.markets/${username}/${slug}`
await sendTemplateEmail(
privateUser.email,
'Your market has closed',
'market-close',
{
name: firstName,
question,
pool,
url,
userId,
creatorFee: (CREATOR_FEE * 100).toString(),
}
)
}

View File

@ -18,3 +18,4 @@ export * from './update-contract-metrics'
export * from './update-user-metrics'
export * from './backup-db'
export * from './change-user-info'
export * from './market-close-emails'

View File

@ -0,0 +1,58 @@
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { Contract } from '../../common/contract'
import { getPrivateUser, getUserByUsername } from './utils'
import { sendMarketCloseEmail } from './emails'
export const marketCloseEmails = functions.pubsub
.schedule('every hour')
.onRun(async () => {
await sendMarketCloseEmails()
})
const firestore = admin.firestore()
async function sendMarketCloseEmails() {
const contracts = await firestore.runTransaction(async (transaction) => {
const snap = await transaction.get(
firestore.collection('contracts').where('isResolved', '!=', true)
)
return snap.docs
.map((doc) => {
const contract = doc.data() as Contract
if (
contract.resolution ||
(contract.closeEmailsSent ?? 0) >= 1 ||
(contract.closeTime ?? 0) > Date.now()
)
return undefined
transaction.update(doc.ref, {
closeEmailsSent: (contract.closeEmailsSent ?? 0) + 1,
})
return contract
})
.filter((x) => !!x) as Contract[]
})
for (let contract of contracts) {
console.log(
'sending close email for',
contract.slug,
'closed',
contract.closeTime
)
const user = await getUserByUsername(contract.creatorUsername)
if (!user) continue
const privateUser = await getPrivateUser(user.id)
if (!privateUser) continue
await sendMarketCloseEmail(user, privateUser, contract)
}
}

View File

@ -14,7 +14,7 @@ const pathsToPrivateKey = {
stephen:
'../../../../../../Downloads/mantic-markets-firebase-adminsdk-1ep46-351a65eca3.json',
stephenDev:
'../../../../Downloads/dev-mantic-markets-firebase-adminsdk-sir5m-b2d27f8970.json',
'../../../../../../Downloads/dev-mantic-markets-firebase-adminsdk-sir5m-b2d27f8970.json',
}
export const initAdmin = (who: keyof typeof pathsToPrivateKey) => {