UNPKG

rsshub

Version:
101 lines (100 loc) 4.13 kB
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs"; import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs"; import { t as cache_default } from "./cache-BkqOokyU.mjs"; import { t as timezone } from "./timezone-BBvDwS_3.mjs"; import { t as InvalidParameterError } from "./invalid-parameter-CGxhjomn.mjs"; import { t as isValidHost } from "./valid-host-BH9Dd2Pf.mjs"; import { load } from "cheerio"; import iconv from "iconv-lite"; //#region lib/routes/people/index.ts const route = { path: "/:site?/:category{.+}?", name: "首页头条", maintainers: ["nczitzk", "pseudoyu"], example: "/people", handler }; async function handler(ctx) { const { site = "www" } = ctx.req.param(); const { category: requestedCategory = site === "www" ? "59476" : "" } = ctx.req.param(); const category = site === "cpc" && requestedCategory === "24h" ? "64093/64387" : requestedCategory; const limit = ctx.req.query("limit") ? Number(ctx.req.query("limit")) : 30; if (!isValidHost(site)) throw new InvalidParameterError("Invalid site"); const rootUrl = `http://${site}.people.com.cn`; const path = site === "politics" && !category ? "GB/1024" : site === "society" && category === "1008" ? "" : category ? `GB/${category}` : ""; const requestedUrl = new URL(path, rootUrl).href; const { $, url: currentUrl } = await fetchChannel(requestedUrl); const articleRootUrl = new URL("/", currentUrl).href; $("em").remove(); $(".bshare-more, .page_n, .page").remove(); $("a img, h3 img").each((_, e) => { $(e).parent().remove(); }); let items = $(".p6, div.p2j_list, div.headingNews, div.ej_list_box, .leftItem, div.p2j_con02 > div.fl, div.jsnew_line").find("a").slice(0, limit).toArray().map((item) => { const $item = $(item); const link = $item.attr("href"); return { title: $item.text(), link: link.startsWith("http") ? link : new URL(link.replace(/^\.\./, ""), articleRootUrl).href }; }); items = await Promise.all(items.map((item) => cache_default.tryGet(item.link, async () => { try { const detailPage = await fetchPage(item.link); detailPage.$(".paper_num, #rwb_tjyd").remove(); item.description = detailPage.$("#rwb_zw, #rm_txt_zw, .rm_txt_con, .show_text").first().html(); item.pubDate = timezone(parseDate(detailPage.html.match(/(\d{4}年\d{2}月\d{2}日\d{2}:\d{2})/)?.[1] || "", "YYYY年MM月DD日 HH:mm"), 8); } catch (error) { item.description = String(error); } return item; }))); return { title: $("title").text(), link: currentUrl, item: items }; } async function fetchChannel(url) { const page = await fetchPage(url); const refreshElement = page.$("meta[http-equiv]").toArray().find((element) => page.$(element).attr("http-equiv")?.toLowerCase() === "refresh"); const refreshContent = refreshElement ? page.$(refreshElement).attr("content") : void 0; const redirectSeparator = refreshContent?.match(/;\s*url\s*=/i); const redirectTarget = redirectSeparator?.index === void 0 ? void 0 : refreshContent?.slice(redirectSeparator.index + redirectSeparator[0].length).trim().replaceAll(/^['"]|['"]$/g, ""); if (!redirectTarget) return { ...page, url }; const redirectUrl = resolvePeopleRedirect(redirectTarget, url); if (!redirectUrl) return { ...page, url }; return { ...await fetchPage(redirectUrl), url: redirectUrl }; } async function fetchPage(url) { const response = await rofetch(url, { responseType: "arrayBuffer" }); let html = iconv.decode(Buffer.from(response), "utf-8"); const parsedCharset = html.match(/<meta.*?charset=["']?([^"'>]+)["']?/i); const encoding = parsedCharset ? parsedCharset[1].toLowerCase() : "utf-8"; html = encoding === "utf-8" ? html : iconv.decode(Buffer.from(response), encoding); return { $: load(html), html }; } function resolvePeopleRedirect(target, sourceUrl) { try { const url = new URL(target, sourceUrl); const isHttp = url.protocol === "http:" || url.protocol === "https:"; const isPeopleHost = url.hostname === "people.com.cn" || url.hostname.endsWith(".people.com.cn"); return isHttp && isPeopleHost ? url.href : void 0; } catch { return; } } //#endregion export { route };