diff options
Diffstat (limited to 'src/student-prod.ts')
| -rw-r--r-- | src/student-prod.ts | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/student-prod.ts b/src/student-prod.ts new file mode 100644 index 0000000..24ac869 --- /dev/null +++ b/src/student-prod.ts @@ -0,0 +1,90 @@ +import type { Graduation } from "./graduation-common.ts"; +import { Student } from "./student-common.ts"; +import { getUserIconUrl, getCourseParticipantsUrl } from "./utils-prod.js" +import { fetchGraduation } from "./graduation-prod.ts"; + +declare module "./student-common.ts" { + interface Student { + getGraduation(): Promise<Graduation>; + getIconUrl(): Promise<string>; + } +} +Student.prototype.getGraduation = function () { + return fetchGraduation(this); +}; + +Student.prototype.getIconUrl = function () { + return getUserIconUrl(this.id); +}; + +// Cache the fetched students. +let students: Array<Student> | null = null; + +const idRegex = /id=(\d+)/; +async function _fetchStudents() { + const res = await fetch(getCourseParticipantsUrl()); + const doc = new DOMParser().parseFromString(await res.text(), "text/html"); + const table = doc.querySelector("tbody")!; + const fetchedStudents: Array<Student> = []; + table.querySelectorAll("tr").forEach(row => { + if (row.classList.contains("emptyrow")) + return; + + const roleCell = row.querySelector(".c4")!; + // TODO(muhq): Is this locale dependent? + if (roleCell.innerHTML.includes("Lehrer")) { + return; + } + + const nameCell = row.querySelector<HTMLElement>(".c1")!; + let name; + const c = nameCell.firstChild!.firstChild! as HTMLElement; + if (c.tagName == "SPAN") + name = c.title; + else + name = nameCell.innerText; + + const profileUrl = nameCell.querySelector<HTMLAnchorElement>("a.aabtn")!.href; + const match = idRegex.exec(profileUrl); + if (match === null) { + console.error("Profile Regex did not match"); + return; + } + const id = match[1]; + + const groupCell = row.querySelector(".c5")!; + const group = groupCell.querySelector<HTMLElement>("a.quickeditlink")!.textContent; + + fetchedStudents.push(new Student(Number(id), name, group)); + }); + return fetchedStudents; +} + +async function fetchStudents(idFilter?: number, nameFilter?: string, groupFilter?: string) { + if (students === null) { + const studentsPromise = _fetchStudents(); + const storedStudents = localStorage.getItem("students"); + if (storedStudents) { + studentsPromise.then((fetched) => localStorage.setItem("students", JSON.stringify(fetched))); + students = []; + for (const o of JSON.parse(storedStudents)) { + students.push(new Student(o.id, o.name, o.group)); + } + } else { + students = await studentsPromise; + localStorage.setItem("students", JSON.stringify(students)); + } + } + + return students.filter((s) => + (typeof idFilter === "undefined" || s.id === idFilter) && + (typeof nameFilter === "undefined" || s.name.includes(nameFilter)) && + (typeof groupFilter === "undefined" || s.group.includes(groupFilter))); +} + +async function fetchStudent(idFilter: number, nameFilter: string, groupFilter: string) { + const students = await fetchStudents(idFilter, nameFilter, groupFilter); + return students[0]; +} + +export { Student, fetchStudents, fetchStudent }; |
