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