diff --git a/src/background/messageListeners/api/video.ts b/src/background/messageListeners/api/video.ts index 2e19d474..57b282e5 100644 --- a/src/background/messageListeners/api/video.ts +++ b/src/background/messageListeners/api/video.ts @@ -73,9 +73,9 @@ const API_VIDEO = { }, afterHandle: AHS.J_D, }, - // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/info.md#%E8%8E%B7%E5%8F%96%E8%A7%86%E9%A2%91%E8%B6%85%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AFweb%E7%AB%AF + // https://socialsisteryi.github.io/bilibili-API-collect/docs/video/info.html#%E8%8E%B7%E5%8F%96%E8%A7%86%E9%A2%91%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF-web%E7%AB%AF getVideoInfo: { - url: 'https://api.bilibili.com/x/web-interface/view/detail', + url: 'https://api.bilibili.com/x/web-interface/view', _fetch: { method: 'get', }, diff --git a/src/components/VideoCard/VideoCard.vue b/src/components/VideoCard/VideoCard.vue index fe750176..d51899fd 100644 --- a/src/components/VideoCard/VideoCard.vue +++ b/src/components/VideoCard/VideoCard.vue @@ -6,6 +6,7 @@ import { useToast } from 'vue-toastification' import Button from '~/components/Button.vue' import { useBewlyApp } from '~/composables/useAppProvider' import { accessKey, settings } from '~/logic' +import type { VideoInfo } from '~/models/video/videoInfo' import type { VideoPreviewResult } from '~/models/video/videoPreview' import api from '~/utils/api' import { getTvSign, TVAppKey } from '~/utils/authProvider' @@ -75,15 +76,28 @@ const previewVideoUrl = ref('') const contentVisibility = ref<'auto' | 'visible'>('auto') const videoElement = ref(null) -watch(() => isHover.value, (newValue) => { +watch(() => isHover.value, async (newValue) => { if (!props.video || !newValue) return if (props.showPreview && settings.value.enableVideoPreview - && !previewVideoUrl.value && props.video.cid) { + && !previewVideoUrl.value && (props.video.aid || props.video.bvid)) { + let cid = props.video.cid + if (!cid) { + try { + const res: VideoInfo = await api.video.getVideoInfo({ + bvid: props.video.bvid, + }) + if (res.code === 0) + cid = res.data.cid + } + catch { + + } + } api.video.getVideoPreview({ bvid: props.video.bvid, - cid: props.video.cid, + cid, }).then((res: VideoPreviewResult) => { if (res.code === 0) previewVideoUrl.value = res.data.durl[0].url diff --git a/src/components/VideoCard/types.ts b/src/components/VideoCard/types.ts index 7356f3e7..a88aa384 100644 --- a/src/components/VideoCard/types.ts +++ b/src/components/VideoCard/types.ts @@ -27,7 +27,7 @@ export interface Video { goto?: string /** After set the `url`, clicking the video will navigate to this url. It won't be affected by aid, bvid or epid */ url?: string - /** If you want to show preview video, you should set the cid value */ + /** Better to provide cid, otherwise video preview will need to call another API to get it */ cid?: number followed?: boolean diff --git a/src/models/video/videoInfo.ts b/src/models/video/videoInfo.ts new file mode 100644 index 00000000..3b149cc7 --- /dev/null +++ b/src/models/video/videoInfo.ts @@ -0,0 +1,198 @@ +// https://app.quicktype.io/?l=ts + +export interface VideoInfo { + code: number + message: string + ttl: number + data: Data +} + +export interface Data { + bvid: string + aid: number + videos: number + tid: number + tname: string + copyright: number + pic: string + title: string + pubdate: number + ctime: number + desc: string + desc_v2: DescV2[] + state: number + duration: number + mission_id: number + rights: { [key: string]: number } + owner: Owner + stat: Stat + argue_info: ArgueInfo + dynamic: string + cid: number + dimension: Dimension + premiere: null + teenage_mode: number + is_chargeable_season: boolean + is_story: boolean + is_upower_exclusive: boolean + is_upower_play: boolean + enable_vt: number + vt_display: string + no_cache: boolean + pages: Page[] + subtitle: Subtitle + staff: Staff[] + is_season_display: boolean + user_garb: UserGarb + honor_reply: HonorReply + like_icon: string + need_jump_bv: boolean + disable_show_up_info: boolean +} + +export interface ArgueInfo { + argue_msg: string + argue_type: number + argue_link: string +} + +export interface DescV2 { + raw_text: string + type: number + biz_id: number +} + +export interface Dimension { + width: number + height: number + rotate: number +} + +export interface HonorReply { + honor: Honor[] +} + +export interface Honor { + aid: number + type: number + desc: string + weekly_recommend_num: number +} + +export interface Owner { + mid: number + name: string + face: string +} + +export interface Page { + cid: number + page: number + from: string + part: string + duration: number + vid: string + weblink: string + dimension: Dimension +} + +export interface Staff { + mid: number + title: string + name: string + face: string + vip: Vip + official: Official + follower: number + label_style: number +} + +export interface Official { + role: number + title: string + desc: string + type: number +} + +export interface Vip { + type: number + status: number + due_date: number + vip_pay_type: number + theme_type: number + label: Label + 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 interface Label { + 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 interface Stat { + 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 interface Subtitle { + allow_submit: boolean + list: List[] +} + +export interface List { + id: number + lan: string + lan_doc: string + is_lock: boolean + subtitle_url: string + type: number + id_str: string + ai_type: number + ai_status: number + author: Author +} + +export interface Author { + mid: number + name: string + sex: string + face: string + sign: string + rank: number + birthday: number + is_fake_account: number + is_deleted: number + in_reg_audit: number + is_senior_member: number +} + +export interface UserGarb { + url_image_ani_cut: string +}