UNPKG

rsshub

Version:
145 lines (142 loc) 6.28 kB
import { n as init_esm_shims, t as __dirname } from "./esm-shims-CzJ_djXG.mjs"; import "./config-C37vj7VH.mjs"; import "./dist-BInvbO1W.mjs"; import "./logger-Czu8UMNd.mjs"; import { t as ofetch_default } from "./ofetch-BIyrKU3Y.mjs"; import { t as parseDate } from "./parse-date-BrP7mxXf.mjs"; import { t as md5 } from "./md5-C8GRvctM.mjs"; import { t as cache_default } from "./cache-Bo__VnGm.mjs"; import { t as art } from "./render-BQo6B4tL.mjs"; import { t as timezone } from "./timezone-D8cuwzTY.mjs"; import path from "node:path"; import { load } from "cheerio"; //#region lib/routes/4ksj/forum.ts init_esm_shims(); const route = { path: "/:id?", name: "分类", url: "4ksj.com", maintainers: ["nczitzk"], handler, example: "/4ksj/4k-uhd-1", parameters: { id: "分类 id,默认为最新4K电影" }, description: `::: tip 若订阅 [最新 4K 电影](https://www.4ksj.com/4k-uhd-1.html),网址为 \`https://www.4ksj.com/4k-uhd-1.html\`。截取 \`https://www.4ksj.com/\` 到末尾 \`.html\` 的部分 \`4k-uhd-1\` 作为参数,此时路由为 [\`/4ksj/4k-uhd-1\`](https://rsshub.app/4ksj/4k-uhd-1)。 若订阅子分类 [Dolby Vision 动作 4K 电影](https://www.4ksj.com/4k-uhd-s7-display-3-dytypes-1-1.html),网址为 \`https://www.4ksj.com/4k-uhd-s7-display-3-dytypes-1-1.html\`。截取 \`https://www.4ksj.com/forum-\` 到末尾 \`.html\` 的部分 \`4kdianying-s7-dianyingbiaozhun-3-dytypes-9-1\` 作为参数,此时路由为 [\`/4ksj/4k-uhd-s7-display-3-dytypes-1-1\`](https://rsshub.app/4ksj/4k-uhd-s7-display-3-dytypes-1-1)。 :::`, categories: ["multimedia"] }; function stringtoHex(acSTR) { let val = ""; for (let i = 0; i <= acSTR.length - 1; i++) { const code = acSTR.charAt(i).codePointAt(); val += code; } return val; } async function handler(ctx) { const { id = "4k-uhd-1" } = ctx.req.param(); const limit = ctx.req.query("limit") ? Number.parseInt(ctx.req.query("limit")) : 25; const rootUrl = "https://www.4ksj.com"; const currentUrl = new URL(`${id}.html`, rootUrl).href; const response = await ofetch_default(currentUrl, { responseType: "arrayBuffer" }); const decoder = new TextDecoder("gbk"); const $ = load(decoder.decode(response)); const language = "zh"; const image = $("div.nexlogo img").prop("src"); let items = $("div.nex_cmo_piv a").slice(0, limit).toArray().map((item) => { item = $(item); return { link: new URL(item.prop("href"), rootUrl).href }; }); const getCookie = () => cache_default.tryGet("4ksj:cookie", async () => { const scriptPath = load(await ofetch_default(items[0].link))("script").attr("src"); const scriptUrl = new URL(scriptPath, rootUrl).href; const scriptResponse = await ofetch_default(scriptUrl); const key = scriptResponse.match(/{var key="(.*?)"/)?.[1]; const value = scriptResponse.match(/",value="(.*?)"/)?.[1]; const getPath = scriptResponse.match(/\.get\("(.*?&key=)"/)?.[1]; if (!key || !value || !getPath) throw new Error("Failed to get cookie"); return (await ofetch_default.raw(`${rootUrl}${getPath}${key}&value=${md5(stringtoHex(value))}`)).headers.getSetCookie().map((c) => c.split(";")[0]).join("; "); }); const cookie = await getCookie(); items = await Promise.all(items.map((item) => cache_default.tryGet(item.link, async () => { const detailResponse = await ofetch_default(item.link, { responseType: "arrayBuffer", headers: { Cookie: cookie } }); const $$ = load(decoder.decode(detailResponse)); $$("div.nex_drama_intros em").first().remove(); $$("strong font").each((_, el) => { el = $$(el); el.parent().remove(); }); const title = $$("div.nex_drama_Top h5").text(); const description = $$("div.nex_drama_intros").html(); const picture = $$("div.nex_drama_pic").html().match(/background:url\((.*?)\)/)?.[1] ?? ""; const details = $$("li.nex_drama_Detail_li, li.nex_drama_Detail_lis dd").toArray().map((li) => { li = $$(li); const key = li.find("em").text().replaceAll(/:|\s/g, ""); const value = li.find("span").length === 0 ? li.contents().last().text().trim() : li.find("span").text().trim(); return { [key]: value }; }); const mergedDetails = Object.assign({}, ...details); const links = $$("td.t_f ignore_js_op").length === 0 ? $$("td.t_f strong").toArray().map((l) => { l = $$(l); const title$1 = l.contents().first().text(); const link = l.next().prop("href") ?? l.nextUntil("a").next().prop("href"); item.enclosure_url = item.enclosure_url ?? link; item.enclosure_type = item.enclosure_type ?? "application/x-bittorrent"; item.enclosure_title = item.enclosure_title ?? title$1; return { title: title$1, tags: l.contents().last().text().match(/【(.*?)】/g), link }; }) : $$("div.newfujian").toArray().map((l) => { l = $$(l); return { title: l.find("p.filename").prop("title") || l.find("p.filename").text(), tags: l.find("div.fileaq").text().match(/【(.*?)】/g), link: l.find("div.down_2 a").prop("href") }; }); const pubDateEl = $$("table.boxtable em").first(); const pubDate = pubDateEl.find("span[title]").length === 0 ? pubDateEl.first().text().replace(/发表于\s/, "") : pubDateEl.find("span[title]").prop("title"); item.title = title; item.description = art(path.join(__dirname, "templates/description-6a5b9b89.art"), { images: picture ? [{ src: picture, alt: title }] : void 0, title, keys: Object.keys(mergedDetails), details: mergedDetails, description, info: $$("div.nex_drama_sums").html(), links }); item.pubDate = timezone(parseDate(pubDate, "YYYY-M-D HH:mm:ss"), 8); item.category = Object.values(mergedDetails).flatMap((c) => c.split(/\s/)).filter(Boolean); item.author = mergedDetails["导演"]; item.content = { html: description, text: $$("div.nex_drama_intros").text() }; item.image = picture; item.banner = picture; item.language = language; return item; }))); return { title: `4k世界 - ${$("#fontsearch ul.cl li.a").toArray().map((a) => $(a).text()).join("+") || "不限"}`, description: $("meta[name=\"description\"]").prop("content"), link: currentUrl, item: items, allowEmpty: true, image, author: $("meta[name=\"application-name\"]").prop("content"), language }; } //#endregion export { route };