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:
@@ -18,8 +18,8 @@ use crate::{
|
||||
bangumi_info::BangumiInfo, bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo,
|
||||
cheese_media_url::CheeseMediaUrl, get_bangumi_info_params::GetBangumiInfoParams,
|
||||
get_cheese_info_params::GetCheeseInfoParams, get_normal_info_params::GetNormalInfoParams,
|
||||
normal_info::NormalInfo, normal_media_url::NormalMediaUrl, qrcode_data::QrcodeData,
|
||||
qrcode_status::QrcodeStatus, user_info::UserInfo,
|
||||
normal_info::NormalInfo, normal_media_url::NormalMediaUrl, player_info::PlayerInfo,
|
||||
qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -386,6 +386,44 @@ impl BiliClient {
|
||||
Ok(media_url)
|
||||
}
|
||||
|
||||
pub async fn get_player_info(&self, aid: i64, cid: i64) -> anyhow::Result<PlayerInfo> {
|
||||
let params = json!({
|
||||
"aid": aid,
|
||||
"cid": cid,
|
||||
});
|
||||
// 发送获取播放器信息的请求
|
||||
let request = self
|
||||
.api_client
|
||||
.read()
|
||||
.get("https://api.bilibili.com/x/player/wbi/v2")
|
||||
.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 != 0 {
|
||||
return Err(anyhow!("预料之外的code: {bili_resp:?}"));
|
||||
}
|
||||
// 检查BiliResp的data是否存在
|
||||
let Some(data) = bili_resp.data else {
|
||||
return Err(anyhow!("BiliResp中不存在data字段: {bili_resp:?}"));
|
||||
};
|
||||
// 尝试将data解析为PlayerInfo
|
||||
let data_str = data.to_string();
|
||||
let player_info: PlayerInfo = serde_json::from_str(&data_str)
|
||||
.context(format!("将data解析为PlayerInfo失败: {data_str}"))?;
|
||||
|
||||
Ok(player_info)
|
||||
}
|
||||
|
||||
fn get_cookie(&self) -> String {
|
||||
let sessdata = self.app.get_config().read().sessdata.clone();
|
||||
format!("SESSDATA={sessdata}")
|
||||
|
||||
@@ -7,7 +7,11 @@ use crate::{
|
||||
extensions::AppHandleExt,
|
||||
logger,
|
||||
types::{
|
||||
bangumi_info::BangumiInfo, bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo, cheese_media_url::CheeseMediaUrl, get_bangumi_info_params::GetBangumiInfoParams, get_cheese_info_params::GetCheeseInfoParams, get_normal_info_params::GetNormalInfoParams, normal_info::NormalInfo, normal_media_url::NormalMediaUrl, qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo
|
||||
bangumi_info::BangumiInfo, bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo,
|
||||
cheese_media_url::CheeseMediaUrl, get_bangumi_info_params::GetBangumiInfoParams,
|
||||
get_cheese_info_params::GetCheeseInfoParams, get_normal_info_params::GetNormalInfoParams,
|
||||
normal_info::NormalInfo, normal_media_url::NormalMediaUrl, player_info::PlayerInfo,
|
||||
qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -172,3 +176,14 @@ pub async fn get_cheese_url(app: AppHandle, ep_id: i64) -> CommandResult<CheeseM
|
||||
.map_err(|err| CommandError::from("获取课程视频url失败", err))?;
|
||||
Ok(media_url)
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[specta::specta]
|
||||
pub async fn get_player_info(app: AppHandle, aid: i64, cid: i64) -> CommandResult<PlayerInfo> {
|
||||
let bili_client = app.get_bili_client();
|
||||
let player_info = bili_client
|
||||
.get_player_info(aid, cid)
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取播放器信息失败", err))?;
|
||||
Ok(player_info)
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ pub fn run() {
|
||||
get_normal_url,
|
||||
get_bangumi_url,
|
||||
get_cheese_url,
|
||||
get_player_info,
|
||||
])
|
||||
.events(tauri_specta::collect_events![LogEvent]);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ pub mod get_normal_info_params;
|
||||
pub mod log_level;
|
||||
pub mod normal_info;
|
||||
pub mod normal_media_url;
|
||||
pub mod player_info;
|
||||
pub mod qrcode_data;
|
||||
pub mod qrcode_status;
|
||||
pub mod user_info;
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct PlayerInfo {
|
||||
pub aid: i64,
|
||||
pub bvid: String,
|
||||
pub allow_bp: bool,
|
||||
pub no_share: bool,
|
||||
pub cid: i64,
|
||||
pub max_limit: i64,
|
||||
pub page_no: i64,
|
||||
pub has_next: bool,
|
||||
pub ip_info: IpInfo,
|
||||
pub login_mid: i64,
|
||||
pub login_mid_hash: String,
|
||||
pub is_owner: bool,
|
||||
pub name: String,
|
||||
pub permission: String,
|
||||
pub level_info: LevelInfoInPlayerInfo,
|
||||
pub vip: VipInPlayerInfo,
|
||||
pub answer_status: i64,
|
||||
pub block_time: i64,
|
||||
pub role: String,
|
||||
pub last_play_time: i64,
|
||||
pub last_play_cid: i64,
|
||||
pub now_time: i64,
|
||||
pub online_count: i64,
|
||||
pub need_login_subtitle: bool,
|
||||
pub subtitle: SubtitleInPlayerInfo,
|
||||
pub view_points: Vec<ViewPoint>,
|
||||
pub preview_toast: String,
|
||||
pub options: Options,
|
||||
pub online_switch: OnlineSwitch,
|
||||
pub fawkes: Fawkes,
|
||||
pub show_switch: ShowSwitch,
|
||||
pub toast_block: bool,
|
||||
pub is_upower_exclusive: bool,
|
||||
pub is_upower_play: bool,
|
||||
pub is_ugc_pay_preview: bool,
|
||||
pub elec_high_level: ElecHighLevel,
|
||||
pub disable_show_up_info: bool,
|
||||
pub is_upower_exclusive_with_qa: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct IpInfo {
|
||||
pub ip: String,
|
||||
pub zone_ip: String,
|
||||
pub zone_id: i64,
|
||||
pub country: String,
|
||||
pub province: String,
|
||||
pub city: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct LevelInfoInPlayerInfo {
|
||||
pub current_level: i64,
|
||||
pub current_min: i64,
|
||||
pub current_exp: i64,
|
||||
pub next_exp: i64,
|
||||
pub level_up: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
pub struct VipInPlayerInfo {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
pub status: i64,
|
||||
pub due_date: i64,
|
||||
pub vip_pay_type: i64,
|
||||
pub theme_type: i64,
|
||||
pub label: LabelInPlayerInfo,
|
||||
pub avatar_subscript: i64,
|
||||
pub nickname_color: String,
|
||||
pub role: i64,
|
||||
pub avatar_subscript_url: String,
|
||||
pub tv_vip_status: i64,
|
||||
pub tv_vip_pay_type: i64,
|
||||
pub tv_due_date: i64,
|
||||
pub avatar_icon: AvatarIcon,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
pub struct LabelInPlayerInfo {
|
||||
pub path: String,
|
||||
pub text: String,
|
||||
pub label_theme: String,
|
||||
pub text_color: String,
|
||||
pub bg_style: i64,
|
||||
pub bg_color: String,
|
||||
pub border_color: String,
|
||||
pub use_img_label: bool,
|
||||
pub img_label_uri_hans: String,
|
||||
pub img_label_uri_hant: String,
|
||||
pub img_label_uri_hans_static: String,
|
||||
pub img_label_uri_hant_static: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct AvatarIcon {
|
||||
pub icon_resource: IconResource,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct IconResource {}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct SubtitleInPlayerInfo {
|
||||
pub allow_submit: bool,
|
||||
pub lan: String,
|
||||
pub lan_doc: String,
|
||||
pub subtitles: Vec<SubtitleDetailInPlayerInfo>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct SubtitleDetailInPlayerInfo {
|
||||
pub id: i64,
|
||||
pub lan: String,
|
||||
pub lan_doc: String,
|
||||
pub is_lock: bool,
|
||||
pub subtitle_url: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
pub id_str: String,
|
||||
pub ai_type: i64,
|
||||
pub ai_status: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct ViewPoint {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
pub from: i64,
|
||||
pub to: i64,
|
||||
pub content: String,
|
||||
pub img_url: Option<String>,
|
||||
pub logo_url: Option<String>,
|
||||
pub team_type: String,
|
||||
pub team_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Options {
|
||||
pub is_360: bool,
|
||||
pub without_vip: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct OnlineSwitch {
|
||||
pub enable_gray_dash_playback: String,
|
||||
pub new_broadcast: String,
|
||||
pub realtime_dm: String,
|
||||
pub subtitle_submit_switch: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Fawkes {
|
||||
pub config_version: i64,
|
||||
pub ff_version: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct ShowSwitch {
|
||||
pub long_progress: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct ElecHighLevel {
|
||||
pub privilege_type: i64,
|
||||
pub title: String,
|
||||
pub sub_title: String,
|
||||
pub show_button: bool,
|
||||
pub button_text: String,
|
||||
pub jump_url: String,
|
||||
pub intro: String,
|
||||
pub new: bool,
|
||||
pub question_text: String,
|
||||
pub qa_title: String,
|
||||
}
|
||||
Reference in New Issue
Block a user