rsshub
Version:
Make RSS Great Again!
156 lines (154 loc) • 7.21 kB
JavaScript
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs";
import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs";
import { t as md5 } from "./md5-CpIHIxCO.mjs";
import { t as cache_default } from "./cache-BkqOokyU.mjs";
import { t as timezone } from "./timezone-BBvDwS_3.mjs";
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
import { load } from "cheerio";
import { renderToString } from "hono/jsx/dom/server";
import { raw } from "hono/html";
//#region lib/routes/4ksj/forum.tsx
const renderDescription = ({ images, title, keys, details, description, info, links }) => renderToString(/* @__PURE__ */ jsxs(Fragment, { children: [
images?.map((image) => image?.src ? /* @__PURE__ */ jsx("figure", { children: /* @__PURE__ */ jsx("img", {
src: image.src,
alt: image.alt ?? void 0
}) }) : null),
title ? /* @__PURE__ */ jsx("h1", { children: title }) : null,
keys && details ? /* @__PURE__ */ jsx("table", { children: /* @__PURE__ */ jsx("tbody", { children: keys.map((key) => /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: key }), /* @__PURE__ */ jsx("td", { children: details[key] })] })) }) }) : null,
description ? /* @__PURE__ */ jsx("p", { children: description }) : null,
info ? /* @__PURE__ */ jsx("blockquote", { children: raw(info) }) : null,
links ? /* @__PURE__ */ jsx("table", { children: /* @__PURE__ */ jsx("tbody", { children: links.map((link) => /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
href: link.link,
children: link.title
}) }), /* @__PURE__ */ jsx("td", { children: link.tags?.join("") ?? "" })] })) }) }) : null
] }));
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 rofetch(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) => {
const $item = $(item);
return {
link: new URL($item.prop("href"), rootUrl).href,
title: ""
};
});
const getCookie = () => cache_default.tryGet("4ksj:cookie", async () => {
const scriptPath = load(await rofetch(items[0].link))("script").attr("src");
const scriptUrl = new URL(scriptPath, rootUrl).href;
const scriptResponse = await rofetch(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 rofetch.raw(`${rootUrl}${getPath}${key}&value=${md5(stringtoHex(value))}`)).headers.getSetCookie().map((c) => c.split(";", 1)[0]).join("; ");
});
const cookie = await getCookie();
items = await Promise.all(items.map((item) => cache_default.tryGet(item.link, async () => {
const detailResponse = await rofetch(item.link, {
responseType: "arrayBuffer",
headers: { Cookie: cookie }
});
const $$ = load(decoder.decode(detailResponse));
$$("div.nex_drama_intros em").first().remove();
$$("strong font").each((_, 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) => {
const $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) => {
const $l = $$(l);
const title = $l.contents().first().text();
const link = $l.next().prop("href") ?? $l.nextUntil("a").next().prop("href");
item.enclosure_url ??= link;
item.enclosure_type ??= "application/x-bittorrent";
item.enclosure_title ??= title;
return {
title,
tags: $l.contents().last().text().match(/【(.*?)】/g),
link
};
}) : $$("div.newfujian").toArray().map((l) => {
const $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 = renderDescription({
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 };