-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
147 lines (128 loc) · 4.31 KB
/
server.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
const express = require('express');
let rp = require('request-promise');
const bodyParser = require('body-parser');
const cheerio = require('cheerio');
const sampleData = require('./sample_data');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static('app'));
// Setup Cookie Jar
let jar = rp.jar();
rp = rp.defaults({ jar: jar });
// Setup Request Options
const loginPage = 'https://mealacct.mcmaster.ca/OneWeb/Account/LogOn';
const transactionPage =
'https://mealacct.mcmaster.ca/OneWeb/Financial/TransactionsPass?dateFrom=2016%2F01%2F13+00%3A00%3A00&dateTo=2100%2F08%2F13+23%3A59%3A59&returnRows=1000&_=' +
Date.now();
// Handle API Call
app.post('/api', (req, res) => {
// Clear cookie jar on each request
jar = rp.jar();
let token = 0;
let studentNumber = req.body.studentNumber;
let accountPin = req.body.accountPin;
const getTokenOptions = {
uri: loginPage,
transform: body => {
return cheerio.load(body);
}
};
function sendResults(data) {
res.send(data);
}
if (+studentNumber === 400120999 && +accountPin === 1234)
return sendResults(sampleData);
// Acquire Login Token
rp(getTokenOptions)
.then($ => {
token = $('[name=__RequestVerificationToken]').val();
params = {
__RequestVerificationToken: token,
Account: studentNumber,
Password: accountPin
};
console.log('Request Token Acquired');
const loginOptions = {
method: 'POST',
uri: loginPage,
form: params
};
// Login to Payment System
rp(loginOptions)
// Returns 200 if login is bad
.then(res => {
sendResults('Incorrect student number / pin');
console.log('Incorrect student number / pin');
})
.catch((res, err) => {
if (res.statusCode == 302) {
console.log('Logged in');
const scrapeOptions = {
uri: transactionPage,
transform: body => {
return cheerio.load(body);
}
};
// Scrape Transaction History
rp(scrapeOptions)
.then($ => {
let trns = [];
$('table.table > tbody > tr').each((i, elem) => {
let dateTime = $(elem)
.children('td[data-title="Date:"]')
.html();
let date = dateTime.match(/\d{2}\/\d{2}\/\d{4}/g)[0];
let time = dateTime.match(
/\d{1,2}:\d{2}:\d{2} (?:PM|AM)/g
)[0];
trns[i] = {
date: date,
time: time,
amount: $(elem)
.children('td[data-title="Amount:"]')
.html()
.replace(',', ''),
account: parseInt(
$(elem)
.children('td[data-title="Balance:"]')
.html()
),
desposit: parseInt(
$(elem)
.children('td[data-title="Units:"]')
.html()
),
trantype: $(elem)
.children('td[data-title="Trantype:"]')
.html()
.trim(),
terminal: $(elem)
.children('td[data-title="Terminal:"]')
.html()
.trim()
.slice(8) // Fix this hack with regex
};
});
trns.reverse();
console.log('Data processed');
sendResults(trns);
})
.catch(err => {
sendResults('Error scraping transaction page');
console.log('Error scraping transaction page');
});
} else {
sendResults('Error logging in:\n', res.statusCode);
console.error('Error logging in:\n', res.statusCode);
}
});
})
.catch(err => {
sendResults('Error acquiring login token');
return console.error(err);
});
});
const port = process.env.PORT || 3000;
app.listen(port);
console.log('Magic happens on port', port);