manaba_sdk/scrape/
exam.rs

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