Skip to content

Commit

Permalink
Cobalt stream URL WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Dobby233Liu committed Aug 27, 2024
1 parent 9f00955 commit 64d7367
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const CRAWLER_UAS = [
"Mozilla/5.0 (compatible; Schema-Markup-Validator; +https://validator.schema.org/)"
];

export const COBALT_API_INSTANCE = "https://api.cobalt.tools";

export const ERROR_TEMPLATE = `<!DOCTYPE HTML>
<html>
<head>
Expand Down
9 changes: 6 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getMyBaseURL,
stripTrailingSlashes,
isUAEndUser,
shouldLieAboutPlayerContentType,
doesHTML5EmbedFunctionOnClient,
shouldNotAddRedirectMetaprop,
oembedAddExtraMetadata,
isUserAStupidKidAndTryingToAccessAWordpressApi
Expand Down Expand Up @@ -70,8 +70,11 @@ export default async function handler(req, res) {
sendError(res, req, "解析请求的 URL 时发生错误", e, responseType);
return;
}

let html5EmbedWorks = doesHTML5EmbedFunctionOnClient(req);
try {
data = await getVideoData(info);
// CHANGEME
data = await getVideoData(info, !html5EmbedWorks, !req.query.__bef_dont_drop_cobalt_errs);
} catch (e) {
sendError(res, req, "获取视频信息时发生错误", e, responseType);
return;
Expand Down Expand Up @@ -107,7 +110,7 @@ export default async function handler(req, res) {
}
data.oembed_json = oembedJson;
data.oembed_xml = oembedXml;
data.lie_about_embed_player = shouldLieAboutPlayerContentType(req);
data.lie_about_embed_player = html5EmbedWorks;
data.do_not_add_redirect_metaprop = shouldNotAddRedirectMetaprop(req);

sendTemplate(res, req, responseType, "video", data);
Expand Down
9 changes: 7 additions & 2 deletions src/templates/video.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,17 @@
<meta property="og:description" content="<%= compat_description %>" />
<meta property="og:image:width" content="<%= thumbnail_width %>" />
<meta property="og:image:height" content="<%= thumbnail_height %>" />
<meta property="og:video:url" content="<%= embed_url %>" />
<% if (video_url) {%><meta property="og:video:url" content="<%= video_url %>" />
<meta property="og:video:secure_url" content="<%= video_url %>" />
<meta
property="og:video:type"
content="video/mp4"
/><% } else {%><meta property="og:video:url" content="<%= embed_url %>" />
<meta property="og:video:secure_url" content="<%= embed_url %>" />
<meta
property="og:video:type"
content="<%= lie_about_embed_player ? 'video/mp4' : 'text/html'%>"
/>
/><% } %>
<meta property="og:video:width" content="<%= width %>" />
<meta property="og:video:height" content="<%= height %>" />
<meta property="twitter:card" content="player" />
Expand Down
14 changes: 7 additions & 7 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ export function getMyBaseURL(req) {
const headers = req.headers;
return new URL(
`${encodeURI(headers["x-forwarded-proto"] ?? "https")}://` +
encodeURI(
headers["x-vercel-deployment-url"] ??
headers["x-forwarded-host"] ??
headers["host"]
)
encodeURI(
headers["x-vercel-deployment-url"] ??
headers["x-forwarded-host"] ??
headers["host"]
)
);
}

Expand Down Expand Up @@ -61,7 +61,7 @@ export function isUAEndUser(req) {
);
}

export function shouldLieAboutPlayerContentType(req) {
export function doesHTML5EmbedFunctionOnClient(req) {
return req.headers["user-agent"].includes("Discordbot");
}

Expand Down Expand Up @@ -93,7 +93,7 @@ export function sendError(
me: MY_NAME,
code: code,
message: message,
data: data.stack ? data.stack : data.toString(),
data: data.stack ? data.stack : (data.toString() == "[object Object]" ? JSON.stringify(data) : data),
issues_url: PROJECT_ISSUES_URL,
};

Expand Down
70 changes: 58 additions & 12 deletions src/utils_bilibili.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
} from "./utils.js";
import { COBALT_API_INSTANCE } from "./constants.js";

// Group 4 is the ID of the video
const MAIN_SITE_VIDEO_PAGE_PATHNAME_REGEX =
Expand Down Expand Up @@ -130,25 +131,25 @@ async function getOriginalURLOfB23TvRedir(url) {
throw errorFromBilibili(
new Error(
`对 ${url} 的请求失败。(HTTP 状态码为 ${response.status})请检查您的链接。` +
"\n" +
responseData
"\n" +
responseData
),
responseDataJson
);
} else if (responseDataJson.code && responseDataJson.code != 0) {
throw errorFromBilibili(
new Error(
`对 ${url} 的请求失败。(HTTP 状态码为 ${response.status})请检查您的链接。` +
"\n" +
responseData
"\n" +
responseData
),
responseDataJson
);
}
throw new Error(
`请求了 ${url},但是服务器返回了一段奇妙的内容?(HTTP 状态码为 ${response.status})请检查您的链接,如果正常,那么就是我们的 bug。` +
"\n" +
responseData
"\n" +
responseData
);
}

Expand All @@ -171,15 +172,15 @@ export async function getRequestedInfo(path, search) {
if (url.pathname.startsWith(knownNonVideoPrefix))
throw new Error(
"这似乎不是一个视频——本服务目前只支持对视频页面进行 embed 修正。\n" +
`拼接的 URL:${originalURL.href} 匹配已知非视频前缀:${knownNonVideoPrefix}`
`拼接的 URL:${originalURL.href} 匹配已知非视频前缀:${knownNonVideoPrefix}`
);
}
// must've a b23.tv shortlink
url = await getOriginalURLOfB23TvRedir(url);
if (!isUrlBilibiliVideo(url)) {
throw new Error(
"这似乎不是一个视频——本服务目前只支持对视频页面进行 embed 修正。\n" +
`跳转到了 ${url.href} (未跳转的 URL:${originalURL.href})`
`跳转到了 ${url.href} (未跳转的 URL:${originalURL.href})`
);
}
}
Expand All @@ -190,7 +191,7 @@ export async function getRequestedInfo(path, search) {
return ret;
}

export async function getVideoData(info) {
export async function getVideoData(info, getVideoUrl, dropCobaltErrs) {
const id = info.id;

const requestURL = new URL("https://api.bilibili.com/x/web-interface/view");
Expand Down Expand Up @@ -218,15 +219,59 @@ export async function getVideoData(info) {
let page = info.page && info.page <= resInfo.pages.length ? info.page : 1;
let cid = resInfo.pages[page - 1].cid ?? resInfo.cid;
let width =
resInfo.pages[page - 1].dimension.width ??
resInfo.dimension.width ??
DEFAULT_WIDTH,
resInfo.pages[page - 1].dimension.width ??
resInfo.dimension.width ??
DEFAULT_WIDTH,
height =
resInfo.pages[page - 1].dimension.height ??
resInfo.dimension.height ??
DEFAULT_HEIGHT;
let tWidth = resInfo.dimension.width ?? DEFAULT_WIDTH,
tHeight = resInfo.dimension.height ?? DEFAULT_HEIGHT;

let videoUrl;
if (getVideoUrl) {
console.log(makeVideoPage(id, page));
const cobaltRep = await fetch(new URL("/api/json", COBALT_API_INSTANCE).href, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: makeVideoPage(id, page),
vQuality: 720,
disableMetadata: true
})
})
const cobaltRepRaw = await cobaltRep.text();
console.log(cobaltRepRaw);
let cobaltRepParsed;
if (!response.ok) {
if (!dropCobaltErrs)
throw cobaltRepRaw;
} else {
try {
cobaltRepParsed = JSON.parse(cobaltRepRaw);
} catch (e) {
if (!dropCobaltErrs)
throw e;
}
}
if (cobaltRepParsed) {
if ((cobaltRepParsed.status == "error" || cobaltRepParsed.status == "rate-limit") && !dropCobaltErrs)
throw cobaltRepParsed;
if (cobaltRepParsed.status != "picker") {
videoUrl = cobaltRepParsed.url;
} else {
assert(cobaltRepParsed.pickerType == "various");
videoUrl = cobaltRepParsed.picker[page] ? cobaltRepParsed.picker[page].url : cobaltRepParsed.picker[0].url;
// todo: picker[xx].thumb
}
console.log(videoUrl);
}
}

const pic = new URL(resInfo.pic);
pic.protocol = "https:";
if (pic.hostname.endsWith("hdslb.com") && pic.pathname.startsWith("/bfs/"))
Expand All @@ -238,6 +283,7 @@ export async function getVideoData(info) {
page: page,
cid: cid,
embed_url: makeEmbedPlayerURL(resInfo.bvid, cid, page),
video_url: videoUrl,
title: resInfo.title,
author: resInfo.owner.name,
author_mid: resInfo.owner.mid,
Expand Down

0 comments on commit 64d7367

Please sign in to comment.