From 03b49bbdbd1888751d7078fc16f3555bb0b8b8f8 Mon Sep 17 00:00:00 2001 From: brMonteiro-G Date: Mon, 20 May 2024 23:32:41 -0300 Subject: [PATCH 01/20] wip: first draft to new integration --- src/scripts/contentScriptSigaa.js | 157 ++++++++++++++++++++++++++++++ src/scripts/contentscript.js | 7 +- 2 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 src/scripts/contentScriptSigaa.js diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js new file mode 100644 index 0000000..39c245d --- /dev/null +++ b/src/scripts/contentScriptSigaa.js @@ -0,0 +1,157 @@ +import Toastify from "toastify-js"; + + +//function getValuesFromMainPageSigaa(){ + +//Scrapping Sigaa values +// Get values from table +const trs = document.querySelectorAll('#agenda-docente tbody tr') + +// transform to key-value object +const keypair = Array.from(trs) + .map((line) => Array.from(line.children) + .map((column) => normalizeDiacritcs(column.innerText))) + +const completeObject = Object.fromEntries(keypair) + + +completeObject +//} + + + +// or accents +function normalizeDiacritcs(stringElement) { + return stringElement.trim() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .toLocaleLowerCase() +} + + +function isIndexSigaa() { + return ( + document.location.href.indexOf("https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf") !== -1 + ); +} + + + +// function getValuesFromGetGradesPageSigaa(){ + + +// // * Data da consulta no SIGAA +// // preferi pegar o innerText ao invés do innerHTML por conta de trim() +// const updateTimeHTML = document +// .querySelector('.dataAtual') +// .innerText.split(' '); + +// // escolhi pegar os valores diretamente mas não acredito ser a melhor opção +// const updateDate = updateTimeHTML[2]; +// const updateHour = updateTimeHTML[3]; + +// // * dados do aluno +// const studentDataHTML = document.querySelector( +// '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td' +// ).innerText; + +// const [nameStudent, ra] = studentDataHTML.trim().split(' - '); +// // pegar curso! + +// // quads +// const quadsTableHTML = Array.from( +// document.getElementsByClassName('tabelaRelatorio') +// ); + +// // dá pra deixar em um reduce ou map muito foda +// // for Of +// // histórico completo +// let studentHistory = new Map(); +// for (let table of quadsTableHTML) { +// const [year, quad] = table +// .getElementsByTagName('caption')[0] +// .innerText.split('.'); + +// if (!studentHistory.has(year)) { +// studentHistory.set(year, new Object()); +// } + +// const tableHeaders = Array.from(table.getElementsByTagName('th')); +// const tableRows = Array.from(table.querySelectorAll('tbody > tr')); + +// const quadData = []; + +// // dá pra melhorar isso aqui, tá zuado +// // usar a estrutura Set em alguns momentos para evitar repetições!!! +// // e quando essa página estiver vazia? +// for (let row of tableRows) { +// const cells = Array.from(row.children).map((cell) => cell.innerText); +// const disciplineInfo = {}; +// cells.forEach((item, index) => { +// disciplineInfo[tableHeaders[index].innerText] = item; +// }); +// quadData.push(disciplineInfo); +// } + +// studentHistory.get(year)[quad] = [...quadData]; +// } + +// const result = { +// updateTime: new Date(`${updateDate} ${updateHour}`), // tá retornando junho, cuidado! +// userData: { +// name: nameStudent, +// ra, +// }, +// history: Object.fromEntries(studentHistory), +// }; +// console.log(''); +// console.log(''); +// console.log(''); +// console.log( +// '========== Parabéns por participar da versão Beta disso aqui kkkkkk ============' +// ); +// console.log('TO-DO:'); +// console.log('[] remover campos vazios da tabela;'); +// console.log('[] verificar possíveis repetições de dados'); +// console.log('[] pegar o curso do aluno'); +// console.log('[] Adaptação para quadrimestre suplementar'); +// console.log('[] cada quadrimestre suplementar é uma tabela na página do SIGAA'); +// console.log('qualquer coisa me chama no zap'); +// console.log(result); + +// } + +const toast = new Toastify({ + text: ` +
+

Atualizando suas informações...

\n\n + Olá ${completeObject["e-mail"]} +

apenas aguarde, no máx. 5 min 🙏

+
`, + duration: -1, + close: false, + gravity: "bottom", + position: "right", + escapeMarkup: false, + style: { + background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, +}); + + +if (isIndexSigaa()) { + + const observer = new MutationObserver(list => { + if (document.contains(document.querySelector('.notas'))) { + console.log("It's in the DOM!"); + toast.showToast(); + observer.disconnect(); + } + + }); + observer.observe(document.body, { attributes: true, childList: true, subtree: true }); + + +} + + diff --git a/src/scripts/contentscript.js b/src/scripts/contentscript.js index 67b129a..24dcdff 100644 --- a/src/scripts/contentscript.js +++ b/src/scripts/contentscript.js @@ -36,6 +36,7 @@ if (process.env.NODE_ENV == "production") { "ufabc-matricula-test.cdd.naoseiprogramar.com.br/snapshot/backup.html", "locahost:8011/snapshot", "locahost:8011/snapshot/backup.html", + "https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf" ]; } @@ -54,9 +55,9 @@ async function load() { Utils.injectScript("lib/init.js"); setupStorage(); - require("./contentScriptPortal"); + require("./contentScriptSigaa"); - if (matricula_url.some((url) => currentUrl.indexOf(url) != -1)) { + if (matricula_url.some((url) => currentUrl.indexOf(url) != -1)) { // esse if quer dizer que a url deu match pois é diferente a -1 // update teachers locally setTimeout(async () => { let lastUpdate = null; @@ -70,7 +71,7 @@ async function load() { // this is the main vue app // i.e, where all the filters live - const anchor = document.createElement("div"); + const anchor = document.createElement("div"); // filtros da tela de matriculas anchor.setAttribute("id", "app"); $("#meio").prepend(anchor); From 2617811521b593d9e1042a504f96c02130c453ce Mon Sep 17 00:00:00 2001 From: brMonteiro-G Date: Mon, 20 May 2024 23:50:59 -0300 Subject: [PATCH 02/20] wip: setup storage --- src/scripts/contentScriptSigaa.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 39c245d..7f754c4 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,4 +1,8 @@ import Toastify from "toastify-js"; +import Utils from "../utils/extensionUtils"; +Utils.injectStyle("styles/portal.css"); + + //function getValuesFromMainPageSigaa(){ @@ -13,9 +17,9 @@ const keypair = Array.from(trs) .map((column) => normalizeDiacritcs(column.innerText))) const completeObject = Object.fromEntries(keypair) - - -completeObject +localStorage.setItem("name",JSON.stringify(completeObject)) +console.log(completeObject) +console.log("this is my loc", localStorage.getItem("name")) //} From d2a20c1e9df80a9557de8bb3f43849a88e8926ad Mon Sep 17 00:00:00 2001 From: brMonteiro-G Date: Tue, 21 May 2024 23:12:35 -0300 Subject: [PATCH 03/20] wip: solve scrapping issues and working on make a call to backend --- src/scripts/contentScriptSigaa.js | 229 +++++++++++++++++------------- 1 file changed, 129 insertions(+), 100 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 7f754c4..2ecfb73 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,7 +1,12 @@ import Toastify from "toastify-js"; +import "toastify-js/src/toastify.css"; import Utils from "../utils/extensionUtils"; Utils.injectStyle("styles/portal.css"); +const loading = require("../images/loading.svg"); +const errorSVG = require("../images/error.svg"); +const logoWhite = require("../images/logo-white.svg"); + @@ -17,9 +22,10 @@ const keypair = Array.from(trs) .map((column) => normalizeDiacritcs(column.innerText))) const completeObject = Object.fromEntries(keypair) -localStorage.setItem("name",JSON.stringify(completeObject)) -console.log(completeObject) -console.log("this is my loc", localStorage.getItem("name")) +//chrome.storage.local.set({ "name":'JSON.stringify(completeObject)' }); + +//console.log("this is my loc",chrome.storage.local.get("name")) + //} @@ -41,121 +47,144 @@ function isIndexSigaa() { -// function getValuesFromGetGradesPageSigaa(){ - - -// // * Data da consulta no SIGAA -// // preferi pegar o innerText ao invés do innerHTML por conta de trim() -// const updateTimeHTML = document -// .querySelector('.dataAtual') -// .innerText.split(' '); - -// // escolhi pegar os valores diretamente mas não acredito ser a melhor opção -// const updateDate = updateTimeHTML[2]; -// const updateHour = updateTimeHTML[3]; - -// // * dados do aluno -// const studentDataHTML = document.querySelector( -// '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td' -// ).innerText; - -// const [nameStudent, ra] = studentDataHTML.trim().split(' - '); -// // pegar curso! - -// // quads -// const quadsTableHTML = Array.from( -// document.getElementsByClassName('tabelaRelatorio') -// ); - -// // dá pra deixar em um reduce ou map muito foda -// // for Of -// // histórico completo -// let studentHistory = new Map(); -// for (let table of quadsTableHTML) { -// const [year, quad] = table -// .getElementsByTagName('caption')[0] -// .innerText.split('.'); - -// if (!studentHistory.has(year)) { -// studentHistory.set(year, new Object()); -// } - -// const tableHeaders = Array.from(table.getElementsByTagName('th')); -// const tableRows = Array.from(table.querySelectorAll('tbody > tr')); - -// const quadData = []; - -// // dá pra melhorar isso aqui, tá zuado -// // usar a estrutura Set em alguns momentos para evitar repetições!!! -// // e quando essa página estiver vazia? -// for (let row of tableRows) { -// const cells = Array.from(row.children).map((cell) => cell.innerText); -// const disciplineInfo = {}; -// cells.forEach((item, index) => { -// disciplineInfo[tableHeaders[index].innerText] = item; -// }); -// quadData.push(disciplineInfo); -// } - -// studentHistory.get(year)[quad] = [...quadData]; -// } - -// const result = { -// updateTime: new Date(`${updateDate} ${updateHour}`), // tá retornando junho, cuidado! -// userData: { -// name: nameStudent, -// ra, -// }, -// history: Object.fromEntries(studentHistory), -// }; -// console.log(''); -// console.log(''); -// console.log(''); -// console.log( -// '========== Parabéns por participar da versão Beta disso aqui kkkkkk ============' -// ); -// console.log('TO-DO:'); -// console.log('[] remover campos vazios da tabela;'); -// console.log('[] verificar possíveis repetições de dados'); -// console.log('[] pegar o curso do aluno'); -// console.log('[] Adaptação para quadrimestre suplementar'); -// console.log('[] cada quadrimestre suplementar é uma tabela na página do SIGAA'); -// console.log('qualquer coisa me chama no zap'); -// console.log(result); - -// } - -const toast = new Toastify({ - text: ` +function getValuesFromGetGradesPageSigaa(){ + + + // * Data da consulta no SIGAA + // preferi pegar o innerText ao invés do innerHTML por conta de trim() + const updateTimeHTML = document + .querySelector('.dataAtual') + .innerText.split(' '); + +// escolhi pegar os valores diretamente mas não acredito ser a melhor opção +const updateDate = updateTimeHTML[2]; +const updateHour = updateTimeHTML[3]; + +// * dados do aluno +const studentDataHTML = document.querySelector( + '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td' +).innerText; + +const [nameStudent, ra] = studentDataHTML.trim().split(' - '); +// pegar curso! + +// quads +const quadsTableHTML = Array.from( + document.getElementsByClassName('tabelaRelatorio') +); + +// dá pra deixar em um reduce ou map muito foda +// for Of +// histórico completo +let studentHistory = new Map(); +for (let table of quadsTableHTML) { + const [year, quad] = table + .getElementsByTagName('caption')[0] + .innerText.split('.'); + + if (!studentHistory.has(year)) { + studentHistory.set(year, new Object()); + } + + const tableHeaders = Array.from(table.getElementsByTagName('th')); + const tableRows = Array.from(table.querySelectorAll('tbody > tr')); + + const quadData = []; + + // dá pra melhorar isso aqui, tá zuado + // usar a estrutura Set em alguns momentos para evitar repetições!!! + // e quando essa página estiver vazia? + for (let row of tableRows) { + const cells = Array.from(row.children).map((cell) => cell.innerText); + const disciplineInfo = {}; + cells.forEach((item, index) => { + disciplineInfo[tableHeaders[index].innerText] = item; + }); + quadData.push(disciplineInfo); + } + + studentHistory.get(year)[quad] = [...quadData]; +} + +const result = { + updateTime: new Date(`${updateDate} ${updateHour}`), // tá retornando junho, cuidado! + userData: { + name: nameStudent, + ra, + }, + history: Object.fromEntries(studentHistory), +}; + +return result + } + +const toast = () => { + const name = JSON.parse(localStorage.getItem("name"))["e-mail:"] + + return new Toastify({ + text: `

Atualizando suas informações...

\n\n - Olá ${completeObject["e-mail"]} + Olá ${name}

apenas aguarde, no máx. 5 min 🙏

`, - duration: -1, - close: false, - gravity: "bottom", - position: "right", - escapeMarkup: false, - style: { + duration: -1, + close: false, + gravity: "bottom", + position: "right", + className: "toast-loading", + escapeMarkup: false, + avatar: loading, + style: { background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, -}); + }, + }); +} if (isIndexSigaa()) { + const observer = new MutationObserver(list => { if (document.contains(document.querySelector('.notas'))) { + console.log("local", localStorage.getItem("name")) + const result = getValuesFromGetGradesPageSigaa() + localStorage.setItem("name", JSON.stringify(result)) + console.log("It's in the DOM!"); - toast.showToast(); + toast().showToast(); observer.disconnect(); } - + + }); + + const newObserver = new MutationObserver(list => { + if (document.contains(document.querySelector('#agenda-docente'))) { + localStorage.setItem("name", JSON.stringify(completeObject)) + console.log("It's in the DOM!"); + toast.showToast(); + newObserver.disconnect(); + } + }); + + newObserver.observe(document.body, { attributes: true, childList: true, subtree: true }); observer.observe(document.body, { attributes: true, childList: true, subtree: true }); } +await nextApi.post( + "/histories/sigaa", + { + ra: ra, + disciplinas: jsonFicha.data, + curso: nomeDoCurso, + grade: anoDaGrade, + }, + { + timeout: 60 * 1 * 1000, // 1 minute + } + ); + From bb85a7e71c39603ed1355a4d22eea01098cb1b9f Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Thu, 23 May 2024 21:48:40 -0300 Subject: [PATCH 04/20] fix: scrap datetime --- src/scripts/contentScriptSigaa.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 2ecfb73..24f14c9 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -48,17 +48,13 @@ function isIndexSigaa() { function getValuesFromGetGradesPageSigaa(){ - - // * Data da consulta no SIGAA - // preferi pegar o innerText ao invés do innerHTML por conta de trim() - const updateTimeHTML = document + const updateDatetimeHTML = document .querySelector('.dataAtual') - .innerText.split(' '); + .textContent.trim(); -// escolhi pegar os valores diretamente mas não acredito ser a melhor opção -const updateDate = updateTimeHTML[2]; -const updateHour = updateTimeHTML[3]; + const [day, month, year, hour, minute] = updateDatetimeHTML.match(/\d+/g); + const updateDatetime = new Date(year, month - 1, day, hour, minute); // * dados do aluno const studentDataHTML = document.querySelector( From db52dd7c39560c8a91acbeb555cd384a652e3443 Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Thu, 23 May 2024 21:51:55 -0300 Subject: [PATCH 05/20] feat: student course --- src/scripts/contentScriptSigaa.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 24f14c9..87e2ef7 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -59,10 +59,13 @@ function getValuesFromGetGradesPageSigaa(){ // * dados do aluno const studentDataHTML = document.querySelector( '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td' -).innerText; +).textContent; +const courseHTML = document.querySelector( + '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td' +); const [nameStudent, ra] = studentDataHTML.trim().split(' - '); -// pegar curso! +const studentCourse = courseHTML.innerText; // quads const quadsTableHTML = Array.from( @@ -103,10 +106,11 @@ for (let table of quadsTableHTML) { } const result = { - updateTime: new Date(`${updateDate} ${updateHour}`), // tá retornando junho, cuidado! + updateTime: updateDatetime, userData: { name: nameStudent, ra, + course: studentCourse }, history: Object.fromEntries(studentHistory), }; From 7a02dca2febbf0fe4132b7018246e9918e872abe Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Thu, 23 May 2024 22:07:52 -0300 Subject: [PATCH 06/20] fix: removing blank spaces and some improvements by @Joabesv --- src/scripts/contentScriptSigaa.js | 74 +++++++++++++++++++------------ 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 87e2ef7..6850af2 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -68,38 +68,54 @@ const [nameStudent, ra] = studentDataHTML.trim().split(' - '); const studentCourse = courseHTML.innerText; // quads -const quadsTableHTML = Array.from( - document.getElementsByClassName('tabelaRelatorio') -); +const quadsTableElement = document.querySelectorAll('.tabelaRelatorio'); +const quadsTable = Array.from(quadsTableElement); // dá pra deixar em um reduce ou map muito foda // for Of // histórico completo -let studentHistory = new Map(); -for (let table of quadsTableHTML) { - const [year, quad] = table - .getElementsByTagName('caption')[0] - .innerText.split('.'); +const studentHistory = new Map(); +for (const table of quadsTable) { + const studentseason = table.querySelector('caption'); + const [year, quad] = studentseason.textContent.trim().split('.'); if (!studentHistory.has(year)) { - studentHistory.set(year, new Object()); + studentHistory.set(year, {}); } - const tableHeaders = Array.from(table.getElementsByTagName('th')); - const tableRows = Array.from(table.querySelectorAll('tbody > tr')); + const tableHeadersElement = table.querySelectorAll('th'); + const tableRowsElement = table.querySelectorAll('tbody > tr'); + const rawTableHeaders = Array.from(tableHeadersElement); - const quadData = []; + const wantedFields = ['codigo', 'disciplina', 'resultado', 'situacao']; + const indexWantedFields = []; + const tableHeaders = rawTableHeaders.filter((rawItem, index) => { + const item = normalizeDiacritcs(rawItem.innerText) + if (wantedFields.includes(item)) indexWantedFields.push(index); // finding exact positions (sorry for that) + return wantedFields.includes(item); + }); + + const tableRows = Array.from(tableRowsElement); // dá pra melhorar isso aqui, tá zuado // usar a estrutura Set em alguns momentos para evitar repetições!!! // e quando essa página estiver vazia? - for (let row of tableRows) { - const cells = Array.from(row.children).map((cell) => cell.innerText); - const disciplineInfo = {}; + // joabe: só sétar null mesmo, o histórico seria atualizado futuramente em outro acesso + const quadData = []; + for (const row of tableRows) { + const rowChildrens = Array.from(row.children); + const cells = rowChildrens + .filter((cellHTML, index) => indexWantedFields.includes(index)) + .map((cellHTML) => cellHTML.innerText); // picking exact header positions + + const disciplina = {}; + cells.forEach((item, index) => { - disciplineInfo[tableHeaders[index].innerText] = item; + const normalizedHeaderText = normalizeDiacritcs(tableHeaders[index].textContent) + disciplina[normalizedHeaderText] = item; }); - quadData.push(disciplineInfo); + + quadData.push(disciplina); } studentHistory.get(year)[quad] = [...quadData]; @@ -174,17 +190,17 @@ if (isIndexSigaa()) { } -await nextApi.post( - "/histories/sigaa", - { - ra: ra, - disciplinas: jsonFicha.data, - curso: nomeDoCurso, - grade: anoDaGrade, - }, - { - timeout: 60 * 1 * 1000, // 1 minute - } - ); +// await nextApi.post( +// "/histories/sigaa", +// { +// ra: ra, +// disciplinas: jsonFicha.data, +// curso: nomeDoCurso, +// grade: anoDaGrade, +// }, +// { +// timeout: 60 * 1 * 1000, // 1 minute +// } +// ); From 171fef646feaf87216dc2737c67b2907ad7bfda4 Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Thu, 23 May 2024 22:26:41 -0300 Subject: [PATCH 07/20] refactor: change scrap result --- src/scripts/contentScriptSigaa.js | 38 +++++++++++-------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 6850af2..79badeb 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -74,15 +74,11 @@ const quadsTable = Array.from(quadsTableElement); // dá pra deixar em um reduce ou map muito foda // for Of // histórico completo -const studentHistory = new Map(); +const studentHistory = []; for (const table of quadsTable) { const studentseason = table.querySelector('caption'); const [year, quad] = studentseason.textContent.trim().split('.'); - if (!studentHistory.has(year)) { - studentHistory.set(year, {}); - } - const tableHeadersElement = table.querySelectorAll('th'); const tableRowsElement = table.querySelectorAll('tbody > tr'); const rawTableHeaders = Array.from(tableHeadersElement); @@ -97,11 +93,6 @@ for (const table of quadsTable) { }); const tableRows = Array.from(tableRowsElement); - // dá pra melhorar isso aqui, tá zuado - // usar a estrutura Set em alguns momentos para evitar repetições!!! - // e quando essa página estiver vazia? - // joabe: só sétar null mesmo, o histórico seria atualizado futuramente em outro acesso - const quadData = []; for (const row of tableRows) { const rowChildrens = Array.from(row.children); const cells = rowChildrens @@ -114,25 +105,22 @@ for (const table of quadsTable) { const normalizedHeaderText = normalizeDiacritcs(tableHeaders[index].textContent) disciplina[normalizedHeaderText] = item; }); + disciplina['ano'] = year; + disciplina['periodo'] = quad; - quadData.push(disciplina); + studentHistory.push(disciplina); } - - studentHistory.get(year)[quad] = [...quadData]; } -const result = { - updateTime: updateDatetime, - userData: { - name: nameStudent, - ra, - course: studentCourse - }, - history: Object.fromEntries(studentHistory), -}; - -return result - } + const result = { + updateTime: updateDatetime, + curso: studentCourse, + ra: Number(ra), + disciplinas: studentHistory, + }; + + return result +} const toast = () => { const name = JSON.parse(localStorage.getItem("name"))["e-mail:"] From 2bd592aa1c3b2f2d411aa50786f47f201d6b448f Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Thu, 23 May 2024 22:42:49 -0300 Subject: [PATCH 08/20] fix: removing special characters in localstorage --- src/scripts/contentScriptSigaa.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 79badeb..eb47431 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -35,6 +35,7 @@ function normalizeDiacritcs(stringElement) { return stringElement.trim() .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') + .replace(/[-:]/g, '') // Remove "-" and ":" .toLocaleLowerCase() } From adc568f4e6aa0700c36686ab83e6a6896091f916 Mon Sep 17 00:00:00 2001 From: Joabesv Date: Thu, 23 May 2024 22:48:33 -0300 Subject: [PATCH 09/20] fix: run linter --- src/scripts/contentScriptSigaa.js | 288 ++++++++++++++---------------- 1 file changed, 135 insertions(+), 153 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index eb47431..8aaaacf 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -7,176 +7,160 @@ const loading = require("../images/loading.svg"); const errorSVG = require("../images/error.svg"); const logoWhite = require("../images/logo-white.svg"); +const trs = document.querySelectorAll("#agenda-docente tbody tr"); +const keypair = Array.from(trs).map((line) => + Array.from(line.children).map((column) => + normalizeDiacritcs(column.innerText), + ), +); +const completeObject = Object.fromEntries(keypair); - -//function getValuesFromMainPageSigaa(){ - -//Scrapping Sigaa values -// Get values from table -const trs = document.querySelectorAll('#agenda-docente tbody tr') - -// transform to key-value object -const keypair = Array.from(trs) - .map((line) => Array.from(line.children) - .map((column) => normalizeDiacritcs(column.innerText))) - -const completeObject = Object.fromEntries(keypair) -//chrome.storage.local.set({ "name":'JSON.stringify(completeObject)' }); - -//console.log("this is my loc",chrome.storage.local.get("name")) - -//} - - - -// or accents function normalizeDiacritcs(stringElement) { - return stringElement.trim() - .normalize('NFD') - .replace(/[\u0300-\u036f]/g, '') - .replace(/[-:]/g, '') // Remove "-" and ":" - .toLocaleLowerCase() + return stringElement + .trim() + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .replace(/[-:]/g, "") + .toLocaleLowerCase(); } - function isIndexSigaa() { - return ( - document.location.href.indexOf("https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf") !== -1 - ); + return ( + document.location.href.indexOf( + "https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf", + ) !== -1 + ); } - - -function getValuesFromGetGradesPageSigaa(){ - // * Data da consulta no SIGAA - const updateDatetimeHTML = document - .querySelector('.dataAtual') - .textContent.trim(); - - const [day, month, year, hour, minute] = updateDatetimeHTML.match(/\d+/g); - const updateDatetime = new Date(year, month - 1, day, hour, minute); - -// * dados do aluno -const studentDataHTML = document.querySelector( - '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td' -).textContent; -const courseHTML = document.querySelector( - '#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td' -); - -const [nameStudent, ra] = studentDataHTML.trim().split(' - '); -const studentCourse = courseHTML.innerText; - -// quads -const quadsTableElement = document.querySelectorAll('.tabelaRelatorio'); -const quadsTable = Array.from(quadsTableElement); - -// dá pra deixar em um reduce ou map muito foda -// for Of -// histórico completo -const studentHistory = []; -for (const table of quadsTable) { - const studentseason = table.querySelector('caption'); - const [year, quad] = studentseason.textContent.trim().split('.'); - - const tableHeadersElement = table.querySelectorAll('th'); - const tableRowsElement = table.querySelectorAll('tbody > tr'); - const rawTableHeaders = Array.from(tableHeadersElement); - - const wantedFields = ['codigo', 'disciplina', 'resultado', 'situacao']; - const indexWantedFields = []; - const tableHeaders = rawTableHeaders.filter((rawItem, index) => { - const item = normalizeDiacritcs(rawItem.innerText) - - if (wantedFields.includes(item)) indexWantedFields.push(index); // finding exact positions (sorry for that) - return wantedFields.includes(item); - }); - - const tableRows = Array.from(tableRowsElement); - for (const row of tableRows) { - const rowChildrens = Array.from(row.children); - const cells = rowChildrens - .filter((cellHTML, index) => indexWantedFields.includes(index)) - .map((cellHTML) => cellHTML.innerText); // picking exact header positions - - const disciplina = {}; - - cells.forEach((item, index) => { - const normalizedHeaderText = normalizeDiacritcs(tableHeaders[index].textContent) - disciplina[normalizedHeaderText] = item; - }); - disciplina['ano'] = year; - disciplina['periodo'] = quad; - - studentHistory.push(disciplina); - } -} - - const result = { - updateTime: updateDatetime, - curso: studentCourse, - ra: Number(ra), - disciplinas: studentHistory, - }; - - return result +function getValuesFromGetGradesPageSigaa() { + const updateDatetimeHTML = document + .querySelector(".dataAtual") + .textContent.trim(); + + const [day, month, year, hour, minute] = updateDatetimeHTML.match(/\d+/g); + const updateDatetime = new Date(year, month - 1, day, hour, minute); + + // * dados do aluno + const studentDataHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td", + ).textContent; + const courseHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td", + ); + + const [nameStudent, ra] = studentDataHTML.trim().split(" - "); + const studentCourse = courseHTML.innerText; + + const quadsTableElement = document.querySelectorAll(".tabelaRelatorio"); + const quadsTable = Array.from(quadsTableElement); + + const studentHistory = []; + for (const table of quadsTable) { + const studentseason = table.querySelector("caption"); + const [year, quad] = studentseason.textContent.trim().split("."); + + const tableHeadersElement = table.querySelectorAll("th"); + const tableRowsElement = table.querySelectorAll("tbody > tr"); + const rawTableHeaders = Array.from(tableHeadersElement); + + const wantedFields = ["codigo", "disciplina", "resultado", "situacao"]; + const indexWantedFields = []; + const tableHeaders = rawTableHeaders.filter((rawItem, index) => { + const item = normalizeDiacritcs(rawItem.innerText); + + if (wantedFields.includes(item)) indexWantedFields.push(index); + return wantedFields.includes(item); + }); + + const tableRows = Array.from(tableRowsElement); + for (const row of tableRows) { + const rowChildrens = Array.from(row.children); + const cells = rowChildrens + .filter((cellHTML, index) => indexWantedFields.includes(index)) + .map((cellHTML) => cellHTML.innerText); // picking exact header positions + + const disciplina = {}; + + cells.forEach((item, index) => { + const normalizedHeaderText = normalizeDiacritcs( + tableHeaders[index].textContent, + ); + disciplina[normalizedHeaderText] = item; + }); + disciplina["ano"] = year; + disciplina["periodo"] = quad; + + studentHistory.push(disciplina); + } + } + + const result = { + updateTime: updateDatetime, + curso: studentCourse, + ra: Number(ra), + disciplinas: studentHistory, + }; + + return result; } const toast = () => { - const name = JSON.parse(localStorage.getItem("name"))["e-mail:"] + const name = JSON.parse(localStorage.getItem("name"))["e-mail:"]; - return new Toastify({ - text: ` + return new Toastify({ + text: `

Atualizando suas informações...

\n\n Olá ${name}

apenas aguarde, no máx. 5 min 🙏

`, - duration: -1, - close: false, - gravity: "bottom", - position: "right", - className: "toast-loading", - escapeMarkup: false, - avatar: loading, - style: { - background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, - }); -} - + duration: -1, + close: false, + gravity: "bottom", + position: "right", + className: "toast-loading", + escapeMarkup: false, + avatar: loading, + style: { + background: + "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, + }); +}; if (isIndexSigaa()) { - - - const observer = new MutationObserver(list => { - if (document.contains(document.querySelector('.notas'))) { - console.log("local", localStorage.getItem("name")) - const result = getValuesFromGetGradesPageSigaa() - localStorage.setItem("name", JSON.stringify(result)) - - console.log("It's in the DOM!"); - toast().showToast(); - observer.disconnect(); - } - - }); - - const newObserver = new MutationObserver(list => { - if (document.contains(document.querySelector('#agenda-docente'))) { - localStorage.setItem("name", JSON.stringify(completeObject)) - console.log("It's in the DOM!"); - toast.showToast(); - newObserver.disconnect(); - } - - }); - - newObserver.observe(document.body, { attributes: true, childList: true, subtree: true }); - observer.observe(document.body, { attributes: true, childList: true, subtree: true }); - - + const observer = new MutationObserver((list) => { + if (document.contains(document.querySelector(".notas"))) { + console.log("local", localStorage.getItem("name")); + const result = getValuesFromGetGradesPageSigaa(); + localStorage.setItem("name", JSON.stringify(result)); + + console.log("It's in the DOM!"); + toast().showToast(); + observer.disconnect(); + } + }); + + const newObserver = new MutationObserver((list) => { + if (document.contains(document.querySelector("#agenda-docente"))) { + localStorage.setItem("name", JSON.stringify(completeObject)); + console.log("It's in the DOM!"); + toast.showToast(); + newObserver.disconnect(); + } + }); + + newObserver.observe(document.body, { + attributes: true, + childList: true, + subtree: true, + }); + observer.observe(document.body, { + attributes: true, + childList: true, + subtree: true, + }); } // await nextApi.post( @@ -191,5 +175,3 @@ if (isIndexSigaa()) { // timeout: 60 * 1 * 1000, // 1 minute // } // ); - - From acfb2544ba95ee57326e254ed05c4f5e3c2e7c20 Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Fri, 24 May 2024 00:16:11 -0300 Subject: [PATCH 10/20] fix: email user in toast --- src/scripts/contentScriptSigaa.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 8aaaacf..460d65d 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -106,7 +106,7 @@ function getValuesFromGetGradesPageSigaa() { } const toast = () => { - const name = JSON.parse(localStorage.getItem("name"))["e-mail:"]; + const name = JSON.parse(localStorage.getItem("name"))["email"]; return new Toastify({ text: ` @@ -132,9 +132,9 @@ const toast = () => { if (isIndexSigaa()) { const observer = new MutationObserver((list) => { if (document.contains(document.querySelector(".notas"))) { - console.log("local", localStorage.getItem("name")); + console.log("userInfo", localStorage.getItem("name")); const result = getValuesFromGetGradesPageSigaa(); - localStorage.setItem("name", JSON.stringify(result)); + localStorage.setItem("userGraduationInfo", JSON.stringify(result)); console.log("It's in the DOM!"); toast().showToast(); From dacc9c0a185f3805b6c21a6f0ff509014c79ed8b Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 09:39:25 -0300 Subject: [PATCH 11/20] feat: break functions in utils --- src/scripts/contentScriptSigaa.js | 110 ++++-------------------------- src/utils/sigaa/index.js | 89 ++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 97 deletions(-) create mode 100644 src/utils/sigaa/index.js diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 460d65d..5e12716 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,6 +1,7 @@ import Toastify from "toastify-js"; import "toastify-js/src/toastify.css"; import Utils from "../utils/extensionUtils"; +import { normalizeDiacritics, scrapeGradesConsulting } from "../utils/sigaa"; Utils.injectStyle("styles/portal.css"); const loading = require("../images/loading.svg"); @@ -8,102 +9,17 @@ const errorSVG = require("../images/error.svg"); const logoWhite = require("../images/logo-white.svg"); const trs = document.querySelectorAll("#agenda-docente tbody tr"); -const keypair = Array.from(trs).map((line) => +const tablesRowsArray = Array.from(trs); +const rawStudentInfo = tablesRowsArray.map((line) => Array.from(line.children).map((column) => - normalizeDiacritcs(column.innerText), + normalizeDiacritics(column.innerText), ), ); -const completeObject = Object.fromEntries(keypair); +const studentInfo = Object.fromEntries(rawStudentInfo); -function normalizeDiacritcs(stringElement) { - return stringElement - .trim() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .replace(/[-:]/g, "") - .toLocaleLowerCase(); -} - -function isIndexSigaa() { - return ( - document.location.href.indexOf( - "https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf", - ) !== -1 - ); -} - -function getValuesFromGetGradesPageSigaa() { - const updateDatetimeHTML = document - .querySelector(".dataAtual") - .textContent.trim(); - - const [day, month, year, hour, minute] = updateDatetimeHTML.match(/\d+/g); - const updateDatetime = new Date(year, month - 1, day, hour, minute); - - // * dados do aluno - const studentDataHTML = document.querySelector( - "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td", - ).textContent; - const courseHTML = document.querySelector( - "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td", - ); - - const [nameStudent, ra] = studentDataHTML.trim().split(" - "); - const studentCourse = courseHTML.innerText; - - const quadsTableElement = document.querySelectorAll(".tabelaRelatorio"); - const quadsTable = Array.from(quadsTableElement); - - const studentHistory = []; - for (const table of quadsTable) { - const studentseason = table.querySelector("caption"); - const [year, quad] = studentseason.textContent.trim().split("."); - - const tableHeadersElement = table.querySelectorAll("th"); - const tableRowsElement = table.querySelectorAll("tbody > tr"); - const rawTableHeaders = Array.from(tableHeadersElement); - - const wantedFields = ["codigo", "disciplina", "resultado", "situacao"]; - const indexWantedFields = []; - const tableHeaders = rawTableHeaders.filter((rawItem, index) => { - const item = normalizeDiacritcs(rawItem.innerText); - - if (wantedFields.includes(item)) indexWantedFields.push(index); - return wantedFields.includes(item); - }); - - const tableRows = Array.from(tableRowsElement); - for (const row of tableRows) { - const rowChildrens = Array.from(row.children); - const cells = rowChildrens - .filter((cellHTML, index) => indexWantedFields.includes(index)) - .map((cellHTML) => cellHTML.innerText); // picking exact header positions - - const disciplina = {}; - - cells.forEach((item, index) => { - const normalizedHeaderText = normalizeDiacritcs( - tableHeaders[index].textContent, - ); - disciplina[normalizedHeaderText] = item; - }); - disciplina["ano"] = year; - disciplina["periodo"] = quad; - - studentHistory.push(disciplina); - } - } - - const result = { - updateTime: updateDatetime, - curso: studentCourse, - ra: Number(ra), - disciplinas: studentHistory, - }; - - return result; -} +const sigaaURL = new URL(document.location.href); +const isDiscentesPath = sigaaURL.pathname.includes("discente.jsf"); const toast = () => { const name = JSON.parse(localStorage.getItem("name"))["email"]; @@ -129,12 +45,12 @@ const toast = () => { }); }; -if (isIndexSigaa()) { +if (isDiscentesPath) { const observer = new MutationObserver((list) => { if (document.contains(document.querySelector(".notas"))) { - console.log("userInfo", localStorage.getItem("name")); - const result = getValuesFromGetGradesPageSigaa(); - localStorage.setItem("userGraduationInfo", JSON.stringify(result)); + console.log("local", localStorage.getItem("name")); + const result = scrapeGradesConsulting(); + localStorage.setItem("name", JSON.stringify(result)); console.log("It's in the DOM!"); toast().showToast(); @@ -144,9 +60,9 @@ if (isIndexSigaa()) { const newObserver = new MutationObserver((list) => { if (document.contains(document.querySelector("#agenda-docente"))) { - localStorage.setItem("name", JSON.stringify(completeObject)); + localStorage.setItem("name", JSON.stringify(studentInfo)); console.log("It's in the DOM!"); - toast.showToast(); + toast().showToast(); newObserver.disconnect(); } }); diff --git a/src/utils/sigaa/index.js b/src/utils/sigaa/index.js new file mode 100644 index 0000000..f3556f9 --- /dev/null +++ b/src/utils/sigaa/index.js @@ -0,0 +1,89 @@ +function normalizeDiacritics(stringElement) { + return stringElement + .trim() + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .replace(/[-:]/g, "") + .toLocaleLowerCase(); +} + +function scrapeGradesConsulting() { + const sigaaUpdatetime = document + .querySelector(".dataAtual") + .textContent.trim(); + + const [day, month, year, hour, minute] = sigaaUpdatetime.match(/\d+/g); + const updateDatetime = new Date(year, month - 1, day, hour, minute); + + // * dados do aluno + const studentDataHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td", + ).textContent; + const courseHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td", + ); + const studentCourse = courseHTML.innerText; + const [, ra] = studentDataHTML.trim().split(" - "); + + const quadsTableElement = document.querySelectorAll(".tabelaRelatorio"); + const quadsTable = Array.from(quadsTableElement); + + const studentDisciplinaHistory = []; + for (const tableElement of quadsTable) { + const studentseason = tableElement.querySelector("caption"); + const [year, quad] = studentseason.textContent.trim().split("."); + + const tableHeadersElement = tableElement.querySelectorAll("th"); + const tableRowsElement = tableElement.querySelectorAll("tbody > tr"); + const rawTableHeaders = Array.from(tableHeadersElement); + + const wantedFields = ["codigo", "disciplina", "resultado", "situacao"]; + const indexWantedFields = []; + const tableHeaders = rawTableHeaders.filter((rawItem, index) => { + const item = normalizeDiacritics(rawItem.innerText); + + if (wantedFields.includes(item)) { + // crimes + indexWantedFields.push(index); + } + + return wantedFields.includes(item); + }); + + const tableRows = Array.from(tableRowsElement); + for (const row of tableRows) { + const rowChildrens = Array.from(row.children); + const cells = rowChildrens + .filter((_, index) => indexWantedFields.includes(index)) + .map((cellHTML) => cellHTML.innerText); // picking exact header positions + + const disciplina = {}; + + cells.forEach((item, index) => { + const normalizedHeaderText = normalizeDiacritics( + tableHeaders[index].textContent, + ); + disciplina[normalizedHeaderText] = item; + }); + + disciplina.ano = year; + disciplina.periodo = quad; + + studentDisciplinaHistory.push(disciplina); + } + } + + const userHistory = { + updateTime: updateDatetime, + curso: studentCourse, + ra: Number(ra), + disciplinas: studentDisciplinaHistory, + }; + + return userHistory; +} + +module.exports = { + normalizeDiacritics, + scrapeGradesConsulting, +}; From 25560ab0c02be2db07fe2f0b7e18ed7003bf7ccd Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 09:39:35 -0300 Subject: [PATCH 12/20] wip: better script --- src/scripts/contentScriptSigaa.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 5e12716..f441826 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,7 +1,7 @@ import Toastify from "toastify-js"; import "toastify-js/src/toastify.css"; import Utils from "../utils/extensionUtils"; -import { normalizeDiacritics, scrapeGradesConsulting } from "../utils/sigaa"; +import { normalizeDiacritics, scrapeGradesConsulting } from "../utils/sigaa"; Utils.injectStyle("styles/portal.css"); const loading = require("../images/loading.svg"); @@ -17,18 +17,17 @@ const rawStudentInfo = tablesRowsArray.map((line) => ); const studentInfo = Object.fromEntries(rawStudentInfo); - const sigaaURL = new URL(document.location.href); const isDiscentesPath = sigaaURL.pathname.includes("discente.jsf"); const toast = () => { - const name = JSON.parse(localStorage.getItem("name"))["email"]; - - return new Toastify({ + const name = JSON.parse(localStorage.getItem("studentInfo")); + console.log(name) + return new Toastify({ text: `

Atualizando suas informações...

\n\n - Olá ${name} + Olá ${name.email}

apenas aguarde, no máx. 5 min 🙏

`, duration: -1, @@ -48,11 +47,11 @@ const toast = () => { if (isDiscentesPath) { const observer = new MutationObserver((list) => { if (document.contains(document.querySelector(".notas"))) { - console.log("local", localStorage.getItem("name")); + console.log("local", localStorage.getItem("studentHistory")); const result = scrapeGradesConsulting(); - localStorage.setItem("name", JSON.stringify(result)); + localStorage.setItem("studentHistory", JSON.stringify(result)); - console.log("It's in the DOM!"); + console.log("It's in the DOM! 0"); toast().showToast(); observer.disconnect(); } @@ -60,8 +59,8 @@ if (isDiscentesPath) { const newObserver = new MutationObserver((list) => { if (document.contains(document.querySelector("#agenda-docente"))) { - localStorage.setItem("name", JSON.stringify(studentInfo)); - console.log("It's in the DOM!"); + localStorage.setItem("userInfo", JSON.stringify(studentInfo)); + console.log("It's in the DOM! 1"); toast().showToast(); newObserver.disconnect(); } From e816a1f03b29187bdb7c91450b6958e570e4537b Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 09:52:57 -0300 Subject: [PATCH 13/20] feat: better contentscript --- src/scripts/contentscript.js | 153 ++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/src/scripts/contentscript.js b/src/scripts/contentscript.js index 24dcdff..3a6fa6b 100644 --- a/src/scripts/contentscript.js +++ b/src/scripts/contentscript.js @@ -17,90 +17,91 @@ import Utils from "../utils/extensionUtils"; // CSS imports import "element-ui/lib/theme-chalk/index.css"; -let matricula_url; +let matriculasURL; if (process.env.NODE_ENV == "production") { - matricula_url = [ - "matricula.ufabc.edu.br/matricula", - "ufabc-matricula.cdd.naoseiprogramar.com.br/snapshot", - "api.ufabcnext.com/snapshot", - ]; + matriculasURL = [ + "matricula.ufabc.edu.br/matricula", + "ufabc-matricula.cdd.naoseiprogramar.com.br/snapshot", + "api.ufabcnext.com/snapshot", + ]; } else { - matricula_url = [ - "matricula.ufabc.edu.br/matricula", - "api.ufabcnext.com/snapshot", - "api.ufabcnext.com/snapshot/backup.html", - "ufabc-matricula.cdd.naoseiprogramar.com.br/snapshot", - "ufabc-matricula.cdd.naoseiprogramar.com.br/snapshot/backup.html", - "ufabc-matricula-test.cdd.naoseiprogramar.com.br/snapshot", - "ufabc-matricula-test.cdd.naoseiprogramar.com.br/snapshot/backup.html", - "locahost:8011/snapshot", - "locahost:8011/snapshot/backup.html", - "https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf" - ]; + matriculasURL = [ + "matricula.ufabc.edu.br/matricula", + "api.ufabcnext.com/snapshot", + "api.ufabcnext.com/snapshot/backup.html", + "locahost:8011/snapshot", + "locahost:8011/snapshot/backup.html", + "https://sig.ufabc.edu.br/sigaa/portais/discente/discente.jsf", + ]; } if (!isBrowser) { - console.log("Not running on browser!"); - load(); + console.log("Not running on browser!"); + load(); } else { - window.addEventListener("load", load); + window.addEventListener("load", load); } async function load() { - const currentUrl = document.location.href; - // add cross-domain local storage - Utils.injectScript("lib/xdLocalStorage.min.js"); - Utils.injectIframe("pages/iframe.html"); - Utils.injectScript("lib/init.js"); - - setupStorage(); - require("./contentScriptSigaa"); - - if (matricula_url.some((url) => currentUrl.indexOf(url) != -1)) { // esse if quer dizer que a url deu match pois é diferente a -1 - // update teachers locally - setTimeout(async () => { - let lastUpdate = null; - try { - lastUpdate = await Utils.storage.getItem("ufabc-extension-last"); - } catch (err) { - lastUpdate = Date.now(); - } finally { - matriculaUtils.updateProfessors(lastUpdate); - } - - // this is the main vue app - // i.e, where all the filters live - const anchor = document.createElement("div"); // filtros da tela de matriculas - anchor.setAttribute("id", "app"); - $("#meio").prepend(anchor); - - //inject styles - Utils.injectStyle("styles/main.css"); - - // manda as informacoes para o servidor - matriculaUtils.sendAlunoData(); - - // load vue app modal - const modal = document.createElement("div"); - modal.setAttribute("id", "modal"); - modal.setAttribute("data-app", true); - document.body.append(modal); - - // load vue app teacherReview - const teacherReview = document.createElement("div"); - teacherReview.setAttribute("id", "teacherReview"); - teacherReview.setAttribute("data-app", true); - document.body.append(teacherReview); - - // load vue app review subjects - const reviewSubject = document.createElement("div"); - reviewSubject.setAttribute("id", "review-subject"); - reviewSubject.setAttribute("data-app", true); - document.body.append(reviewSubject); - - // inject Vue app - Utils.injectScript("scripts/main.js"); - }, 1500); - } + const currentURL = new URL(document.location); + // add cross-domain local storage + Utils.injectScript("lib/xdLocalStorage.min.js"); + Utils.injectIframe("pages/iframe.html"); + Utils.injectScript("lib/init.js"); + + setupStorage(); + require("./contentScriptSigaa"); + + const shouldInject = matriculasURL.some((url) => + currentURL.href.includes(url), + ); + + if (!shouldInject) { + return; + } + // update teachers locally + setTimeout(async () => { + let lastUpdate = null; + try { + lastUpdate = await Utils.storage.getItem("ufabc-extension-last"); + } catch (err) { + lastUpdate = Date.now(); + } finally { + matriculaUtils.updateProfessors(lastUpdate); + } + + // this is the main vue app + // i.e, where all the filters live + const anchor = document.createElement("div"); // filtros da tela de matriculas + anchor.setAttribute("id", "app"); + $("#meio").prepend(anchor); + + //inject styles + Utils.injectStyle("styles/main.css"); + + // manda as informacoes para o servidor + matriculaUtils.sendAlunoData(); + + // load vue app modal + const modal = document.createElement("div"); + modal.setAttribute("id", "modal"); + modal.setAttribute("data-app", true); + document.body.append(modal); + + // load vue app teacherReview + const teacherReview = document.createElement("div"); + teacherReview.setAttribute("id", "teacherReview"); + teacherReview.setAttribute("data-app", true); + document.body.append(teacherReview); + + // load vue app review subjects + const reviewSubject = document.createElement("div"); + reviewSubject.setAttribute("id", "review-subject"); + reviewSubject.setAttribute("data-app", true); + document.body.append(reviewSubject); + + // inject Vue app + Utils.injectScript("scripts/main.js"); + }, 1500); } From f09aa4ddef0dc47ff582bb856092a9295c040751 Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 11:16:53 -0300 Subject: [PATCH 14/20] feat: another scrapping util --- src/utils/sigaa/index.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/utils/sigaa/index.js b/src/utils/sigaa/index.js index f3556f9..1cf30b3 100644 --- a/src/utils/sigaa/index.js +++ b/src/utils/sigaa/index.js @@ -44,7 +44,7 @@ function scrapeGradesConsulting() { if (wantedFields.includes(item)) { // crimes - indexWantedFields.push(index); + indexWantedFields.push(index); } return wantedFields.includes(item); @@ -83,7 +83,28 @@ function scrapeGradesConsulting() { return userHistory; } +function scrapeHomepage() { + const trs = document.querySelectorAll("#agenda-docente tbody tr"); + const tablesRowsArray = Array.from(trs); + const rawStudentInfo = tablesRowsArray.map((line) => + Array.from(line.children).map((column) => + normalizeDiacritics(column.innerText), + ), + ); + + + const [rawName] = document.querySelectorAll("#perfil-docente p.info-docente"); + const [name] = rawName.textContent.split(/\n\n\t+\n\t+/); + const studentInfo = Object.fromEntries(rawStudentInfo); + + return { + name: name.trim(), + studentInfo, + } +} + module.exports = { normalizeDiacritics, scrapeGradesConsulting, + scrapeHomepage, }; From c1ffc3695e3d92828d192da97879b568dde44230 Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 11:17:46 -0300 Subject: [PATCH 15/20] refac: better usability --- src/scripts/contentScriptSigaa.js | 77 ++++++++++++------------------- 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index f441826..8a394ea 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,33 +1,22 @@ import Toastify from "toastify-js"; import "toastify-js/src/toastify.css"; import Utils from "../utils/extensionUtils"; -import { normalizeDiacritics, scrapeGradesConsulting } from "../utils/sigaa"; +import { scrapeGradesConsulting, scrapeHomepage } from "../utils/sigaa"; Utils.injectStyle("styles/portal.css"); const loading = require("../images/loading.svg"); -const errorSVG = require("../images/error.svg"); const logoWhite = require("../images/logo-white.svg"); -const trs = document.querySelectorAll("#agenda-docente tbody tr"); -const tablesRowsArray = Array.from(trs); -const rawStudentInfo = tablesRowsArray.map((line) => - Array.from(line.children).map((column) => - normalizeDiacritics(column.innerText), - ), -); -const studentInfo = Object.fromEntries(rawStudentInfo); const sigaaURL = new URL(document.location.href); const isDiscentesPath = sigaaURL.pathname.includes("discente.jsf"); -const toast = () => { - const name = JSON.parse(localStorage.getItem("studentInfo")); - console.log(name) - return new Toastify({ +const toast = Toastify({ text: `
+

Atualizando suas informações...

\n\n - Olá ${name.email} + NÃO SAIA DESSA PÁGINA,

apenas aguarde, no máx. 5 min 🙏

`, duration: -1, @@ -41,41 +30,35 @@ const toast = () => { background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", }, - }); -}; +}); -if (isDiscentesPath) { - const observer = new MutationObserver((list) => { - if (document.contains(document.querySelector(".notas"))) { - console.log("local", localStorage.getItem("studentHistory")); - const result = scrapeGradesConsulting(); - localStorage.setItem("studentHistory", JSON.stringify(result)); - console.log("It's in the DOM! 0"); - toast().showToast(); - observer.disconnect(); - } - }); - - const newObserver = new MutationObserver((list) => { - if (document.contains(document.querySelector("#agenda-docente"))) { - localStorage.setItem("userInfo", JSON.stringify(studentInfo)); - console.log("It's in the DOM! 1"); - toast().showToast(); - newObserver.disconnect(); - } - }); +if (isDiscentesPath && document.contains(document.querySelector("#agenda-docente"))) { + Utils.injectStyle("styles/portal.css"); + const student = scrapeHomepage(); + localStorage.setItem("studentInfo", JSON.stringify(student)); + Toastify({ + text: ` +
+ +

${student.name.split(' ')[0]} Acesse suas notas!

\n\n + Clique no menu Ensino > consultar minhas notas +
`, + gravity: "bottom", + position: "right", + duration: 5000, + style: { + background: + "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, + escapeMarkup: false, + }).showToast() +} - newObserver.observe(document.body, { - attributes: true, - childList: true, - subtree: true, - }); - observer.observe(document.body, { - attributes: true, - childList: true, - subtree: true, - }); +if(isDiscentesPath && document.contains(document.querySelector('.notas'))) { + const student = JSON.parse(localStorage.getItem("studentInfo")); + const result = scrapeGradesConsulting(); + toast.showToast(); } // await nextApi.post( From 10f815783ad9e5bd17b135e706a67e2d5935462d Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 11:18:14 -0300 Subject: [PATCH 16/20] refac: lint --- src/scripts/contentScriptSigaa.js | 60 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 8a394ea..707958a 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -7,58 +7,58 @@ Utils.injectStyle("styles/portal.css"); const loading = require("../images/loading.svg"); const logoWhite = require("../images/logo-white.svg"); - const sigaaURL = new URL(document.location.href); const isDiscentesPath = sigaaURL.pathname.includes("discente.jsf"); const toast = Toastify({ - text: ` + text: `

Atualizando suas informações...

\n\n NÃO SAIA DESSA PÁGINA,

apenas aguarde, no máx. 5 min 🙏

`, - duration: -1, - close: false, - gravity: "bottom", - position: "right", - className: "toast-loading", - escapeMarkup: false, - avatar: loading, - style: { - background: - "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, + duration: -1, + close: false, + gravity: "bottom", + position: "right", + className: "toast-loading", + escapeMarkup: false, + avatar: loading, + style: { + background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, }); - -if (isDiscentesPath && document.contains(document.querySelector("#agenda-docente"))) { - Utils.injectStyle("styles/portal.css"); - const student = scrapeHomepage(); - localStorage.setItem("studentInfo", JSON.stringify(student)); - Toastify({ - text: ` +if ( + isDiscentesPath && + document.contains(document.querySelector("#agenda-docente")) +) { + Utils.injectStyle("styles/portal.css"); + const student = scrapeHomepage(); + localStorage.setItem("studentInfo", JSON.stringify(student)); + Toastify({ + text: `
-

${student.name.split(' ')[0]} Acesse suas notas!

\n\n +

${student.name.split(" ")[0]} Acesse suas notas!

\n\n Clique no menu Ensino > consultar minhas notas
`, - gravity: "bottom", + gravity: "bottom", position: "right", - duration: 5000, - style: { + duration: 5000, + style: { background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", }, - escapeMarkup: false, - }).showToast() + escapeMarkup: false, + }).showToast(); } -if(isDiscentesPath && document.contains(document.querySelector('.notas'))) { - const student = JSON.parse(localStorage.getItem("studentInfo")); - const result = scrapeGradesConsulting(); - toast.showToast(); +if (isDiscentesPath && document.contains(document.querySelector(".notas"))) { + const student = JSON.parse(localStorage.getItem("studentInfo")); + const result = scrapeGradesConsulting(); + toast.showToast(); } // await nextApi.post( From 773ab920556e421392d68ca0da8f592dff81e459 Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 14:56:02 -0300 Subject: [PATCH 17/20] refac: move toast to utils --- src/scripts/contentScriptSigaa.js | 75 +++++++------------------------ src/utils/nextToasts.js | 68 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 59 deletions(-) create mode 100644 src/utils/nextToasts.js diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 707958a..c965de4 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,75 +1,32 @@ -import Toastify from "toastify-js"; -import "toastify-js/src/toastify.css"; -import Utils from "../utils/extensionUtils"; import { scrapeGradesConsulting, scrapeHomepage } from "../utils/sigaa"; -Utils.injectStyle("styles/portal.css"); +import { NextAPI } from "../services/NextAPI"; +import { errorToast, redirectToast, processingToast } from "../utils/nextToasts"; -const loading = require("../images/loading.svg"); -const logoWhite = require("../images/logo-white.svg"); +const nextApi = NextAPI(); const sigaaURL = new URL(document.location.href); const isDiscentesPath = sigaaURL.pathname.includes("discente.jsf"); -const toast = Toastify({ - text: ` -
- -

Atualizando suas informações...

\n\n - NÃO SAIA DESSA PÁGINA, -

apenas aguarde, no máx. 5 min 🙏

-
`, - duration: -1, - close: false, - gravity: "bottom", - position: "right", - className: "toast-loading", - escapeMarkup: false, - avatar: loading, - style: { - background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, -}); - if ( isDiscentesPath && document.contains(document.querySelector("#agenda-docente")) ) { - Utils.injectStyle("styles/portal.css"); const student = scrapeHomepage(); + const toast = redirectToast(student.name); localStorage.setItem("studentInfo", JSON.stringify(student)); - Toastify({ - text: ` -
- -

${student.name.split(" ")[0]} Acesse suas notas!

\n\n - Clique no menu Ensino > consultar minhas notas -
`, - gravity: "bottom", - position: "right", - duration: 5000, - style: { - background: - "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, - escapeMarkup: false, - }).showToast(); + toast.showToast(); } if (isDiscentesPath && document.contains(document.querySelector(".notas"))) { - const student = JSON.parse(localStorage.getItem("studentInfo")); - const result = scrapeGradesConsulting(); - toast.showToast(); -} + processingToast.showToast(); + const studentHistory = scrapeGradesConsulting(); + const { data: res } = nextApi.post("/histories/sigaa", studentHistory, { + timeout: 60 * 1 * 1000, // 1 minute + }).catch(err => { + processingToast.hideToast(); + console.log(err); + errorToast.showToast(); + }); -// await nextApi.post( -// "/histories/sigaa", -// { -// ra: ra, -// disciplinas: jsonFicha.data, -// curso: nomeDoCurso, -// grade: anoDaGrade, -// }, -// { -// timeout: 60 * 1 * 1000, // 1 minute -// } -// ); + console.log(res) +} diff --git a/src/utils/nextToasts.js b/src/utils/nextToasts.js new file mode 100644 index 0000000..ade5bec --- /dev/null +++ b/src/utils/nextToasts.js @@ -0,0 +1,68 @@ +import Toastify from "toastify-js"; +import "toastify-js/src/toastify.css"; +import Utils from "../utils/extensionUtils"; +const loading = require("../images/loading.svg"); +const logoWhite = require("../images/logo-white.svg"); +const errorSVG = require("../images/error.svg"); + +Utils.injectStyle("styles/portal.css"); + +const errorToast = Toastify({ + text: ` +
+ + Não foi possível salvar seus dados, recarregue a página e aguarde. +
`, + duration: -1, + close: true, + gravity: "top", + position: "right", + className: "toast-error-container", + escapeMarkup: false, + style: { + background: "#E74C3C;", + }, +}); + +const redirectToast = (studentname) => Toastify({ + text: ` +
+ +

${studentname} Acesse suas notas!

\n\n + Clique no menu Ensino > consultar minhas notas +
`, + gravity: "bottom", + position: "right", + duration: 5000, + style: { + background: + "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, + escapeMarkup: false, +}); + +const processingToast = Toastify({ + text: ` +
+ +

Atualizando suas informações...

\n\n + NÃO SAIA DESSA PÁGINA, +

apenas aguarde, no máx. 5 min 🙏

+
`, + duration: -1, + close: false, + gravity: "bottom", + position: "right", + className: "toast-loading", + escapeMarkup: false, + avatar: loading, + style: { + background: "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, +}); + +module.exports = { + errorToast, + redirectToast, + processingToast, +} From 92c99bf30a711675970398cfa10b5f0e347c18df Mon Sep 17 00:00:00 2001 From: Joabesv Date: Fri, 24 May 2024 14:56:42 -0300 Subject: [PATCH 18/20] run linter --- src/scripts/contentScriptSigaa.js | 32 +++++++++++-------- src/utils/nextToasts.js | 53 ++++++++++++++++--------------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index c965de4..75ef5f2 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -1,6 +1,10 @@ import { scrapeGradesConsulting, scrapeHomepage } from "../utils/sigaa"; import { NextAPI } from "../services/NextAPI"; -import { errorToast, redirectToast, processingToast } from "../utils/nextToasts"; +import { + errorToast, + redirectToast, + processingToast, +} from "../utils/nextToasts"; const nextApi = NextAPI(); @@ -12,21 +16,23 @@ if ( document.contains(document.querySelector("#agenda-docente")) ) { const student = scrapeHomepage(); - const toast = redirectToast(student.name); + const toast = redirectToast(student.name); localStorage.setItem("studentInfo", JSON.stringify(student)); - toast.showToast(); + toast.showToast(); } if (isDiscentesPath && document.contains(document.querySelector(".notas"))) { - processingToast.showToast(); - const studentHistory = scrapeGradesConsulting(); - const { data: res } = nextApi.post("/histories/sigaa", studentHistory, { - timeout: 60 * 1 * 1000, // 1 minute - }).catch(err => { - processingToast.hideToast(); - console.log(err); - errorToast.showToast(); - }); + processingToast.showToast(); + const studentHistory = scrapeGradesConsulting(); + const { data: res } = nextApi + .post("/histories/sigaa", studentHistory, { + timeout: 60 * 1 * 1000, // 1 minute + }) + .catch((err) => { + processingToast.hideToast(); + console.log(err); + errorToast.showToast(); + }); - console.log(res) + console.log(res); } diff --git a/src/utils/nextToasts.js b/src/utils/nextToasts.js index ade5bec..6e1835e 100644 --- a/src/utils/nextToasts.js +++ b/src/utils/nextToasts.js @@ -8,40 +8,41 @@ const errorSVG = require("../images/error.svg"); Utils.injectStyle("styles/portal.css"); const errorToast = Toastify({ - text: ` + text: `
Não foi possível salvar seus dados, recarregue a página e aguarde.
`, - duration: -1, - close: true, - gravity: "top", - position: "right", - className: "toast-error-container", - escapeMarkup: false, - style: { - background: "#E74C3C;", - }, + duration: -1, + close: true, + gravity: "top", + position: "right", + className: "toast-error-container", + escapeMarkup: false, + style: { + background: "#E74C3C;", + }, }); -const redirectToast = (studentname) => Toastify({ - text: ` +const redirectToast = (studentname) => + Toastify({ + text: `

${studentname} Acesse suas notas!

\n\n Clique no menu Ensino > consultar minhas notas
`, - gravity: "bottom", - position: "right", - duration: 5000, - style: { - background: - "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", - }, - escapeMarkup: false, -}); + gravity: "bottom", + position: "right", + duration: 5000, + style: { + background: + "linear-gradient(to right, #2E7EED, rgba(46, 126, 237, 0.5));", + }, + escapeMarkup: false, + }); -const processingToast = Toastify({ +const processingToast = Toastify({ text: `
@@ -62,7 +63,7 @@ const processingToast = Toastify({ }); module.exports = { - errorToast, - redirectToast, - processingToast, -} + errorToast, + redirectToast, + processingToast, +}; From b4e25cbe8dd0a8c0edef9a6c082d0e5aa486db20 Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Sat, 15 Jun 2024 11:12:50 -0300 Subject: [PATCH 19/20] feat: update nextapi --- src/scripts/contentScriptSigaa.js | 1 + src/services/NextAPI.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripts/contentScriptSigaa.js b/src/scripts/contentScriptSigaa.js index 75ef5f2..f41876d 100644 --- a/src/scripts/contentScriptSigaa.js +++ b/src/scripts/contentScriptSigaa.js @@ -24,6 +24,7 @@ if ( if (isDiscentesPath && document.contains(document.querySelector(".notas"))) { processingToast.showToast(); const studentHistory = scrapeGradesConsulting(); + // todo: fazer o endpoint const { data: res } = nextApi .post("/histories/sigaa", studentHistory, { timeout: 60 * 1 * 1000, // 1 minute diff --git a/src/services/NextAPI.js b/src/services/NextAPI.js index 8647b06..5c887ac 100644 --- a/src/services/NextAPI.js +++ b/src/services/NextAPI.js @@ -3,10 +3,10 @@ import Axios from "axios"; function resolveEndpoint(env) { return ( { - development: "http://localhost:8011/v1", + development: "http://localhost:5000/v2", staging: "https://ufabc-matricula-test.cdd.naoseiprogramar.com.br/v1", production: "https://api.ufabcnext.com/v1", - }[env] || "http://localhost:8011/v1" + }[env] || "http://localhost:5000/v2" ); } From d25ade3d848cffdbce812b8150660e8c2fa92f8d Mon Sep 17 00:00:00 2001 From: Mateus Braga Date: Sat, 15 Jun 2024 11:44:57 -0300 Subject: [PATCH 20/20] feat: scrap turno --- src/utils/sigaa/index.js | 179 ++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 85 deletions(-) diff --git a/src/utils/sigaa/index.js b/src/utils/sigaa/index.js index 1cf30b3..f92bbda 100644 --- a/src/utils/sigaa/index.js +++ b/src/utils/sigaa/index.js @@ -1,86 +1,88 @@ +// todo: save to localStorage + function normalizeDiacritics(stringElement) { - return stringElement - .trim() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .replace(/[-:]/g, "") - .toLocaleLowerCase(); + return stringElement + .trim() + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .replace(/[-:]/g, "") + .toLocaleLowerCase(); } function scrapeGradesConsulting() { - const sigaaUpdatetime = document - .querySelector(".dataAtual") - .textContent.trim(); - - const [day, month, year, hour, minute] = sigaaUpdatetime.match(/\d+/g); - const updateDatetime = new Date(year, month - 1, day, hour, minute); - - // * dados do aluno - const studentDataHTML = document.querySelector( - "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td", - ).textContent; - const courseHTML = document.querySelector( - "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td", - ); - const studentCourse = courseHTML.innerText; - const [, ra] = studentDataHTML.trim().split(" - "); - - const quadsTableElement = document.querySelectorAll(".tabelaRelatorio"); - const quadsTable = Array.from(quadsTableElement); - - const studentDisciplinaHistory = []; - for (const tableElement of quadsTable) { - const studentseason = tableElement.querySelector("caption"); - const [year, quad] = studentseason.textContent.trim().split("."); - - const tableHeadersElement = tableElement.querySelectorAll("th"); - const tableRowsElement = tableElement.querySelectorAll("tbody > tr"); - const rawTableHeaders = Array.from(tableHeadersElement); - - const wantedFields = ["codigo", "disciplina", "resultado", "situacao"]; - const indexWantedFields = []; - const tableHeaders = rawTableHeaders.filter((rawItem, index) => { - const item = normalizeDiacritics(rawItem.innerText); - - if (wantedFields.includes(item)) { - // crimes - indexWantedFields.push(index); - } - - return wantedFields.includes(item); - }); - - const tableRows = Array.from(tableRowsElement); - for (const row of tableRows) { - const rowChildrens = Array.from(row.children); - const cells = rowChildrens - .filter((_, index) => indexWantedFields.includes(index)) - .map((cellHTML) => cellHTML.innerText); // picking exact header positions - - const disciplina = {}; - - cells.forEach((item, index) => { - const normalizedHeaderText = normalizeDiacritics( - tableHeaders[index].textContent, - ); - disciplina[normalizedHeaderText] = item; - }); - - disciplina.ano = year; - disciplina.periodo = quad; - - studentDisciplinaHistory.push(disciplina); - } - } - - const userHistory = { - updateTime: updateDatetime, - curso: studentCourse, - ra: Number(ra), - disciplinas: studentDisciplinaHistory, - }; - - return userHistory; + const sigaaUpdatetime = document + .querySelector(".dataAtual") + .textContent.trim(); + + const [day, month, year, hour, minute] = sigaaUpdatetime.match(/\d+/g); + const updateDatetime = new Date(year, month - 1, day, hour, minute); + + // * dados do aluno + const studentDataHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(1) > td" + ).textContent; + const courseHTML = document.querySelector( + "#identificacao > tbody > tr > td:nth-child(2) > table > tbody > tr:nth-child(2) > td" + ); + const studentCourse = courseHTML.innerText; + const [, ra] = studentDataHTML.trim().split(" - "); + + const quadsTableElement = document.querySelectorAll(".tabelaRelatorio"); + const quadsTable = Array.from(quadsTableElement); + + const studentDisciplinaHistory = []; + for (const tableElement of quadsTable) { + const studentseason = tableElement.querySelector("caption"); + const [year, quad] = studentseason.textContent.trim().split("."); + + const tableHeadersElement = tableElement.querySelectorAll("th"); + const tableRowsElement = tableElement.querySelectorAll("tbody > tr"); + const rawTableHeaders = Array.from(tableHeadersElement); + + const wantedFields = ["codigo", "disciplina", "resultado", "situacao"]; + const indexWantedFields = []; + const tableHeaders = rawTableHeaders.filter((rawItem, index) => { + const item = normalizeDiacritics(rawItem.innerText); + + if (wantedFields.includes(item)) { + // crimes + indexWantedFields.push(index); + } + + return wantedFields.includes(item); + }); + + const tableRows = Array.from(tableRowsElement); + for (const row of tableRows) { + const rowChildrens = Array.from(row.children); + const cells = rowChildrens + .filter((_, index) => indexWantedFields.includes(index)) + .map((cellHTML) => cellHTML.innerText); // picking exact header positions + + const disciplina = {}; + + cells.forEach((item, index) => { + const normalizedHeaderText = normalizeDiacritics( + tableHeaders[index].textContent + ); + disciplina[normalizedHeaderText] = item; + }); + + disciplina.ano = year; + disciplina.periodo = quad; + + studentDisciplinaHistory.push(disciplina); + } + } + + const userHistory = { + updateTime: updateDatetime, + curso: studentCourse, + ra: Number(ra), + disciplinas: studentDisciplinaHistory, + }; + + return userHistory; } function scrapeHomepage() { @@ -88,23 +90,30 @@ function scrapeHomepage() { const tablesRowsArray = Array.from(trs); const rawStudentInfo = tablesRowsArray.map((line) => Array.from(line.children).map((column) => - normalizeDiacritics(column.innerText), - ), + normalizeDiacritics(column.innerText) + ) ); - const [rawName] = document.querySelectorAll("#perfil-docente p.info-docente"); const [name] = rawName.textContent.split(/\n\n\t+\n\t+/); const studentInfo = Object.fromEntries(rawStudentInfo); + const courseInfo = studentInfo.curso.split(" "); + + studentInfo.curso = courseInfo[0]; + let turno = courseInfo[courseInfo.length - 1]; + + if (turno === 'n') turno = 'noturno' + if (turno === 'm') turno = 'matutino' return { name: name.trim(), studentInfo, - } + turno: turno, + }; } module.exports = { - normalizeDiacritics, - scrapeGradesConsulting, + normalizeDiacritics, + scrapeGradesConsulting, scrapeHomepage, };