From 2d3ca47b52001ea8b668060a533351357e50d37d Mon Sep 17 00:00:00 2001 From: SirSaltyy <104849031+SirSaltyy@users.noreply.github.com> Date: Fri, 5 Aug 2022 03:03:02 +0900 Subject: [PATCH] 500 mana email (#687) * Create 500-mana.html * Update 500-mana.html Fixed typos and links not working * Added "create a good market" guide added page creating-market.html For Stephen to set up condition (email 3 days after signing up) * Update 500-mana.html updated 500 Mana email (still need to make changes to create market guide) * email changes * sendOneWeekBonusEmail logic * add dayjs as dependency * don't use mailgun scheduling Co-authored-by: mantikoros --- common/user.ts | 2 + functions/package.json | 1 + functions/src/create-user.ts | 5 +- functions/src/email-templates/500-mana.html | 267 ++++++- .../src/email-templates/creating-market.html | 738 ++++++++++++++++++ functions/src/emails.ts | 5 +- functions/src/index.ts | 19 + functions/src/mana-bonus-email.ts | 42 + functions/src/send-email.ts | 6 +- yarn.lock | 5 + 10 files changed, 1065 insertions(+), 25 deletions(-) create mode 100644 functions/src/email-templates/creating-market.html create mode 100644 functions/src/mana-bonus-email.ts diff --git a/common/user.ts b/common/user.ts index 78b76511..2aeb7122 100644 --- a/common/user.ts +++ b/common/user.ts @@ -47,6 +47,7 @@ export const STARTING_BALANCE = ENV_CONFIG.startingBalance ?? 1000 // for sus users, i.e. multiple sign ups for same person export const SUS_STARTING_BALANCE = ENV_CONFIG.startingBalance ?? 10 export const REFERRAL_AMOUNT = ENV_CONFIG.referralBonus ?? 500 + export type PrivateUser = { id: string // same as User.id username: string // denormalized from User @@ -56,6 +57,7 @@ export type PrivateUser = { unsubscribedFromCommentEmails?: boolean unsubscribedFromAnswerEmails?: boolean unsubscribedFromGenericEmails?: boolean + manaBonusEmailSent?: boolean initialDeviceToken?: string initialIpAddress?: string apiKey?: string diff --git a/functions/package.json b/functions/package.json index b20a8fd0..b0d8e458 100644 --- a/functions/package.json +++ b/functions/package.json @@ -31,6 +31,7 @@ "@tiptap/extension-link": "2.0.0-beta.43", "@tiptap/extension-mention": "2.0.0-beta.102", "@tiptap/starter-kit": "2.0.0-beta.190", + "dayjs": "1.11.4", "cors": "2.8.5", "express": "4.18.1", "firebase-admin": "10.0.0", diff --git a/functions/src/create-user.ts b/functions/src/create-user.ts index 70e81055..c30e78c3 100644 --- a/functions/src/create-user.ts +++ b/functions/src/create-user.ts @@ -1,5 +1,7 @@ import * as admin from 'firebase-admin' import { z } from 'zod' +import { uniq } from 'lodash' + import { MANIFOLD_AVATAR_URL, MANIFOLD_USERNAME, @@ -24,7 +26,6 @@ import { import { track } from './analytics' import { APIError, newEndpoint, validate } from './api' import { Group, NEW_USER_GROUP_SLUGS } from '../../common/group' -import { uniq } from 'lodash' import { DEV_HOUSE_LIQUIDITY_PROVIDER_ID, HOUSE_LIQUIDITY_PROVIDER_ID, @@ -93,8 +94,8 @@ export const createuser = newEndpoint(opts, async (req, auth) => { await firestore.collection('private-users').doc(auth.uid).create(privateUser) - await sendWelcomeEmail(user, privateUser) await addUserToDefaultGroups(user) + await sendWelcomeEmail(user, privateUser) await track(auth.uid, 'create user', { username }, { ip: req.ip }) return user diff --git a/functions/src/email-templates/500-mana.html b/functions/src/email-templates/500-mana.html index 5f0c450e..1ef9dbb7 100644 --- a/functions/src/email-templates/500-mana.html +++ b/functions/src/email-templates/500-mana.html @@ -1,12 +1,48 @@ - + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+

Thanks for + using Manifold Markets. Running low + on mana (M$)? Click the link below to receive a one time gift of M$500!

+
+
+

+
+ + + + +
+ + + + +
+ + Claim M$500 + +
+
+
+
+

+ +

 

+

Cheers,

+

David from Manifold

+

 

+
+
+
+ +
+
+ +
+ + + +
+ +
+ + + +
+ + + +
+
+ + + + + +
+ +
+ + + + + + +
+ + + + + + + + + +
+
+

This e-mail has been sent to {{name}}, click here to unsubscribe.

+
+
+
+
+
+
+
+ +
+ + + + + + \ No newline at end of file diff --git a/functions/src/email-templates/creating-market.html b/functions/src/email-templates/creating-market.html new file mode 100644 index 00000000..64273e7c --- /dev/null +++ b/functions/src/email-templates/creating-market.html @@ -0,0 +1,738 @@ + + + + (no subject) + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + +
+ +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+
+

+ On Manifold Markets, several important factors + go into making a good question. These lead to + more people betting on them and allowing a more + accurate prediction to be formed! +

+

+   +

+

+ Manifold also gives its creators 10 Mana for + each unique trader that bets on your + market! +

+

+   +

+

+ What makes a good question? +

+
    +
  • + Clear resolution criteria. This is + needed so users know how you are going to + decide on what the correct answer is. +
  • +
  • + Clear resolution date. This is + sometimes slightly different from the closing + date. We recommend leaving the market open up + until you resolve it, but if it is different + make sure you say what day you intend to + resolve it in the description! +
  • +
  • + Detailed description. Use the rich + text editor to create an easy to read + description. Include any context or background + information that could be useful to people who + are interested in learning more that are + uneducated on the subject. +
  • +
  • + Add it to a group. Groups are the + primary way users filter for relevant markets. + Also, consider making your own groups and + inviting friends/interested communities to + them from other sites! +
  • +
  • + Bonus: Add a comment on your + prediction and explain (with links and + sources) supporting it. +
  • +
+

+   +

+

+ Examples of markets you should + emulate!  +

+ +

+   +

+

+ Why not + + + + create a market + while it is still fresh on your mind? +

+

+ Thanks for reading! +

+

+ David from Manifold +

+
+
+
+ +
+
+ +
+ + + +
+ + +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + +
+
+

+ This e-mail has been sent to {{name}}, + click here to unsubscribe. +

+
+
+
+
+ +
+
+ + + + diff --git a/functions/src/emails.ts b/functions/src/emails.ts index a29f982c..b7469e9f 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -165,7 +165,6 @@ export const sendWelcomeEmail = async ( ) } -// TODO: use manalinks to give out M$500 export const sendOneWeekBonusEmail = async ( user: User, privateUser: PrivateUser @@ -185,12 +184,12 @@ export const sendOneWeekBonusEmail = async ( await sendTemplateEmail( privateUser.email, - 'Manifold one week anniversary gift', + 'Manifold Markets one week anniversary gift', 'one-week', { name: firstName, unsubscribeLink, - manalink: '', // TODO + manalink: 'https://manifold.markets/link/lj4JbBvE', }, { from: 'David from Manifold ', diff --git a/functions/src/index.ts b/functions/src/index.ts index b8f3eedb..76e54f1c 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -27,6 +27,25 @@ export * from './on-delete-group' export * from './score-contracts' // v2 +export * from './health' +export * from './transact' +export * from './change-user-info' +export * from './create-user' +export * from './create-answer' +export * from './place-bet' +export * from './cancel-bet' +export * from './sell-bet' +export * from './sell-shares' +export * from './claim-manalink' +export * from './create-contract' +export * from './add-liquidity' +export * from './withdraw-liquidity' +export * from './create-group' +export * from './resolve-market' +export * from './unsubscribe' +export * from './stripe' +export * from './mana-bonus-email' + import { health } from './health' import { transact } from './transact' import { changeuserinfo } from './change-user-info' diff --git a/functions/src/mana-bonus-email.ts b/functions/src/mana-bonus-email.ts new file mode 100644 index 00000000..29a7e6e0 --- /dev/null +++ b/functions/src/mana-bonus-email.ts @@ -0,0 +1,42 @@ +import * as functions from 'firebase-functions' +import * as admin from 'firebase-admin' +import * as dayjs from 'dayjs' + +import { getPrivateUser } from './utils' +import { sendOneWeekBonusEmail } from './emails' +import { User } from 'common/user' + +export const manabonusemail = functions + .runWith({ secrets: ['MAILGUN_KEY'] }) + .pubsub.schedule('0 9 * * 1-7') + .onRun(async () => { + await sendOneWeekEmails() + }) + +const firestore = admin.firestore() + +async function sendOneWeekEmails() { + const oneWeekAgo = dayjs().subtract(1, 'week').valueOf() + const twoWeekAgo = dayjs().subtract(2, 'weeks').valueOf() + + const userDocs = await firestore + .collection('users') + .where('createdTime', '<=', oneWeekAgo) + .get() + + for (const user of userDocs.docs.map((d) => d.data() as User)) { + if (user.createdTime < twoWeekAgo) continue + + const privateUser = await getPrivateUser(user.id) + if (!privateUser || privateUser.manaBonusEmailSent) continue + + await firestore + .collection('private-users') + .doc(user.id) + .update({ manaBonusEmailSent: true }) + + console.log('sending m$ bonus email to', user.username) + await sendOneWeekBonusEmail(user, privateUser) + return + } +} diff --git a/functions/src/send-email.ts b/functions/src/send-email.ts index f97234f6..d081997f 100644 --- a/functions/src/send-email.ts +++ b/functions/src/send-email.ts @@ -26,9 +26,10 @@ export const sendTemplateEmail = ( subject: string, templateId: string, templateData: Record, - options?: { from: string } + options?: Partial ) => { - const data = { + const data: mailgun.messages.SendTemplateData = { + ...options, from: options?.from ?? 'Manifold Markets ', to, subject, @@ -36,6 +37,7 @@ export const sendTemplateEmail = ( 'h:X-Mailgun-Variables': JSON.stringify(templateData), } const mg = initMailgun() + return mg.messages().send(data, (error) => { if (error) console.log('Error sending email', error) else console.log('Sent template email', templateId, to, subject) diff --git a/yarn.lock b/yarn.lock index 9334b737..bbf8d3ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5144,6 +5144,11 @@ dayjs@1.10.7: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== +dayjs@1.11.4: + version "1.11.4" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.4.tgz#3b3c10ca378140d8917e06ebc13a4922af4f433e" + integrity sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g== + debug@2, debug@2.6.9, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"