bpi_rs/login/login_action/
captcha.rs1use 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}