diff --git a/src-tauri/src/bili_client.rs b/src-tauri/src/bili_client.rs index 9af539d..f06febf 100644 --- a/src-tauri/src/bili_client.rs +++ b/src-tauri/src/bili_client.rs @@ -6,12 +6,13 @@ use reqwest::StatusCode; use reqwest_middleware::ClientWithMiddleware; use reqwest_retry::{policies::ExponentialBackoff, Jitter, RetryTransientMiddleware}; use serde::{Deserialize, Serialize}; +use serde_json::json; use tauri::{ http::{HeaderMap, HeaderValue}, AppHandle, }; -use crate::types::qrcode_data::QrcodeData; +use crate::types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus}; const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"; const REFERRER: &str = "https://www.bilibili.com/"; @@ -60,6 +61,42 @@ impl BiliClient { Ok(qrcode_data) } + + pub async fn get_qrcode_status(&self, qrcode_key: &str) -> anyhow::Result { + // 发送获取二维码状态请求 + let params = json!({"qrcode_key": qrcode_key}); + let request = self + .api_client + .read() + .get("https://passport.bilibili.com/x/passport-login/web/qrcode/poll") + .query(¶ms); + let http_resp = request.send().await?; + // 检查http响应状态码 + let status = http_resp.status(); + let body = http_resp.text().await?; + if status != StatusCode::OK { + return Err(anyhow!("预料之外的状态码({status}): {body}")); + } + // 尝试将body解析为BiliResp + let bili_resp: BiliResp = + serde_json::from_str(&body).context(format!("将body解析为BiliResp失败: {body}"))?; + // 检查BiliResp的code字段 + if bili_resp.code != 0 { + return Err(anyhow!("预料之外的code: {bili_resp:?}")); + } + // 检查BiliResp的data是否存在 + let Some(data) = bili_resp.data else { + return Err(anyhow!("BiliResp中不存在data字段: {bili_resp:?}")); + }; + // 尝试将data解析为二维码状态 + let data_str = data.to_string(); + let qrcode_status: QrcodeStatus = serde_json::from_str(&data_str) + .context(format!("将data解析为QrcodeStatus失败: {data_str}"))?; + if ![0, 86101, 86090, 86038].contains(&qrcode_status.code) { + return Err(anyhow!("预料之外的二维码code: {qrcode_status:?}")); + } + Ok(qrcode_status) + } } fn create_api_client(_app: &AppHandle) -> ClientWithMiddleware { diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 1fd506b..ae7a5b7 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -6,7 +6,7 @@ use crate::{ errors::{CommandError, CommandResult}, extensions::AppHandleExt, logger, - types::qrcode_data::QrcodeData, + types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus}, }; #[tauri::command] @@ -68,3 +68,15 @@ pub async fn generate_qrcode(app: AppHandle) -> CommandResult { .map_err(|err| CommandError::from("生成二维码失败", err))?; Ok(qrcode_data) } + +#[allow(clippy::needless_pass_by_value)] +#[tauri::command(async)] +#[specta::specta] +pub async fn get_qrcode_status(app: AppHandle, qrcode_key: String) -> CommandResult { + let bili_client = app.get_bili_client(); + let qrcode_status = bili_client + .get_qrcode_status(&qrcode_key) + .await + .map_err(|err| CommandError::from("获取二维码状态", err))?; + Ok(qrcode_status) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6aa10e1..1dc21b8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -28,6 +28,7 @@ pub fn run() { get_config, save_config, generate_qrcode, + get_qrcode_status, ]) .events(tauri_specta::collect_events![LogEvent]); diff --git a/src-tauri/src/types/mod.rs b/src-tauri/src/types/mod.rs index e96479a..336b80a 100644 --- a/src-tauri/src/types/mod.rs +++ b/src-tauri/src/types/mod.rs @@ -1,2 +1,3 @@ pub mod log_level; pub mod qrcode_data; +pub mod qrcode_status; diff --git a/src-tauri/src/types/qrcode_status.rs b/src-tauri/src/types/qrcode_status.rs new file mode 100644 index 0000000..5aaa089 --- /dev/null +++ b/src-tauri/src/types/qrcode_status.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; +use specta::Type; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +pub struct QrcodeStatus { + pub url: String, + pub refresh_token: String, + pub timestamp: i64, + pub code: i64, + pub message: String, +} diff --git a/src/App.vue b/src/App.vue index 8d5ee12..4593f61 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,6 +13,10 @@ async function greet() { async function test() { const result = await commands.generateQrcode() console.log(result) + if (result.status === 'ok') { + const result2 = await commands.getQrcodeStatus(result.data.qrcode_key) + console.log(result2) + } } diff --git a/src/bindings.ts b/src/bindings.ts index bf377cf..c3af336 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -26,6 +26,14 @@ async generateQrcode() : Promise> { if(e instanceof Error) throw e; else return { status: "error", error: e as any }; } +}, +async getQrcodeStatus(qrcodeKey: string) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("get_qrcode_status", { qrcodeKey }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} } } @@ -50,6 +58,7 @@ export type JsonValue = null | boolean | number | string | JsonValue[] | { [key export type LogEvent = { timestamp: string; level: LogLevel; fields: { [key in string]: JsonValue }; target: string; filename: string; line_number: number } export type LogLevel = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" export type QrcodeData = { url: string; qrcode_key: string } +export type QrcodeStatus = { url: string; refresh_token: string; timestamp: number; code: number; message: string } /** tauri-specta globals **/