UNPKG

rsshub

Version:
137 lines (136 loc) 5.73 kB
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs"; import { t as config } from "./config-CCmw1BNE.mjs"; import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs"; import { t as cache_default } from "./cache-BkqOokyU.mjs"; import { t as InvalidParameterError } from "./invalid-parameter-CGxhjomn.mjs"; import { t as ConfigNotFoundError } from "./config-not-found-fQ5mxvDU.mjs"; import { load } from "cheerio"; import iconv from "iconv-lite"; //#region lib/routes/discuz/discuz.ts function fixUrl(itemLink, baseUrl) { if (itemLink) { if (baseUrl && !/^https?:\/\//.test(baseUrl)) baseUrl = baseUrl.startsWith("//") ? "http:" + baseUrl : "http://" + baseUrl; itemLink = new URL(itemLink, baseUrl).href; } return itemLink; } async function fetchWithAntiBot(url, header) { let response = await rofetch.raw(url, { method: "get", responseType: "arrayBuffer", headers: header }); let responseData = Buffer.from(response._data); if (iconv.decode(responseData, "utf-8").includes("document.location.reload()")) { const cookieStr = (response.headers.getSetCookie?.() ?? []).map((c) => c.split(";", 1)[0]).join("; "); if (cookieStr) { response = await rofetch.raw(url, { method: "get", responseType: "arrayBuffer", headers: { ...header, Cookie: [header.Cookie, cookieStr].filter(Boolean).join("; ") } }); responseData = Buffer.from(response._data); } } return { response, responseData }; } async function loadContent(itemLink, charset, header) { const { responseData: rawData } = await fetchWithAntiBot(itemLink, header); const responseData = iconv.decode(rawData, charset ?? "utf-8"); if (!responseData) return { description: "获取详细内容失败" }; const $ = load(responseData); const post = $("div#postlist div[id^=post] td[id^=postmessage]").first(); post.find("img").each((_, img) => { const $img = $(img); if ($img.attr("src")?.endsWith("none.gif") && $img.attr("file")) { $img.attr("src", $img.attr("file") || $img.attr("zoomfile")); $img.removeAttr("file"); $img.removeAttr("zoomfile"); } }); return { description: post.html() }; } const route = { path: [ "/:ver{[7x]}/:cid{[0-9]{2}}/:link{.+}", "/:ver{[7x]}/:link{.+}", "/:link{.+}" ], categories: ["bbs"], example: "/discuz/x/https%3a%2f%2fwww.52pojie.cn%2fforum-16-1.html", parameters: { ver: "discuz version,see below table", cid: "Cookie id,require self hosted and set environment parameters, see Deploy - Configuration pages for detail", link: "link of subforum, require url encoded" }, name: "通用子版块", maintainers: ["junfengP", "pseudoyu"], handler, description: `| Discuz X Series | Discuz 7.x Series | | --------------- | ----------------- | | x | 7 |` }; async function handler(ctx) { let link = ctx.req.param("link"); const ver = ctx.req.param("ver") ? ctx.req.param("ver").toUpperCase() : void 0; const cid = ctx.req.param("cid"); link = link.replace(/:\/\//, ":/").replace(/:\//, "://"); const cookie = cid === void 0 ? "" : config.discuz.cookies[cid]; if (cookie === void 0) throw new ConfigNotFoundError("缺少对应论坛的cookie."); const header = { Cookie: cookie }; const { response, responseData } = await fetchWithAntiBot(link, header); const contentType = response.headers["content-type"] || ""; let $ = load(iconv.decode(responseData, "utf-8")); const charset = contentType.match(/charset=([^;]*)/)?.[1] ?? $("meta[charset]").attr("charset") ?? $("meta[http-equiv=\"Content-Type\"]").attr("content")?.split("charset=", 2)?.[1]; if (charset?.toLowerCase() !== "utf-8") $ = load(iconv.decode(responseData, charset ?? "utf-8")); const version = ver ? `DISCUZ! ${ver}` : $("head > meta[name=generator]").attr("content"); if (!version) throw new InvalidParameterError("无法检测 Discuz 版本,请在路由中指定版本参数,如 /discuz/x/ 或 /discuz/7/"); let items; if (version.toUpperCase().startsWith("DISCUZ! 7")) { const list = $("tbody[id^=\"normalthread\"] > tr").slice(0, ctx.req.query("limit") ? Number(ctx.req.query("limit")) : 5).toArray().map((item) => { const $item = $(item); const a = $item.find("span[id^=thread] a"); return { title: a.text().trim(), link: fixUrl(a.attr("href"), link), pubDate: $item.find("td.author em").length ? parseDate($item.find("td.author em").text().trim()) : void 0, author: $item.find("td.author cite a").text().trim() }; }); items = await Promise.all(list.map((item) => cache_default.tryGet(item.link, async () => { const { description } = await loadContent(item.link, charset, header); item.description = description; return item; }))); } else if (version.toUpperCase().startsWith("DISCUZ! X")) { const list = $("tbody[id^=\"normalthread\"] > tr").slice(0, ctx.req.query("limit") ? Number(ctx.req.query("limit")) : 5).toArray().map((item) => { const $item = $(item); const a = $item.find("a.xst"); return { title: a.text(), link: fixUrl(a.attr("href"), link), pubDate: $item.find("td.by:nth-child(3) em span").last().length ? parseDate($item.find("td.by:nth-child(3) em span").last().text().trim()) : void 0, author: $item.find("td.by:nth-child(3) cite a").text().trim() }; }); items = await Promise.all(list.map((item) => cache_default.tryGet(item.link, async () => { const { description } = await loadContent(item.link, charset, header); item.description = description; return item; }))); } else throw new InvalidParameterError("不支持当前Discuz版本."); return { title: $("head > title").text(), description: $("head > meta[name=description]").attr("content"), link, item: items }; } //#endregion export { route };