manaba_sdk/scrape/
exam.rs

1use crate::Client;
2use crate::assignment::{AssignmentDate, AssignmentReceptibleState, AssignmentSubmitState};
3use crate::{Course, error::Result};
4use reqwest::Method;
5use scraper::Selector;
6
7pub struct Exam {
8    pub title: String,
9    pub submit_state: AssignmentSubmitState,
10    pub receptiable_state: AssignmentReceptibleState,
11    pub start_date: Option<AssignmentDate>,
12    pub due_date: Option<AssignmentDate>,
13}
14
15impl Client {
16    pub async fn get_exams(&self, course: &Course) -> Result<Vec<Exam>> {
17        let url = format!("{}_query", course.id);
18        let html = self.get_html(Method::GET, url).await?;
19
20        let selector = Selector::parse("table.stdlist tr:not(.title)").unwrap();
21        let exam_element = html.select(&selector);
22
23        let exams = exam_element
24            .map(|report_element| {
25                let selector = Selector::parse("td").unwrap();
26                let mut rows = report_element.select(&selector);
27
28                let title = {
29                    let row = rows.next().unwrap();
30                    let selector = Selector::parse("a").unwrap();
31                    let report_title_element = row.select(&selector).next().unwrap();
32                    report_title_element.inner_html()
33                };
34
35                let (receptiable_state, submit_state) = {
36                    let row = rows.next().unwrap();
37
38                    let receptiable_state = match row.text().next().unwrap().trim() {
39                        "受付中" => AssignmentReceptibleState::Open,
40                        "受付終了" => AssignmentReceptibleState::Closed,
41                        _ => AssignmentReceptibleState::NotStarted,
42                    };
43
44                    let selector = Selector::parse("span").unwrap();
45                    let submit_state = row.select(&selector).next().map_or(
46                        AssignmentSubmitState::Done,
47                        |submit_state| {
48                            if submit_state.inner_html().trim() == "未提出" {
49                                AssignmentSubmitState::Todo
50                            } else {
51                                AssignmentSubmitState::Done
52                            }
53                        },
54                    );
55
56                    (receptiable_state, submit_state)
57                };
58
59                let start_date = {
60                    let row = rows.next().unwrap();
61                    let date = row.inner_html();
62                    if date.is_empty() {
63                        None
64                    } else {
65                        Some(AssignmentDate::new(&date))
66                    }
67                };
68
69                let due_date = {
70                    let row = rows.next().unwrap();
71                    let date = row.inner_html();
72                    if date.is_empty() {
73                        None
74                    } else {
75                        Some(AssignmentDate::new(&date))
76                    }
77                };
78
79                Exam {
80                    title,
81                    receptiable_state,
82                    submit_state,
83                    start_date,
84                    due_date,
85                }
86            })
87            .collect::<Vec<Exam>>();
88
89        Ok(exams)
90    }
91}