bpi_rs/login/login_action/
sms.rs1use reqwest::header::SET_COOKIE;
2
3use serde::{Deserialize, Serialize};
4use tracing::{error, info};
5
6use crate::{BilibiliRequest, BpiClient, BpiError, BpiResponse};
7
8#[derive(Debug, Deserialize, Serialize)]
9pub struct SMSSendData {
10 captcha_key: String, }
12
13#[derive(Debug, Deserialize, Serialize)]
14struct SMSLoginData {
15 is_new: bool, status: i32, url: String, }
19
20impl BpiClient {
21 pub async fn login_send_sms_code(
32 &self,
33 cid: u32,
34 tel: u32,
35 source: &str,
36 token: &str,
37 challenge: &str,
38 validate: &str,
39 seccode: &str,
40 ) -> Result<BpiResponse<SMSSendData>, BpiError> {
41 let form = vec![
43 ("cid", cid.to_string()),
44 ("tel", tel.to_string()),
45 ("source", source.to_string()),
46 ("token", token.to_string()),
47 ("challenge", challenge.to_string()),
48 ("validate", validate.to_string()),
49 ("seccode", seccode.to_string()),
50 ];
51
52 let result = self
54 .post("https://passport.bilibili.com/x/passport-login/web/sms/send")
55 .form(&form)
56 .send_bpi("发送短信验证码")
57 .await?;
58
59 Ok(result)
60 }
61
62 pub async fn login_with_sms(
69 &self,
70 cid: u32,
71 tel: u32,
72 captcha_key: &str,
73 code: &str,
74 ) -> Result<(), String> {
75 let form = vec![
76 ("cid", cid.to_string()),
77 ("tel", tel.to_string()),
78 ("code", code.to_string()),
79 ("source", "main_web".to_string()),
80 ("captcha_key", captcha_key.to_string()),
81 ("go_url", "https://www.bilibili.com".to_string()),
82 ("keep", true.to_string()),
83 ];
84
85 let response = BpiClient::new()
86 .post("https://passport.bilibili.com/x/passport-login/web/login/sms")
87 .form(&form)
88 .send()
89 .await
90 .map_err(|e| e.to_string())?;
91
92 if let Some(cookies) = response
93 .headers()
94 .get_all(SET_COOKIE)
95 .iter()
96 .map(|v| v.to_str().unwrap_or(""))
97 .collect::<Vec<_>>()
98 .join("; ")
99 .into()
100 {
101 info!("登录返回的 Cookie: {}", cookies);
102 }
103
104 let resp = response
105 .json::<BpiResponse<SMSLoginData>>()
106 .await
107 .map_err(|e| {
108 error!("解析短信登录响应失败: {:?}", e);
109 e.to_string()
110 })?;
111
112 if resp.code != 0 {
113 error!("短信登录失败: code={}, message={}", resp.code, resp.message);
114 return Err(resp.message);
115 }
116
117 match resp.code {
118 0 => {
119 info!("短信登录成功");
120 Ok(())
121 }
122 code => {
123 error!("验证码发送失败: code={}, message={}", code, resp.message);
124 let msg = match code {
125 -400 => "请求错误".to_string(),
126 1006 => "请输入正确的短信验证码".to_string(),
127 1007 => "短信验证码已过期".to_string(),
128
129 _ => resp.message,
130 };
131 Err(msg)
132 }
133 }
134 }
135}