rsshub
Version:
Make RSS Great Again!
177 lines (174 loc) • 7.12 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 "./ofetch-BIyrKU3Y.mjs";
import { t as parseDate } from "./parse-date-BrP7mxXf.mjs";
import { t as cache_default } from "./cache-Bo__VnGm.mjs";
import "./helpers-DxBp0Pty.mjs";
import { t as art } from "./render-BQo6B4tL.mjs";
import { t as got_default } from "./got-KxxWdaxq.mjs";
import path from "node:path";
import { load } from "cheerio";
//#region lib/routes/newzmz/util.ts
init_esm_shims();
const rootUrl = "https://nzmz.xyz";
/**
* Retrieve all movies and TV shows under a specified category on the homepage and obtain their detail links.
* @param {function} tryGet - cache.tryGet
* @param {string} homeUrl - Homepage URL
* @param {string} id - Category id
* @param {string} modSelector - Selector for mods
* @param {string} itemSelector - Selector for items
* @returns {Array} An array containing the links in the map.
*/
const getItems = async (tryGet, homeUrl, id, modSelector, itemSelector) => {
const $ = load(await tryGet(homeUrl, async () => {
const { data: response } = await got_default(homeUrl);
return response;
}));
return $(modSelector).eq(Number.parseInt(id, 10)).find(itemSelector).toArray().map((item) => {
item = $(item);
return { link: new URL(item.prop("href"), rootUrl).href };
});
};
/**
* Obtain the information corresponding to a given movie or TV show item based on the provided URL.
* @param {function} tryGet - cache.tryGet
* @param {string} itemUrl - Item URL
* @returns {Object} An object containing information of the item.
*/
const getItemInfo = (tryGet, itemUrl) => tryGet(`newzmz#${itemUrl.match(/details-(.*?)\.html/)[1]}`, async () => {
const { data: detailResponse } = await got_default(itemUrl);
const content = load(detailResponse);
const nameZh = content("div.chsname").text();
const nameEn = content("div.engname").text();
const alias = content("div.aliasname").text().replace(/又名:/, "").split("/").map((a) => a.trim()).filter(Boolean);
return {
link: content("a.addgz").prop("href"),
pubDate: parseDate(content("span.duration").first().text().match(/(\d{4}-\d{2}-\d{2})/)[1]),
description: {
image: content("div.details-bg img").prop("src"),
nameZh,
nameEn,
alias,
update: content("span.upday").text(),
links: content("div.ep-infos a[title]").toArray().map((a) => {
a = content(a);
return {
title: a.prop("title"),
link: a.prop("href")
};
})
},
author: content("ul.sws-list").first().find("h5.title").toArray().map((a) => content(a).text()).join(" / "),
category: [
nameZh,
nameEn,
...alias
]
};
});
/**
* Retrieve all the episode items from the corresponding download page of a movie or TV show.
* @param {Object} i - Preprocessed item object
* @param {string} downLinkType - Type of download link, with the default value being `磁力链`. The website provides various types of download links, including but not limited to `磁力链`, `百度网盘`, `阿里云盘`, `夸克网盘`, `UC网盘`, and more. If the specified download link type cannot be found, the first download link will be returned instead.
* @param {string} itemSelector - Selector for items
* @param {string} categorySelector - Selector for categories
* @param {string} downLinkSelector - Selector for download links
* @returns {Array} An array containing RSS feed objects in the map.
*/
const processItems = async (i, downLinkType, itemSelector, categorySelector, downLinkSelector) => {
const { data: detailResponse } = await got_default(i.link);
const content = load(detailResponse);
return content(itemSelector).toArray().map((item) => {
item = content(item);
const categories = item.find(categorySelector).toArray().map((c) => content(c).text());
const downLinks = item.find(downLinkSelector).toArray().map((downLink) => {
downLink = content(downLink);
return {
title: downLink.find("p.link-name").text(),
link: downLink.find("a[title]").prop("href")
};
});
const subtitle = item.find("span.up").text().replaceAll(/[\s-]+/g, "");
const title = `${i.description.nameZh || i.description.nameEn}|${subtitle}`;
return {
guid: `newzmz#${i.link.match(/view\/(.*?)\.html/)[1]}-${subtitle}`,
title,
link: i.link,
description: art(path.join(__dirname, "templates/description-f7b4d948.art"), {
...i.description,
categories,
downLinks
}),
author: i.author,
category: [...i.category, ...categories].filter(Boolean),
pubDate: i.pubDate,
enclosure_url: downLinks.findLast((l) => l.title === downLinkType)?.link ?? downLinks[0].link,
enclosure_type: "application/x-bittorrent"
};
});
};
//#endregion
//#region lib/routes/newzmz/index.ts
const route = {
path: "/:id?/:downLinkType?",
categories: ["multimedia"],
example: "/newzmz/qEzRyY3v",
parameters: {
id: "剧集 id,可在剧集下载页 URL 中找到",
downLinkType: "下载链接类型,默认为磁力链"
},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["newzmz.com/"],
target: ""
}],
name: "指定剧集",
maintainers: ["nczitzk"],
handler,
url: "newzmz.com/",
description: `::: tip
[雪国列车 (剧版)](https://nzmz.xyz/details-qEzRyY3v.html) 的下载页 URL 为 \`https://v.ys99.xyz/view/qEzRyY3v.html\`,即剧集 id 为 \`qEzRyY3v\`
:::`
};
async function handler(ctx) {
const { id = "1", downLinkType = "磁力链" } = ctx.req.param();
const limit = ctx.req.query("limit") ? Number.parseInt(ctx.req.query("limit"), 10) : 50;
const isCategory = !Number.isNaN(id);
const currentUrl = new URL(isCategory ? "index.html" : `details-${id}.html`, rootUrl).href;
const $ = load(await cache_default.tryGet(currentUrl, async () => {
const { data: response } = await got_default(currentUrl);
return response;
}));
let items = isCategory ? await getItems(cache_default.tryGet, currentUrl, id, "div.rowMod", "ul.slides li a") : [{ link: currentUrl }];
items = await Promise.all(items.slice(0, limit).map((item) => getItemInfo(cache_default.tryGet, item.link)));
items = await Promise.all(items.filter((item) => item.link !== "#").map((i) => processItems(i, downLinkType, "div.team-con-area", "div.item-label a", "ul.team-icons li")));
items = items.flat();
const headerTitle = isCategory ? $("div.rowMod").eq(Number.parseInt(id, 10)).find("h2.row-header-title").text() : "";
const title = `${$("title").text()}${headerTitle ? ` - ${headerTitle}` : ""}`;
const icon = $("link[rel=\"shortcut icon\"]").prop("href");
return {
item: isCategory ? items : items.slice(0, limit),
title,
link: currentUrl,
description: $("meta[name=\"description\"]").prop("content"),
language: "zh-cn",
image: $("img.logo-img").prop("src"),
icon,
logo: icon,
subtitle: $("meta[name=\"keywords\"]").prop("content"),
author: title,
allowEmpty: true
};
}
//#endregion
export { route };