rsshub
Version:
Make RSS Great Again!
131 lines (130 loc) • 4.48 kB
JavaScript
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs";
import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs";
import { t as cache_default } from "./cache-BkqOokyU.mjs";
import { t as timezone } from "./timezone-BBvDwS_3.mjs";
import { n as fetchArticle, t as WeChatMpError } from "./wechat-mp-BPi_ETC7.mjs";
import { Fragment, jsxs } from "hono/jsx/jsx-runtime";
import { load } from "cheerio";
import { renderToString } from "hono/jsx/dom/server";
//#region lib/routes/sjtu/cs/xshd.tsx
const host = "https://www.cs.sjtu.edu.cn";
function absolutize(url) {
if (!url) return "";
return new URL(url, host).href;
}
function parseListing(html) {
const $ = load(html);
return $(".ny-con .u12 > li").toArray().map((el) => {
const $el = $(el);
const link = absolutize($el.find("> a").attr("href"));
const title = $el.find(".txt .tit").text();
const image = absolutize($el.find(".imgk img").attr("src"));
const adRows = $el.find(".txt .ad p").toArray().map((p) => $(p).find("span").text().trim()).filter(Boolean);
const findRow = (prefix) => adRows.find((s) => s.startsWith(prefix))?.slice(prefix.length) ?? "";
return {
title,
link,
image,
timeText: findRow("时间:"),
location: findRow("地点:"),
speakers: findRow("报告人:"),
topic: findRow("主题:")
};
}).filter((it) => it.link && it.title);
}
function publishDateFromImage(imageUrl) {
const m = imageUrl.match(/\/upload\/[^/]+\/(\d{4})(\d{2})(\d{2})\//);
if (!m) return;
const [, y, mo, d] = m;
return timezone(parseDate(`${y}-${mo}-${d}`, "YYYY-MM-DD"), 8);
}
function renderDescription(item) {
return renderToString(/* @__PURE__ */ jsxs(Fragment, { children: [
item.timeText && /* @__PURE__ */ jsxs("p", { children: ["举办时间:", item.timeText] }),
item.location && /* @__PURE__ */ jsxs("p", { children: ["地点:", item.location] }),
item.topic && /* @__PURE__ */ jsxs("p", { children: ["主题:", item.topic] })
] }));
}
function extractWechatUrl(finalUrl) {
return new URL(finalUrl).searchParams.get("target_url") || finalUrl;
}
function basicItem(item) {
return {
title: item.title,
link: item.link,
description: renderDescription(item),
author: item.speakers || void 0,
image: item.image || void 0,
pubDate: publishDateFromImage(item.image)
};
}
function enrichItem(item) {
return cache_default.tryGet(item.link, async () => {
const response = await rofetch.raw(item.link);
const finalUrl = response.url;
let description = renderDescription(item);
let pubDate = publishDateFromImage(item.image);
if (new URL(finalUrl).hostname === "mp.weixin.qq.com") try {
const article = await fetchArticle(extractWechatUrl(finalUrl));
description += `<hr>${article.description}`;
pubDate = article.pubDate || pubDate;
} catch (error) {
if (!(error instanceof WeChatMpError)) throw error;
}
else {
const $body = load(response._data ?? "")(".xw-cont");
if ($body.length > 0) {
const $txt = $body.find(".txt");
description += `<hr>${$txt.html() ?? ""}`;
const publishedMatch = $body.find(".jj p").first().text().match(/(\d{4})-(\d{1,2})-(\d{1,2})/);
if (publishedMatch) {
const [, y, m, d] = publishedMatch;
pubDate = timezone(parseDate(`${y}-${m.padStart(2, "0")}-${d.padStart(2, "0")}`, "YYYY-MM-DD"), 8);
}
}
}
return {
title: item.title,
link: item.link,
description,
author: item.speakers || void 0,
image: item.image || void 0,
pubDate
};
});
}
const route = {
path: "/cs/xshd",
categories: ["university"],
example: "/sjtu/cs/xshd",
parameters: {},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["www.cs.sjtu.edu.cn/xshd.html"],
target: "/cs/xshd"
}],
name: "计算机学院 - 学术活动",
maintainers: ["BeaCox"],
handler,
url: "www.cs.sjtu.edu.cn/xshd.html"
};
async function handler() {
const listLink = `${host}/xshd.html`;
const items = parseListing(await rofetch(listLink));
return {
title: "上海交通大学计算机学院 - 学术活动",
link: listLink,
description: "上海交通大学计算机学院(网络空间安全学院、密码学院)学术活动",
language: "zh-CN",
item: (await Promise.allSettled(items.map((it) => enrichItem(it)))).map((result, index) => result.status === "fulfilled" ? result.value : basicItem(items[index]))
};
}
//#endregion
export { route };