manaba-sdk 0.5.2

Get information from manaba
Documentation
use scraper::Selector;

use crate::{
    Client, Course,
    assignment::{AssignmentDate, AssignmentReceptibleState, AssignmentSubmitState},
    error::Result,
};

#[derive(Debug)]
pub struct Report {
    pub title: String,
    pub submit_state: AssignmentSubmitState,
    pub receptiable_state: AssignmentReceptibleState,
    pub start_date: Option<AssignmentDate>,
    pub due_date: Option<AssignmentDate>,
}

impl Client {
    pub async fn get_reports(&self, course: &Course) -> Result<Vec<Report>> {
        let url = format!("{}_report", course.id);
        let html = self.get_html(reqwest::Method::GET, url).await?;

        let selector = Selector::parse("table.stdlist tr:not(.title)")?;
        let reports_element = html.select(&selector);

        let reports = reports_element
            .map(|report_element| {
                let selector = Selector::parse("td").unwrap();
                let mut rows = report_element.select(&selector);

                let title = {
                    let row = rows.next().unwrap();
                    let selector = Selector::parse("a").unwrap();
                    let report_title_element = row.select(&selector).next().unwrap();
                    report_title_element.inner_html()
                };

                let (receptiable_state, submit_state) = {
                    let row = rows.next().unwrap();

                    let selector = Selector::parse("div").unwrap();
                    let receptiable_state = row.select(&selector).next().map_or(
                        AssignmentReceptibleState::NotStarted,
                        |state| match state.inner_html().as_str() {
                            "受付中" => AssignmentReceptibleState::Open,
                            "受付終了" => AssignmentReceptibleState::Closed,
                            _ => AssignmentReceptibleState::NotStarted,
                        },
                    );

                    let selector = Selector::parse("span").unwrap();
                    let submit_state = row.select(&selector).next().map_or(
                        AssignmentSubmitState::Done,
                        |submit_state| {
                            if submit_state.inner_html() == "未提出" {
                                AssignmentSubmitState::Todo
                            } else {
                                AssignmentSubmitState::Done
                            }
                        },
                    );

                    (receptiable_state, submit_state)
                };

                let start_date = {
                    let row = rows.next().unwrap();
                    let date = row.inner_html();
                    if date.is_empty() {
                        None
                    } else {
                        Some(AssignmentDate::new(&date))
                    }
                };

                let due_date = {
                    let row = rows.next().unwrap();
                    let date = row.inner_html();
                    if date.is_empty() {
                        None
                    } else {
                        Some(AssignmentDate::new(&date))
                    }
                };

                Report {
                    title,
                    receptiable_state,
                    submit_state,
                    start_date,
                    due_date,
                }
            })
            .collect::<Vec<Report>>();

        Ok(reports)
    }
}