-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcalendar.js
121 lines (101 loc) · 3.24 KB
/
calendar.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
#!/usr/bin/env node
import express from 'express';
import morgan from 'morgan';
import fetch from 'node-fetch';
import puppeteer from 'puppeteer-core';
import fs from 'fs';
import path from 'path';
const app = express();
const port = process.env.PORT || 8080;
const host = process.env.HOST || 'localhost';
const browser_path = process.env.BROWSER_PATH;
if (!browser_path) {
throw new Error("Path to the browser must be specified");
}
app.use(morgan('combined'));
async function getTitles(page, filterId) {
const subjectFilter = filterId.split(';', 4).pop();
if (subjectFilter !== '0') {
const ids = subjectFilter.split(',');
return await page.evaluate((ids) => {
return ids.map(id => document.querySelector(`tr[data-rk="${id}"]`).querySelector('span').innerHTML);
}, ids);
}
return null;
}
async function clickExport(page) {
await page.evaluate(() => {
const node = document.querySelector('a[title="Izvoz celotnega urnika v ICS formatu "]');
if (node == null) {
throw 'Export button not found';
}
const handler = node.getAttributeNode('onclick').nodeValue;
node.setAttribute('onclick', handler.replace('_blank', '_self'));
node.click();
});
}
function setupDownloadHook(page, cookies) {
return new Promise(resolve => {
page.on('request', async request => {
console.log(request.url());
if (request.url() === 'https://www.wise-tt.com/wtt_um_feri/TextViewer') {
const response = await fetch(request.url(), {
headers: {
...request.headers(),
'cookie': cookies.map(cookie => `${cookie.name}=${cookie.value}`).join(';'),
}
});
const data = await response.text();
resolve(data);
} else {
request.continue(); // Redirect 302
}
});
});
}
async function fetchCalendar(filterId) {
const browser = await puppeteer.launch({executablePath: browser_path});
try {
const page = await browser.newPage();
await page.goto(`https://www.wise-tt.com/wtt_um_feri/index.jsp?filterId=${filterId}`);
await page.setRequestInterception(true);
const cookies = await page.cookies();
const download = setupDownloadHook(page, cookies);
const titles = await getTitles(page, filterId);
await clickExport(page);
let data = await download;
if (titles != null) {
data = data.replace(/\s*BEGIN:VEVENT[\s\S]*?END:VEVENT\s*/g, event => {
return titles.some(title => event.includes(`SUMMARY:${title}`)) ? event : '';
});
}
const position = data.indexOf('BEGIN:VEVENT');
data = data.substr(0, position) + 'X-WR-TIMEZONE:Europe/Ljubljana\n' + data.substr(position);
return data;
} finally {
await browser.close();
}
}
app.get('/', (req, res) => {
res.redirect('https://github.com/brokenpylons/Calendar');
});
app.get('/up', (req, res) => {
res.set('content-type', 'text/plain');
res.send('yes');
});
app.get('/calendar', async (req, res) => {
res.set('content-type', 'text/plain');
if (!('filterId' in req.query)) {
res.sendStatus(400);
return;
}
try {
const data = await fetchCalendar(req.query.filterId);
res.send(data);
} catch(e) {
console.log(e);
res.sendStatus(404);
}
});
app.listen(port, host);
console.log(`${host}:${port}`);