rsshub
Version:
Make RSS Great Again!
145 lines (142 loc) • 6.28 kB
JavaScript
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 };