-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
214 lines (192 loc) · 7.13 KB
/
index.js
File metadata and controls
214 lines (192 loc) · 7.13 KB
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
const NODE_ENV = process.env.NODE_ENV;
const SMTP_HOST = process.env.SMTP_HOST;
const SMTP_PORT = process.env.SMTP_PORT;
const SMTP_USERNAME = process.env.SMTP_USERNAME;
const SMTP_PASSWORD = process.env.SMTP_PASSWORD;
const FROM_EMAIL = process.env.FROM_EMAIL;
const SYNC_BASE_URL = process.env.SYNC_BASE_URL;
if (!NODE_ENV) return console.error(`Env-Var NODE_ENV missing`);
if (!SMTP_HOST) return console.error(`Env-Var SMTP_HOST missing`);
if (!SMTP_PORT) return console.error(`Env-Var SMTP_PORT missing`);
if (!SMTP_USERNAME) return console.error(`Env-Var SMTP_USERNAME missing`);
if (!SMTP_PASSWORD) return console.error(`Env-Var SMTP_PASSWORD missing`);
if (!FROM_EMAIL) return console.error(`Env-Var FROM_EMAIL missing`);
if (!SYNC_BASE_URL) return console.error(`Env-Var SYNC_BASE_URL missing`);
if (!(NODE_ENV && SMTP_HOST && SMTP_PORT && SMTP_USERNAME && SMTP_PASSWORD && FROM_EMAIL && SYNC_BASE_URL)) return exit(1);
console.log(`NODE_ENV: ${NODE_ENV}`);
console.log(`SMTP_HOST: ${SMTP_HOST}`);
console.log(`SMTP_PORT: ${SMTP_PORT}`);
console.log(`SMTP_USERNAME: ${SMTP_USERNAME}`);
console.log(`SMTP_PASSWORD: ${SMTP_PASSWORD}`);
console.log(`FROM_EMAIL: ${FROM_EMAIL}`);
console.log(`SYNC_BASE_URL: ${SYNC_BASE_URL}`);
const {interval} = require('linklet');
const fs = require('fs');
const _ = require('lodash');
const moment = require('moment');
const SMTPConnection = require('nodemailer/lib/smtp-connection');
const MailComposer = require('nodemailer/lib/mail-composer');
const PouchDB = require('pouchdb');
PouchDB.plugin(require('pouchdb-adapter-memory'));
const usersDB = new PouchDB('users', {adapter: 'memory'});
const statisticsDB = new PouchDB('statistics', {adapter: 'memory'});
const deploymentsDB = new PouchDB('deployments', {adapter: 'memory'});
let currentUsers = [];
let currentStats = [];
let currentDeployments = [];
PouchDB.replicate(new PouchDB(`${SYNC_BASE_URL}/users`), usersDB, {
live: true,
retry: true,
batch_size: 1000
})
.on('change', changes => usersChangedHandler(changes))
.on('complete', () => console.log(`Sync from ${SYNC_BASE_URL}/users completed`))
.on('error', error => console.error(`Sync from ${SYNC_BASE_URL}/users error`));
PouchDB.replicate(new PouchDB(`${SYNC_BASE_URL}/statistics`), statisticsDB, {
live: true,
retry: true,
batch_size: 1000
})
.on('change', changes => statisticsChangedHandler(changes))
.on('complete', () => console.log(`Sync from ${SYNC_BASE_URL}/statistics completed`))
.on('error', error => console.error(`Sync from ${SYNC_BASE_URL}/statistics error`));
PouchDB.replicate(new PouchDB(`${SYNC_BASE_URL}/deployments`), deploymentsDB, {
live: true,
retry: true,
batch_size: 1000
})
.on('change', changes => deploymentsChangedHandler(changes))
.on('complete', () => console.log(`Sync from ${SYNC_BASE_URL}/deployments completed`))
.on('error', error => console.error(`Sync from ${SYNC_BASE_URL}/deployments error`));
module.exports = interval({period: 1000})(() => {
const endOfDay = moment()
.endOf('day')
.toString();
const currentDateTime = moment().toString();
if (currentDateTime === endOfDay) {
currentStats.forEach(x => {
x.services = Object.keys(x.services)
.map(i => x.services[i])
.filter(x => x.active)
.map(y => {
const currentDeployment = currentDeployments.find(z => z.serviceName === y.name && z.userId === x.id);
if (!currentDeployment) return;
return Object.assign({}, y, currentDeployment);
})
.filter(x => x);
sendUsageEmail({to: x.id, usage: x})
.then(data => console.log(`Statistic email to ${x.id}. ${data}`))
.catch(console.error);
});
}
});
function deploymentsChangedHandler(changes) {
deploymentsDB.allDocs({include_docs: true}).then(
data =>
(currentDeployments = data.rows.map(x =>
Object.assign({}, x.doc, {
id: x.doc._id,
_id: undefined,
_rev: undefined
})
))
);
}
function statisticsChangedHandler(changes) {
statisticsDB.allDocs({include_docs: true}).then(data => {
currentStats = data.rows.map(x =>
Object.assign({}, x.doc, {
id: x.doc._id,
_id: undefined,
_rev: undefined
})
);
currentStats = NODE_ENV === 'development' ? currentStats.filter(x => x.id === 'go@dropstack.run') : currentStats.filter(x => x.id !== 'admin');
});
}
function usersChangedHandler(changes) {
const changedUsers = changes.docs.filter(x => !x._deleted).map(x => Object.assign({}, {id: x._id}, x.metadata));
if (currentUsers.length === 0) currentUsers = changedUsers;
// changed users to send welcome email
const newUsers = _.differenceWith(changedUsers, currentUsers, (a, b) => a.id === b.id);
newUsers.forEach(x =>
sendWelcomeEmail({to: x.id})
.then(data => console.log(`Welcome email to ${x.id}. ${data}`))
.catch(console.error)
);
currentUsers = _.uniqBy(currentUsers.concat(newUsers), x => x.id);
// changed plan email
const changedUser = changedUsers[0] || {};
const currentUser = currentUsers.find(({id, plan}) => id === changedUser.id && plan !== changedUser.plan);
if (currentUser) {
currentUser.plan = changedUser.plan;
sendPlanEmail({to: changedUser.id, plan: changedUser.plan})
.then(data => console.log(`Plan changed email to ${changedUser.plan} for ${changedUser.id}. ${data}`))
.catch(console.error);
}
}
function sendWelcomeEmail({to}) {
console.log(`Sending welcome email to ${to}`);
const html = fs.readFileSync('templates/welcome.tpl.html');
return sendEMail({
to,
subject: `Welcome to Awesomeness!`,
html
});
}
function sendPlanEmail({to, plan = 'free'}) {
console.log(`Sending plan email to ${to}`);
const html = _.template(fs.readFileSync('templates/plan.tpl.html'))({
plan: plan.toUpperCase()
});
return sendEMail({
to,
subject: `${plan.toUpperCase()} Plan Activated!`,
html
});
}
function sendUsageEmail({to, usage}) {
console.log(`Sending usage email to ${to}`);
const html = _.template(fs.readFileSync('templates/daily-usage.tpl.html'))({
usage
});
return sendEMail({
to,
subject: `Daily Usage Statistics`,
html
});
}
function sendEMail({to, subject, html}) {
return new Promise((resolve, reject) => {
const connection = new SMTPConnection({
host: SMTP_HOST,
port: SMTP_PORT,
secure: true
});
connection.connect(error => {
if (error) return reject(error);
connection.login({credentials: {user: SMTP_USERNAME, pass: SMTP_PASSWORD}}, (error, data) => {
if (error) {
connection.quit();
return reject(error);
}
const mail = new MailComposer({
from: `DROPSTACK | CLOUD <${FROM_EMAIL}>`,
to,
subject,
html
});
const mailStream = mail.compile().createReadStream();
connection.send({from: FROM_EMAIL, to}, mailStream, (error, data) => {
if (error) {
connection.quit();
return reject(error);
}
connection.quit();
if (!data.accepted) return reject(new Error('Email sending error'));
return resolve(`Email sent.`);
});
});
});
});
}