1pub mod errors;
2pub mod graphql;
3pub mod types;
4use errors::AppResult;
5pub use graphql::client::GQLLeetcodeRequest;
6pub use graphql::query::problemset_question_list::Query as QuestionRequest;
7pub use graphql::query::question_content::Query as QuestionContentRequest;
8pub use graphql::query::run_code::RunCodeRequest;
9pub use graphql::query::submit_code::SubmitCodeRequest;
10pub use graphql::query::EditorDataRequest;
11use reqwest::header::{HeaderMap, HeaderValue};
12use reqwest::Client;
13use std::sync::OnceLock;
14pub use types::editor_data::QuestionData as EditorDataResponse;
15pub use types::problemset_question_list::Root as QuestionResponse;
16
17pub static REQ_CLIENT: OnceLock<reqwest::Client> = OnceLock::new();
18
19pub async fn init(csrf: &str, sess: &str) -> AppResult<()> {
20 let client = build_reqwest_client(csrf, sess).await?;
21 REQ_CLIENT.get_or_init(|| client);
22 Ok(())
23}
24
25pub(crate) fn get_client() -> &'static Client {
26 REQ_CLIENT.get().expect("Client not initialized")
27}
28
29pub async fn build_reqwest_client(csrf: &str, sess: &str) -> AppResult<Client> {
30 let mut headers = HeaderMap::new();
31 let header_k_v = [
32 (
33 "Cookie",
34 format!("LEETCODE_SESSION={sess}; csrftoken={csrf}"),
35 ),
36 ("Content-Type", "application/json".to_string()),
37 ("x-csrftoken", csrf.to_string()),
38 ("Origin", "https://leetcode.com".to_string()),
39 ("Referer", "https://leetcode.com".to_string()),
40 ("Connection", "keep-alive".to_string()),
41 ];
42
43 for (key, value) in header_k_v {
44 headers.append(key, HeaderValue::from_str(value.as_str())?);
45 }
46
47 let client = reqwest::ClientBuilder::new()
48 .default_headers(headers)
49 .build()?;
50 Ok(client)
51}