UNPKG

rsshub

Version:
155 lines (152 loc) 5.69 kB
import "./esm-shims-CzJ_djXG.mjs"; import "./config-C37vj7VH.mjs"; import "./dist-BInvbO1W.mjs"; import "./logger-Czu8UMNd.mjs"; import "./ofetch-BIyrKU3Y.mjs"; import { n as parseRelativeDate, t as parseDate } from "./parse-date-BrP7mxXf.mjs"; import { t as cache_default } from "./cache-Bo__VnGm.mjs"; import "./helpers-DxBp0Pty.mjs"; import { t as got_default } from "./got-KxxWdaxq.mjs"; import { t as timezone } from "./timezone-D8cuwzTY.mjs"; import { load } from "cheerio"; //#region lib/routes/hupu/types.ts /** * 用于区分不同数据项类型的类型守卫 */ function isHomePostItem(item) { return "url" in item && "isNews" in item; } //#endregion //#region lib/routes/hupu/index.ts const categories = { nba: { title: "NBA", data: "newsData" }, cba: { title: "CBA", data: "newsData" }, soccer: { title: "足球", data: "news" }, "": { title: "首页", data: "res" } }; const route = { path: ["/dept/:category?", "/:category?"], name: "手机虎扑网", url: "m.hupu.com", maintainers: ["nczitzk", "hyoban"], example: "/hupu/nba", parameters: { category: { description: "分类,可选值:nba、cba、soccer,默认为空(首页)", default: "", options: Object.entries(categories).map(([key, value]) => ({ label: value.title, value: key })) } }, description: `::: tip 电竞分类参见 [游戏热帖](https://bbs.hupu.com/all-gg) 的对应路由 [\`/hupu/all/all-gg\`](https://rsshub.app/hupu/all/all-gg)。 :::`, categories: ["bbs"], radar: [{ source: ["m.hupu.com/:category", "m.hupu.com/"], target: "/:category" }], handler: async (ctx) => { const c = ctx.req.param("category") || ""; if (!(c in categories)) throw new Error("Invalid category. Valid options are: " + Object.keys(categories).filter(Boolean).join(", ")); const category = c; const currentUrl = `https://m.hupu.com/${category}`; const scriptMatch = (await got_default({ method: "get", url: currentUrl })).data.match(/<script id="__NEXT_DATA__" type="application\/json">(.*?)<\/script>/); if (!scriptMatch || !scriptMatch[1]) throw new Error(`Failed to find __NEXT_DATA__ script tag in page: ${currentUrl}`); const fullJsonString = scriptMatch[1]; let fullData; try { fullData = JSON.parse(fullJsonString); } catch (error) { throw new Error(`Failed to parse full JSON data: ${error instanceof Error ? error.message : String(error)}`); } const { pageProps } = fullData.props; const dataKey = categories[category].data; if (!(dataKey in pageProps)) throw new Error(`Expected '${dataKey}' property not found in pageProps for category: ${category || "home"}`); let items = (() => { const data = pageProps[dataKey]; return Array.isArray(data) ? data : []; })().map((item) => isHomePostItem(item) ? { title: item.title, link: item.url.replace(/bbs\.hupu.com/, "m.hupu.com/bbs"), guid: item.tid, category: item.label ? [item.label] : void 0 } : { title: item.title, pubDate: timezone(parseDate(item.publishTime), 8), link: item.link.replace(/bbs\.hupu.com/, "m.hupu.com/bbs"), guid: item.tid }); items = await Promise.all(items.filter((item) => item.link && !/subject/.test(item.link)).map((item) => cache_default.tryGet(item.link, async () => { try { const content = load((await got_default({ method: "get", url: item.link })).data); const author = content(".bbs-user-info-name, .bbs-user-wrapper-content-name-span").text(); const pubDateString = content(".second-line-user-info span:not([class])").text(); const currentYear = (/* @__PURE__ */ new Date()).getFullYear(); const currentDate = /* @__PURE__ */ new Date(); const monthDayTimePattern = /^(\d{2})-(\d{2}) (\d{2}):(\d{2})$/; const timeOnlyPattern = /^(\d{1,2}):(\d{2})$/; let processedDateString = pubDateString; if (monthDayTimePattern.test(pubDateString)) processedDateString = `${currentYear}-${pubDateString}`; else if (timeOnlyPattern.test(pubDateString)) processedDateString = `${currentYear}-${String(currentDate.getMonth() + 1).padStart(2, "0")}-${String(currentDate.getDate()).padStart(2, "0")} ${pubDateString}`; const pubDate = [ item.pubDate, timezone(parseDate(processedDateString), 8), timezone(parseRelativeDate(pubDateString), 8) ].find((d) => d instanceof Date && !Number.isNaN(d.getTime())); const categories$1 = content(".basketballTobbs_tag > a, .tag-player-team").toArray().map((c$1) => content(c$1).text()).filter(Boolean); content(".basketballTobbs_tag").remove(); content(".hupu-img").each(function() { const imgSrc = content(this).attr("data-gif") || content(this).attr("data-origin") || content(this).attr("src"); content(this).parent().html(`<img src="${imgSrc}">`); }); const descriptionParts = []; const mainContent = content("#bbs-thread-content, .bbs-content-font").html(); if (mainContent) descriptionParts.push(mainContent); const videoWrapper = content(".header-video-wrapper"); if (videoWrapper.length > 0) { const videoElement = videoWrapper.find("video"); if (videoElement.length > 0) { const videoHtml = videoElement.prop("outerHTML"); if (videoHtml) descriptionParts.push(videoHtml); } } const description = descriptionParts.length > 0 ? descriptionParts.join("") : void 0; return { ...item, author, category: categories$1.length > 0 ? categories$1 : item.category, description, pubDate }; } catch { return item; } }))); return { title: `虎扑 - ${categories[category].title}`, link: currentUrl, item: items }; } }; //#endregion export { route };