1use reqwest::{IntoUrl, Method, RequestBuilder, header::HeaderMap};
2use scraper::{Html, Selector};
3use std::fmt::Display;
4
5use crate::{
6 Cookie,
7 error::{ManabaError, Result},
8};
9
10pub struct Client {
11 pub base_url: String,
12 pub(crate) reqwest_client: reqwest::Client,
13 pub(crate) headers: HeaderMap,
14}
15
16impl Client {
17 pub async fn new(base_url: &str, cookie: &Cookie) -> Result<Self> {
18 let reqwest_client = reqwest::Client::builder().build().unwrap();
19
20 let headers = {
21 let mut headers = HeaderMap::new();
22 headers.insert("Cookie", cookie.0.parse().unwrap());
23 headers
24 };
25
26 let client = Client {
27 base_url: base_url.to_owned(),
28 reqwest_client,
29 headers,
30 };
31
32 if client.is_valid_cookie().await? {
33 Ok(client)
34 } else {
35 Err(ManabaError::InvalidCookie)
36 }
37 }
38
39 pub(crate) fn request<U>(&self, method: Method, url: U) -> RequestBuilder
40 where
41 U: IntoUrl + Display,
42 {
43 self.reqwest_client
44 .request(method, format!("{}/{}", self.base_url, url))
45 .headers(self.headers.clone())
46 }
47
48 pub(crate) async fn get_html<U>(&self, method: reqwest::Method, url: U) -> Result<Html>
49 where
50 U: IntoUrl + Display,
51 {
52 let request = self.request(method, url);
53
54 let response = request
55 .send()
56 .await
57 .map_err(ManabaError::SendRequestError)?;
58
59 let body = response
60 .text()
61 .await
62 .map_err(ManabaError::HtmlBodyParseError)?;
63
64 let document = Html::parse_document(&body);
65 Ok(document)
66 }
67
68 pub async fn is_valid_cookie(&self) -> Result<bool> {
69 let request = self.request(reqwest::Method::GET, "");
70
71 let response = request
72 .send()
73 .await
74 .map_err(ManabaError::SendRequestError)?;
75
76 let body = response
77 .text()
78 .await
79 .map_err(ManabaError::HtmlBodyParseError)?;
80
81 let document = Html::parse_document(&body);
82
83 let selector = Selector::parse("div#orgheader").unwrap();
84 let elements = document.select(&selector);
85
86 Ok(elements.count() != 0)
87 }
88}