bpi_rs/login/login_action/
captcha.rs

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