mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-05-21 05:25:45 +08:00
✨ B站视频基本信息获取,支持分享图生成
This commit is contained in:
BIN
public/source/UI/video_play_bili.png
Normal file
BIN
public/source/UI/video_play_bili.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
@@ -35,31 +35,59 @@
|
|||||||
"core:window:default",
|
"core:window:default",
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-exists",
|
"identifier": "fs:allow-exists",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-mkdir",
|
"identifier": "fs:allow-mkdir",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-read-dir",
|
"identifier": "fs:allow-read-dir",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-read-text-file",
|
"identifier": "fs:allow-read-text-file",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-remove",
|
"identifier": "fs:allow-remove",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-write-file",
|
"identifier": "fs:allow-write-file",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "fs:allow-write-text-file",
|
"identifier": "fs:allow-write-text-file",
|
||||||
"allow": [{ "path": "**" }]
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "**"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identifier": "http:default",
|
"identifier": "http:default",
|
||||||
@@ -76,6 +104,9 @@
|
|||||||
{
|
{
|
||||||
"url": "https://*.bilibili.com/*"
|
"url": "https://*.bilibili.com/*"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"url": "http://*.hdslb.com/*"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"url": "https://*.hoyoverse.com/*"
|
"url": "https://*.hoyoverse.com/*"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -124,6 +124,7 @@
|
|||||||
{ "url": "https://*.mihoyo.com/*" },
|
{ "url": "https://*.mihoyo.com/*" },
|
||||||
{ "url": "https://*.mihoyogift.com/*" },
|
{ "url": "https://*.mihoyogift.com/*" },
|
||||||
{ "url": "https://*.bilibili.com/*" },
|
{ "url": "https://*.bilibili.com/*" },
|
||||||
|
{ "url": "http://*.hdslb.com/*" },
|
||||||
{ "url": "https://*.hoyoverse.com/*" },
|
{ "url": "https://*.hoyoverse.com/*" },
|
||||||
{ "url": "https://*.genshinnet.com/*" }
|
{ "url": "https://*.genshinnet.com/*" }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<!-- todo 优化 -->
|
|
||||||
<template>
|
<template>
|
||||||
<div class="tp-video-box">
|
<div class="tp-video-box" v-if="videoData">
|
||||||
<!-- todo https://socialsisteryi.github.io/bilibili-API-collect/docs/video/videostream_url.html#%E8%A7%86%E9%A2%91%E4%BC%B4%E9%9F%B3%E9%9F%B3%E8%B4%A8%E4%BB%A3%E7%A0%81 -->
|
<!-- todo https://socialsisteryi.github.io/bilibili-API-collect/docs/video/videostream_url.html#%E8%A7%86%E9%A2%91%E4%BC%B4%E9%9F%B3%E9%9F%B3%E8%B4%A8%E4%BB%A3%E7%A0%81 -->
|
||||||
<iframe
|
<iframe
|
||||||
class="tp-video-container"
|
class="tp-video-container"
|
||||||
@@ -9,26 +8,32 @@
|
|||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
sandbox="allow-forms allow-same-origin allow-popups allow-presentation allow-scripts"
|
sandbox="allow-forms allow-same-origin allow-popups allow-presentation allow-scripts"
|
||||||
:id="`tp-video-${props.data.insert.video}`"
|
:id="`tp-video-${props.data.insert.video}`"
|
||||||
>
|
/>
|
||||||
</iframe>
|
<div class="tp-video-share">
|
||||||
<div class="tp-video-cover" v-if="videoCover">
|
<img alt="cover" :src="videoCover" class="tp-video-cover" />
|
||||||
<img alt="cover" :src="videoCover" />
|
<img alt="icon" src="/source/UI/video_play_bili.png" class="tp-video-icon" />
|
||||||
<img src="/source/UI/video_play.svg" alt="icon" />
|
<div class="tp-video-info">
|
||||||
<span>{{ getVideoTime() }}</span>
|
<span>{{ videoData.bvid }}|{{ timestampToDate(videoData.ctime * 1000) }}</span>
|
||||||
|
<span>{{ videoData.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tp-video-view">
|
||||||
|
<v-icon size="12">mdi-eye</v-icon>
|
||||||
|
<span>{{ videoData.stat.view }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tp-video-time">
|
||||||
|
<v-icon size="12">mdi-clock-time-four-outline</v-icon>
|
||||||
|
<span>{{ getVideoDuration(videoData.duration) }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// todo https://artplayer.org/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/4.5.2/dash.all.min.js&example=dash
|
|
||||||
// todo flv
|
|
||||||
// https://artplayer.org/document/library/flv.html
|
|
||||||
// https://api.bilibili.com/x/player/playurl?avid=666064953&cid=1400018762&qn=64&otype=json
|
|
||||||
import Bili from "@Bili/index.js";
|
import Bili from "@Bili/index.js";
|
||||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import { onBeforeMount, onMounted, onUnmounted, ref, shallowRef, useTemplateRef } from "vue";
|
import { onMounted, onUnmounted, ref, shallowRef } from "vue";
|
||||||
|
|
||||||
import TGLogger from "@/utils/TGLogger.js";
|
import { getImageBuffer } from "@/utils/TGShare.js";
|
||||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
import { getVideoDuration, timestampToDate } from "@/utils/toolFunc.js";
|
||||||
|
|
||||||
type TpVideo = { insert: { video: string } };
|
type TpVideo = { insert: { video: string } };
|
||||||
type TpVideoProps = { data: TpVideo };
|
type TpVideoProps = { data: TpVideo };
|
||||||
@@ -37,60 +42,28 @@ const props = defineProps<TpVideoProps>();
|
|||||||
const videoAspectRatio = ref<number>(16 / 9);
|
const videoAspectRatio = ref<number>(16 / 9);
|
||||||
const videoCover = ref<string>();
|
const videoCover = ref<string>();
|
||||||
const videoData = shallowRef<TGApp.Plugins.Bili.Video.ViewData>();
|
const videoData = shallowRef<TGApp.Plugins.Bili.Video.ViewData>();
|
||||||
const videoRef = useTemplateRef<HTMLIFrameElement>(`#tp-video-${props.data.insert.video}`);
|
const coverBuffer = shallowRef<Uint8Array | null>(null);
|
||||||
|
|
||||||
console.log("tpVideo", props.data.insert.video);
|
console.log("tpVideo", props.data.insert.video);
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onMounted(async () => {
|
||||||
const url = new URL(props.data.insert.video);
|
const url = new URL(props.data.insert.video);
|
||||||
const aid = url.searchParams.get("aid") ?? undefined;
|
const aid = url.searchParams.get("aid") ?? undefined;
|
||||||
const bvid = url.searchParams.get("bvid") ?? undefined;
|
const bvid = url.searchParams.get("bvid") ?? undefined;
|
||||||
try {
|
videoData.value = await Bili.video.view(aid, bvid);
|
||||||
videoData.value = await Bili.video.view(aid, bvid);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Error) {
|
|
||||||
await TGLogger.Error(`获取视频信息失败: ${e.message}`);
|
|
||||||
} else await TGLogger.Error(`获取视频信息失败: ${e}`);
|
|
||||||
}
|
|
||||||
if (!videoData.value) {
|
if (!videoData.value) {
|
||||||
console.error("videoData is null");
|
showSnackbar.error(`获取B站视频信息失败:${props.data.insert.video}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const meta = videoData.value.dimension;
|
const meta = videoData.value.dimension;
|
||||||
if (meta.width > meta.height) videoAspectRatio.value = meta.width / meta.height;
|
if (meta.width > meta.height) videoAspectRatio.value = meta.width / meta.height;
|
||||||
else videoAspectRatio.value = meta.height / meta.width;
|
else videoAspectRatio.value = meta.height / meta.width;
|
||||||
|
coverBuffer.value = await getImageBuffer(videoData.value.pic);
|
||||||
|
videoCover.value = URL.createObjectURL(new Blob([coverBuffer.value], { type: "image/png" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (videoData.value && videoData.value.pic) {
|
|
||||||
videoCover.value = await saveImgLocal(videoData.value.pic);
|
|
||||||
}
|
|
||||||
if (videoRef.value === null) return;
|
|
||||||
videoRef.value.addEventListener("fullscreenchange", listenFullScreen);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function listenFullScreen(): Promise<void> {
|
|
||||||
if (document.fullscreenElement) await getCurrentWindow().setFullscreen(true);
|
|
||||||
else await getCurrentWindow().setFullscreen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVideoTime(): string {
|
|
||||||
const duration = videoData.value?.duration ?? 0;
|
|
||||||
const seconds = duration % 60;
|
|
||||||
const minutes = Math.floor(duration / 60) % 60;
|
|
||||||
const hours = Math.floor(duration / 3600);
|
|
||||||
let result = "";
|
|
||||||
if (hours > 0) result += `${hours.toString().padStart(2, "0")}:`;
|
|
||||||
result += `${minutes.toString().padStart(2, "0")}:`;
|
|
||||||
result += `${seconds.toString().padStart(2, "0")}`;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (videoCover.value) URL.revokeObjectURL(videoCover.value);
|
if (videoCover.value) URL.revokeObjectURL(videoCover.value);
|
||||||
if (videoRef.value !== null) {
|
|
||||||
videoRef.value.removeEventListener("fullscreenchange", listenFullScreen);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
@@ -102,6 +75,8 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tp-video-container {
|
.tp-video-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -110,7 +85,7 @@ onUnmounted(() => {
|
|||||||
aspect-ratio: v-bind(videoAspectRatio);
|
aspect-ratio: v-bind(videoAspectRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-video-cover {
|
.tp-video-share {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -124,28 +99,64 @@ onUnmounted(() => {
|
|||||||
aspect-ratio: v-bind(videoAspectRatio);
|
aspect-ratio: v-bind(videoAspectRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-video-cover :first-child {
|
.tp-video-cover {
|
||||||
width: 100%;
|
position: absolute;
|
||||||
|
max-width: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-video-cover :nth-child(2) {
|
.tp-video-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - 40px);
|
top: 50%;
|
||||||
left: calc(50% - 40px);
|
left: 50%;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tp-video-cover :nth-child(3) {
|
.tp-video-time {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
padding: 0 5px;
|
left: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: rgb(0 0 0/50%);
|
background: rgb(0 0 0/50%);
|
||||||
color: var(--tgc-white-4);
|
color: var(--tgc-white-4);
|
||||||
font-family: var(--font-title);
|
font-family: var(--font-title);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tp-video-info {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: rgb(0 0 0 / 50%);
|
||||||
|
color: var(--tgc-white-1);
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tp-video-view {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: rgb(0 0 0/50%);
|
||||||
|
color: var(--tgc-white-4);
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-size: 12px;
|
||||||
|
gap: 5px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
/**
|
/**
|
||||||
* @file plugins/Bili/request/getNav.ts
|
* @file plugins/Bili/request/getNav.ts
|
||||||
* @description Bili 插件导航请求文件
|
* @description Bili 插件导航请求文件
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import headerBili from "@Bili/utils/getHeader.js";
|
||||||
|
|
||||||
import TGHttp from "@/utils/TGHttp.js";
|
import TGHttp from "@/utils/TGHttp.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Bili 插件导航请求
|
* @description Bili 插件导航请求
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.7
|
||||||
* @return {Promise<TGApp.Plugins.Bili.Nav.NavData>} Bili 插件导航请求返回
|
* @return {Promise<TGApp.Plugins.Bili.Nav.Data>} Bili 插件导航请求返回
|
||||||
*/
|
*/
|
||||||
async function getNav(): Promise<TGApp.Plugins.Bili.Nav.NavData> {
|
async function getNav(): Promise<TGApp.Plugins.Bili.Nav.Data> {
|
||||||
const url = "https://api.bilibili.com/x/web-interface/nav";
|
const url = "https://api.bilibili.com/x/web-interface/nav";
|
||||||
const resp = await TGHttp<TGApp.Plugins.Bili.Nav.NavResponse>(url, { method: "GET" });
|
const resp = await TGHttp<TGApp.Plugins.Bili.Nav.Response>(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: headerBili,
|
||||||
|
});
|
||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import headerBili from "@Bili/utils/getHeader.js";
|
||||||
import getWrid from "@Bili/utils/getWrid.js";
|
import getWrid from "@Bili/utils/getWrid.js";
|
||||||
|
|
||||||
import TGHttp from "@/utils/TGHttp.js";
|
import TGHttp from "@/utils/TGHttp.js";
|
||||||
@@ -18,22 +19,13 @@ import TGHttp from "@/utils/TGHttp.js";
|
|||||||
*/
|
*/
|
||||||
async function getVideoUrl(cid: number, bvid: string): Promise<TGApp.Plugins.Bili.Video.UrlData> {
|
async function getVideoUrl(cid: number, bvid: string): Promise<TGApp.Plugins.Bili.Video.UrlData> {
|
||||||
const url = "https://api.bilibili.com/x/player/playurl";
|
const url = "https://api.bilibili.com/x/player/playurl";
|
||||||
let params: Record<string, string> = {
|
let params: Record<string, string> = { bvid, cid: cid.toString(), fnval: "16", platform: "pc" };
|
||||||
bvid,
|
|
||||||
cid: cid.toString(),
|
|
||||||
fnval: "16",
|
|
||||||
platform: "pc",
|
|
||||||
};
|
|
||||||
const wridRes = await getWrid(params);
|
const wridRes = await getWrid(params);
|
||||||
params = {
|
params = { ...params, wts: wridRes[0], w_rid: wridRes[1] };
|
||||||
...params,
|
|
||||||
wts: wridRes[0],
|
|
||||||
wrid: wridRes[1],
|
|
||||||
};
|
|
||||||
const resp = await TGHttp<TGApp.Plugins.Bili.Video.UrlResponse>(url, {
|
const resp = await TGHttp<TGApp.Plugins.Bili.Video.UrlResponse>(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
query: params,
|
query: params,
|
||||||
headers: { referer: "https://www.bilibili.com/" },
|
headers: headerBili,
|
||||||
});
|
});
|
||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import headerBili from "@Bili/utils/getHeader.js";
|
||||||
|
import getWrid from "@Bili/utils/getWrid.js";
|
||||||
|
|
||||||
import TGHttp from "@/utils/TGHttp.js";
|
import TGHttp from "@/utils/TGHttp.js";
|
||||||
|
import TGLogger from "@/utils/TGLogger.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取视频基本信息
|
* @description 获取视频基本信息
|
||||||
@@ -18,26 +22,24 @@ async function getVideoView(
|
|||||||
bvid?: string,
|
bvid?: string,
|
||||||
): Promise<TGApp.Plugins.Bili.Video.ViewData> {
|
): Promise<TGApp.Plugins.Bili.Video.ViewData> {
|
||||||
const url = "https://api.bilibili.com/x/web-interface/wbi/view";
|
const url = "https://api.bilibili.com/x/web-interface/wbi/view";
|
||||||
const params: Record<string, string | number | boolean> = {
|
let params: Record<string, string | number | boolean> = { need_view: 1, isGaiaAvoided: true };
|
||||||
need_view: 1,
|
if (aid) params.aid = aid;
|
||||||
isGaiaAoided: true,
|
if (bvid) params.bvid = bvid;
|
||||||
};
|
if (!aid && !bvid) throw new Error("aid和bVid不能同时为空");
|
||||||
if (aid) {
|
const wrid = await getWrid(params);
|
||||||
params.aid = aid;
|
params = { ...params, wts: wrid[0], w_rid: wrid[1] };
|
||||||
} else if (bvid) {
|
try {
|
||||||
params.bvid = bvid;
|
const resp = await TGHttp<TGApp.Plugins.Bili.Video.ViewResponse>(url, {
|
||||||
} else {
|
method: "GET",
|
||||||
throw new Error("参数错误");
|
query: params,
|
||||||
|
headers: headerBili,
|
||||||
|
});
|
||||||
|
return resp.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) await TGLogger.Error(`获取视频基本信息失败: ${error.message}`);
|
||||||
|
else await TGLogger.Error(`获取视频基本信息失败: ${error}`);
|
||||||
}
|
}
|
||||||
const resp = await TGHttp<TGApp.Plugins.Bili.Video.ViewResponse>(url, {
|
throw new Error("获取视频基本信息失败");
|
||||||
method: "GET",
|
|
||||||
query: params,
|
|
||||||
}).catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
return err;
|
|
||||||
});
|
|
||||||
console.warn(resp.data);
|
|
||||||
return resp.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getVideoView;
|
export default getVideoView;
|
||||||
|
|||||||
13
src/plugins/Bili/types/Base.d.ts
vendored
13
src/plugins/Bili/types/Base.d.ts
vendored
@@ -4,12 +4,6 @@
|
|||||||
* @since Beta v0.4.0
|
* @since Beta v0.4.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Bili 插件基础类型
|
|
||||||
* @since Beta v0.4.0
|
|
||||||
* @namespace Base
|
|
||||||
* @memberof TGApp.Plugins.Bili
|
|
||||||
*/
|
|
||||||
declare namespace TGApp.Plugins.Bili.Base {
|
declare namespace TGApp.Plugins.Bili.Base {
|
||||||
/**
|
/**
|
||||||
* @description Bili Response 统一接口
|
* @description Bili Response 统一接口
|
||||||
@@ -21,10 +15,5 @@ declare namespace TGApp.Plugins.Bili.Base {
|
|||||||
* @property {any} data 数据
|
* @property {any} data 数据
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
interface Response {
|
type Response = { code: number; message: string; ttl: number; data: unknown };
|
||||||
code: number;
|
|
||||||
message: string;
|
|
||||||
ttl: number;
|
|
||||||
data: any;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/plugins/Bili/types/Nav.d.ts
vendored
31
src/plugins/Bili/types/Nav.d.ts
vendored
@@ -1,42 +1,29 @@
|
|||||||
/**
|
/**
|
||||||
* @file plugins/Bili/types/Nav.d.ts
|
* @file plugins/Bili/types/Nav.d.ts
|
||||||
* @description Bili 插件导航类型定义文件
|
* @description Bili 插件导航类型定义文件
|
||||||
* @since Beta v0.4.0
|
* @since Beta v0.5.7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Bili 插件导航类型
|
|
||||||
* @since Beta v0.4.0
|
|
||||||
* @namespace Nav
|
|
||||||
* @memberof TGApp.Plugins.Bili
|
|
||||||
*/
|
|
||||||
declare namespace TGApp.Plugins.Bili.Nav {
|
declare namespace TGApp.Plugins.Bili.Nav {
|
||||||
/**
|
/**
|
||||||
* @description Bili 导航基本信息返回
|
* @description Bili 导航基本信息返回
|
||||||
* @since Beta v0.4.0
|
* @since Beta v0.5.7
|
||||||
* @interface NavResponse
|
* @interface Response
|
||||||
* @extends {TGApp.Plugins.Bili.Base.Response}
|
* @extends {TGApp.Plugins.Bili.Base.Response}
|
||||||
* @property {NavData} data 导航基本信息
|
* @property {Data} data 导航基本信息
|
||||||
* @return NavResponse
|
* @return NavResponse
|
||||||
*/
|
*/
|
||||||
interface NavResponse extends TGApp.Plugins.Bili.Base.Response {
|
type Response = TGApp.Plugins.Bili.Base.Response & { data: Data };
|
||||||
data: NavData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Bili 导航基本信息
|
* @description Bili 导航基本信息
|
||||||
* @since Beta v0.4.0
|
* @since Beta v0.5.7
|
||||||
* @interface NavData
|
* @interface Data
|
||||||
* @see https://api.bilibili.com/x/web-interface/nav
|
* @see https://api.bilibili.com/x/web-interface/nav
|
||||||
* @desc 只写了用到的部分
|
* @desc 只写了用到的部分
|
||||||
* @property {string} wbi_img.img_url 网站图标
|
* @property {string} wbi_img.img_url 网站图标
|
||||||
* @property {string} wbi_img.sub_url 网站图标(小)
|
* @property {string} wbi_img.sub_url 网站图标(小)
|
||||||
* @return NavData
|
* @return Data
|
||||||
*/
|
*/
|
||||||
interface NavData {
|
type Data = { wbi_img: { img_url: string; sub_url: string } };
|
||||||
wbi_img: {
|
|
||||||
img_url: string;
|
|
||||||
sub_url: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/plugins/Bili/types/Video.d.ts
vendored
6
src/plugins/Bili/types/Video.d.ts
vendored
@@ -187,7 +187,7 @@ declare namespace TGApp.Plugins.Bili.Video {
|
|||||||
* @property {string} seek_type 视频跳转类型
|
* @property {string} seek_type 视频跳转类型
|
||||||
* @property {UrlDash} dash 视频播放地址
|
* @property {UrlDash} dash 视频播放地址
|
||||||
* @property {UrlDurl[]} durl 视频播放地址
|
* @property {UrlDurl[]} durl 视频播放地址
|
||||||
* @property {UrlFormats} support_formats 视频支持格式
|
* @property {UrlFormat[]} support_formats 视频支持格式
|
||||||
* @property {unknown} high_format 视频高清格式
|
* @property {unknown} high_format 视频高清格式
|
||||||
* @property {number} last_play_time 视频上次播放时间
|
* @property {number} last_play_time 视频上次播放时间
|
||||||
* @property {number} last_play_cid 视频上次播放分P号
|
* @property {number} last_play_cid 视频上次播放分P号
|
||||||
@@ -208,7 +208,7 @@ declare namespace TGApp.Plugins.Bili.Video {
|
|||||||
seek_type: string;
|
seek_type: string;
|
||||||
dash: UrlDash; // dash 返回
|
dash: UrlDash; // dash 返回
|
||||||
durl: UrlDurl[]; // mp4 返回
|
durl: UrlDurl[]; // mp4 返回
|
||||||
support_formats: UrlFormats;
|
support_formats: UrlFormat[];
|
||||||
high_format: unknown;
|
high_format: unknown;
|
||||||
last_play_time: number;
|
last_play_time: number;
|
||||||
last_play_cid: number;
|
last_play_cid: number;
|
||||||
@@ -331,7 +331,7 @@ declare namespace TGApp.Plugins.Bili.Video {
|
|||||||
* @property {unknown} codecs 视频编码
|
* @property {unknown} codecs 视频编码
|
||||||
* @return UrlFormats
|
* @return UrlFormats
|
||||||
*/
|
*/
|
||||||
interface UrlFormats {
|
interface UrlFormat {
|
||||||
quality: number;
|
quality: number;
|
||||||
format: string;
|
format: string;
|
||||||
new_description: string;
|
new_description: string;
|
||||||
|
|||||||
13
src/plugins/Bili/utils/getHeader.ts
Normal file
13
src/plugins/Bili/utils/getHeader.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file plugins/Bili/utils/getHeader.ts
|
||||||
|
* @description 获取请求头
|
||||||
|
* @since Beta v0.5.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
const headerBili = {
|
||||||
|
cookie: "",
|
||||||
|
"user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0",
|
||||||
|
origin: "https://www.bilibili.com",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default headerBili;
|
||||||
@@ -43,13 +43,12 @@ async function getMixinKey(): Promise<string> {
|
|||||||
* @param {Record<string,string|number>} params 请求参数
|
* @param {Record<string,string|number>} params 请求参数
|
||||||
* @returns {Promise<[string|string]>} wrid
|
* @returns {Promise<[string|string]>} wrid
|
||||||
*/
|
*/
|
||||||
async function getWrid(params: Record<string, string | number>): Promise<[string, string]> {
|
async function getWrid(
|
||||||
|
params: Record<string, string | number | boolean>,
|
||||||
|
): Promise<[string, string]> {
|
||||||
const mixin_key = await getMixinKey();
|
const mixin_key = await getMixinKey();
|
||||||
const wts = Math.floor(Date.now() / 1000);
|
const wts = Math.floor(Date.now() / 1000);
|
||||||
const obj: Record<string, string | number> = {
|
const obj: Record<string, string | number> = { ...params, wts };
|
||||||
...params,
|
|
||||||
wts,
|
|
||||||
};
|
|
||||||
const keys = Object.keys(obj).sort();
|
const keys = Object.keys(obj).sort();
|
||||||
let md5Str = "";
|
let md5Str = "";
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
|||||||
@@ -232,3 +232,20 @@ export function getZhElement(element: string): string {
|
|||||||
return "未知";
|
return "未知";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取视频时长
|
||||||
|
* @since Beta v0.5.7
|
||||||
|
* @param {number} duration - 视频时长(秒)
|
||||||
|
* @returns {string} 视频时长
|
||||||
|
*/
|
||||||
|
export function getVideoDuration(duration: number): string {
|
||||||
|
const seconds = duration % 60;
|
||||||
|
const minutes = Math.floor(duration / 60) % 60;
|
||||||
|
const hours = Math.floor(duration / 3600);
|
||||||
|
let result = "";
|
||||||
|
if (hours > 0) result += `${hours.toString().padStart(2, "0")}:`;
|
||||||
|
result += `${minutes.toString().padStart(2, "0")}:`;
|
||||||
|
result += `${seconds.toString().padStart(2, "0")}`;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user