mirror of
https://github.com/lanyeeee/bilibili-video-downloader.git
synced 2026-09-05 23:57:23 +08:00
feat: 后端支持搜索
This commit is contained in:
@@ -7,14 +7,30 @@ use crate::{
|
||||
extensions::AppHandleExt,
|
||||
logger,
|
||||
types::{
|
||||
bangumi_info::BangumiInfo, bangumi_media_url::BangumiMediaUrl, cheese_info::CheeseInfo,
|
||||
cheese_media_url::CheeseMediaUrl, create_download_task_params::CreateDownloadTaskParams,
|
||||
fav_folders::FavFolders, fav_info::FavInfo, get_bangumi_info_params::GetBangumiInfoParams,
|
||||
get_cheese_info_params::GetCheeseInfoParams, get_fav_info_params::GetFavInfoParams,
|
||||
bangumi_info::{BangumiInfo, EpInBangumi},
|
||||
bangumi_media_url::BangumiMediaUrl,
|
||||
cheese_info::CheeseInfo,
|
||||
cheese_media_url::CheeseMediaUrl,
|
||||
create_download_task_params::CreateDownloadTaskParams,
|
||||
fav_folders::FavFolders,
|
||||
fav_info::FavInfo,
|
||||
get_bangumi_info_params::GetBangumiInfoParams,
|
||||
get_cheese_info_params::GetCheeseInfoParams,
|
||||
get_fav_info_params::GetFavInfoParams,
|
||||
get_normal_info_params::GetNormalInfoParams,
|
||||
get_user_video_info_params::GetUserVideoInfoParams, normal_info::NormalInfo,
|
||||
normal_media_url::NormalMediaUrl, player_info::PlayerInfo, qrcode_data::QrcodeData,
|
||||
qrcode_status::QrcodeStatus, user_info::UserInfo, user_video_info::UserVideoInfo,
|
||||
get_user_video_info_params::GetUserVideoInfoParams,
|
||||
normal_info::NormalInfo,
|
||||
normal_media_url::NormalMediaUrl,
|
||||
player_info::PlayerInfo,
|
||||
qrcode_data::QrcodeData,
|
||||
qrcode_status::QrcodeStatus,
|
||||
search_params::SearchParams,
|
||||
search_result::{
|
||||
BangumiSearchResult, CheeseSearchResult, FavSearchResult, NormalSearchResult,
|
||||
SearchResult, UserVideoSearchResult,
|
||||
},
|
||||
user_info::UserInfo,
|
||||
user_video_info::UserVideoInfo,
|
||||
watch_later_info::WatchLaterInfo,
|
||||
},
|
||||
};
|
||||
@@ -291,3 +307,74 @@ pub fn restore_download_tasks(app: AppHandle) -> CommandResult<()> {
|
||||
tracing::debug!("恢复下载任务成功");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[specta::specta]
|
||||
pub async fn search(app: AppHandle, params: SearchParams) -> CommandResult<SearchResult> {
|
||||
use SearchParams::{Bangumi, Cheese, Fav, Normal, UserVideo};
|
||||
let bili_client = app.get_bili_client();
|
||||
let search_result = match params {
|
||||
Normal(params) => {
|
||||
let info = bili_client
|
||||
.get_normal_info(params)
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取普通视频信息失败", err))?;
|
||||
SearchResult::Normal(NormalSearchResult(info))
|
||||
}
|
||||
Bangumi(GetBangumiInfoParams::EpId(ep_id)) => {
|
||||
let info = bili_client
|
||||
.get_bangumi_info(GetBangumiInfoParams::EpId(ep_id))
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取番剧视频信息失败", err))?;
|
||||
let episodes: Vec<&EpInBangumi> = info
|
||||
.episodes
|
||||
.iter()
|
||||
.chain(
|
||||
info.section
|
||||
.iter()
|
||||
.flat_map(|sections| sections.iter())
|
||||
.flat_map(|section| section.episodes.iter()),
|
||||
)
|
||||
.collect();
|
||||
let ep = episodes.iter().find(|ep| ep.id == ep_id).copied().cloned();
|
||||
SearchResult::Bangumi(BangumiSearchResult { ep, info })
|
||||
}
|
||||
Bangumi(GetBangumiInfoParams::SeasonId(season_id)) => {
|
||||
let info = bili_client
|
||||
.get_bangumi_info(GetBangumiInfoParams::SeasonId(season_id))
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取番剧视频信息失败", err))?;
|
||||
SearchResult::Bangumi(BangumiSearchResult { ep: None, info })
|
||||
}
|
||||
Cheese(GetCheeseInfoParams::EpId(ep_id)) => {
|
||||
let info = bili_client
|
||||
.get_cheese_info(GetCheeseInfoParams::EpId(ep_id))
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取课程视频信息失败", err))?;
|
||||
let ep = info.episodes.iter().find(|ep| ep.id == ep_id).cloned();
|
||||
SearchResult::Cheese(CheeseSearchResult { ep, info })
|
||||
}
|
||||
Cheese(GetCheeseInfoParams::SeasonId(season_id)) => {
|
||||
let info = bili_client
|
||||
.get_cheese_info(GetCheeseInfoParams::SeasonId(season_id))
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取课程视频信息失败", err))?;
|
||||
SearchResult::Cheese(CheeseSearchResult { ep: None, info })
|
||||
}
|
||||
UserVideo(params) => {
|
||||
let info = bili_client
|
||||
.get_user_video_info(params)
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取用户视频信息失败", err))?;
|
||||
SearchResult::UserVideo(UserVideoSearchResult(info))
|
||||
}
|
||||
Fav(params) => {
|
||||
let info = bili_client
|
||||
.get_fav_info(params)
|
||||
.await
|
||||
.map_err(|err| CommandError::from("获取收藏夹内容失败", err))?;
|
||||
SearchResult::Fav(FavSearchResult(info))
|
||||
}
|
||||
};
|
||||
Ok(search_result)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ pub fn run() {
|
||||
delete_download_tasks,
|
||||
restart_download_tasks,
|
||||
restore_download_tasks,
|
||||
search,
|
||||
])
|
||||
.events(tauri_specta::collect_events![LogEvent, DownloadEvent]);
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ pub mod normal_media_url;
|
||||
pub mod player_info;
|
||||
pub mod qrcode_data;
|
||||
pub mod qrcode_status;
|
||||
pub mod search_params;
|
||||
pub mod search_result;
|
||||
pub mod subtitle;
|
||||
pub mod tags;
|
||||
pub mod user_info;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
use super::{
|
||||
get_bangumi_info_params::GetBangumiInfoParams, get_cheese_info_params::GetCheeseInfoParams,
|
||||
get_fav_info_params::GetFavInfoParams, get_normal_info_params::GetNormalInfoParams,
|
||||
get_user_video_info_params::GetUserVideoInfoParams,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub enum SearchParams {
|
||||
Normal(GetNormalInfoParams),
|
||||
Bangumi(GetBangumiInfoParams),
|
||||
Cheese(GetCheeseInfoParams),
|
||||
UserVideo(GetUserVideoInfoParams),
|
||||
Fav(GetFavInfoParams),
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
use super::{
|
||||
bangumi_info::{self, BangumiInfo},
|
||||
cheese_info::{self, CheeseInfo},
|
||||
fav_info::FavInfo,
|
||||
normal_info::NormalInfo,
|
||||
user_video_info::UserVideoInfo,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub enum SearchResult {
|
||||
Normal(NormalSearchResult),
|
||||
Bangumi(BangumiSearchResult),
|
||||
Cheese(CheeseSearchResult),
|
||||
UserVideo(UserVideoSearchResult),
|
||||
Fav(FavSearchResult),
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct NormalSearchResult(pub NormalInfo);
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct BangumiSearchResult {
|
||||
pub ep: Option<bangumi_info::EpInBangumi>,
|
||||
pub info: BangumiInfo,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct CheeseSearchResult {
|
||||
pub ep: Option<cheese_info::EpInCheese>,
|
||||
pub info: CheeseInfo,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct UserVideoSearchResult(pub UserVideoInfo);
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Type)]
|
||||
pub struct FavSearchResult(pub FavInfo);
|
||||
+16
-1
@@ -153,6 +153,14 @@ async restoreDownloadTasks() : Promise<Result<null, CommandError>> {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async search(params: SearchParams) : Promise<Result<SearchResult, CommandError>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("search", { params }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,8 +191,9 @@ export type AudioTask = { selected: boolean; url: string; audio_quality: AudioQu
|
||||
export type Author = { mid: number; name: string; face: string }
|
||||
export type AvatarIcon = { icon_resource: IconResource }
|
||||
export type BadgeInfo = { bg_color: string; bg_color_night: string; text: string }
|
||||
export type BangumiMediaUrl = { accept_format: string; code: number; seek_param: string; is_preview: number; fnval: number; video_project: boolean; fnver: number; type: string; bp: number; seek_type: string; result: string; vip_type: number | null; from: string; video_codecid: number; record_info: RecordInfo | null; is_drm: boolean; no_rexcode: number; format: string; support_formats: SupportFormatInBangumi[]; message: string; accept_quality: number[]; quality: number; timelength: number; durls: DurlInBangumi[]; has_paid: boolean; vip_status: number | null; error_code: number; dash: DashInBangumi | null; clip_info_list: ClipInfoList[]; accept_description: string[]; status: number }
|
||||
export type BangumiInfo = { activity: Activity; actors: string; alias: string; areas: Area[]; bkg_cover: string; cover: string; delivery_fragment_video: boolean; enable_vt: boolean; episodes: EpInBangumi[]; evaluate: string; hide_ep_vv_vt_dm: number; icon_font: IconFont; jp_title: string; link: string; media_id: number; mode: number; new_ep: NewEp; payment: PaymentInBangumi | null; play_strategy: PlayStrategy | null; positive: Positive; publish: Publish; rating: Rating | null; record: string; rights: RightsInBangumi; season_id: number; season_title: string; seasons: Season[]; section: SectionInBangumi[] | null; series: Series; share_copy: string; share_sub_title: string; share_url: string; show: Show; show_season_type: number; square_cover: string; staff: string; stat: StatInBangumi; status: number; styles: string[]; subtitle: string; title: string; total: number; type: number; up_info: UpInfoInBangumi | null; user_status: UserStatusInBangumi }
|
||||
export type BangumiMediaUrl = { accept_format: string; code: number; seek_param: string; is_preview: number; fnval: number; video_project: boolean; fnver: number; type: string; bp: number; seek_type: string; result: string; vip_type: number | null; from: string; video_codecid: number; record_info: RecordInfo | null; is_drm: boolean; no_rexcode: number; format: string; support_formats: SupportFormatInBangumi[]; message: string; accept_quality: number[]; quality: number; timelength: number; durls: DurlInBangumi[]; has_paid: boolean; vip_status: number | null; error_code: number; dash: DashInBangumi | null; clip_info_list: ClipInfoList[]; accept_description: string[]; status: number }
|
||||
export type BangumiSearchResult = { ep: EpInBangumi | null; info: BangumiInfo }
|
||||
export type Brief = { content: string; img: Img[]; title: string; type: number }
|
||||
export type CanvasConfig = {
|
||||
/**
|
||||
@@ -243,6 +252,7 @@ outline: number;
|
||||
time_offset: number }
|
||||
export type CheeseInfo = { abtest_info: AbtestInfo; be_subscription: boolean; brief: Brief; consulting: Consulting; cooperation: Cooperation; course_content: string; cover: string; ep_count: number; episode_page: EpPage; episode_sort: number; episode_tag: EpTag; episodes: EpInCheese[]; expiry_day: number; expiry_info_content: string; faq: Faq; faq1: Faq1; is_enable_cash: boolean; is_series: boolean; live_ep_count: number; opened_ep_count: number; paid_jump: PaidJump; paid_view: boolean; payment: Payment; previewed_purchase_note: PreviewedPurchaseNote; purchase_format_note: PurchaseFormatNote; purchase_note: PurchaseNote; purchase_protocol: PurchaseProtocol; recommend_seasons: RecommendSeason[]; release_bottom_info: string; release_info: string; release_info2: string; release_status: string; season_id: number; season_tag: number; share_url: string; short_link: string; show_watermark: boolean; stat: StatInCheese; status: number; stop_sell: boolean; subscription_update_count_cycle_text: string; subtitle: string; title: string; up_info: UpInfoInCheese; update_status: number; user_status: UserStatusInCheese; watermark_interval: number }
|
||||
export type CheeseMediaUrl = { accept_format: string; code: number; seek_param: string; is_preview: number; fnval: number; video_project: boolean; play_view_business_info: PlayViewBusinessInfo | null; fnver: number; type: string; result: string; seek_type: string; from: string; video_codecid: number; no_rexcode: number; format: string; support_formats: SupportFormatInCheese[]; message: string; accept_quality: number[]; quality: number; timelength: number; durls: DurlInCheese[]; has_paid: boolean; dash: DashInCheese | null; accept_description: string[]; status: number }
|
||||
export type CheeseSearchResult = { ep: EpInCheese | null; info: CheeseInfo }
|
||||
export type ClipInfoList = { materialNo: number; start: number; end: number; toastText: string; clipType: string }
|
||||
export type CntInfo = { collect: number; play: number; thumb_up: number; share: number }
|
||||
export type CntInfoInMedia = { collect: number; play: number; danmaku: number; vt: number; play_switch: number; reply: number; view_text_1: string }
|
||||
@@ -287,6 +297,7 @@ export type Faq1 = { items: Faq1Item[]; title: string }
|
||||
export type Faq1Item = { answer: string; question: string }
|
||||
export type FavFolders = { count: number; list: Folder[] }
|
||||
export type FavInfo = { info: Info; medias: MediaInFav[] | null; has_more: boolean; ttl: number }
|
||||
export type FavSearchResult = FavInfo
|
||||
export type Fawkes = { config_version: number; ff_version: number }
|
||||
export type Flac = { display: boolean; audio: MediaInNormal | null }
|
||||
export type Folder = { id: number; fid: number; mid: number; attr: number; title: string; fav_state: number; media_count: number }
|
||||
@@ -323,6 +334,7 @@ export type NewEpInSeason = { cover: string; id: number; index_show: string }
|
||||
export type NfoTask = { selected: boolean; completed: boolean }
|
||||
export type NormalInfo = { bvid: string; aid: number; videos: number; tid: number; tid_v2: number; tname: string; tname_v2: string; copyright: number; pic: string; title: string; pubdate: number; ctime: number; desc: string; desc_v2: DescV2[] | null; state: number; duration: number; rights: Rights; owner: OwnerInNormal; stat: StatInNormal; argue_info: ArgueInfo; dynamic: string; cid: number; dimension: Dimension; teenage_mode: number; is_chargeable_season: boolean; is_story: boolean; is_upower_exclusive: boolean; is_upower_play: boolean; is_upower_preview: boolean; enable_vt: number; vt_display: string; is_upower_exclusive_with_qa: boolean; no_cache: boolean; pages: PageInNormal[]; subtitle: SubtitleInNormal; staff: Staff[] | null; ugc_season: UgcSeason | null; is_season_display: boolean; user_garb: UserGarb; honor_reply: HonorReply; like_icon: string; need_jump_bv: boolean; disable_show_up_info: boolean; is_story_play: number; is_view_self: boolean }
|
||||
export type NormalMediaUrl = { from: string; result: string; message: string; quality: number; format: string; timelength: number; accept_format: string; accept_description: string[]; accept_quality: number[]; video_codecid: number; seek_param: string; seek_type: string; dash: DashInNormal; support_formats: SupportFormatInNormal[]; last_play_time: number; last_play_cid: number; play_conf: PlayConf }
|
||||
export type NormalSearchResult = NormalInfo
|
||||
export type Official = { role: number; title: string; desc: string; type: number }
|
||||
export type OfficialVerify = { type: number; desc: string }
|
||||
export type OnlineSwitch = { enable_gray_dash_playback: string; new_broadcast: string; realtime_dm: string; subtitle_submit_switch: string }
|
||||
@@ -363,6 +375,8 @@ export type RightsInBangumi = { allow_bp: number; allow_bp_rank: number; allow_d
|
||||
export type RightsInBangumiEp = { allow_dm: number; allow_download: number; area_limit: number }
|
||||
export type RightsInNormalEp = { bp: number; elec: number; download: number; movie: number; pay: number; hd5: number; no_reprint: number; autoplay: number; ugc_pay: number; is_cooperation: number; ugc_pay_preview: number; arc_pay: number; free_watch: number }
|
||||
export type RightsInWatchLater = { bp: number; elec: number; download: number; movie: number; pay: number; hd5: number; no_reprint: number; autoplay: number; ugc_pay: number; is_cooperation: number; ugc_pay_preview: number; no_background: number; arc_pay: number; pay_free_watch: number }
|
||||
export type SearchParams = { Normal: GetNormalInfoParams } | { Bangumi: GetBangumiInfoParams } | { Cheese: GetCheeseInfoParams } | { UserVideo: GetUserVideoInfoParams } | { Fav: GetFavInfoParams }
|
||||
export type SearchResult = { Normal: NormalSearchResult } | { Bangumi: BangumiSearchResult } | { Cheese: CheeseSearchResult } | { UserVideo: UserVideoSearchResult } | { Fav: FavSearchResult }
|
||||
export type Season = { badge: string; badge_info: BadgeInfo; badge_type: number; cover: string; enable_vt: boolean; horizontal_cover_1610: string; horizontal_cover_169: string; icon_font: IconFont; media_id: number; new_ep: NewEpInSeason; season_id: number; season_title: string; season_type: number; stat: StatInSeason }
|
||||
export type SectionInBangumi = { attr: number; episodes: EpInBangumi[]; id: number; title: string; type: number; type2: number }
|
||||
export type SectionInNormal = { season_id: number; id: number; title: string; type: number; episodes: EpInNormal[] }
|
||||
@@ -403,6 +417,7 @@ export type UserStatusInCheese = { bp: number; expire_at: number; favored: numbe
|
||||
export type UserStatusInCheeseUrl = { watch_progress: WatchProgress }
|
||||
export type UserVideoInfo = { list: UserVideoList; page: PageInUserVideo }
|
||||
export type UserVideoList = { vlist: EpInUserVideo[] }
|
||||
export type UserVideoSearchResult = UserVideoInfo
|
||||
export type VideoQuality = "Unknown" | "240P" | "360P" | "480P" | "720P" | "720P60" | "1080P" | "AiRepair" | "1080P+" | "1080P60" | "4K" | "HDR" | "Dolby" | "8K"
|
||||
export type VideoTask = { selected: boolean; url: string; video_quality: VideoQuality; codec_type: CodecType; content_length: number; chunks: MediaChunk[]; completed: boolean }
|
||||
export type ViewPoint = { type: number; from: number; to: number; content: string; img_url: string | null; logo_url: string | null; team_type: string; team_name: string }
|
||||
|
||||
Reference in New Issue
Block a user