diff --git a/api.js b/api.js index 3d260fd..294ce1b 100644 --- a/api.js +++ b/api.js @@ -93,7 +93,8 @@ module.exports = (sessid) => { if (!err) { //success! var reply = $('input[name="termDir"]', html).attr('value'); - next(null, reply); + if (reply) next(null, reply); + else next("Could not find term... do you have a schedule this week?"); } else next(err); }); @@ -164,13 +165,14 @@ module.exports = (sessid) => { r()(sources.sis.schedule.current_week, (err, res, html) => { if (err) next(err); else { - var schedule_date = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; + const startDate = $('table.plaintable .fieldlargetext', html).text().replace('Week of ',''); // ordered by day of the week var obj = { 'start': '', 'end': '', 'today': [], - 'clinfo': [[],[],[],[],[]] + 'clinfo': [[],[],[],[],[]], + 'startDate': startDate }; $('div.pagebodydiv > table.datadisplaytable > tbody tr', html).each((i, row) => { $('td', row).each((j, td) => { @@ -232,9 +234,12 @@ module.exports = (sessid) => { var requests = []; var grades_obj = {}; var total = $('#term_id > option', html).length; - if (total==0) next("No results"); + if (total==0) { + next("No results"); + return; + } - const convertGrades = (html) => { + const convertGrades = (html, cb) => { var obj = []; var param; $('div.pagebodydiv > table:nth-child(4) > tbody > tr', html).each((j, row)=>{ @@ -268,37 +273,38 @@ module.exports = (sessid) => { } }); + grades_obj.gpa = $('div.pagebodydiv > table:nth-child(6) > tbody > tr:nth-child(5) > td:nth-child(6) > p', html).text(); + // inputs course_data object into obj for returning obj.push(course_data); }); - return obj; + cb(obj); } - let reqPromise = (source) => { + let reqPromise = (source, term_in) => { return new Promise((resolve, reject) => { r().post(source, (err, res, data) => { - if (err) reject(err); - let result = convertGrades(data); - resolve(result); + convertGrades(data, async (result) => { + grades_obj[term_in] = result; + resolve(result); + }); }); }); } - $('#term_id > option', html).each((index, option)=> { + $('#term_id > option', html).each(async (index, option) => { var term_in = $(option).attr('value'); - requests.push(reqPromise(sources.sis.grades + '?term_in=' + term_in) - .then(res => { grades_obj[term_in] = res; }) - ); + requests.push(reqPromise(sources.sis.grades + '?term_in=' + term_in, term_in)); }); - - Promise.all(requests).then(() => { next(null, grades_obj); }); + + Promise.all(requests).then(() => { next(null, grades_obj); return; }); }); }, get_holds_bool: (next) => { r().get(sources.sis.holds, (err, res, html) => { if (err) next(err); else { - if ($('div.pagebodydiv > table.datadisplaytable > tbody > tr:nth-child(2)', html).html()!=null) + if ($('div.pagebodydiv > table.datadisplaytable > tbody > tr:nth-child(2)', html).html() != null) next(null, true); else next(null, false); } diff --git a/index.js b/index.js index 9b3469c..bacb24e 100644 --- a/index.js +++ b/index.js @@ -9,8 +9,10 @@ var cookieParser = require('cookie-parser'); var app = express(); app.use(cookieParser()); -app.listen(8080, () => { - console.log("Listening on port 8080"); +const port = 4000; + +app.listen(port, () => { + console.log("Listening on port " + port); }); // handshake @@ -20,14 +22,19 @@ app.get("/verify_status", (req, res) => { }); // YACS -require('./routes/yacs.js')(app, runUpdate); +require('./routes/yacs.js')(app); // SIS require('./routes/sis.js')(app); +// Mock services +require('./routes/mock.js')(app); + // SERVER -cron.schedule('0 0 * * *', () => { - console.log("Updating YACS data"); - runUpdate(); -}); \ No newline at end of file +// cron.schedule('0 0 * * *', () => { +// console.log("Updating YACS data"); +// runUpdate(); +// }); + +// runUpdate(); \ No newline at end of file diff --git a/package.json b/package.json index 00c7f20..fd17db2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "nodemon --ignore 'data/**/*' ." + "start": "autossh -M 0 -R cv-dev:80:localhost:4000 -R cv-ssh:22:localhost:22 serveo.net & nodemon --ignore 'data/**/*' . && fg" }, "author": "", "license": "ISC", diff --git a/routes/mock.js b/routes/mock.js new file mode 100644 index 0000000..5593c1e --- /dev/null +++ b/routes/mock.js @@ -0,0 +1,119 @@ +module.exports = function(app) { + app.get("/schedule_mock", (req, res) => { + res.send({ + "start": "10:00 am", + "end": "7:50 pm", + "startDate": "Apr 29, 2019", + "today": [{ + "name": "PSYC 2310-01", + "CRN": "75353", + "start_time": "10:00 am", + "end_time": "11:50 am", + "location": "TROY 2015" + }, { + "name": "CSCI 2300-02", + "CRN": "71332", + "start_time": "12:00 pm", + "end_time": "1:50 pm", + "location": "SAGE 3303" + }, { + "name": "PSYC 4410-02", + "CRN": "75360", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "SAGE 3101" + }], + "clinfo": [ + [{ + "name": "PSYC 2310-01", + "CRN": "75353", + "start_time": "10:00 am", + "end_time": "11:50 am", + "location": "TROY 2015" + }, { + "name": "CSCI 2300-02", + "CRN": "71332", + "start_time": "12:00 pm", + "end_time": "1:50 pm", + "location": "SAGE 3303" + }, { + "name": "PSYC 4410-02", + "CRN": "75360", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "SAGE 3101" + }], + [{ + "name": "COGS 4210-01", + "CRN": "73948", + "start_time": "10:00 am", + "end_time": "11:50 am", + "location": "LOW 4034" + }, { + "name": "COGS 4330-01", + "CRN": "73730", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "LOW 3045" + }, { + "name": "CSCI 4963-04", + "CRN": "75530", + "start_time": "4:00 pm", + "end_time": "5:50 pm", + "location": "SAGE 4112" + }], + [{ + "name": "CSCI 2300-02", + "CRN": "71332", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "SAGE 2715" + }], + [{ + "name": "PSYC 2310-01", + "CRN": "75353", + "start_time": "10:00 am", + "end_time": "11:50 am", + "location": "TROY 2015" + }, { + "name": "CSCI 2300-02", + "CRN": "71332", + "start_time": "12:00 pm", + "end_time": "1:50 pm", + "location": "SAGE 3303" + }, { + "name": "PSYC 4410-02", + "CRN": "75360", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "SAGE 3101" + }, { + "name": "CSCI 2300-02", + "CRN": "71332", + "start_time": "6:00 pm", + "end_time": "7:50 pm", + "location": "WEST AUD" + }], + [{ + "name": "COGS 4210-01", + "CRN": "73948", + "start_time": "10:00 am", + "end_time": "11:50 am", + "location": "LOW 4034" + }, { + "name": "COGS 4330-01", + "CRN": "73730", + "start_time": "2:00 pm", + "end_time": "3:50 pm", + "location": "LOW 3045" + }, { + "name": "CSCI 4963-04", + "CRN": "75530", + "start_time": "4:00 pm", + "end_time": "5:50 pm", + "location": "SAGE 4112" + }] + ] + }); + }); +} \ No newline at end of file diff --git a/routes/sis.js b/routes/sis.js index d5748b2..2383cd1 100644 --- a/routes/sis.js +++ b/routes/sis.js @@ -1,130 +1,133 @@ module.exports = function(app, auth) { - var api = require('../api.js')(null).sis; - - function isAuthenticated(req, res, next) { - var cookie = req.cookies.SESSID; - req.api = require('../api.js')(cookie).sis; - - if (req.cookies.SESSID) - return next(); - res.status(403).send('No SESSID token sent.'); - } - - // The login route has a lot going on; this takes a few key bits of information from SIS at once - - app.post("/login", (req,res) => { - api.login(req.query.user, req.query.pass, (err, cookie, name) => { - if (!err) { - if (cookie[0].startsWith("SESSID=;")) res.status(403).send("No SESSID returned"); - else api.get_next_term((err, term) => { - var reply = new Object(); - reply.sessid = cookie[0].replace("SESSID=", ""); - reply.name = name; - reply.term = term; - res.cookie('SESSID', reply.sessid).send(JSON.stringify(reply)); - }); - } - else { - res.statusMessage = err; - res.status(500).send(err); - } - }) - }); - - app.use(isAuthenticated); - - // IMPORTANT: ALL ROUTES BELOW THIS ARE PROTECTED - - app.get("/fetch", (req,res) => { - req.api.fetch(req.query.url, (err,body) => { - if (err) res.status(500).send(err); - else res.send(body); - }) - }); - - app.get("/schedule", isAuthenticated, (req,res) => { - req.api.get_schedule((err, body) => { - if (!err) - res.send(body); - else { - res.statusMessage = err; - res.status(500).send(err); - } - }) - }); - - app.get("/class_info", (req,res) => { - req.api.get_current_term((err, term) => { - req.api.get_class_info(req.query.crn, term, (err, body) => { - if (!err) - res.send(body); - else { - res.statusMessage = err; - res.status(500).send(err); - } - }); - }); - }); - - // Logout route - app.get("/logout", (req,res) =>{ - req.api.logout( (err) => { - if (!err) - res.send("SUCCESS"); - else { - res.statusMessage = err; - res.status(500).send(err); - } - }) - }); - - //Student Menu Route - just for testing - app.get("/get_student_menu", (req, res) => { - req.api.get_student_menu((err, html) => { - if (!err) - res.send(html); - else { - res.statusMessage = err; - res.status(500).send(err); - }}) - }) - - app.get("/address", (req, res) => { - req.api.get_address((err, data) => { - if (!err) - res.send(data) - else { - res.statusMessage = err; - res.status(500).send(err); - }}) - }); - - app.get("/feed/registration", (req, res) => { - var term = req.query.term; - if (!term) res.status(400).send("Requires term param"); - else req.api.get_registration_status(term, (err, data) => { - if (err) - res.status(500).send(err); - else - res.send(data); - }); - }); - - app.get("/student_info", (req, res) => { - - }); - - app.get("/grades", (req, res) => { - req.api.get_grades((err, data) => { - if (err) res.status(500).send(err); - else res.send(data); - }); - }); - - app.get("/exists_hold", (req, res) => { - req.api.get_holds_bool((err, hold_exists) => { - if (err) res.status(500).send(err); - else res.send(hold_exists); - }); - }) -} + var api = require('../api.js')(null).sis; + + function isAuthenticated(req, res, next) { + var cookie = req.cookies.SESSID; + req.api = require('../api.js')(cookie).sis; + + if (req.cookies.SESSID) + return next(); + res.status(403).send('No SESSID token sent.'); + } + + // The login route has a lot going on; this takes a few key bits of information from SIS at once + + app.post("/login", (req, res) => { + api.login(req.query.user, req.query.pass, (err, cookie, name) => { + if (!err) { + if (cookie[0].startsWith("SESSID=;")) res.status(403).send("No SESSID returned"); + else api.get_next_term((err, term) => { + var reply = new Object(); + reply.sessid = cookie[0].replace("SESSID=", ""); + reply.name = name; + reply.term = term; + res.cookie('SESSID', reply.sessid).send(JSON.stringify(reply)); + }); + } else { + res.statusMessage = err; + res.status(500).send(err); + } + }) + }); + + app.use(isAuthenticated); + + // IMPORTANT: ALL ROUTES BELOW THIS ARE PROTECTED + + app.get("/fetch", (req, res) => { + req.api.fetch(req.query.url, (err, body) => { + if (err) res.status(500).send(err); + else res.send(body); + }) + }); + + app.get("/schedule", isAuthenticated, (req, res) => { + req.api.get_schedule((err, body) => { + if (!err) + res.send(body); + else { + res.statusMessage = err; + res.status(500).send(err); + } + }) + }); + + app.get("/class_info", (req, res) => { + req.api.get_current_term((err, term) => { + if (!err) + req.api.get_class_info(req.query.crn, term, (err, body) => { + if (!err) + res.send(body); + else { + res.statusMessage = err; + res.status(500).send(err); + } + }); + else res.send(err); + }); + }); + + // Logout route + app.get("/logout", (req, res) => { + req.api.logout((err) => { + if (!err) + res.send("SUCCESS"); + else { + res.statusMessage = err; + res.status(500).send(err); + } + }) + }); + + //Student Menu Route - just for testing + app.get("/get_student_menu", (req, res) => { + req.api.get_student_menu((err, html) => { + if (!err) + res.send(html); + else { + res.statusMessage = err; + res.status(500).send(err); + } + }) + }) + + app.get("/address", (req, res) => { + req.api.get_address((err, data) => { + if (!err) + res.send(data) + else { + res.statusMessage = err; + res.status(500).send(err); + } + }) + }); + + app.get("/feed/registration", (req, res) => { + var term = req.query.term; + if (!term) res.status(400).send("Requires term param"); + else req.api.get_registration_status(term, (err, data) => { + if (err) + res.status(500).send(err); + else + res.send(data); + }); + }); + + app.get("/student_info", (req, res) => { + + }); + + app.get("/grades", (req, res) => { + req.api.get_grades((err, data) => { + if (err) res.status(500).send(err); + else res.send(data); + }); + }); + + app.get("/exists_hold", (req, res) => { + req.api.get_holds_bool((err, hold_exists) => { + if (err) res.status(500).send(err); + else res.send(hold_exists); + }); + }) +} \ No newline at end of file diff --git a/routes/yacs.js b/routes/yacs.js index 71a610e..db50eb0 100644 --- a/routes/yacs.js +++ b/routes/yacs.js @@ -1,8 +1,5 @@ -module.exports = (app, update) => { +module.exports = (app) => { - app.get("/api/update", (req,res) => { - update(); - res.send("Ran update"); - }); + } \ No newline at end of file diff --git a/sources.json b/sources.json index 922a4f0..f0fb209 100644 --- a/sources.json +++ b/sources.json @@ -15,7 +15,7 @@ } }, "yacs": { - "departments": "https://yacs.cs.rpi.edu/api/v5/schools.json?show_departments=true", - "courses": "https://yacs.cs.rpi.edu/api/v5/courses.json?department_id=" + "departments": "https://yacs.cs.rpi.edu/api/v6/schools?show_departments=true", + "courses": "https://yacs.cs.rpi.edu/api/v6/courses?department_id=" } } diff --git a/update_data.js b/update_data.js index 138faec..834f5b9 100644 --- a/update_data.js +++ b/update_data.js @@ -1,4 +1,4 @@ -const api = require('./api.js').yacs; +const api = require('./api.js')(null).yacs; const fs = require('fs'); const path = require('path'); @@ -38,12 +38,18 @@ module.exports = () => { var obj = JSON.parse(body) total = 0; - obj.schools.forEach((school) => total+=school.departments.length); - obj.schools.forEach( - (school) => school.departments.forEach((item) => { - writeDepartment(item) - }) - ); + try { + obj.schools.forEach((school) => total+=school.departments.length); + obj.schools.forEach( + (school) => school.departments.forEach((item) => { + writeDepartment(item) + }) + ); + } + catch (err) { + console.error("Could not load departments.") + console.error(obj); + } }); }); });