-
Notifications
You must be signed in to change notification settings - Fork 20
/
app.ts
89 lines (81 loc) · 3.32 KB
/
app.ts
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
import * as appInsights from "applicationinsights";
import express from "express";
import hbs from "hbs";
import NodeCache from "node-cache";
import { Config } from "./config";
import { MenuFetcher, IMenuResult } from "./menuFetcher";
import { isError } from "util";
import { sk } from "date-fns/locale";
import { formatDistance, parse, isValid } from "date-fns";
console.debug("Initializing...");
const config = new Config();
const cache = new NodeCache({
checkperiod: (config.cacheExpiration / 2),
useClones: false
});
const menuFetcher = new MenuFetcher(config, cache);
if (config.appInsightsConnectionString) {
appInsights.setup(config.appInsightsConnectionString).setAutoCollectConsole(true, true);
appInsights.start();
}
const actions = new Map<string, ((date: Date, done: (result: IMenuResult) => void) => void)>();
for (const location of config.restaurants.keys()) {
for (const restaurant of config.restaurants.get(location)) {
console.log(`Processing: ${location}/${restaurant.id} - ${restaurant.name}`);
try {
const id = location + "-" + restaurant.id;
if (actions.has(id)) {
throw new Error("Non unique id '" + id + "' provided within '" + location + "' restaurants");
}
actions.set(id, (date, doneCallback) => menuFetcher.fetchMenu(restaurant.urlFactory, date, restaurant.parser, doneCallback));
} catch (e) {
console.warn(e);
}
}
}
if (actions.size === 0) {
throw new Error("Actions initialization failed");
}
console.debug("Express setup...");
const app = express();
app.set("view engine", "html");
app.engine("html", hbs.__express);
app.use(express.static(__dirname + "/../static"));
app.get("/:location?", (req, res) => {
res.setHeader("Content-Type", "text/html; charset=UTF-8");
res.setHeader("Content-Language", "sk");
const location = req.params.location || config.restaurants.keys().next().value; // use first location if not specified
res.render(__dirname + "/../views/index.html", {
locations: [...config.restaurants.keys()].map(k => ({ name: k, selected: k === location })),
restaurants: config.restaurants.get(location).map(x => ({
id: location + "-" + x.id,
name: x.name,
url: x.urlFactory(new Date())
})),
appInsightsConnectionString: config.appInsightsConnectionString
});
});
app.get("/menu/:id", (req, res) => {
const date = parse(req.query.date as string, "yyyy-M-d", new Date());
if (!isValid(date)) {
res.statusCode = 400;
res.send("Missing/incorrect 'date' query parameter");
return;
}
if (!actions.has(req.params.id)) {
res.statusCode = 404;
res.send("Restaurant " + req.params.id + " not found");
return;
}
actions.get(req.params.id)(date, result => {
const timeago = formatDistance(result.timestamp, new Date(), { addSuffix: true, locale: sk });
if (isError(result.value)) {
res.status(500).json({ error: result.value.toString(), timeago });
} else {
res.json({ menu: result.value, timeago });
}
});
});
const server = app.listen(config.port, () => {
console.info("Done, listening on", server.address());
});