This commit is contained in:
Gaspard Jankowiak 2026-06-04 00:04:48 +02:00
commit f5c23dc867

View file

@ -18,7 +18,7 @@ async function getXSRFToken() {
} }
async function getApplicant(applicant, token) { async function getApplicant(applicant, token) {
content.fetch(`https://personal.uni-graz.at/api/erec/job-applications/${applicant.id}`, return content.fetch(`https://personal.uni-graz.at/api/erec/job-applications/${applicant.id}`,
{ {
headers: { "X-XSRF-TOKEN": token } headers: { "X-XSRF-TOKEN": token }
}) })
@ -28,7 +28,25 @@ async function getApplicant(applicant, token) {
} }
throw `Failed to get applicant ${applicant.id}` throw `Failed to get applicant ${applicant.id}`
}) })
.then((jsonData) => { .then(async (jsonData) => {
const files = jsonData.application_files ?? []
await Promise.all(files.map(async (afile) => {
const response = await content.fetch(
`https://personal.uni-graz.at/api/erec/download-file/${afile.file_id}`,
{
credentials: "same-origin",
headers: { "X-XSRF-TOKEN": token }
}
)
if (!response.ok) {
throw `Failed to download file ${afile.file_id} for applicant ${applicant.id}`
}
afile.blob = await response.blob()
}))
return jsonData return jsonData
}) })
} }
@ -36,7 +54,7 @@ async function getApplicant(applicant, token) {
async function getApplicants() { async function getApplicants() {
const aid = getApplicationId() const aid = getApplicationId()
const token = await getXSRFToken() const token = await getXSRFToken()
content.fetch(`https://personal.uni-graz.at/api/erec/job-applications/procedure/${aid}`, return content.fetch(`https://personal.uni-graz.at/api/erec/job-applications/procedure/${aid}`,
{ {
credentials: "same-origin", credentials: "same-origin",
headers: { "X-XSRF-TOKEN": token } headers: { "X-XSRF-TOKEN": token }
@ -49,19 +67,73 @@ async function getApplicants() {
throw "Failed to get list of applications" throw "Failed to get list of applications"
}) })
.then((jsonData) => { .then((jsonData) => {
const sliced = jsonData.slice(0, 10); const sliced = jsonData.slice(0, 2);
return Promise.allSettled(sliced.map(async (applicant) => getApplicant(applicant, token))) return Promise.allSettled(sliced.map(async (applicant) => getApplicant(applicant, token)))
}) })
} }
function sanitizeZipPathSegment(value, fallback = "unnamed") {
const sanitized = String(value ?? "")
.replace(/[\/\\:*?"<>|]/g, "_")
.trim()
return sanitized === "" ? fallback : sanitized
}
function downloadBlob(blob, fileName) {
const url = URL.createObjectURL(blob)
const link = document.createElement("a")
link.href = url
link.download = fileName
link.click()
setTimeout(() => URL.revokeObjectURL(url), 0)
}
function rip(event) { function rip(event) {
const btn = event.target; const btn = event.target;
btn.textContent = "working ..." btn.textContent = "working ..."
btn.classList.add("loading") btn.classList.add("loading")
btn.disabled = true; btn.disabled = true;
getApplicants().then((applicants) => { getApplicants()
btn.textContent = "done" .then(async (applicants) => {
}) const zip = new JSZip()
applicants.forEach((result) => {
if (result.status !== "fulfilled") {
throw result.reason
}
const applicant = result.value
const dirName = `${applicant.last_name}_${applicant.first_name}`
// const dirName = `${sanitizeZipPathSegment(applicant.last_name)}_${sanitizeZipPathSegment(applicant.first_name)}`
const applicantDir = zip.folder(dirName)
const files = applicant.application_files ?? []
files.forEach((afile) => {
if (afile.blob.size > 2_000_000) return;
const ext = afile.file_name.split(".").slice(-1)
const filename = `${afile.field_name}.${ext}`
// const filename = sanitizeZipPathSegment(afile.file_name)
console.log(filename)
console.log(afile.blob)
applicantDir.file(filename, afile.blob)
})
})
const zipBlob = await zip.generateAsync({ type: "blob" })
downloadBlob(zipBlob, `applications_${getApplicationId()}.zip`)
btn.textContent = "done"
})
// .catch((error) => {
// console.error(error)
// btn.textContent = "failed"
// btn.disabled = false
// })
.finally(() => {
btn.classList.remove("loading")
})
} }
// injection of rip button // injection of rip button
@ -93,3 +165,5 @@ const contentObserver = new MutationObserver((mutations) => {
}) })
contentObserver.observe(document.querySelector("app-root"), { subtree: true, childList: true }); contentObserver.observe(document.querySelector("app-root"), { subtree: true, childList: true });
console.log(JSZip.support)