-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
119 lines (107 loc) · 3.33 KB
/
main.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
const https = require("https");
const MongoClient = require("mongodb").MongoClient;
const sentry = require("@sentry/node");
const { ClistClient } = require("./src/clist-client");
const { ContestsSource } = require("./src/contests-source");
const { DataStoreFileImpl, DataStoreMongoImpl } = require("./src/data-store");
const { googleApiClient } = require("./src/google-api");
const { maybeAddSomeUsers, matchContest } = require("./src/helpers");
const { Logger } = require("./src/logger");
const {
CLIST_KEY,
CLIST_USER_NAME,
MONGO_CONNECTION_URL,
MONGO_DB_NAME,
SENTRY_DSN
} = process.env;
const cleanUpTasks = [];
if (SENTRY_DSN) {
sentry.init({ dsn: SENTRY_DSN });
}
const logger = new Logger(SENTRY_DSN ? sentry : undefined);
const clistClient = new ClistClient(CLIST_KEY, CLIST_USER_NAME, logger, https);
const contestsSource = new ContestsSource(clistClient, logger);
googleApiClient.init(logger);
// Put stuff into run to get the async sugar.
async function run() {
let createDataStoreImpl;
// Try using mongo if possible, otherwise, the file system will be used as the data store.
if (MONGO_CONNECTION_URL) {
const mongoClient = new MongoClient(MONGO_CONNECTION_URL, {
useNewUrlParser: true
});
await mongoClient
.connect()
.then(() => {
const mongoDb = mongoClient.db(
MONGO_DB_NAME ? MONGO_DB_NAME : "contests-sub"
);
createDataStoreImpl = name => {
return new DataStoreMongoImpl(name, mongoDb);
};
cleanUpTasks.push(() => mongoClient.close());
})
.catch(e => {
logger.captureException(e);
process.exit();
});
}
if (!createDataStoreImpl) {
logger.captureMessage(
"Because MONGO_CONNECTION_URL is not provided, file system will be used as storage"
);
createDataStoreImpl = name => new DataStoreFileImpl(name);
}
const userStore = createDataStoreImpl("users");
const users = await userStore.getAll();
await maybeAddSomeUsers(users, userStore, logger);
const eventStore = createDataStoreImpl("events");
const events = await eventStore.getAll();
const subscribe = (contest, user) => {
googleApiClient
.invite({
name: contest.event,
start: contest.start,
end: contest.end,
eventLink: contest.href,
email: user.email
})
.then(ret => {
if (!ret.invited) return;
const event = {
userEmail: user.email,
contestId: contest.id
};
events.push(event);
eventStore.append(event);
});
};
const contestsObserver = {
update: ret => {
users.forEach(u => {
const handledEvents = new Set();
events.forEach(d => {
if (d.userEmail != u.email) return;
handledEvents.add(d.contestId);
});
const matchedContest = ret.filter(
d => matchContest(d, u) && !handledEvents.has(d.id)
);
matchedContest.forEach(d => subscribe(d, u));
});
}
};
contestsSource.registerObserver(contestsObserver);
contestsSource.startQuery(30 * 60 * 1000);
}
run();
function cleanupProcess() {
while (cleanUpTasks.length) {
cleanUpTasks.pop()();
}
process.exit();
}
process.on("exit", cleanupProcess);
process.on("SIGINT", cleanupProcess);
process.on("SIGUSR1", cleanupProcess);
process.on("SIGUSR2", cleanupProcess);