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:
parent
d6f15deff4
commit
dcbdc66df5
|
@ -28,6 +28,7 @@ export type Contract = {
|
||||||
resolutionTime?: number // When the contract creator resolved the market
|
resolutionTime?: number // When the contract creator resolved the market
|
||||||
resolution?: outcome // Chosen by creator; must be one of outcomes
|
resolution?: outcome // Chosen by creator; must be one of outcomes
|
||||||
resolutionProbability?: number
|
resolutionProbability?: number
|
||||||
|
closeEmailsSent?: number
|
||||||
|
|
||||||
volume24Hours: number
|
volume24Hours: number
|
||||||
volume7Days: number
|
volume7Days: number
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import _ = require('lodash')
|
||||||
import { getProbability } from '../../common/calculate'
|
import { getProbability } from '../../common/calculate'
|
||||||
import { Contract } from '../../common/contract'
|
import { Contract } from '../../common/contract'
|
||||||
|
import { CREATOR_FEE } from '../../common/fees'
|
||||||
import { PrivateUser, User } from '../../common/user'
|
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 { sendTemplateEmail, sendTextEmail } from './send-email'
|
||||||
import { getPrivateUser, getUser } from './utils'
|
import { getPrivateUser, getUser } from './utils'
|
||||||
|
|
||||||
|
@ -88,3 +90,37 @@ Austin from Manifold
|
||||||
https://manifold.markets/`
|
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(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -18,3 +18,4 @@ export * from './update-contract-metrics'
|
||||||
export * from './update-user-metrics'
|
export * from './update-user-metrics'
|
||||||
export * from './backup-db'
|
export * from './backup-db'
|
||||||
export * from './change-user-info'
|
export * from './change-user-info'
|
||||||
|
export * from './market-close-emails'
|
||||||
|
|
58
functions/src/market-close-emails.ts
Normal file
58
functions/src/market-close-emails.ts
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ const pathsToPrivateKey = {
|
||||||
stephen:
|
stephen:
|
||||||
'../../../../../../Downloads/mantic-markets-firebase-adminsdk-1ep46-351a65eca3.json',
|
'../../../../../../Downloads/mantic-markets-firebase-adminsdk-1ep46-351a65eca3.json',
|
||||||
stephenDev:
|
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) => {
|
export const initAdmin = (who: keyof typeof pathsToPrivateKey) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user