-
Notifications
You must be signed in to change notification settings - Fork 3
/
handler.js
183 lines (169 loc) · 5.3 KB
/
handler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
'use strict';
const _ = require('underscore');
const fs = require('fs');
const YAML = require('js-yaml');
const AWS = require('aws-sdk');
const mongodb = require('mongodb');
const postmark = require('postmark');
const moment = require('moment');
let mailClient;
let prod = false;
let sentEmails = 0;
const driveStart = 'kpccPlusDriveStart';
const driveEnd = 'kpccPlusDriveEnd';
const secretPath = './secrets';
const kms = new AWS.KMS({ region: 'us-west-2' });
const encryptedSecret = fs.readFileSync(secretPath);
const MongoClient = mongodb.MongoClient;
const kmsParams = {
CiphertextBlob: encryptedSecret,
};
const emailSubject = 'Welcome to KPCC Plus!';
const startingTime = new Date().getTime();
function driveTimePromise(db) {
const collection = db.collection('iPhoneSettings');
return new Promise((resolve) => {
collection.find({ settingName: { $in: [driveStart, driveEnd] } }).toArray((err, results) => {
let driveStartTimestamp;
let driveEndTimestamp;
_.each(results, (setting) => {
if (setting.settingName === driveStart) {
driveStartTimestamp = setting.settingValue;
} else if (setting.settingName === driveEnd) {
driveEndTimestamp = setting.settingValue;
}
});
resolve(driveStartTimestamp && driveEndTimestamp
&& moment(driveStartTimestamp).isBefore(startingTime)
&& moment(driveEndTimestamp).isAfter(startingTime));
});
});
}
function sendIndividualEmail(userObject, callback) {
let name = userObject.firstName || userObject.name
if (!name) {
name = '';
}
const emailBody = `Dear ${name},<br />
<p>Congratulations! You can now stream KPCC on your computer or mobile device
during our member drives - without any fundraising interruptions.</p>
<p>The fundraising-free stream KPCC Plus is easy to access. Click or paste this link to listen on your
desktop or mobile web browser:<br />
http://www.scpr.org/listen_live/pledge-free?pledgeToken=${userObject.pledgeToken}<br /></p>
<p>
To access KPCC Plus via the Android app, tap the antenna icon in the orange navigation bar at the top of the screen.
Choose the "KPCC Plus" stream, and type in ${userObject.pledgeToken}
</p>
<p>
To access KPCC Plus on your iPhone or iPad using our iOS app, tap the Settings button (with the gear icon) on
the top-right corner of the screen. Choose the "KPCC Standard" option under the Live Stream section, and type
in ${userObject.pledgeToken}
</p>
<p>
Thanks again for your generous support! Your contribution will go right back into the balanced coverage and inspiring stories you love.
</p>
<p>
Sincerely,<br />
Rob Risko
</p>
<p>
P.S. Having trouble accessing KPCC Plus? Call us at 626-583-5121 or visit our FAQ page: http://www.kpcc.org/plus
</p>`
const email = prod ? userObject.email : '[email protected]';
mailClient.sendEmail({
To: email,
From: 'Rob Risko <[email protected]>',
Subject: emailSubject,
HtmlBody: emailBody,
}, (error) => {
if (error) {
console.error(error.message);
callback.error('Failed to send an email');
return;
}
console.log(`Email sent to ${email}`);
sentEmails += sentEmails + 1;
callback.success(true);
});
}
function findMembersToEmail(db) {
const collection = db.collection('PfsUser');
collection.find({ emailSent: { $eq: false } }).toArray((err, results) => {
if (err) {
console.log(err);
} else if (results.length) {
const handleResult = _.after(results.length, () => {
const elapsedTime = new Date().getTime() - startingTime;
console.log(`Attempted to send ${results.length} emails in ${elapsedTime}ms`);
console.log(`Successfully sent ${sentEmails} emails`);
db.close();
});
_.each(results, (result) => {
const sendIndividualEmailCallback = {
success: () => {
if (prod) {
collection.updateOne(
{ _id: result._id },
{ $set: { emailSent: true } }
);
}
handleResult();
},
error: (error) => {
console.log(error);
handleResult();
},
};
sendIndividualEmail(result, sendIndividualEmailCallback);
});
} else {
console.log('No users to email');
db.close();
}
});
}
function sendEmails() {
console.log(`Running sendEmails (in production? ${prod})`);
new Promise((resolve, reject) => {
kms.decrypt(kmsParams, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
}).then((data) => {
const secrets = YAML.safeLoad(data.Plaintext.toString());
mailClient = new postmark.Client(secrets.postmarkKey);
return new Promise((resolve, reject) => {
MongoClient.connect(secrets.mongoDbUri, (err, db) => {
if (err) {
reject(err);
} else {
resolve(db);
}
});
});
})
.then((db) => {
driveTimePromise(db).then((driveTime) => {
if (!driveTime) {
console.log('Not drive time. Not emailing anyone');
db.close();
return;
}
findMembersToEmail(db);
});
})
.catch((err) => {
console.log(err);
});
}
module.exports.sendEmails_prod = () => {
prod = true;
sendEmails();
};
module.exports.sendEmails_dev = () => {
prod = false;
sendEmails();
};