rsshub
Version:
Make RSS Great Again!
94 lines (81 loc) • 3.41 kB
text/typescript
import { Route } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
export const route: Route = {
path: '/manga/update/:comicid',
categories: ['social-media'],
example: '/bilibili/manga/update/26009',
parameters: { comicid: '漫画 id, 可在 URL 中找到, 支持带有`mc`前缀' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['manga.bilibili.com/detail/:comicid'],
},
],
name: '漫画更新',
maintainers: ['hoilc'],
handler,
};
// Based on https://github.com/SocialSisterYi/bilibili-API-collect/issues/1168#issuecomment-2620749895
async function genReqSign(query, body) {
// Don't import on top-level to avoid a cyclic dependency - wasm-exec.js generated via `pnpm build`, which in turn needs wasm-exec.js to import routes correctly
const { Go } = await import('./wasm-exec');
// Cache the wasm binary as it's quite large (~2MB)
// Here the binary is saved as base64 as the cache stores strings
const wasmBufferBase64 = await cache.tryGet('bilibili-manga-wasm-20250208', async () => {
const wasmResp = await got('https://s1.hdslb.com/bfs/manga-static/manga-pc/6732b1bf426cfc634293.wasm', {
responseType: 'arrayBuffer',
});
return Buffer.from(wasmResp.data).toString('base64');
});
const wasmBuffer = Buffer.from(wasmBufferBase64, 'base64');
const go = new Go();
const { instance } = await WebAssembly.instantiate(wasmBuffer, go.importObject);
go.run(instance);
if (void 0 === globalThis.genReqSign) {
throw new Error('WASM function not available');
}
const signature = globalThis.genReqSign(query, body, Date.now());
return signature.sign;
}
async function handler(ctx) {
const comic_id = ctx.req.param('comicid').startsWith('mc') ? ctx.req.param('comicid').replace('mc', '') : ctx.req.param('comicid');
const link = `https://manga.bilibili.com/detail/mc${comic_id}`;
const spi_response = await got('https://api.bilibili.com/x/frontend/finger/spi');
const query = 'device=pc&platform=web&nov=25';
const body = JSON.stringify({
comic_id: Number(comic_id),
});
const ultraSign = await genReqSign(query, body);
const response = await got({
method: 'POST',
url: `https://manga.bilibili.com/twirp/comic.v2.Comic/ComicDetail?${query}&ultra_sign=${ultraSign}`,
body,
headers: {
Referer: link,
Cookie: `buvid3=${spi_response.data.data.b_3}; buvid4=${spi_response.data.data.b_4}`,
},
});
const data = response.data.data;
const author = data.author_name.join(', ');
return {
title: `${data.title} - 哔哩哔哩漫画`,
link,
image: data.vertical_cover,
description: data.classic_lines,
item: data.ep_list.slice(0, 20).map((item) => ({
title: item.short_title === item.title ? item.short_title : `${item.short_title} ${item.title}`,
author,
description: `<img src="${item.cover}">`,
pubDate: new Date(item.pub_time + ' +0800'),
link: `https://manga.bilibili.com/mc${comic_id}/${item.id}`,
})),
};
}