From c9dd7139ff18a14cade9fcaa0f4565756d0929b0 Mon Sep 17 00:00:00 2001 From: lanyeeee Date: Tue, 15 Jul 2025 06:15:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8E=E7=AB=AF=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=AF=BE=E7=A8=8B=E8=A7=86=E9=A2=91=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/bili_client.rs | 42 ++- src-tauri/src/commands.rs | 19 +- src-tauri/src/lib.rs | 1 + src-tauri/src/types/cheese_info.rs | 255 ++++++++++++++++++ src-tauri/src/types/get_cheese_info_params.rs | 8 + src-tauri/src/types/mod.rs | 2 + src/bindings.ts | 33 +++ 7 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 src-tauri/src/types/cheese_info.rs create mode 100644 src-tauri/src/types/get_cheese_info_params.rs diff --git a/src-tauri/src/bili_client.rs b/src-tauri/src/bili_client.rs index 3f824ef..4d45d3f 100644 --- a/src-tauri/src/bili_client.rs +++ b/src-tauri/src/bili_client.rs @@ -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 { + 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}") diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index cd71254..1c69d88 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -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 { + 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) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 9cf6831..18cf368 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -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]); diff --git a/src-tauri/src/types/cheese_info.rs b/src-tauri/src/types/cheese_info.rs new file mode 100644 index 0000000..779283d --- /dev/null +++ b/src-tauri/src/types/cheese_info.rs @@ -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, + 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, + 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, + 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, + 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, + 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, + 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, +} diff --git a/src-tauri/src/types/get_cheese_info_params.rs b/src-tauri/src/types/get_cheese_info_params.rs new file mode 100644 index 0000000..2a31745 --- /dev/null +++ b/src-tauri/src/types/get_cheese_info_params.rs @@ -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), +} diff --git a/src-tauri/src/types/mod.rs b/src-tauri/src/types/mod.rs index d10fd9f..2b44dbc 100644 --- a/src-tauri/src/types/mod.rs +++ b/src-tauri/src/types/mod.rs @@ -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; diff --git a/src/bindings.ts b/src/bindings.ts index dbdec0f..e5b6f9a 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -58,6 +58,14 @@ async getBangumiInfo(params: GetBangumiInfoParams) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("get_cheese_info", { params }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} } } @@ -76,6 +84,7 @@ logEvent: "log-event" /** user-defined types **/ +export type AbtestInfo = { style_abtest: number } export type Activity = { head_bg_url: string; id: number; title: string } export type Arc = { aid: number; videos: number; type_id: number; type_name: string; copyright: number; pic: string; title: string; pubdate: number; ctime: number; desc: string; state: number; duration: number; rights: RightsInNormalEp; author: Author; stat: StatInNormalEp; dynamic: string; dimension: Dimension; is_chargeable_season: boolean; is_blooper: boolean; enable_vt: number; vt_display: string; type_id_v2: number; type_name_v2: string; is_lesson_video: number } export type Area = { id: number; name: string } @@ -83,19 +92,32 @@ export type ArgueInfo = { argue_msg: string; argue_type: number; argue_link: str export type Author = { mid: number; name: string; face: string } export type BadgeInfo = { bg_color: string; bg_color_night: string; text: string } 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 Brief = { content: string; img: Img[]; title: string; type: 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 CommandError = { err_title: string; err_message: string } export type Config = { downloadDir: string; enableFileLogger: boolean; sessdata: string } +export type Consulting = { consulting_flag: boolean; consulting_url: string } +export type ContentList = { bold: boolean; content: string; number: string } +export type Cooperation = { link: string } export type DescV2 = { raw_text: string; type: number; biz_id: number } export type Dimension = { width: number; height: number; rotate: number } export type DimensionInBangumi = { height: number; rotate: number; width: number } export type Ed = { end: number; start: number } export type EpInBangumi = { aid: number; badge: string; badge_info: BadgeInfo; badge_type: number | null; bvid: string | null; cid: number; cover: string; dimension: DimensionInBangumi | null; duration: number | null; enable_vt: boolean; ep_id: number; from: string | null; id: number; is_view_hide: boolean; link: string; link_type: string | null; long_title: string | null; pub_time: number; pv: number; release_date: string | null; rights: RightsInBangumiEp | null; section_type: number; share_copy: string | null; share_url: string | null; short_link: string | null; showDrmLoginDialog: boolean; show_title: string | null; skip: Skip | null; status: number; subtitle: string | null; title: string; vid: string | null; icon_font: IconFont | null } +export type EpInCheese = { aid: number; catalogue_index: number; cid: number; cover: string; duration: number; ep_status: number; episode_can_view: boolean; from: string; id: number; index: number; label: string | null; page: number; play: number; play_way: number; playable: boolean; release_date: number; show_vt: boolean; status: number; subtitle: string; title: string; watched: boolean; watchedHistory: number } export type EpInNormal = { season_id: number; section_id: number; id: number; aid: number; cid: number; title: string; attribute: number; arc: Arc; page: PageInNormalEp; bvid: string; pages: PageInNormalEp[] } +export type EpPage = { next: boolean; num: number; size: number; total: number } +export type EpTag = { part_preview_tag: string; pay_tag: string; preview_tag: string } +export type Faq = { content: string; link: string; title: string } +export type Faq1 = { items: Faq1Item[]; title: string } +export type Faq1Item = { answer: string; question: string } export type GetBangumiInfoParams = { EpId: number } | { SeasonId: number } +export type GetCheeseInfoParams = { EpId: number } | { SeasonId: number } export type GetNormalInfoParams = { Bvid: string } | { Aid: number } export type Honor = { aid: number; type: number; desc: string; weekly_recommend_num: number } export type HonorReply = { honor: Honor[] | null } export type IconFont = { name: string; text: string } +export type Img = { aspect_ratio: number; url: string } export type JsonValue = null | boolean | number | string | JsonValue[] | { [key in string]: JsonValue } export type LabelInUserInfo = { path: string; text: string; label_theme: string; text_color: string; bg_style: number; bg_color: string; border_color: string; use_img_label: boolean; img_label_uri_hans: string; img_label_uri_hant: string; img_label_uri_hans_static: string; img_label_uri_hant_static: string } export type LevelInfoInUserInfo = { current_level: number; current_min: number; current_exp: number } @@ -110,15 +132,23 @@ export type Op = { end: number; start: number } export type OwnerInNormal = { mid: number; name: string; face: string } export type PageInNormal = { cid: number; page: number; from: string; part: string; duration: number; vid: string; weblink: string; dimension: Dimension; ctime: number } export type PageInNormalEp = { cid: number; page: number; from: string; part: string; duration: number; vid: string; weblink: string; dimension: Dimension } +export type PaidJump = { jump_url_for_app: string; url: string } export type PayType = { allow_discount: number; allow_pack: number; allow_ticket: number; allow_time_limit: number; allow_vip_discount: number; forbid_bb: number } +export type Payment = { bp_enough: number; desc: string; my_bp: number; pay_shade: string; price: number; price_format: string; price_unit: string; refresh_text: string; select_text: string } export type PaymentInBangumi = { discount: number; pay_type: PayType; price: string; promotion: string; tip: string; view_start_time: number; vip_discount: number; vip_first_promotion: string; vip_price: string; vip_promotion: string } +export type PendantInCheese = { image: string; name: string; pid: number } export type PendantInUserInfo = { pid: number; name: string; image: string; expire: number; image_enhance: string; image_enhance_frame: string; n_pid: number } export type PlayStrategy = { strategies: string[] } export type Positive = { id: number; title: string } +export type PreviewedPurchaseNote = { long_watch_text: string; pay_text: string; price_format: string; watch_text: string; watching_text: string } export type Publish = { is_finish: number; is_started: number; pub_time: string; pub_time_show: string; unknow_pub_date: number; weekday: number } +export type PurchaseFormatNote = { content_list: ContentList[]; link: string; title: string } +export type PurchaseNote = { content: string; link: string; title: string } +export type PurchaseProtocol = { link: string; title: string } export type QrcodeData = { url: string; qrcode_key: string } export type QrcodeStatus = { url: string; refresh_token: string; timestamp: number; code: number; message: string } export type Rating = { count: number; score: number } +export type RecommendSeason = { cover: string; ep_count: string; id: number; season_url: string; subtitle: string; title: string; view: number } export type Rights = { 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; clean_mode: number; is_stein_gate: number; is_360: number; no_share: number; arc_pay: number; free_watch: number } export type RightsInBangumi = { allow_bp: number; allow_bp_rank: number; allow_download: number; allow_review: number; area_limit: number; ban_area_show: number; can_watch: number; copyright: string; forbid_pre: number; freya_white: number; is_cover_show: number; is_preview: number; only_vip_download: number; resource: string; watch_platform: number } export type RightsInBangumiEp = { allow_dm: number; allow_download: number; area_limit: number } @@ -131,6 +161,7 @@ export type Show = { wide_screen: number } export type Skip = { ed: Ed; op: Op } export type Staff = { mid: number; title: string; name: string; face: string; follower: number; label_style: number } export type StatInBangumi = { coins: number; danmakus: number; favorite: number; favorites: number; follow_text: string; likes: number; reply: number; share: number; views: number; vt: number } +export type StatInCheese = { play: number; play_desc: string; show_vt: boolean } export type StatInNormal = { aid: number; view: number; danmaku: number; reply: number; favorite: number; coin: number; share: number; now_rank: number; his_rank: number; like: number; dislike: number; evaluation: string; vt: number } export type StatInNormalEp = { aid: number; view: number; danmaku: number; reply: number; fav: number; coin: number; share: number; now_rank: number; his_rank: number; like: number; dislike: number; evaluation: string; argue_msg: string; vt: number; vv: number } export type StatInNormalSeason = { season_id: number; view: number; danmaku: number; reply: number; fav: number; coin: number; share: number; now_rank: number; his_rank: number; like: number; vt: number; vv: number } @@ -139,9 +170,11 @@ export type SubtitleDetailInNormal = { id: number; lan: string; lan_doc: string; export type SubtitleInNormal = { allow_submit: boolean; list: SubtitleDetailInNormal[] } export type UgcSeason = { id: number; title: string; cover: string; mid: number; intro: string; sign_state: number; attribute: number; sections: SectionInNormal[]; stat: StatInNormalSeason; ep_count: number; season_type: number; is_pay_season: boolean; enable_vt: number } export type UpInfoInBangumi = { avatar: string; mid: number; uname: string } +export type UpInfoInCheese = { avatar: string; brief: string; follower: number; is_follow: number; is_living: boolean; link: string; mid: number; pendant: PendantInCheese; season_count: number; uname: string } export type UserGarb = { url_image_ani_cut: string } export type UserInfo = { isLogin: boolean; email_verified: number; face: string; face_nft: number; face_nft_type: number; level_info: LevelInfoInUserInfo; mid: number; mobile_verified: number; money: number; moral: number; official: Official; officialVerify: OfficialVerify; pendant: PendantInUserInfo; scores: number; uname: string; vipDueDate: number; vipStatus: number; vipType: number; vip_pay_type: number; vip_theme_type: number; vip_label: VipLabel; vip_avatar_subscript: number; vip_nickname_color: string; vip: VipInUserInfo; wallet: Wallet | null; has_shop: boolean; shop_url: string; answer_status: number; is_senior_member: number; wbi_img: WbiImg; is_jury: boolean } export type UserStatusInBangumi = { area_limit: number; ban_area_show: number; follow: number; follow_status: number; login: number; pay: number; pay_pack_paid: number; sponsor: number } +export type UserStatusInCheese = { bp: number; expire_at: number; favored: number; favored_count: number; is_expired: boolean; is_first_paid: boolean; payed: number; user_expiry_content: string } export type VipInUserInfo = { type: number; status: number; due_date: number; vip_pay_type: number; theme_type: number; label: LabelInUserInfo; avatar_subscript: number; nickname_color: string; role: number; avatar_subscript_url: string; tv_vip_status: number; tv_vip_pay_type: number; tv_due_date: number } export type VipLabel = { path: string; text: string; label_theme: string; text_color: string; bg_style: number; bg_color: string; border_color: string; use_img_label: boolean; img_label_uri_hans: string; img_label_uri_hant: string; img_label_uri_hans_static: string; img_label_uri_hant_static: string } export type Wallet = { mid: number; bcoin_balance: number; coupon_balance: number; coupon_due_time: number }