Feat: DJI & Bili API

大疆和哔哩哔哩的 iframe API
This commit is contained in:
2022-04-17 00:49:45 +08:00
parent 99c196afad
commit 8cdf2a6655
5 changed files with 267 additions and 3 deletions
+93
View File
@@ -0,0 +1,93 @@
import { Api, Get, Query, useContext } from "@midwayjs/hooks";
import { getVideoInfo } from "./utils/bili";
import { client } from "./utils/redis";
const availableStyle = ["gray", "white", "black", "shadow"];
export default Api(
Get(),
Query<{ av?: string, bv?: string }>(),
async () => {
const ctx = useContext();
const id = ctx.query.av || ctx.query.bv;
const type = "av" in ctx.query ? "av" : "bv" in ctx.query ? "bv" : undefined;
if (!id) {
return "请输入 ID";
}
if (!type) {
return "无效的 type";
}
// 增加使用数量
await client.incr("api-next:stat:bili");
// 尝试使用缓存
const cached = await client.lRange(`api-next:bili:${id}`, 0, 3);
let result;
if (cached.length) {
result = {
title: cached[0],
image: cached[1],
desc: cached[2],
};
}
else {
const info = await getVideoInfo(id, type);
if (!info) {
return "获取失败";
}
await client.rPush(`api-next:bili:${id}`, [
info.title,
info.image,
info.desc,
]);
await client.expire(`api-next:bili:${id}`, 21600);
result = info;
}
// 后期参数填补
let classname = "bili-box";
if (ctx.query.style && availableStyle.includes(ctx.query.style)) {
classname += ` ${ctx.query.style}`;
}
const link = `https://www.bilibili.com/video/${type === "av" ? "av" : ""}/${id}`;
return (`
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<meta charset="UTF-8">
<title>哔哩小窗 iFrame API</title>
<meta name="referrer" content="no-referrer" />
<link href="/assets/bili.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="${classname}">
<a class="bili-img" href="${link}" target="_blank">
<img src="${result.image}" alt="${result.title}" referrerpolicy="no-referrer" />
</a>
<div class="bili-info">
<h1><a href="${link}" target="_blank">${result.title}</a></h1>
<p>${result.desc}</p>
</div>
<div class="bili-powered">
<a href="https://api.paugram.com" target="_blank" title="使用了奇趣保罗的哔哩哔哩小窗接口">哔哩小窗</a>
</div>
<div class="bili-hidden">Cached: ${cached.length ? true : false}</div>
</div>
</body>
</html>`)
}
);
+27
View File
@@ -0,0 +1,27 @@
import { Api, Get, Query, useContext } from "@midwayjs/hooks";
import { client } from "./utils/redis";
export default Api(
Get(),
Query<{ id?: string, loop?: string }>(),
async () => {
const ctx = useContext();
// 增加使用数量
await client.incr("api-next:stat:dji");
return (`
<!DOCTYPE html>
<html lang="zh-cmn-hans">
<head>
<title>大疆视频外链</title>
<meta name="referrer" content="no-referrer"/>
<style>*{ margin: 0 } video{ width: 100%; height: 100%; background: #000; max-width: 100%; outline: none }</style>
</head>
<body>
${ctx.query.id ? `<video src="https://cn-videos.dji.net/video_trans/${ctx.query.id}/720.mp4" controls${"loop" in ctx.query ? " loop" : ""}></video>` : "<p>没有输入 ID</p>"}
</body>
</html>`)
}
);
+3 -3
View File
@@ -14,9 +14,6 @@ export default Api(
ctx.set("access-control-allow-origin", "*");
ctx.set("access-control-allow-headers", "x-requested-with");
// 增加使用数量
await client.incr("api-next:stat:netease");
const { id } = ctx.query;
if (!id) {
@@ -26,6 +23,9 @@ export default Api(
}
}
// 增加使用数量
await client.incr("api-next:stat:netease");
// 直接播放
if ("play" in ctx.query) {
ctx.status = 302;
+23
View File
@@ -0,0 +1,23 @@
import fetch from "isomorphic-unfetch";
export const getVideoInfo = async (id: number | string, type: "av" | "bv") => {
return fetch(`https://api.bilibili.com/x/web-interface/view?${type === "av" ? "aid" : "bvid"}=${id}`).then(res => {
try{
return res.json();
}
catch(e){
// Todo: 这个地方可能会有问题
return undefined;
}
}).then(json => {
return json ? parseVideoData(json.data) : undefined;
})
}
export const parseVideoData = (json: any) => {
return {
title: json.title,
image: json.pic.replace(/^http:\/\//, "https://"),
desc: json.desc.length > 60 ? `${json.desc.substring(0, 60)}...` : json.desc,
}
}