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) {
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 }
})
@ -28,7 +28,25 @@ async function getApplicant(applicant, token) {
}
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
})
}
@ -36,7 +54,7 @@ async function getApplicant(applicant, token) {
async function getApplicants() {
const aid = getApplicationId()
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",
headers: { "X-XSRF-TOKEN": token }
@ -49,19 +67,73 @@ async function getApplicants() {
throw "Failed to get list of applications"
})
.then((jsonData) => {
const sliced = jsonData.slice(0, 10);
const sliced = jsonData.slice(0, 2);
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) {
const btn = event.target;
btn.textContent = "working ..."
btn.classList.add("loading")
btn.disabled = true;
getApplicants().then((applicants) => {
btn.textContent = "done"
})
getApplicants()
.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
@ -93,3 +165,5 @@ const contentObserver = new MutationObserver((mutations) => {
})
contentObserver.observe(document.querySelector("app-root"), { subtree: true, childList: true });
console.log(JSZip.support)