mirror of
https://github.com/lanyeeee/bilibili-video-downloader.git
synced 2026-09-08 17:16:52 +08:00
feat: 后端支持获取二维码的状态
This commit is contained in:
@@ -6,12 +6,13 @@ use reqwest::StatusCode;
|
|||||||
use reqwest_middleware::ClientWithMiddleware;
|
use reqwest_middleware::ClientWithMiddleware;
|
||||||
use reqwest_retry::{policies::ExponentialBackoff, Jitter, RetryTransientMiddleware};
|
use reqwest_retry::{policies::ExponentialBackoff, Jitter, RetryTransientMiddleware};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::json;
|
||||||
use tauri::{
|
use tauri::{
|
||||||
http::{HeaderMap, HeaderValue},
|
http::{HeaderMap, HeaderValue},
|
||||||
AppHandle,
|
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 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/";
|
const REFERRER: &str = "https://www.bilibili.com/";
|
||||||
@@ -60,6 +61,42 @@ impl BiliClient {
|
|||||||
|
|
||||||
Ok(qrcode_data)
|
Ok(qrcode_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_qrcode_status(&self, qrcode_key: &str) -> anyhow::Result<QrcodeStatus> {
|
||||||
|
// 发送获取二维码状态请求
|
||||||
|
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 {
|
fn create_api_client(_app: &AppHandle) -> ClientWithMiddleware {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
errors::{CommandError, CommandResult},
|
errors::{CommandError, CommandResult},
|
||||||
extensions::AppHandleExt,
|
extensions::AppHandleExt,
|
||||||
logger,
|
logger,
|
||||||
types::qrcode_data::QrcodeData,
|
types::{qrcode_data::QrcodeData, qrcode_status::QrcodeStatus},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -68,3 +68,15 @@ pub async fn generate_qrcode(app: AppHandle) -> CommandResult<QrcodeData> {
|
|||||||
.map_err(|err| CommandError::from("生成二维码失败", err))?;
|
.map_err(|err| CommandError::from("生成二维码失败", err))?;
|
||||||
Ok(qrcode_data)
|
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<QrcodeStatus> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ pub fn run() {
|
|||||||
get_config,
|
get_config,
|
||||||
save_config,
|
save_config,
|
||||||
generate_qrcode,
|
generate_qrcode,
|
||||||
|
get_qrcode_status,
|
||||||
])
|
])
|
||||||
.events(tauri_specta::collect_events![LogEvent]);
|
.events(tauri_specta::collect_events![LogEvent]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
pub mod log_level;
|
pub mod log_level;
|
||||||
pub mod qrcode_data;
|
pub mod qrcode_data;
|
||||||
|
pub mod qrcode_status;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ async function greet() {
|
|||||||
async function test() {
|
async function test() {
|
||||||
const result = await commands.generateQrcode()
|
const result = await commands.generateQrcode()
|
||||||
console.log(result)
|
console.log(result)
|
||||||
|
if (result.status === 'ok') {
|
||||||
|
const result2 = await commands.getQrcodeStatus(result.data.qrcode_key)
|
||||||
|
console.log(result2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,14 @@ async generateQrcode() : Promise<Result<QrcodeData, CommandError>> {
|
|||||||
if(e instanceof Error) throw e;
|
if(e instanceof Error) throw e;
|
||||||
else return { status: "error", error: e as any };
|
else return { status: "error", error: e as any };
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async getQrcodeStatus(qrcodeKey: string) : Promise<Result<QrcodeStatus, CommandError>> {
|
||||||
|
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 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 LogLevel = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR"
|
||||||
export type QrcodeData = { url: string; qrcode_key: string }
|
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 **/
|
/** tauri-specta globals **/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user