manaba_sdk/scrape/
exam.rs1use 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}