From e1ae2b02003daebf3ebb819b8ed091cd9a5e92b9 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Fri, 9 May 2025 01:19:28 +0800 Subject: [PATCH] fix(route/bilibili/video): fallback to dynamic api (#19058) * fix(route/bilibili/video): fallback to dynamic api * update * update --- lib/routes/bilibili/utils.ts | 6 ++- lib/routes/bilibili/video.ts | 100 ++++++++++++++++++++++++++--------- 2 files changed, 79 insertions(+), 27 deletions(-) diff --git a/lib/routes/bilibili/utils.ts b/lib/routes/bilibili/utils.ts index 7035716eb..a6109afaa 100644 --- a/lib/routes/bilibili/utils.ts +++ b/lib/routes/bilibili/utils.ts @@ -295,7 +295,11 @@ export const renderOGVDescription = (embed: boolean, img: string, description: s return rendered; }; -export const getVideoUrl = (bvid?: string) => (bvid ? `https://www.bilibili.com/blackboard/newplayer.html?isOutside=true&autoplay=true&danmaku=true&muted=false&highQuality=true&bvid=${bvid}` : undefined); +export function getVideoUrl(bvid: string): string; +export function getVideoUrl(bvid?: string): string | undefined; +export function getVideoUrl(bvid?: string): string | undefined { + return bvid ? `https://www.bilibili.com/blackboard/newplayer.html?isOutside=true&autoplay=true&danmaku=true&muted=false&highQuality=true&bvid=${bvid}` : undefined; +} export const getLiveUrl = (roomId?: string) => (roomId ? `https://www.bilibili.com/blackboard/live/live-activity-player.html?cid=${roomId}` : undefined); export default { diff --git a/lib/routes/bilibili/video.ts b/lib/routes/bilibili/video.ts index 543ecb2bc..7faa87bed 100644 --- a/lib/routes/bilibili/video.ts +++ b/lib/routes/bilibili/video.ts @@ -1,8 +1,12 @@ -import { Route, ViewType } from '@/types'; +import type { Context } from 'hono'; +import JSONbig from 'json-bigint'; +import { DataItem, Route, ViewType } from '@/types'; import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; import cache from './cache'; import utils, { getVideoUrl } from './utils'; import logger from '@/utils/logger'; +import type { BilibiliWebDynamicResponse } from './api-interface'; export const route: Route = { path: '/user/video/:uid/:embed?', @@ -29,7 +33,7 @@ export const route: Route = { handler, }; -async function handler(ctx) { +async function handler(ctx: Context) { const uid = ctx.req.param('uid'); const embed = !ctx.req.param('embed'); const cookie = await cache.getCookie(); @@ -50,37 +54,81 @@ async function handler(ctx) { }, }); const data = response.data; + let fallbackItem: DataItem[] | undefined; if (data.code) { - logger.error(JSON.stringify(data.data)); - throw new Error(`Got error code ${data.code} while fetching: ${data.message}`); + try { + // Fallback to get video from dynamic API + const params = utils.addDmVerifyInfo(`host_mid=${uid}&platform=web&features=itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote`, utils.getDmImgList()); + const response = await got(`https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?${params}`, { + headers: { + Referer: `https://space.bilibili.com/${uid}/`, + Cookie: cookie, + }, + }); + const body = JSONbig.parse(response.body); + if (body?.code === -352) { + throw new Error('Request failed, please try again.'); + } + const items = (body as BilibiliWebDynamicResponse)?.data?.items.filter((item) => item.modules.module_dynamic?.major?.type === 'MAJOR_TYPE_ARCHIVE'); + if (items && items.length > 0) { + fallbackItem = items.map((item) => { + const dynamic = item?.modules?.module_dynamic?.major?.archive; + const author = item?.modules?.module_author; + + const aid = dynamic?.aid; + const bvid = dynamic?.bvid; + + const data: DataItem = { + title: dynamic?.title ?? '', + description: !aid && !bvid ? '' : utils.renderUGCDescription(embed, '', '', aid, undefined, bvid), + pubDate: author?.pub_ts ? parseDate(author.pub_ts, 'X') : undefined, + link: author?.pub_ts && author.pub_ts > utils.bvidTime && bvid ? `https://www.bilibili.com/video/${bvid}` : `https://www.bilibili.com/video/av${aid}`, + author: name ?? undefined, + attachments: bvid + ? [ + { + url: getVideoUrl(bvid), + mime_type: 'text/html', + }, + ] + : undefined, + }; + return data; + }); + } + } catch { + logger.error(JSON.stringify(data.data)); + throw new Error(`Got error code ${data.code} while fetching: ${data.message}`); + } } return { title: `${name} 的 bilibili 空间`, link: `https://space.bilibili.com/${uid}`, description: `${name} 的 bilibili 空间`, - image: face, - logo: face, - icon: face, + image: face ?? undefined, + logo: face ?? undefined, + icon: face ?? undefined, item: - data.data && - data.data.list && - data.data.list.vlist && - data.data.list.vlist.map((item) => ({ - title: item.title, - description: utils.renderUGCDescription(embed, item.pic, item.description, item.aid, undefined, item.bvid), - pubDate: new Date(item.created * 1000).toUTCString(), - link: item.created > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`, - author: name, - comments: item.comment, - attachments: item.bvid - ? [ - { - url: getVideoUrl(item.bvid), - mime_type: 'text/html', - }, - ] - : undefined, - })), + fallbackItem ?? + (data.data && + data.data.list && + data.data.list.vlist && + data.data.list.vlist.map((item) => ({ + title: item.title, + description: utils.renderUGCDescription(embed, item.pic, item.description, item.aid, undefined, item.bvid), + pubDate: new Date(item.created * 1000).toUTCString(), + link: item.created > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`, + author: name, + comments: item.comment, + attachments: item.bvid + ? [ + { + url: getVideoUrl(item.bvid), + mime_type: 'text/html', + }, + ] + : undefined, + }))), }; }