manaba_sdk/scrape/
report.rs1use crate::assignment::{AssignmentDate, AssignmentReceptibleState, AssignmentSubmitState};
2use crate::error::Result;
3use crate::{Client, Course};
4use scraper::Selector;
5
6#[derive(Debug)]
7pub struct Report {
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_reports(&self, course: &Course) -> Result<Vec<Report>> {
17 let url = format!("{}_report", course.id);
18 let html = self.get_html(reqwest::Method::GET, url).await?;
19
20 let selector = Selector::parse("table.stdlist tr:not(.title)")?;
21 let reports_element = html.select(&selector);
22
23 let reports = reports_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 selector = Selector::parse("div").unwrap();
39 let receptiable_state = row.select(&selector).next().map_or(
40 AssignmentReceptibleState::NotStarted,
41 |state| match state.inner_html().as_str() {
42 "受付中" => AssignmentReceptibleState::Open,
43 "受付終了" => AssignmentReceptibleState::Closed,
44 _ => AssignmentReceptibleState::NotStarted,
45 },
46 );
47
48 let selector = Selector::parse("span").unwrap();
49 let submit_state = row.select(&selector).next().map_or(
50 AssignmentSubmitState::Done,
51 |submit_state| {
52 if submit_state.inner_html() == "未提出" {
53 AssignmentSubmitState::Todo
54 } else {
55 AssignmentSubmitState::Done
56 }
57 },
58 );
59
60 (receptiable_state, submit_state)
61 };
62
63 let start_date = {
64 let row = rows.next().unwrap();
65 let date = row.inner_html();
66 if date.is_empty() {
67 None
68 } else {
69 Some(AssignmentDate::new(&date))
70 }
71 };
72
73 let due_date = {
74 let row = rows.next().unwrap();
75 let date = row.inner_html();
76 if date.is_empty() {
77 None
78 } else {
79 Some(AssignmentDate::new(&date))
80 }
81 };
82
83 Report {
84 title,
85 receptiable_state,
86 submit_state,
87 start_date,
88 due_date,
89 }
90 })
91 .collect::<Vec<Report>>();
92
93 Ok(reports)
94 }
95}