canvas_grading/
file.rs

1use std::{io::Cursor, path::Path};
2
3use anyhow::{anyhow, Result};
4use serde::Deserialize;
5use tracing::info;
6
7use crate::Submission;
8
9#[derive(Debug, Clone)]
10pub struct FileSubmission {
11    user_id: u64,
12    assignment_id: u64,
13    attempt: u64,
14    file: CanvasFile,
15}
16
17impl std::fmt::Display for FileSubmission {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        write!(
20            f,
21            "{}_{}_{}_{}",
22            self.user_id,
23            self.assignment_id,
24            self.attempt,
25            self.file.filename()
26        )
27    }
28}
29
30impl FileSubmission {
31    pub fn new(submission: &Submission, file: CanvasFile) -> Self {
32        Self {
33            user_id: submission.user(),
34            assignment_id: submission.assignment(),
35            attempt: submission.attempt(),
36            file,
37        }
38    }
39
40    pub async fn download(&self, directiory: &Path) -> Result<()> {
41        let path = directiory.join(self.to_string());
42
43        info!(
44            "Downloading \"{}\" to {}",
45            self.file.url(),
46            path.to_str().unwrap()
47        );
48        self.file.download(&path).await
49    }
50}
51
52#[derive(Debug, Clone, Deserialize)]
53pub struct CanvasFile {
54    url: String,
55    filename: String,
56}
57
58impl CanvasFile {
59    pub fn url(&self) -> &str {
60        &self.url
61    }
62
63    pub fn filename(&self) -> &str {
64        &self.filename
65    }
66
67    pub async fn download(&self, path: &Path) -> Result<()> {
68        let response = reqwest::get(&self.url).await?;
69
70        // Create parent directories
71        std::fs::create_dir_all(
72            path.parent()
73                .ok_or(anyhow!("Path does not have a parent directory!"))?,
74        )?;
75
76        let mut file = std::fs::File::create(path)?;
77        let mut contents = Cursor::new(response.bytes().await?);
78        std::io::copy(&mut contents, &mut file)?;
79
80        Ok(())
81    }
82}