rsshub
Version:
Make RSS Great Again!
194 lines (189 loc) • 6.81 kB
JavaScript
import { n as init_esm_shims, t as __dirname } from "./esm-shims-CzJ_djXG.mjs";
import "./config-C37vj7VH.mjs";
import { t as ViewType } from "./types-D84BRIt4.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 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/oschina/column.ts
init_esm_shims();
const handler = async (ctx) => {
const { id } = ctx.req.param();
const limit = Number.parseInt(ctx.req.query("limit") ?? "10", 10);
const baseUrl = "https://www.oschina.net";
const userHostRegex = String.raw`https://my\.oschina\.net`;
const targetUrl = new URL(`news/column?columnId=${id}`, baseUrl).href;
const $ = load(await ofetch_default(targetUrl));
const language = $("html").attr("lang") ?? "zh-CN";
let items = [];
items = $("div.news-item").slice(0, limit).toArray().map((el) => {
const $el = $(el);
const title = $el.find("div.title").text();
const description = art(path.join(__dirname, "templates/description-881baa33.art"), { intro: $el.find("div.description p.line-clamp").text() });
const pubDateStr = $el.find("inddiv.item").contents().last().text().trim();
const linkUrl = $el.attr("data-url");
const authors = $el.find("inddiv.item a").toArray().map((authorEl) => {
const $authorEl = $(authorEl);
return {
name: $authorEl.text(),
url: $authorEl.attr("href")
};
});
const image = $el.find("img").attr("src");
const upDatedStr = pubDateStr;
return {
title,
description,
pubDate: pubDateStr ? timezone(parseDate(pubDateStr), 8) : void 0,
link: linkUrl,
author: authors,
content: {
html: description,
text: description
},
image,
banner: image,
updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : void 0,
language
};
});
items = (await Promise.all(items.map((item) => {
if (!item.link) return item;
return cache_default.tryGet(item.link, async () => {
const $$ = load(await ofetch_default(item.link));
$$(".ad-wrap").remove();
const title = $$("h1.article-box__title").text();
const description = art(path.join(__dirname, "templates/description-881baa33.art"), { description: $$("div.content").html() });
const pubDateEl = $$("div.article-box__meta div.item-list div.item").toArray().find((i) => /\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/.test($$(i).text()));
const pubDateStr = pubDateEl ? $$(pubDateEl).text() : void 0;
const linkUrl = $$("val[data-name=\"shareUrl\"]").attr("data-value");
const categoryEls = [
...$$("div.breadcrumb-box a.item").toArray().slice(0, -1),
...$$("div.article-box__meta div.item-list div.item span.label").toArray(),
...$$("div.tags-box a.tag-item").toArray()
];
const categories = [...new Set(categoryEls.map((el) => $$(el).text()).filter(Boolean))];
const authors = $$("div.article-box__meta div.item-list div.item a").toArray().filter((i) => $$(i).attr("href") ? new RegExp(String.raw`^${userHostRegex}/u/\d+$`).test($$(i).attr("href")) : false).map((authorEl) => {
const $authorEl = $$(authorEl);
return {
name: $authorEl.text(),
url: $authorEl.attr("href")
};
});
const guid = `oschina-${$$("val[data-name=\"objId\"]").attr("data-value")}`;
const image = $$("val[data-name=\"sharePic\"]").attr("data-value");
const upDatedStr = $$("meta[property=\"bytedance:updated_time\"]").attr("content") || pubDateStr;
let processedItem = {
title,
description,
pubDate: pubDateStr ? timezone(parseDate(pubDateStr), 8) : item.pubDate,
link: linkUrl ? new URL(linkUrl, baseUrl).href : item.link,
category: categories,
author: authors,
guid,
id: guid,
content: {
html: description,
text: description
},
image,
banner: image,
updated: upDatedStr ? parseDate(upDatedStr) : item.updated,
language
};
const extraLinks = $$("div.related-links-box ul.link-list li a").toArray().map((extraLinkEl) => {
const $$extraLinkEl = $$(extraLinkEl);
return {
url: $$extraLinkEl.attr("href"),
type: "related",
content_html: $$extraLinkEl.parent().html()
};
}).filter((_) => true);
if (extraLinks) processedItem = {
...processedItem,
_extra: { links: extraLinks }
};
return {
...item,
...processedItem
};
});
}))).filter((_) => true);
const author = $("a.logo").attr("title");
return {
title: `${author} - ${$("div#tabDropdownListOpen a.selected").text()}`,
description: $("meta[name=\"description\"]").attr("content"),
link: targetUrl,
item: items,
allowEmpty: true,
image: $("a.logo img").attr("src"),
author,
language,
id: $("val[data-name=\"weixinShareUrl\"]").attr("data-value")
};
};
const route = {
path: "/column/:id",
name: "专栏",
url: "www.oschina.net",
maintainers: ["nczitzk"],
handler,
example: "/oschina/column/14",
parameters: { id: "专栏 id,可在对应专栏页 URL 中找到" },
description: `::: tip
若订阅 [开源安全专栏](https://www.oschina.net/news/column?columnId=14),网址为 \`https://www.oschina.net/news/column?columnId=14\`,请截取 \`https://www.oschina.net/news/column?columnId=\` 到末尾的部分 \`14\` 作为 \`id\` 参数填入,此时目标路由为 [\`/oschina/column/14\`](https://rsshub.app/oschina/column/14)。
:::
<details>
<summary>更多专栏</summary>
| 名称 | ID |
| --------------- | --- |
| 古典主义 Debian | 4 |
| 自由&开源 | 5 |
| 溯源 | 6 |
| 开源先懂协议 | 7 |
| 开源变局 | 8 |
| 创造者说 | 9 |
| 精英主义 BSD | 10 |
| 苹果有开源 | 11 |
| 开源访谈 | 12 |
| 抱团找组织 | 13 |
| 开源安全 | 14 |
| OSPO | 15 |
| 创业小辑 | 16 |
| 星推荐 | 17 |
| 单口开源 | 18 |
| 编辑部观察直播 | 19 |
| 开源商业化 | 20 |
| ChatGPT 专题 | 21 |
| 开源新思 | 24 |
| 开源日报 | 25 |
| 大模型思辨 | 26 |
| 家里有个程序员 | 27 |
| 开源漫谈 | 23 |
</details>
`,
categories: ["programming"],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["www.oschina.net"],
target: (_, url) => {
return `/oschina/column/${new URL(url).searchParams.get("id") ?? void 0}`;
}
}],
view: ViewType.Articles
};
//#endregion
export { handler, route };