mirror of
https://github.com/lanyeeee/bilibili-video-downloader.git
synced 2026-09-09 01:27:27 +08:00
feat: 后端支持获取课程视频信息
This commit is contained in:
@@ -15,7 +15,8 @@ use tauri::{
|
||||
use crate::{
|
||||
extensions::AppHandleExt,
|
||||
types::{
|
||||
bangumi_info::BangumiInfo, get_bangumi_info_params::GetBangumiInfoParams,
|
||||
bangumi_info::BangumiInfo, cheese_info::CheeseInfo,
|
||||
get_bangumi_info_params::GetBangumiInfoParams, get_cheese_info_params::GetCheeseInfoParams,
|
||||
get_normal_info_params::GetNormalInfoParams, normal_info::NormalInfo,
|
||||
qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo,
|
||||
},
|
||||
@@ -221,6 +222,45 @@ impl BiliClient {
|
||||
Ok(bangumi_info)
|
||||
}
|
||||
|
||||
pub async fn get_cheese_info(&self, params: GetCheeseInfoParams) -> anyhow::Result<CheeseInfo> {
|
||||
use GetCheeseInfoParams::{EpId, SeasonId};
|
||||
let params = match params {
|
||||
EpId(ep_id) => json!({"ep_id": ep_id}),
|
||||
SeasonId(season_id) => json!({"season_id": season_id}),
|
||||
};
|
||||
// 发送获取课程视频信息的请求
|
||||
let request = self
|
||||
.api_client
|
||||
.read()
|
||||
.get("https://api.bilibili.com/pugv/view/web/season")
|
||||
.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解析为CheeseInfo
|
||||
let data_str = data.to_string();
|
||||
let cheese_info: CheeseInfo = serde_json::from_str(&data_str)
|
||||
.context(format!("将data解析为CheeseInfo失败: {data_str}"))?;
|
||||
|
||||
Ok(cheese_info)
|
||||
}
|
||||
|
||||
fn get_cookie(&self) -> String {
|
||||
let sessdata = self.app.get_config().read().sessdata.clone();
|
||||
format!("SESSDATA={sessdata}")
|
||||
|
||||
@@ -7,7 +7,10 @@ use crate::{
|
||||
extensions::AppHandleExt,
|
||||
logger,
|
||||
types::{
|
||||
bangumi_info::BangumiInfo, get_bangumi_info_params::GetBangumiInfoParams, get_normal_info_params::GetNormalInfoParams, normal_info::NormalInfo, qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo
|
||||
bangumi_info::BangumiInfo, cheese_info::CheeseInfo,
|
||||
get_bangumi_info_params::GetBangumiInfoParams, get_cheese_info_params::GetCheeseInfoParams,
|
||||
get_normal_info_params::GetNormalInfoParams, normal_info::NormalInfo,
|
||||
qrcode_data::QrcodeData, qrcode_status::QrcodeStatus, user_info::UserInfo,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -121,3 +124,17 @@ pub async fn get_bangumi_info(
|
||||
.map_err(|err| CommandError::from("获取番剧视频信息失败", err))?;
|
||||
Ok(bangumi_info)
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[specta::specta]
|
||||
pub async fn get_cheese_info(
|
||||
app: AppHandle,
|
||||
params: GetCheeseInfoParams,
|
||||
) -> CommandResult<CheeseInfo> {
|
||||
let bili_client = app.get_bili_client();
|
||||
let cheese_info = bili_client
|
||||
.get_cheese_info(params)
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取课程视频信息失败", err))?;
|
||||
Ok(cheese_info)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ pub fn run() {
|
||||
get_user_info,
|
||||
get_normal_info,
|
||||
get_bangumi_info,
|
||||
get_cheese_info,
|
||||
])
|
||||
.events(tauri_specta::collect_events![LogEvent]);
|
||||
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct CheeseInfo {
|
||||
pub abtest_info: AbtestInfo,
|
||||
pub be_subscription: bool,
|
||||
pub brief: Brief,
|
||||
pub consulting: Consulting,
|
||||
pub cooperation: Cooperation,
|
||||
pub course_content: String,
|
||||
pub cover: String,
|
||||
pub ep_count: i64,
|
||||
pub episode_page: EpPage,
|
||||
pub episode_sort: i64,
|
||||
pub episode_tag: EpTag,
|
||||
pub episodes: Vec<EpInCheese>,
|
||||
pub expiry_day: i64,
|
||||
pub expiry_info_content: String,
|
||||
pub faq: Faq,
|
||||
pub faq1: Faq1,
|
||||
pub is_enable_cash: bool,
|
||||
pub is_series: bool,
|
||||
pub live_ep_count: i64,
|
||||
pub opened_ep_count: i64,
|
||||
pub paid_jump: PaidJump,
|
||||
pub paid_view: bool,
|
||||
pub payment: Payment,
|
||||
pub previewed_purchase_note: PreviewedPurchaseNote,
|
||||
pub purchase_format_note: PurchaseFormatNote,
|
||||
pub purchase_note: PurchaseNote,
|
||||
pub purchase_protocol: PurchaseProtocol,
|
||||
pub recommend_seasons: Vec<RecommendSeason>,
|
||||
pub release_bottom_info: String,
|
||||
pub release_info: String,
|
||||
pub release_info2: String,
|
||||
pub release_status: String,
|
||||
pub season_id: i64,
|
||||
pub season_tag: i64,
|
||||
pub share_url: String,
|
||||
pub short_link: String,
|
||||
pub show_watermark: bool,
|
||||
pub stat: StatInCheese,
|
||||
pub status: i64,
|
||||
pub stop_sell: bool,
|
||||
pub subscription_update_count_cycle_text: String,
|
||||
pub subtitle: String,
|
||||
pub title: String,
|
||||
pub up_info: UpInfoInCheese,
|
||||
pub update_status: i64,
|
||||
pub user_status: UserStatusInCheese,
|
||||
pub watermark_interval: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct AbtestInfo {
|
||||
pub style_abtest: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Brief {
|
||||
pub content: String,
|
||||
pub img: Vec<Img>,
|
||||
pub title: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Img {
|
||||
pub aspect_ratio: f64,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Consulting {
|
||||
pub consulting_flag: bool,
|
||||
pub consulting_url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Cooperation {
|
||||
pub link: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct EpPage {
|
||||
pub next: bool,
|
||||
pub num: i64,
|
||||
pub size: i64,
|
||||
pub total: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
pub struct EpTag {
|
||||
pub part_preview_tag: String,
|
||||
pub pay_tag: String,
|
||||
pub preview_tag: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
#[allow(clippy::struct_field_names)]
|
||||
pub struct EpInCheese {
|
||||
pub aid: i64,
|
||||
pub catalogue_index: i64,
|
||||
pub cid: i64,
|
||||
pub cover: String,
|
||||
pub duration: u64,
|
||||
pub ep_status: i64,
|
||||
pub episode_can_view: bool,
|
||||
pub from: String,
|
||||
pub id: i64,
|
||||
pub index: i64,
|
||||
pub label: Option<String>,
|
||||
pub page: i64,
|
||||
pub play: i64,
|
||||
pub play_way: i64,
|
||||
pub playable: bool,
|
||||
pub release_date: i64,
|
||||
pub show_vt: bool,
|
||||
pub status: i64,
|
||||
pub subtitle: String,
|
||||
pub title: String,
|
||||
pub watched: bool,
|
||||
#[serde(rename = "watchedHistory")]
|
||||
pub watched_history: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Faq {
|
||||
pub content: String,
|
||||
pub link: String,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Faq1 {
|
||||
pub items: Vec<Faq1Item>,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Faq1Item {
|
||||
pub answer: String,
|
||||
pub question: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PaidJump {
|
||||
pub jump_url_for_app: String,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct Payment {
|
||||
pub bp_enough: i64,
|
||||
pub desc: String,
|
||||
pub my_bp: i64,
|
||||
pub pay_shade: String,
|
||||
pub price: f64,
|
||||
pub price_format: String,
|
||||
pub price_unit: String,
|
||||
pub refresh_text: String,
|
||||
pub select_text: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PreviewedPurchaseNote {
|
||||
pub long_watch_text: String,
|
||||
pub pay_text: String,
|
||||
pub price_format: String,
|
||||
pub watch_text: String,
|
||||
pub watching_text: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PurchaseFormatNote {
|
||||
pub content_list: Vec<ContentList>,
|
||||
pub link: String,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct ContentList {
|
||||
pub bold: bool,
|
||||
pub content: String,
|
||||
pub number: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PurchaseNote {
|
||||
pub content: String,
|
||||
pub link: String,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PurchaseProtocol {
|
||||
pub link: String,
|
||||
pub title: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct RecommendSeason {
|
||||
pub cover: String,
|
||||
pub ep_count: String,
|
||||
pub id: i64,
|
||||
pub season_url: String,
|
||||
pub subtitle: String,
|
||||
pub title: String,
|
||||
pub view: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct StatInCheese {
|
||||
pub play: i64,
|
||||
pub play_desc: String,
|
||||
pub show_vt: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct UpInfoInCheese {
|
||||
pub avatar: String,
|
||||
pub brief: String,
|
||||
pub follower: i64,
|
||||
pub is_follow: i64,
|
||||
pub is_living: bool,
|
||||
pub link: String,
|
||||
pub mid: i64,
|
||||
pub pendant: PendantInCheese,
|
||||
pub season_count: i64,
|
||||
pub uname: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct PendantInCheese {
|
||||
pub image: String,
|
||||
pub name: String,
|
||||
pub pid: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct UserStatusInCheese {
|
||||
pub bp: i64,
|
||||
pub expire_at: i64,
|
||||
pub favored: i64,
|
||||
pub favored_count: i64,
|
||||
pub is_expired: bool,
|
||||
pub is_first_paid: bool,
|
||||
pub payed: i64,
|
||||
pub user_expiry_content: String,
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub enum GetCheeseInfoParams {
|
||||
EpId(i64),
|
||||
SeasonId(i64),
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod bangumi_info;
|
||||
pub mod cheese_info;
|
||||
pub mod get_bangumi_info_params;
|
||||
pub mod get_cheese_info_params;
|
||||
pub mod get_normal_info_params;
|
||||
pub mod log_level;
|
||||
pub mod normal_info;
|
||||
|
||||
Reference in New Issue
Block a user