Advertisement
Guest User

Untitled

a guest
Feb 18th, 2020
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.65 KB | None | 0 0
  1. const puppeteer = require('puppeteer');
  2. const $ = require('cheerio');
  3. const express = require('express')
  4. const bodyParser = require('body-parser');
  5. const weightingObj = require('./classWeightingOutput.json')
  6. const Fuse = require('fuse.js')
  7.  
  8. var options = {
  9. shouldSort: true,
  10. includeScore: true,
  11. threshold: 0.6,
  12. location: 0,
  13. distance: 100,
  14. maxPatternLength: 100,
  15. minMatchCharLength: 2,
  16. keys: [
  17. "Name"
  18. ]
  19. };
  20. var fuse = new Fuse(weightingObj, options);
  21.  
  22. //console.log(getData('10012734@sbstudents.org','Sled%2#9'));
  23.  
  24.  
  25. const app = express()
  26. const port = process.env.PORT || 3000
  27. app.use(bodyParser.json());
  28. app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
  29.  
  30. var currentUsers=[];
  31.  
  32. const admin = require('firebase-admin');
  33.  
  34. var serviceAccount = require('./secureContent/serviceKey.json');
  35.  
  36. admin.initializeApp({
  37. credential: admin.credential.cert(serviceAccount)
  38. });
  39.  
  40. var db = admin.firestore();
  41.  
  42. app.get('/', async (req, res) => {
  43. //res.json({get:"gotten"})
  44. const username = req.query.username;//'10012734'
  45. const password = req.query.password; //'Sled%2#9'
  46. console.log("username: "+username+"; password: "+password);
  47.  
  48. var userRef = db.collection('users').doc(username);
  49.  
  50. userRef.get()
  51. .then(doc => {
  52. if (!doc.exists) {
  53. console.log('No such document!');
  54.  
  55. console.log("cached object not found")
  56. res.json({"Status":"loading..."})
  57.  
  58. updateGrades(username,password,userRef).then(() => {
  59. //res.end();
  60. }).catch(err => {
  61. console.log('Error updating grades', err);
  62. })
  63.  
  64. } else {
  65. console.log('Document data:', doc.data());
  66.  
  67. console.log("returning cached object")
  68. res.json(doc.data())
  69. }
  70.  
  71. })
  72. .catch(err => {
  73. console.log('Error getting document', err);
  74. });
  75. })
  76.  
  77. app.post('/', async (req, res) => {
  78.  
  79. const username = req.body.username;//'10012734'
  80. const password = req.body.password; //'Sled%2#9'
  81. console.log(req.body);
  82.  
  83. var userRef = db.collection('users').doc(username);
  84.  
  85. userRef.get()
  86. .then(doc => {
  87. if (!doc.exists) {
  88. console.log('No such document!');
  89.  
  90. console.log("cached object not found")
  91. res.json({"Status":"loading..."})
  92.  
  93. updateGrades(username,password,userRef).then(() => {
  94. //res.end();
  95. }).catch(err => {
  96. console.log('Error updating grades', err);
  97. })
  98.  
  99.  
  100. } else {
  101. console.log('Document data:', doc.data());
  102.  
  103. console.log("returning cached object")
  104. res.json(doc.data())
  105. }
  106.  
  107. })
  108. .catch(err => {
  109. console.log('Error getting document', err);
  110. });
  111. })
  112.  
  113. app.post('/check', async (req, res) => {
  114.  
  115. const username = req.body.username;//'10012734'
  116. const password = req.body.password; //'Sled%2#9'
  117.  
  118. console.log(req.body);
  119. var signedIn = await checkUser(username,password)
  120. console.log({valid: signedIn})
  121. res.json({valid: signedIn})
  122. res.end();
  123.  
  124. if(signedIn){
  125. var userTokenRef = db.collection('userData').doc(username);
  126. userTokenRef.get().then(doc => {
  127. if (!doc.exists) {
  128. userTokenRef.set({
  129. password: password,
  130. }).then(function() {
  131. console.log("pass added to " + username);
  132. })
  133. }else{
  134. userTokenRef.update({
  135. password: password,
  136. }).then(function() {
  137. console.log("pass added to " + username);
  138. })
  139. }
  140. });
  141. }else{
  142. return null;
  143. }
  144. var userRef = db.collection('users').doc(username);
  145. return updateGrades(username,password,userRef).then(() => {
  146. //res.end();
  147. }).catch(err => {
  148. console.log('Error updating grades', err);
  149. })
  150.  
  151. })
  152.  
  153. app.post('/oldGrades', async (req, res) => {
  154.  
  155. const username = req.body.username;//'10012734'
  156. const password = req.body.password; //'Sled%2#9'
  157.  
  158. return res.json(await getClassGrades(username,password));
  159.  
  160. })
  161.  
  162. app.post('/newGrades', async (req, res) => {
  163.  
  164. const username = req.body.username;//'10012734'
  165. const password = req.body.password; //'Sled%2#9'
  166.  
  167. return res.json(await getCurrentClassGrades(username,password));
  168.  
  169. })
  170.  
  171. async function updateGrades(username,password,userRef){
  172. console.log(currentUsers)
  173. if(!currentUsers.includes(username)){
  174. currentUsers.push(username)
  175. console.log("Updating cache for future requests")
  176.  
  177. var dataObj = await getData(username,password)
  178. if(dataObj["Status"] == "Completed"){
  179. console.log(dataObj["Status"])
  180. userRef.set(dataObj);
  181. }else{
  182. console.log("Not cached due to bad request")
  183. }
  184.  
  185. var index = currentUsers.indexOf(username);
  186. if (index !== -1) currentUsers.splice(index, 1);
  187. }
  188. return "done";
  189. }
  190.  
  191. app.post('/addToken', async (req, res) => {
  192. const username = req.body.user.username;
  193. const password = req.body.user.password;
  194. const token = req.body.token.value;
  195.  
  196. if(username&&token&&password){
  197. var userTokenRef = db.collection('userData').doc(username);
  198. userTokenRef.get().then(async doc => {
  199. if (!doc.exists) {
  200. var valid = await checkUser(username,password);
  201. if(valid){
  202. userTokenRef.set({
  203. Tokens: admin.firestore.FieldValue.arrayUnion(token),
  204. password: password,
  205. }).then(function() {
  206. console.log(token + " added to " + username);
  207. res.json({"Status":"Completed"})
  208. })
  209. }
  210. }else{
  211. //No check needed if password matches stored password
  212. if(doc.data()&&doc.data()[password]&&doc.data()[password]==password){
  213. userTokenRef.update({
  214. Tokens: admin.firestore.FieldValue.arrayUnion(token),
  215. password: password,
  216. }).then(function() {
  217. console.log(token + " added to " + username);
  218. res.json({"Status":"Completed"})
  219. })
  220. }else{
  221. var valid = await checkUser(username,password);
  222. if(valid){
  223. userTokenRef.update({
  224. Tokens: admin.firestore.FieldValue.arrayUnion(token),
  225. password: password,
  226. }).then(function() {
  227. console.log(token + " added to " + username);
  228. res.json({"Status":"Completed"})
  229. })
  230. }
  231. }
  232. }
  233. });
  234.  
  235. }else{
  236. res.json({"Status":"Missing params"})
  237. }
  238. });
  239.  
  240.  
  241.  
  242. app.listen(port, () => console.log(`Example app listening on port ${port}!`))
  243.  
  244. const url = 'https://students.sbschools.org/genesis/parents?gohome=true';
  245.  
  246. //var id = '10012734'
  247.  
  248.  
  249. function func(){
  250. eval("header_goToTab('studentdata&tab2=gradebook','studentid="+id+"');");
  251. }
  252.  
  253. async function checkUser(email,pass) {
  254. if(!email.trim()||!pass.trim())
  255. return false;
  256.  
  257. var email = encodeURIComponent(email);
  258. pass = encodeURIComponent(pass);
  259. var url2 = 'https://students.sbschools.org/genesis/j_security_check?j_username='+email+'&j_password='+pass;
  260.  
  261.  
  262. const browser = await puppeteer.launch({
  263. args: [
  264. '--no-sandbox',
  265. '--disable-setuid-sandbox',
  266. '--disable-dev-shm-usage',
  267. '--disable-accelerated-2d-canvas',
  268. '--disable-gpu',
  269. '--window-size=1920x1080',
  270. ],
  271. /*
  272. headless: false, // launch headful mode
  273. slowMo: 250, // slow down puppeteer script so that it's easier to follow visually
  274. */
  275. });
  276. const page = await browser.newPage();
  277.  
  278. /*await page.setViewport({
  279. width: 1920,
  280. height: 1080
  281. })*/
  282.  
  283. await page.setRequestInterception(true);
  284. const blockedResourceTypes = [
  285. 'image',
  286. 'media',
  287. 'font',
  288. 'texttrack',
  289. 'object',
  290. 'beacon',
  291. 'csp_report',
  292. 'imageset',
  293. 'stylesheet',
  294. ];
  295.  
  296. const skippedResources = [
  297. 'quantserve',
  298. 'adzerk',
  299. 'doubleclick',
  300. 'adition',
  301. 'exelator',
  302. 'sharethrough',
  303. 'cdn.api.twitter',
  304. 'google-analytics',
  305. 'googletagmanager',
  306. 'google',
  307. 'fontawesome',
  308. 'facebook',
  309. 'analytics',
  310. 'optimizely',
  311. 'clicktale',
  312. 'mixpanel',
  313. 'zedo',
  314. 'clicksor',
  315. 'tiqcdn',
  316. ];
  317. page.on('request', (req) => {
  318. const requestUrl = req._url.split('?')[0].split('#')[0];
  319. if (
  320. blockedResourceTypes.indexOf(req.resourceType()) !== -1 ||
  321. skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
  322. ) {
  323. req.abort();
  324. } else {
  325. req.continue();
  326. }
  327. });
  328.  
  329. await page.goto(url, {waitUntil: 'domcontentloaded'});
  330. await page.goto(url2, {waitUntil: 'domcontentloaded'});
  331.  
  332. var signedIn = false;
  333. if(await $('.sectionTitle', await page.content()).text().trim() != "Invalid user name or password. Please try again.")
  334. signedIn = true;
  335. await browser.close();
  336.  
  337. return signedIn;
  338.  
  339.  
  340. }
  341.  
  342. async function scrapeMP(page){
  343. var list = await page.evaluate(() => {
  344. var assignments = [];
  345. for(var node of document.getElementsByClassName("list")[0].childNodes[1].childNodes){
  346.  
  347. if(node.classList && !node.classList.contains("listheading")&&node.childNodes.length>=11){
  348. var assignData={};
  349.  
  350. //console.log(node.childNodes);
  351. //console.log(node.childNodes[3].innerText);
  352. assignData["Date"] = node.childNodes[3].innerText;
  353. //console.log(node.childNodes[7].innerText);
  354. assignData["Category"] = node.childNodes[7].innerText
  355. //console.log(node.childNodes[9].innerText);
  356. assignData["Name"] = node.childNodes[9].innerText;
  357. //console.log(node.childNodes[11].childNodes[0].textContent.replace(/\s/g,''));
  358. assignData["Grade"] = node.childNodes[11].childNodes[0].textContent.replace(/\s/g,'')
  359. assignments.push(assignData);
  360. }
  361. }
  362. return assignments;
  363. });
  364. return list;
  365. }
  366.  
  367.  
  368. async function getData(email, pass) {
  369. var grades = {};
  370.  
  371. var email = encodeURIComponent(email);
  372. pass = encodeURIComponent(pass);
  373. var url2 = 'https://students.sbschools.org/genesis/j_security_check?j_username='+email+'&j_password='+pass;
  374.  
  375. const browser = await puppeteer.launch({
  376. args: [
  377. '--no-sandbox',
  378. '--disable-setuid-sandbox',
  379. '--disable-dev-shm-usage',
  380. '--disable-accelerated-2d-canvas',
  381. '--disable-gpu',
  382. '--window-size=1920x1080',
  383. ],
  384. /*
  385. //headless: false, // launch headful mode
  386. //slowMo: 1000, // slow down puppeteer script so that it's easier to follow visually
  387. */
  388. });
  389. const page = await browser.newPage();
  390.  
  391.  
  392. await page.setRequestInterception(true);
  393. const blockedResourceTypes = [
  394. 'image',
  395. 'media',
  396. 'font',
  397. 'texttrack',
  398. 'object',
  399. 'beacon',
  400. 'csp_report',
  401. 'imageset',
  402. 'stylesheet',
  403. ];
  404.  
  405. const skippedResources = [
  406. 'quantserve',
  407. 'adzerk',
  408. 'doubleclick',
  409. 'adition',
  410. 'exelator',
  411. 'sharethrough',
  412. 'cdn.api.twitter',
  413. 'google-analytics',
  414. 'googletagmanager',
  415. 'google',
  416. 'fontawesome',
  417. 'facebook',
  418. 'analytics',
  419. 'optimizely',
  420. 'clicktale',
  421. 'mixpanel',
  422. 'zedo',
  423. 'clicksor',
  424. 'tiqcdn',
  425. ];
  426. page.on('request', (req) => {
  427. const requestUrl = req._url.split('?')[0].split('#')[0];
  428. if (
  429. blockedResourceTypes.indexOf(req.resourceType()) !== -1 ||
  430. skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
  431. ) {
  432. req.abort();
  433. } else {
  434. req.continue();
  435. }
  436. });
  437.  
  438. await page.goto(url, {waitUntil: 'domcontentloaded'});
  439. await page.goto(url2, {waitUntil: 'domcontentloaded'});
  440.  
  441. var signedIn = false;
  442. if(await $('.sectionTitle', await page.content()).text().trim() != "Invalid user name or password. Please try again.")
  443. signedIn = true;
  444. if(!signedIn){
  445. await browser.close();
  446. console.log("BAD user||pass")
  447. return {Status:"Invalid"};
  448. }
  449.  
  450. const url3 = "https://students.sbschools.org/genesis/parents?tab1=studentdata&tab2=gradebook&tab3=coursesummary&action=form&studentid="+email.split("%40")[0];
  451. await page.goto(url3, {waitUntil: 'domcontentloaded'});
  452.  
  453.  
  454. //await page.evaluate(text => [...document.querySelectorAll('*')].find(e => e.textContent.trim() === text).click(), "Gradebook");
  455. //await page.waitForNavigation({ waitUntil: 'domcontentloaded' })
  456. //await page.evaluate(text => [...document.querySelectorAll('*')].find(e => e.textContent.trim() === text).click(), "Course Summary");
  457. //await page.waitForNavigation({ waitUntil: 'domcontentloaded' })
  458.  
  459. const classes = await page.evaluate( () => (Array.from( (document.getElementById("fldCourse")).childNodes, element => element.value ) ));
  460.  
  461. for(var indivClass of classes){
  462. if(indivClass){
  463. //indivClass
  464. await page.evaluate((classID) => changeCourse(classID),indivClass);
  465. await page.waitForNavigation({ waitUntil: 'domcontentloaded' })
  466. const markingPeriods = await page.evaluate( () => (Array.from( (document.getElementById("fldSwitchMP")).childNodes, element => element.value ) ));
  467. const defaultMP = await page.evaluate(()=>document.getElementById("fldSwitchMP").value);
  468. markingPeriods.splice(markingPeriods.indexOf(defaultMP), 1);
  469.  
  470. const ClassName = await page.evaluate((classID)=>document.querySelectorAll('[value="'+classID+'"]')[0].innerText,indivClass);
  471. if(!grades[ClassName])
  472. grades[ClassName] = {}
  473.  
  474. grades[ClassName]["teacher"] = await page.evaluate(()=>{
  475. let list = document.getElementsByClassName("list")[0].childNodes[1].childNodes[4].childNodes[5];
  476. if(list)
  477. return list.innerText
  478. else
  479. return null;
  480. });
  481.  
  482. if(!grades[ClassName][defaultMP])
  483. grades[ClassName][defaultMP] = {}
  484. grades[ClassName][defaultMP]["Assignments"] = await scrapeMP(page);
  485. grades[ClassName][defaultMP]["avg"] = await page.evaluate(()=>document.getElementsByTagName("b")[0].innerText.replace(/\s+/g, '').replace(/[^\d.%]/g,''))
  486. console.log(ClassName)
  487. for(var indivMarkingPeriod of markingPeriods){
  488. if(indivMarkingPeriod){
  489.  
  490. if(!grades[ClassName]["teacher"]){
  491. grades[ClassName]["teacher"] = await page.evaluate(()=>{
  492. let list = document.getElementsByClassName("list")[0].childNodes[1].childNodes[4].childNodes[5];
  493. if(list)
  494. return list.innerText
  495. else
  496. return null;
  497. });
  498. }
  499.  
  500. await page.evaluate((indivMP) => {
  501.  
  502. document.getElementById("fldSwitchMP").value = indivMP;
  503. displayMPs();
  504. document.getElementsByTagName("BUTTON")[1].click()//"Switch Marking Period btn"
  505. },indivMarkingPeriod);
  506. await page.waitForNavigation({ waitUntil: 'domcontentloaded' })
  507.  
  508. console.log("MP switch")
  509.  
  510. if(!grades[ClassName][indivMarkingPeriod])
  511. grades[ClassName][indivMarkingPeriod] = {}
  512. console.log("Scraping page")
  513. grades[ClassName][indivMarkingPeriod]["Assignments"] = await scrapeMP(page);
  514. console.log("Getting avg")
  515. grades[ClassName][indivMarkingPeriod]["avg"] = await page.evaluate(()=>document.getElementsByTagName("b")[0].innerText.replace(/\s+/g, '').replace(/[^\d.%]/g,''))
  516. console.log("Done")
  517. }
  518. }
  519. }
  520. }
  521. grades["Status"] = "Completed";
  522. console.log("Grades gotten for: "+email)
  523. console.log(grades)
  524. await browser.close();
  525. return grades;
  526. }
  527.  
  528.  
  529.  
  530.  
  531.  
  532. //GPA
  533.  
  534. function cleanStr(str){
  535. return str
  536. .toLowerCase()
  537. .replace(new RegExp("advanced placement", 'g'), 'ap')
  538. .replace(new RegExp(" and ", 'g'), '')
  539. .replace(new RegExp(" ", 'g'), '')
  540. .replace(new RegExp("-", 'g'), '')
  541. .replace(new RegExp("/", 'g'), '')
  542. .replace(new RegExp("&", 'g'), '')
  543. }
  544.  
  545. function cleanStrForFuzzy(str){
  546. if(str.indexOf(" ") != -1 && str.substring(0,str.indexOf(" ")) == "AP")
  547. str = "advanced placement"+str.substring(str.indexOf(" "))
  548.  
  549. return str
  550. .toLowerCase()
  551. .replace(new RegExp("-", 'g'), ' ')
  552. .replace(new RegExp("/", 'g'), ' ')
  553. .replace(new RegExp("&", 'g'), 'and')
  554. }
  555.  
  556. //classGrades[classIndex]["Name"]
  557.  
  558. function findWeight(search) {
  559. for(var className of weightingObj){
  560. //console.log(classGrades[yr][classIndex])
  561. if(cleanStr(search) == cleanStr(className["Name"])){
  562. return className["Weight"];
  563. }
  564. }
  565.  
  566. var result = fuse.search(cleanStrForFuzzy(search));
  567. if(result[0]&&result[0]["item"]){
  568. db.collection('errors').doc("Fuzzy Search Results").update({
  569. err: admin.firestore.FieldValue.arrayUnion("search: "+search+"; res: "+result[0]["item"]["Name"]),
  570. })
  571. return result[0]["item"]["Weight"]
  572. }
  573.  
  574. return null;
  575.  
  576.  
  577. }
  578.  
  579.  
  580. async function scrapeClassGrades(page){
  581. var list = await page.evaluate(() => {
  582. var years = [];
  583. var assignments = [];
  584. for(var node of document.getElementsByClassName("list")[0].childNodes[1].childNodes){
  585.  
  586. if(node.classList && !node.classList.contains("listheading")&&node.childNodes.length>=15){
  587. var assignData={};
  588. if(!Number(node.childNodes[11].innerText))
  589. continue;
  590. assignData["Credits"] = Number(node.childNodes[11].innerText)
  591. //console.log(node.childNodes);
  592. //console.log(node.childNodes[3].innerText);
  593. assignData["FG"] = node.childNodes[9].innerText;
  594.  
  595. assignData["Name"] = node.childNodes[5].innerText;
  596. assignments.push(assignData);
  597. }else if(node.classList && !node.classList.contains("listheading")&&node.childNodes.length>=9){
  598. //year ended
  599. if(assignments.length>0)
  600. years.push(assignments);
  601. var assignments = [];
  602. }
  603. }
  604. return years;
  605. });
  606. return list;
  607. }
  608.  
  609.  
  610. async function getClassGrades(email, pass) {
  611. var grades = {};
  612.  
  613. var email = encodeURIComponent(email);
  614. pass = encodeURIComponent(pass);
  615. var url2 = 'https://students.sbschools.org/genesis/j_security_check?j_username='+email+'&j_password='+pass;
  616.  
  617. const browser = await puppeteer.launch({
  618. args: [
  619. '--no-sandbox',
  620. '--disable-setuid-sandbox',
  621. '--disable-dev-shm-usage',
  622. '--disable-accelerated-2d-canvas',
  623. '--disable-gpu',
  624. '--window-size=1920x1080',
  625. ],
  626. /*
  627. //headless: false, // launch headful mode
  628. //slowMo: 1000, // slow down puppeteer script so that it's easier to follow visually
  629. */
  630. });
  631. const page = await browser.newPage();
  632.  
  633.  
  634. await page.setRequestInterception(true);
  635. const blockedResourceTypes = [
  636. 'image',
  637. 'media',
  638. 'font',
  639. 'texttrack',
  640. 'object',
  641. 'beacon',
  642. 'csp_report',
  643. 'imageset',
  644. 'stylesheet',
  645. ];
  646.  
  647. const skippedResources = [
  648. 'quantserve',
  649. 'adzerk',
  650. 'doubleclick',
  651. 'adition',
  652. 'exelator',
  653. 'sharethrough',
  654. 'cdn.api.twitter',
  655. 'google-analytics',
  656. 'googletagmanager',
  657. 'google',
  658. 'fontawesome',
  659. 'facebook',
  660. 'analytics',
  661. 'optimizely',
  662. 'clicktale',
  663. 'mixpanel',
  664. 'zedo',
  665. 'clicksor',
  666. 'tiqcdn',
  667. ];
  668. page.on('request', (req) => {
  669. const requestUrl = req._url.split('?')[0].split('#')[0];
  670. if (
  671. blockedResourceTypes.indexOf(req.resourceType()) !== -1 ||
  672. skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
  673. ) {
  674. req.abort();
  675. } else {
  676. req.continue();
  677. }
  678. });
  679.  
  680. await page.goto(url, {waitUntil: 'domcontentloaded'});
  681. await page.goto(url2, {waitUntil: 'domcontentloaded'});
  682.  
  683. var signedIn = false;
  684. if(await $('.sectionTitle', await page.content()).text().trim() != "Invalid user name or password. Please try again.")
  685. signedIn = true;
  686. if(!signedIn){
  687. await browser.close();
  688. console.log("BAD user||pass")
  689. return {Status:"Invalid"};
  690. }
  691.  
  692. const url3 = "https://students.sbschools.org/genesis/parents?tab1=studentdata&tab2=grading&tab3=history&action=form&studentid="+email.split("%40")[0];
  693. await page.goto(url3, {waitUntil: 'domcontentloaded'});
  694.  
  695. let classGrades = await scrapeClassGrades(page)
  696.  
  697. for(var yr in classGrades){
  698. var yrData = classGrades[yr]
  699. for(var classIndex in yrData){
  700. if(findWeight(classGrades[yr][classIndex]["Name"]))
  701. classGrades[yr][classIndex]["Weight"] = findWeight(classGrades[yr][classIndex]["Name"])
  702. if(!classGrades[yr][classIndex]["Weight"]){
  703. //console.log("ERR"+classGrades[yr][classIndex]["Name"]+"not found!")
  704. db.collection('errors').doc("Unknown Classes").update({
  705. err: admin.firestore.FieldValue.arrayUnion(classGrades[yr][classIndex]["Name"]),
  706. })
  707. }
  708. }
  709. }
  710. console.log("Grades gotten for: "+email)
  711. console.log(classGrades)
  712. await browser.close();
  713. return classGrades
  714. }
  715.  
  716. async function scrapeCurrentClassGrades(page){
  717. var list = await page.evaluate(() => {
  718. var assignments = [];
  719. for(var node of document.getElementsByClassName("list")[0].childNodes[1].childNodes){
  720.  
  721. if(node.classList && !node.classList.contains("listheading")&&node.childNodes.length>=15){
  722. var assignData={};
  723. if(!Number(node.childNodes[25].innerText))
  724. continue;
  725. assignData["Credits"] = Number(node.childNodes[25].innerText)
  726. //console.log(node.childNodes);
  727. //console.log(node.childNodes[3].innerText);
  728. console.log(node.childNodes)
  729. assignData["MP1"] = node.childNodes[9].innerText.trim()
  730. assignData["MP2"] = node.childNodes[11].innerText.trim()
  731. assignData["ME"] = node.childNodes[13].innerText.trim()
  732. assignData["MP3"] = node.childNodes[17].innerText.trim()
  733. assignData["MP4"] = node.childNodes[19].innerText.trim()
  734. assignData["FE"] = node.childNodes[21].innerText.trim()
  735.  
  736. if(!assignData["MP1"])
  737. delete assignData["MP1"]
  738. if(!assignData["MP2"])
  739. delete assignData["MP2"]
  740. if(!assignData["ME"])
  741. delete assignData["ME"]
  742. if(!assignData["MP3"])
  743. delete assignData["MP3"]
  744. if(!assignData["MP4"])
  745. delete assignData["MP4"]
  746. if(!assignData["FE"])
  747. delete assignData["FE"]
  748.  
  749. assignData["Name"] = node.childNodes[1].innerText;
  750. assignments.push(assignData);
  751. }
  752. }
  753. return assignments;
  754. });
  755. return list;
  756. }
  757.  
  758.  
  759. async function getCurrentClassGrades(email, pass) {
  760. var grades = {};
  761.  
  762. var email = encodeURIComponent(email);
  763. pass = encodeURIComponent(pass);
  764. var url2 = 'https://students.sbschools.org/genesis/j_security_check?j_username='+email+'&j_password='+pass;
  765.  
  766. const browser = await puppeteer.launch({
  767. args: [
  768. '--no-sandbox',
  769. '--disable-setuid-sandbox',
  770. '--disable-dev-shm-usage',
  771. '--disable-accelerated-2d-canvas',
  772. '--disable-gpu',
  773. '--window-size=1920x1080',
  774. ],
  775. /*
  776. //headless: false, // launch headful mode
  777. //slowMo: 1000, // slow down puppeteer script so that it's easier to follow visually
  778. */
  779. });
  780. const page = await browser.newPage();
  781.  
  782.  
  783. await page.setRequestInterception(true);
  784. const blockedResourceTypes = [
  785. 'image',
  786. 'media',
  787. 'font',
  788. 'texttrack',
  789. 'object',
  790. 'beacon',
  791. 'csp_report',
  792. 'imageset',
  793. 'stylesheet',
  794. ];
  795.  
  796. const skippedResources = [
  797. 'quantserve',
  798. 'adzerk',
  799. 'doubleclick',
  800. 'adition',
  801. 'exelator',
  802. 'sharethrough',
  803. 'cdn.api.twitter',
  804. 'google-analytics',
  805. 'googletagmanager',
  806. 'google',
  807. 'fontawesome',
  808. 'facebook',
  809. 'analytics',
  810. 'optimizely',
  811. 'clicktale',
  812. 'mixpanel',
  813. 'zedo',
  814. 'clicksor',
  815. 'tiqcdn',
  816. ];
  817. page.on('request', (req) => {
  818. const requestUrl = req._url.split('?')[0].split('#')[0];
  819. if (
  820. blockedResourceTypes.indexOf(req.resourceType()) !== -1 ||
  821. skippedResources.some(resource => requestUrl.indexOf(resource) !== -1)
  822. ) {
  823. req.abort();
  824. } else {
  825. req.continue();
  826. }
  827. });
  828.  
  829. await page.goto(url, {waitUntil: 'domcontentloaded'});
  830. await page.goto(url2, {waitUntil: 'domcontentloaded'});
  831.  
  832. var signedIn = false;
  833. if(await $('.sectionTitle', await page.content()).text().trim() != "Invalid user name or password. Please try again.")
  834. signedIn = true;
  835. if(!signedIn){
  836. await browser.close();
  837. console.log("BAD user||pass")
  838. return {Status:"Invalid"};
  839. }
  840.  
  841. const url3 = "https://students.sbschools.org/genesis/parents?tab1=studentdata&tab2=grading&tab3=current&action=form&studentid="+email.split("%40")[0];
  842. await page.goto(url3, {waitUntil: 'domcontentloaded'});
  843.  
  844. let classGrades = await scrapeCurrentClassGrades(page)
  845. for(var classIndex in classGrades){
  846. if(findWeight(classGrades[classIndex]["Name"]))
  847. classGrades[classIndex]["Weight"] = findWeight(classGrades[classIndex]["Name"])
  848. if(!classGrades[classIndex]["Weight"]){
  849. //console.log("ERR"+classGrades[yr][classIndex]["Name"]+"not found!")
  850. db.collection('errors').doc("Unknown Classes").update({
  851. err: admin.firestore.FieldValue.arrayUnion(classGrades[classIndex]["Name"]),
  852. })
  853. }
  854. }
  855.  
  856. console.log("Grades gotten for: "+email)
  857. console.log(classGrades)
  858. await browser.close();
  859. return classGrades
  860. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement