From 89666f1559be234b68c4725f8d4574e5f761c2f2 Mon Sep 17 00:00:00 2001 From: lanyeeee Date: Fri, 6 Feb 2026 12:22:35 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=95=AA=E5=89=A7?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96`=E6=99=BA=E8=83=BD?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D`=E4=B8=8B=E8=BD=BD=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/bili_client.rs | 60 +++++++++++++++++++-- src-tauri/src/types/bangumi_media_url_v2.rs | 46 ++++++++++++++++ src-tauri/src/types/mod.rs | 1 + 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src-tauri/src/types/bangumi_media_url_v2.rs diff --git a/src-tauri/src/bili_client.rs b/src-tauri/src/bili_client.rs index 8af22ab..d0cdc68 100644 --- a/src-tauri/src/bili_client.rs +++ b/src-tauri/src/bili_client.rs @@ -22,9 +22,9 @@ use crate::{ protobuf::DmSegMobileReply, types::{ bangumi_follow_info::BangumiFollowInfo, bangumi_info::BangumiInfo, - bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo, - cheese_media_url::CheeseMediaUrl, fav_folders::FavFolders, fav_info::FavInfo, - get_bangumi_follow_info_params::GetBangumiFollowInfoParams, + bangumi_media_url::BangumiMediaUrl, bangumi_media_url_v2::BangumiMediaUrlV2, + cheese_info::CheeseInfo, cheese_media_url::CheeseMediaUrl, fav_folders::FavFolders, + fav_info::FavInfo, get_bangumi_follow_info_params::GetBangumiFollowInfoParams, get_bangumi_info_params::GetBangumiInfoParams, get_cheese_info_params::GetCheeseInfoParams, get_fav_info_params::GetFavInfoParams, get_history_info_params::GetHistoryInfoParams, get_normal_info_params::GetNormalInfoParams, @@ -399,6 +399,15 @@ impl BiliClient { } pub async fn get_bangumi_url(&self, cid: i64) -> anyhow::Result { + let media_url_v2 = self.get_bangumi_url_v2(cid).await?; + if media_url_v2.video_info.is_drm { + self.get_bangumi_url_v1(cid).await + } else { + Ok(media_url_v2.video_info) + } + } + + async fn get_bangumi_url_v1(&self, cid: i64) -> anyhow::Result { let params = json!({ "cid": cid, "qn": 127, @@ -442,6 +451,51 @@ impl BiliClient { Ok(media_url) } + async fn get_bangumi_url_v2(&self, cid: i64) -> anyhow::Result { + let params = json!({ + "cid": cid, + "qn": 127, + "fnval": 4048, + "drm_tech_type": 2, + "from_client": "BROWSER", + }); + // 发送获取番剧url的请求 + let request = self + .api_client + .read() + .get("https://api.bilibili.com/pgc/player/web/v2/playurl") + .query(¶ms) + .header("cookie", self.get_cookie()); + 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 == -10403 { + return Err(anyhow!( + "地区限制,请使用代理或切换线路后重试: {bili_resp:?}" + )); + } else 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解析为BangumiMediaUrlV2 + let data_str = data.to_string(); + let media_url: BangumiMediaUrlV2 = serde_json::from_str(&data_str) + .context(format!("将data解析为BangumiMediaUrlV2失败: {data_str}"))?; + + Ok(media_url) + } + pub async fn get_cheese_url(&self, ep_id: i64) -> anyhow::Result { let params = json!({ "ep_id": ep_id, diff --git a/src-tauri/src/types/bangumi_media_url_v2.rs b/src-tauri/src/types/bangumi_media_url_v2.rs new file mode 100644 index 0000000..c02c074 --- /dev/null +++ b/src-tauri/src/types/bangumi_media_url_v2.rs @@ -0,0 +1,46 @@ +use serde::{Deserialize, Serialize}; +use specta::Type; + +use crate::types::bangumi_media_url::BangumiMediaUrl; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +#[serde(default)] +pub struct BangumiMediaUrlV2 { + pub play_view_business_info: PlayViewBusinessInfo, + pub video_info: BangumiMediaUrl, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +#[serde(default)] +pub struct PlayViewBusinessInfo { + pub episode_info: EpisodeInfoInBangumi, + pub season_info: SeasonInfoInBangumi, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +#[serde(default)] +pub struct EpisodeInfoInBangumi { + pub aid: i64, + pub bvid: String, + pub cid: i64, + pub delivery_business_fragment_video: bool, + pub delivery_fragment_video: bool, + pub ep_id: i64, + pub ep_status: i64, + pub interaction: Interaction, + pub long_title: String, + pub title: String, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +#[serde(default)] +pub struct Interaction { + pub interaction: bool, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +#[serde(default)] +pub struct SeasonInfoInBangumi { + pub season_id: i64, + pub season_type: i64, +} diff --git a/src-tauri/src/types/mod.rs b/src-tauri/src/types/mod.rs index 6f2281d..68e0bb7 100644 --- a/src-tauri/src/types/mod.rs +++ b/src-tauri/src/types/mod.rs @@ -3,6 +3,7 @@ pub mod available_media_formats; pub mod bangumi_follow_info; pub mod bangumi_info; pub mod bangumi_media_url; +pub mod bangumi_media_url_v2; pub mod cheese_info; pub mod cheese_media_url; pub mod codec_type;