leetcode_api/leetcode/impl_lc/
user_info.rs

1use std::path::PathBuf;
2
3use lcode_config::global::{G_CACHE_DIR, G_USER_CONFIG};
4use miette::Result;
5use reqwest::Url;
6use tokio::{
7    fs::OpenOptions,
8    io::{AsyncWriteExt, BufWriter},
9    join,
10};
11
12use crate::{
13    leetcode::{
14        graphqls::*,
15        headers::Headers,
16        resps::{
17            checkin::{CheckInData, TotalPoints},
18            pass_qs::{PassData, Passdata},
19            user_data::{GlobData, UserStatus},
20        },
21        LeetCode,
22    },
23    Json,
24};
25
26// some info
27impl LeetCode {
28    /// download user avatar image
29    pub async fn dow_user_avator(&self, status: &UserStatus) -> Option<PathBuf> {
30        let avatar_url = status.avatar.as_deref()?;
31        let mut avatar_path = G_CACHE_DIR.clone();
32        if let Ok(url) = Url::parse(avatar_url) {
33            if let Some(url_path) = url.path_segments() {
34                let last = url_path.last().unwrap_or("avator.jpeg");
35                avatar_path.push(last);
36            }
37        };
38
39        if let Ok(respond) = reqwest::get(avatar_url).await {
40            if !avatar_path.exists() {
41                if let Ok(f) = OpenOptions::new()
42                    .create(true)
43                    .truncate(true)
44                    .write(true)
45                    .open(&avatar_path)
46                    .await
47                {
48                    let mut avatar_file = BufWriter::new(f);
49                    let var = respond
50                        .bytes()
51                        .await
52                        .unwrap_or_default();
53                    avatar_file.write_all(&var).await.ok();
54                    avatar_file.flush().await.ok();
55                }
56            }
57        }
58        Some(avatar_path)
59    }
60    pub async fn pass_qs_status(&self, user_slug: &str) -> Result<PassData> {
61        let json = GraphqlQuery::pass_status(user_slug);
62        let pat: Passdata = self
63            .request(
64                &G_USER_CONFIG.urls.graphql,
65                Some(&json),
66                self.headers.clone(),
67            )
68            .await?;
69        Ok(pat.data)
70    }
71    pub async fn get_points(&self) -> Result<TotalPoints> {
72        self.request(&G_USER_CONFIG.urls.points, None, self.headers.clone())
73            .await
74    }
75    pub async fn get_user_info(&self) -> Result<UserStatus> {
76        let json = GraphqlQuery::global_data();
77
78        let resp: GlobData = self
79            .request(
80                &G_USER_CONFIG.urls.graphql,
81                Some(&json),
82                self.headers.clone(),
83            )
84            .await?;
85
86        Ok(resp.user_status())
87    }
88    /// # Ensure that the cookies are obtained
89    ///
90    /// ## Example
91    ///
92    /// ```rust,ignore
93    /// let status = glob_leetcode()
94    ///     .await
95    ///     .get_user_info()?
96    ///     .unwrap();
97    /// // if user_slug is None, the cookies were not obtained
98    /// if !status.checked_in_today && status.user_slug.is_some() {
99    ///     let res = glob_leetcode()
100    ///         .await
101    ///         .daily_checkin()
102    ///         .await;
103    /// }
104    /// ```
105    /// return order (cn, com)
106    pub async fn daily_checkin(&self) -> (CheckInData, CheckInData) {
107        let json: Json = GraphqlQuery::daily_checkin();
108
109        let (header_cn, header_com) = join!(
110            Headers::build("leetcode.cn"),
111            Headers::build("leetcode.com")
112        );
113        let (header_cn, header_com) = (
114            header_cn.unwrap_or_default(),
115            header_com.unwrap_or_default(),
116        );
117
118        let resp_cn = self.request::<CheckInData>(
119            "https://leetcode.cn/graphql",
120            Some(&json),
121            header_cn.headers,
122        );
123
124        let resp_com = self.request::<CheckInData>(
125            "https://leetcode.com/graphql",
126            Some(&json),
127            header_com.headers,
128        );
129        let (resp_cn, resp_com) = join!(resp_cn, resp_com);
130
131        (resp_cn.unwrap_or_default(), resp_com.unwrap_or_default())
132    }
133}