UNPKG

rsshub

Version:
289 lines (274 loc) • 11.4 kB
import cache from '@/utils/cache'; import got from '@/utils/got'; import utils from './utils'; import { load } from 'cheerio'; import { config } from '@/config'; import logger from '@/utils/logger'; import { getPuppeteerPage } from '@/utils/puppeteer'; import { JSDOM } from 'jsdom'; const getCookie = (disableConfig = false) => { if (Object.keys(config.bilibili.cookies).length > 0 && !disableConfig) { // Update b_lsid in cookies for (const key of Object.keys(config.bilibili.cookies)) { const cookie = config.bilibili.cookies[key]; if (cookie) { const updatedCookie = cookie.replace(/b_lsid=[0-9A-F]+_[0-9A-F]+/, `b_lsid=${utils.lsid()}`); config.bilibili.cookies[key] = updatedCookie; } } return config.bilibili.cookies[Object.keys(config.bilibili.cookies)[Math.floor(Math.random() * Object.keys(config.bilibili.cookies).length)]]; } const key = 'bili-cookie'; return cache.tryGet(key, async () => { let waitForRequest: Promise<string> = new Promise((resolve) => { resolve(''); }); const { destory } = await getPuppeteerPage('https://space.bilibili.com/1/dynamic', { onBeforeLoad: (page) => { waitForRequest = new Promise<string>((resolve) => { page.on('requestfinished', async (request) => { if (request.url() === 'https://api.bilibili.com/x/internal/gaia-gateway/ExClimbWuzhi') { const cookies = await page.cookies(); let cookieString = cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; '); cookieString = cookieString.replace(/b_lsid=[0-9A-F]+_[0-9A-F]+/, `b_lsid=${utils.lsid()}`); resolve(cookieString); } }); }); }, }); const cookieString = await waitForRequest; logger.debug(`Got bilibili cookie: ${cookieString}`); await destory(); return cookieString; }); }; const getRenderData = (uid) => { const key = 'bili-web-render-data'; return cache.tryGet(key, async () => { const cookie = await getCookie(); const { data: response } = await got(`https://space.bilibili.com/${uid}`, { headers: { Referer: 'https://www.bilibili.com/', Cookie: cookie, }, }); const dom = new JSDOM(response); const document = dom.window.document; const scriptElement = document.querySelector('#__RENDER_DATA__'); const innerText = scriptElement ? scriptElement.textContent || '{}' : '{}'; const renderData = JSON.parse(decodeURIComponent(innerText)); const accessId = renderData.access_id; return accessId; }); }; const getWbiVerifyString = () => { const key = 'bili-wbi-verify-string'; return cache.tryGet(key, async () => { const cookie = await getCookie(); const { data: navResponse } = await got('https://api.bilibili.com/x/web-interface/nav', { headers: { Referer: 'https://www.bilibili.com/', Cookie: cookie, }, }); const imgUrl = navResponse.data.wbi_img.img_url; const subUrl = navResponse.data.wbi_img.sub_url; const r = imgUrl.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length).split('.')[0] + subUrl.substring(subUrl.lastIndexOf('/') + 1, subUrl.length).split('.')[0]; // const { body: spaceResponse } = await got('https://space.bilibili.com/1', { // headers: { // Referer: 'https://www.bilibili.com/', // Cookie: cookie, // }, // }); // const jsUrl = 'https:' + spaceResponse.match(/[^"]*9.space[^"]*/); const jsUrl = 'https://s1.hdslb.com/bfs/seed/laputa-header/bili-header.umd.js'; const { body: jsResponse } = await got(jsUrl, { headers: { Referer: 'https://space.bilibili.com/1', }, }); // const array = [ // 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, // 62, 11, 36, 20, 34, 44, 52, // ]; const array = JSON.parse(jsResponse.match(/\[(?:\d+,){63}\d+]/)); const o = []; for (const t of array) { r.charAt(t) && o.push(r.charAt(t)); } return o.join('').slice(0, 32); }); }; const getUsernameFromUID = (uid) => { const key = 'bili-username-from-uid-' + uid; return cache.tryGet(key, async () => { const cookie = await getCookie(); const wbiVerifyString = await getWbiVerifyString(); // await got(`https://space.bilibili.com/${uid}/`, { // headers: { // Referer: 'https://www.bilibili.com/', // Cookie: cookie, // }, // }); const params = utils.addWbiVerifyInfo(`mid=${uid}&token=&platform=web&web_location=1550101`, wbiVerifyString); const { data: nameResponse } = await got(`https://api.bilibili.com/x/space/wbi/acc/info?${params}`, { headers: { Referer: `https://space.bilibili.com/${uid}/`, Cookie: cookie, }, }); return nameResponse.data ? nameResponse.data.name : undefined; }); }; const getUsernameAndFaceFromUID = async (uid) => { const nameKey = 'bili-username-from-uid-' + uid; const faceKey = 'bili-userface-from-uid-' + uid; let name = await cache.get(nameKey); let face = await cache.get(faceKey); if (!name || !face) { const cookie = await getCookie(); const wbiVerifyString = await getWbiVerifyString(); const dmImgList = utils.getDmImgList(); const renderData = await getRenderData(uid); const params = utils.addWbiVerifyInfo(utils.addRenderData(utils.addDmVerifyInfo(`mid=${uid}&token=&platform=web&web_location=1550101`, dmImgList), renderData), wbiVerifyString); const { data: nameResponse } = await got(`https://api.bilibili.com/x/space/wbi/acc/info?${params}`, { headers: { Referer: `https://space.bilibili.com/${uid}/`, Cookie: cookie, }, }); if (nameResponse.data.name) { name = nameResponse.data.name; face = nameResponse.data.face; } else { logger.error(`Error when visiting /x/space/wbi/acc/info: ${JSON.stringify(nameResponse)}`); } cache.set(nameKey, name); cache.set(faceKey, face); } return [name, face]; }; const getLiveIDFromShortID = (shortID) => { const key = `bili-liveID-from-shortID-${shortID}`; return cache.tryGet(key, async () => { const { data: liveIDResponse } = await got(`https://api.live.bilibili.com/room/v1/Room/room_init?id=${shortID}`, { headers: { Referer: `https://live.bilibili.com/${shortID}`, }, }); return liveIDResponse.data.room_id; }); }; const getUserInfoFromLiveID = (liveID) => { const key = `bili-userinfo-from-liveID-${liveID}`; return cache.tryGet(key, async () => { const { data: nameResponse } = await got(`https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room?roomid=${liveID}`, { headers: { Referer: `https://live.bilibili.com/${liveID}`, }, }); return nameResponse.data.info; }); }; const getVideoNameFromId = (aid, bvid) => { const key = `bili-videoname-from-id-${bvid || aid}`; return cache.tryGet(key, async () => { const { data } = await got(`https://api.bilibili.com/x/web-interface/view`, { searchParams: { aid: aid || undefined, bvid: bvid || undefined, }, referer: `https://www.bilibili.com/video/${bvid || `av${aid}`}`, }); return data.data.title; }); }; const getCidFromId = (aid, pid, bvid) => { const key = `bili-cid-from-id-${bvid || aid}-${pid}`; return cache.tryGet(key, async () => { const { data } = await got(`https://api.bilibili.com/x/web-interface/view?${bvid ? `bvid=${bvid}` : `aid=${aid}`}`, { referer: `https://www.bilibili.com/video/${bvid || `av${aid}`}`, }); return data.data.pages[pid - 1].cid; }); }; const getAidFromBvid = async (bvid) => { const key = `bili-cid-from-bvid-${bvid}`; let aid = await cache.get(key); if (!aid) { const response = await got(`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`, { headers: { Referer: `https://www.bilibili.com/video/${bvid}`, }, }); if (response.data && response.data.data && response.data.data.aid) { aid = response.data.data.aid; } cache.set(key, aid); } return aid; }; const getArticleDataFromCvid = async (cvid, uid) => { const url = `https://www.bilibili.com/read/cv${cvid}/`; const data = await cache.tryGet( url, async () => ( await got({ method: 'get', url, headers: { Referer: `https://space.bilibili.com/${uid}/`, }, }) ).data ); const $ = load(data); let description = $('#read-article-holder').html(); if (!description) { try { const newFormatData = JSON.parse( $('script:contains("window.__INITIAL_STATE__")') .text() .match(/window\.__INITIAL_STATE__\s*=\s*(.*?);\(/)[1] ); if (newFormatData?.readInfo?.opus?.content?.paragraphs) { description = ''; for (const element of newFormatData.readInfo.opus.content.paragraphs) { if (element.para_type === 1) { for (const text of element.text.nodes) { if (text?.word?.words) { description += `<p>${text.word.words}</p>`; } } } if (element.para_type === 2) { for (const image of element.pic.pics) { description += `<p ><img src="${image.url}@progressive.webp"></p>`; } } if (element.para_type === 3 && element.line?.pic?.url) { description += `<figure><img src="${element.line.pic.url}"></figure>`; } } } } catch { /* empty */ } } return { url, description }; }; export default { getCookie, getWbiVerifyString, getUsernameFromUID, getUsernameAndFaceFromUID, getLiveIDFromShortID, getUserInfoFromLiveID, getVideoNameFromId, getCidFromId, getAidFromBvid, getArticleDataFromCvid, getRenderData, };