Skip to main content

bpi_rs/login/login_action/
captcha.rs

1use serde::{ Deserialize, Serialize };
2
3use crate::{ BpiClient, BpiError, BpiResponse, BilibiliRequest };
4
5#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
6pub struct GeetestData {
7    #[serde(rename = "type")]
8    pub type_field: String,
9    pub token: String,
10    pub geetest: Geetest,
11    pub tencent: Tencent,
12}
13
14#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub struct Geetest {
16    pub challenge: String,
17    pub gt: String,
18}
19
20#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub struct Tencent {
22    pub appid: String,
23}
24
25#[derive(Serialize, Deserialize, Clone)]
26pub struct GenerateCaptcha {
27    pub token: String,
28    pub gt: String,
29    pub challenge: String,
30}
31
32impl BpiClient {
33    pub async fn login_generate_captcha(&self) -> Result<GenerateCaptcha, BpiError> {
34        let result: BpiResponse<GeetestData> = self
35            .get("https://passport.bilibili.com/x/passport-login/captcha?source=main_web")
36            .send_bpi("获取验证码").await?;
37
38        let data = result.into_data()?;
39
40        let token = data.token;
41        let geetest = data.geetest;
42
43        Ok(GenerateCaptcha {
44            token,
45            gt: geetest.gt,
46            challenge: geetest.challenge,
47        })
48    }
49}
50
51#[tokio::test]
52async fn test_generate_captcha() {
53    let bpi = BpiClient::new();
54    match bpi.login_generate_captcha().await {
55        Ok(captcha) => {
56            tracing::info!("验证码请求成功!");
57            tracing::info!("Token: {}", captcha.token);
58            tracing::info!("GT: {}", captcha.gt);
59            tracing::info!("Challenge: {}", captcha.challenge);
60        }
61        Err(e) => {
62            tracing::info!("验证码请求失败: {}", e);
63        }
64    }
65}