rsshub
Version:
Make RSS Great Again!
199 lines (196 loc) • 8 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 { t as timezone } from "./timezone-D8cuwzTY.mjs";
import path from "node:path";
import { load } from "cheerio";
import iconv from "iconv-lite";
//#region lib/routes/flyert/util.ts
init_esm_shims();
const rootUrl = "https://www.flyert.com.cn";
/**
* Parses a list of articles based on a CheerioAPI object and a limit.
* @param $ The CheerioAPI object.
* @param limit The maximum number of articles to parse.
* @returns An array of parsed article objects.
*/
const parseArticleList = ($, limit) => $("div.comiis_wzli").slice(0, limit).toArray().map((item) => {
item = $(item);
const title = item.find("div.wzbt").text().trim();
const image = item.find("div.wzpic img").prop("src");
const description = art(path.join(__dirname, "templates/description-881baa33.art"), {
images: image ? [{
src: image,
alt: title
}] : void 0,
description: item.find("div.wznr").html()
});
const pubDate = item.find("div.subcat span.y").contents()?.eq(2)?.text().trim() ?? void 0;
const link = new URL(item.find("div.wzbt a").prop("href"), rootUrl).href;
return {
title,
description,
pubDate: pubDate ? parseDate(pubDate) : void 0,
link,
author: item.find("div.subcat span.y a").first().text(),
content: {
html: description,
text: item.find("div.wznr").text()
},
image,
banner: image
};
});
/**
* Parses a list of posts based on a CheerioAPI object and a limit.
* @param $ The CheerioAPI object.
* @param limit The maximum number of posts to parse.
* @returns An array of parsed post objects.
*/
const parsePostList = ($, limit) => $("div.comiis_postlist").toArray().filter((item) => {
item = $(item);
return item.find("span.comiis_common a[data-track]").toArray().some((a) => {
a = $(a);
return (a.attr("data-track") || "").endsWith("文章");
});
}).slice(0, limit).map((item) => {
item = $(item);
const aEl = $(item.find("span.comiis_common a[data-track]").toArray().find((a) => {
a = $(a);
return (a.attr("data-track") || "").endsWith("文章");
}));
const pubDate = item.find("span.author_b span").prop("title") || void 0;
return {
title: aEl.text().trim(),
pubDate: pubDate ? parseDate(pubDate) : void 0,
link: new URL(aEl.prop("href"), rootUrl).href,
author: item.find("a.author_t").text().trim()
};
});
/**
* Parses an article based on a CheerioAPI object and an item.
* @param $$ The CheerioAPI object.
* @param item The item to parse.
* @returns The parsed article object.
*/
const parseArticle = ($$, item) => {
const title = $$("h1.ph").text().trim();
const description = art(path.join(__dirname, "templates/description-881baa33.art"), {
intro: $$("div.s").text() || void 0,
description: $$("div#artMain").html()
});
const pubDate = $$("p.xg1").contents().first().text().trim()?.match(/(\d{4}-\d{1,2}-\d{1,2}\s\d{2}:\d{2})/)?.[1] ?? void 0;
const guid = `flyert-${item.link.split(/=/).pop()}`;
item.title = title;
item.description = description;
item.pubDate = pubDate ? timezone(parseDate(pubDate), 8) : item.pubDate;
item.author = $$("p.xg1 a").first().text();
item.guid = guid;
item.id = guid;
item.content = {
html: description,
text: $$("div#artMain").text()
};
return item;
};
/**
* Parses a post based on a CheerioAPI object and an item.
* @param $$ The CheerioAPI object.
* @param item The item to parse.
* @returns The parsed post object.
*/
const parsePost = ($$, item) => {
$$("img.zoom").each((_, el) => {
el = $$(el);
el.replaceWith(art(path.join(__dirname, "templates/description-881baa33.art"), { images: el.prop("zoomfile") || el.prop("file") ? [{
src: el.prop("zoomfile") || el.prop("file"),
alt: el.prop("alt") || el.prop("title")
}] : void 0 }));
});
$$("i.pstatus").remove();
$$("div.tip").remove();
const title = $$("span#thread_subject").text().trim();
const description = $$("div.post_message").first().html();
const pubDate = $$("span[title]").first().prop("title");
const tid = item.link.match(/tid=(\d+)/)?.[1] ?? void 0;
const guid = tid ? `flyert-${tid}` : void 0;
item.title = title;
item.description = description;
item.pubDate = pubDate ? timezone(parseDate(pubDate), 8) : item.pubDate;
item.author = $$("a.kmxi2").first().text();
item.guid = guid;
item.id = guid;
item.content = {
html: description,
text: $$("div.post_message").first().text()
};
return item;
};
//#endregion
//#region lib/routes/flyert/forum.ts
const handler = async (ctx) => {
const { params } = ctx.req.param();
const limit = ctx.req.query("limit") ? Number.parseInt(ctx.req.query("limit"), 10) : 5;
const decodedParams = params ? decodeURIComponent(params).split(/&/).filter((p) => p.split(/=/).length === 2).join("&") : void 0;
const currentUrl = new URL(`forum.php${decodedParams ? `?${decodedParams}` : ""}`, rootUrl).href;
const { data: response } = await got_default(currentUrl, { responseType: "buffer" });
const $ = load(iconv.decode(response, "gbk"));
const language = $("meta[http-equiv=\"Content-Language\"]").prop("content");
let items = $("table#threadlisttableid").length === 0 ? parseArticleList($, limit) : parsePostList($, limit);
items = await Promise.all(items.map((item) => cache_default.tryGet(item.link, async () => {
const { data: detailResponse } = await got_default(item.link, { responseType: "buffer" });
const $$ = load(iconv.decode(detailResponse, "gbk").replaceAll(/<\/?ignore_js_op>/g, ""));
item = $$("div.firstpost").length === 0 ? parseArticle($$, item) : parsePost($$, item);
item.language = language;
return item;
})));
const image = `https:${$("div.wp h2 a img").prop("src")}`;
return {
title: `飞客 - ${$("a.forum_name, li.a, li.cur, li.xw1, div.z > a.xw1").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")
};
};
const route = {
path: "/forum/:params{.+}?",
name: "会员说",
url: "www.flyert.com.cn",
maintainers: ["nczitzk"],
handler,
example: "/flyert/forum",
parameters: { params: "参数,默认为空,可在对应分类页 URL 中找到" },
description: `::: tip
若订阅 [酒店集团优惠](https://www.flyert.com.cn/forum.php?mod=forumdisplay&sum=all&fid=all&catid=322&filter=sortid&sortid=144&searchsort=1&youhui_type=19),网址为 \`https://www.flyert.com.cn/forum.php?mod=forumdisplay&sum=all&fid=all&catid=322&filter=sortid&sortid=144&searchsort=1&youhui_type=19\`。截取 \`https://www.flyert.com.cn/forum.php?\` 到末尾的部分 \`mod=forumdisplay&sum=all&fid=all&catid=322&filter=sortid&sortid=144&searchsort=1&youhui_type=19\` **进行 UrlEncode 编码** 后作为参数填入,此时路由为 [\`/flyert/forum/mod%3Dforumdisplay%26sum%3Dall%26fid%3Dall%26catid%3D322%26filter%3Dsortid%26sortid%3D144%26searchsort%3D1%26youhui_type%3D226\`](https://rsshub.app/flyert/forum/mod%3Dforumdisplay%26sum%3Dall%26fid%3Dall%26catid%3D322%26filter%3Dsortid%26sortid%3D144%26searchsort%3D1%26youhui_type%3D226)。
:::
`,
categories: ["bbs"],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["www.flyert.com.cn/forum.php"],
target: (_, url) => {
const params = [...url.searchParams.entries()].map(([key, value]) => key + "=" + value).join("&");
return `/forum${params ? `/${encodeURIComponent(params)}` : ""}`;
}
}]
};
//#endregion
export { handler, route };