Skip to content

Commit

Permalink
feat(api): add assignment file upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Skythrew committed Sep 29, 2024
1 parent 72da565 commit f4f14c8
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ink.literate.pawnote.api

import ink.literate.pawnote.api.helpers.createEntityID
import ink.literate.pawnote.core.RequestFN
import ink.literate.pawnote.core.RequestUpload
import ink.literate.pawnote.models.DocumentKind
import ink.literate.pawnote.models.EntityState
import ink.literate.pawnote.models.SessionHandle
import ink.literate.pawnote.models.TabLocation
import ink.literate.pawnote.models.errors.UploadSizeError
import io.ktor.http.content.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.*
import java.io.File
import java.nio.channels.FileChannel

suspend fun assignmentUploadFile (session: SessionHandle, assignmentID: String, file: File, fileName: String) {
// Check if the file can be uploaded.
// Otherwise we'll get an error during the upload.

val fileSize = file.length()
val maxFileSize = session.user.authorizations.maxAssignmentFileUploadSize

if (fileSize > maxFileSize)
throw UploadSizeError(maxFileSize)

// Ask to the server to store the file for us.
val fileUpload = RequestUpload(session, "SaisieTAFARendreEleve", file, fileName)
fileUpload.send()

val request = RequestFN(session.information, "SaisieTAFARendreEleve", Json.encodeToString(
buildJsonObject {
putJsonObject("_Signature_") {
put("onglet", TabLocation.Assignments.code)
}

putJsonObject("donnees") {
putJsonArray("listeFichiers") {
addJsonObject {
put("E", EntityState.CREATION.code)
put("G", DocumentKind.FILE.code)
put("L", fileName)
put("N", createEntityID())
put("idFichier", fileUpload.id)
putJsonObject("TAF") {
put("N", assignmentID)
}
}
}
}
}
))

request.send()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ink.literate.pawnote.api.helpers

/**
* Defaults to `-1000`, used to generate IDs for newly created objects.
* Whenever an object is created using this ID, it should be decremented by `1`.
*/
var id = -1000

fun createEntityID(): Int {
id -= 1
return id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package ink.literate.pawnote.core

import ink.literate.pawnote.api.private.AES
import ink.literate.pawnote.api.private.aesKeys
import ink.literate.pawnote.models.SessionHandle
import ink.literate.pawnote.models.errors.UploadFailedError
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.util.*
import io.ktor.utils.io.*
import kotlinx.datetime.Clock
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import java.io.File
import java.nio.file.Files

@OptIn(InternalAPI::class)
class RequestUpload(private val session: SessionHandle, functionName: String, file: File, private val fileName: String) {
val id = "selecfile_1_${Clock.System.now().toEpochMilliseconds()}"
var order: String = ""

private var url = ""
private var form: List<PartData>? = null


init {
session.information.order++

val keys = aesKeys(session.information)

order = AES.encrypt(session.information.order.toString().toByteArray(), keys.key, keys.iv)

val form = formData {
append("\"numeroOrdre\"", order)
append("\"numeroSession\"", session.information.id.toString())
append("\"nomRequete\"", functionName)
append("\"idFichier\"", id)
append("\"md5\"", "")
append("\"files[]\"", file.readBytes(), Headers.build {
append(HttpHeaders.ContentDisposition, "filename=\"${fileName}\"")
append(HttpHeaders.ContentType, Files.probeContentType(file.toPath()))
})
}

this.form = form
this.url = session.information.url + "/uploadfilesession/${session.information.accountKind.code}/${session.information.id}"
}

suspend fun send() {
var state = 3

val url = this.url

while (state == 3) {
val response = this.session.client.submitFormWithBinaryData(url = url,form!!) {
headers {
append(HttpHeaders.ContentDisposition, "attachment; filename=\"${fileName}\"")
}
}

val json = Json.parseToJsonElement(response.content.readUTF8Line()!!)
state = json.jsonObject["etat"]!!.jsonPrimitive.int
}

// Even if there's an error, it bumped.
this.session.information.order++

if (state == 0 || state == 2)
throw UploadFailedError()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ink.literate.pawnote.models

enum class DocumentKind (val code: Int) {
URL(0),
FILE(1),
CLOUD(2),
KIOSK_LINK(3),
CONFERENCE_LINK(4)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ink.literate.pawnote.models.errors

class UploadSizeError (maxSizeInBytes: Double) : Error("The file you are trying to upload is too large, maximum allowed is $maxSizeInBytes bytes")

class UploadFailedError : Error("The file upload failed")

0 comments on commit f4f14c8

Please sign in to comment.