1use crate::BilibiliRequest;
6use crate::BpiResult;
7use crate::login::LoginClient;
8use serde::{Deserialize, Serialize};
9
10const LOGOUT_WEB_ENDPOINT: &str = "https://passport.bilibili.com/login/exit/v2";
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct LogoutData {
16 #[serde(rename = "redirectUrl")]
18 pub redirect_url: String,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct LogoutResponse {
24 pub code: i32,
28 pub status: bool,
30 pub ts: u64,
32 pub message: Option<String>,
34 pub data: Option<LogoutData>,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct LogoutWebParams {
41 gourl: String,
42}
43
44impl Default for LogoutWebParams {
45 fn default() -> Self {
46 Self {
47 gourl: "javascript:history.go(-1)".to_string(),
48 }
49 }
50}
51
52impl LogoutWebParams {
53 pub fn new() -> Self {
54 Self::default()
55 }
56
57 pub fn gourl(mut self, gourl: impl Into<String>) -> Self {
58 self.gourl = gourl.into();
59 self
60 }
61
62 fn form_pairs(&self, csrf: &str) -> Vec<(&'static str, String)> {
63 vec![
64 ("biliCSRF", csrf.to_string()),
65 ("gourl", self.gourl.clone()),
66 ]
67 }
68}
69
70impl<'a> LoginClient<'a> {
71 pub async fn logout(&self, params: LogoutWebParams) -> BpiResult<LogoutData> {
73 let csrf = self.client.csrf()?;
74 let form = params.form_pairs(&csrf);
75
76 self.client
77 .post(LOGOUT_WEB_ENDPOINT)
78 .form(&form)
79 .send_bpi_payload("login.logout")
80 .await
81 }
82}
83
84#[cfg(test)]
85mod tests {}