diff --git a/bun.lock b/bun.lock index 428f687..629b17e 100755 --- a/bun.lock +++ b/bun.lock @@ -3,6 +3,7 @@ "workspaces": { "": { "dependencies": { + "buffer": "^6.0.3", "fast-xml-parser": "^4.5.1", "file-type": "^19.6.0", }, @@ -306,7 +307,7 @@ "browserslist": ["browserslist@4.24.3", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA=="], - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "bun-types": ["bun-types@1.1.37", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA=="], @@ -864,6 +865,8 @@ "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], diff --git a/package.json b/package.json index 06abc7e..3400412 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "vite": "^6.0.5" }, "dependencies": { + "buffer": "^6.0.3", "fast-xml-parser": "^4.5.1", "file-type": "^19.6.0" }, diff --git a/src/lib/index.ts b/src/lib/index.ts index bb1d4ca..952dc07 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,3 +1,6 @@ +import { fileTypeFromBuffer } from 'file-type'; +import { Buffer } from 'buffer'; + export function getColorForGrade(grade: string | number) { if (typeof grade == 'number') { if (grade > 100) return 'blue'; @@ -47,3 +50,15 @@ export const shortDateFormatter = new Intl.DateTimeFormat('en-US', { export const fullDateFormatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'full' }); + +export async function getBlobURLFromBase64String(base64: string) { + const byteArray = new Uint8Array(Buffer.from(base64, 'base64')); + + const mimeType = (await fileTypeFromBuffer(byteArray))?.mime; + + if (!mimeType) throw new Error('Could not determine MIME type'); + + const blob = new Blob([byteArray], { type: mimeType }); + + return URL.createObjectURL(blob); +} diff --git a/src/lib/synergy.ts b/src/lib/synergy.ts index cd26409..8c933fa 100644 --- a/src/lib/synergy.ts +++ b/src/lib/synergy.ts @@ -4,7 +4,7 @@ import type { AuthToken } from '$lib/types/AuthToken'; import type { Documents } from '$lib/types/Documents'; import type { Gradebook } from '$lib/types/Gradebook'; import type { MailData } from '$lib/types/MailData'; -import type { ReportCard } from '$lib/types/ReportCard'; +import type { ReportCard, ReportCardNotFound } from '$lib/types/ReportCard'; import type { StudentInfo } from '$lib/types/StudentInfo'; import { XMLBuilder, XMLParser } from 'fast-xml-parser'; @@ -122,13 +122,8 @@ export class StudentAccount { } async reportCard(documentGU: string): Promise { - const documentData: ReportCard = ( - await this.request('GetReportCardDocumentData', { DocumentGU: documentGU }) - ).DocumentData; - - if ('Base64Code' in documentData) return documentData; - - throw new Error('Document not found'); + return (await this.request('GetReportCardDocumentData', { DocumentGU: documentGU })) + .DocumentData; } async mailData(): Promise { diff --git a/src/lib/types/ReportCard.ts b/src/lib/types/ReportCard.ts index 43704f6..dca1c3b 100644 --- a/src/lib/types/ReportCard.ts +++ b/src/lib/types/ReportCard.ts @@ -1,9 +1,12 @@ -export interface ReportCard { - Base64Code?: string; +export interface ReportCardNotFound { '_xmlns:xsd': string; '_xmlns:xsi': string; - _DocumentGU?: string; - _FileName?: string; - _DocFileName?: string; - _DocType?: string; +} + +export interface ReportCard extends ReportCardNotFound { + Base64Code: string; + _DocumentGU: string; + _FileName: string; + _DocFileName: string; + _DocType: string; } diff --git a/src/routes/(authed)/documents/document/+page.svelte b/src/routes/(authed)/documents/document/+page.svelte index a63476c..be7e5f8 100644 --- a/src/routes/(authed)/documents/document/+page.svelte +++ b/src/routes/(authed)/documents/document/+page.svelte @@ -1,17 +1,18 @@ @@ -40,8 +47,8 @@ Document - GradeVue -{#if reportCardPromise} - {#await reportCardPromise} +{#if reportCardURLPromise} + {#await reportCardURLPromise} {:then} @@ -50,7 +57,7 @@

{error}

- +
{/await} diff --git a/src/routes/(authed)/mail/attachment/+page.svelte b/src/routes/(authed)/mail/attachment/+page.svelte index 1f1609c..55b193f 100644 --- a/src/routes/(authed)/mail/attachment/+page.svelte +++ b/src/routes/(authed)/mail/attachment/+page.svelte @@ -1,19 +1,18 @@ @@ -55,8 +47,8 @@ Attachment - GradeVue -{#if $studentAccount} - {#await attachmentPromise} +{#if attachmentURLPromise} + {#await attachmentURLPromise} {:then}