rsshub
Version:
Make RSS Great Again!
294 lines (291 loc) • 8.09 kB
JavaScript
import "./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 { load } from "cheerio";
//#region lib/routes/jandan/utils.ts
const USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36";
/**
* Extract page ID from script tags in HTML
*/
const extractPageId = async (url, referer) => {
const $ = load(await ofetch_default(url, { headers: {
"User-Agent": USER_AGENT,
Referer: referer,
Accept: "application/json, text/plain, */*"
} }));
let pageId = "";
$("script").each((_, script) => {
const match = ($(script).html() || "").match(/PAGE\s*=\s*{\s*id\s*:\s*(\d+)\s*}/);
if (match) pageId = match[1];
});
return pageId;
};
/**
* Handle the top section (热榜)
*/
const handleTopSection = async (rootUrl, type) => {
const response = await ofetch_default(`${rootUrl}/api/top/${type}`, { headers: {
"User-Agent": USER_AGENT,
Referer: rootUrl,
Accept: "application/json, text/plain, */*"
} });
let title = "热榜";
switch (type) {
case "pic3days":
title += " - 3天内无聊图";
break;
case "pic7days":
title += " - 7天内无聊图";
break;
default:
title += " - 4小时热门";
break;
}
if (response.code === 0 && response.data && Array.isArray(response.data)) {
const items = response.data.map((item) => {
const content = item.content.replaceAll(/img src="(.*?)"/g, (match, src) => match.replace(src, src.replace(/^https?:\/\/(\w+)\.moyu\.im/, "https://$1.sinaimg.cn")));
return {
author: item.author,
title: `${item.author}: ${content.replaceAll(/<[^>]+>/g, "")}`,
description: content,
pubDate: parseDate(item.date),
link: `${rootUrl}/t/${item.id}`
};
});
return {
title,
items
};
}
return {
title,
items: [{
title: `获取失败: ${title}`,
description: "未能获取热榜数据",
link: `${rootUrl}/top`,
pubDate: /* @__PURE__ */ new Date()
}]
};
};
/**
* Handle the forum/bbs section (鱼塘)
*/
const handleForumSection = async (rootUrl) => {
const title = "煎蛋 - 鱼塘";
const currentUrl = `${rootUrl}/bbs`;
try {
const forumId = await extractPageId(currentUrl, rootUrl);
if (!forumId) return {
title,
items: [{
title: `获取失败: ${title}`,
description: "无法获取论坛ID",
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
const forumData = await ofetch_default(`${rootUrl}/api/forum/posts/${forumId}?page=1`, { headers: {
"User-Agent": USER_AGENT,
Referer: currentUrl,
Accept: "application/json, text/plain, */*"
} });
if (forumData.code === 0 && forumData.data && forumData.data.list && Array.isArray(forumData.data.list)) return {
title,
items: forumData.data.list.map((post) => {
const content = post.content.replaceAll(/img src="(.*?)"/g, (match, src) => match.replace(src, src.replace(/^https?:\/\/(\w+)\.moyu\.im/, "https://$1.sinaimg.cn")));
return {
author: post.author_name,
title: post.title || `${post.author_name}发表了新主题`,
description: content,
pubDate: parseDate(post.update_time || post.create_time),
link: `${rootUrl}/bbs#/topic/${post.post_id}`,
category: post.reply_count > 0 ? [`${post.reply_count}条回复`] : void 0
};
})
};
return {
title,
items: [{
title: `获取失败: ${title}`,
description: "未能获取鱼塘数据",
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
} catch (error) {
return {
title,
items: [{
title: `解析错误: 鱼塘`,
description: `解析鱼塘页面时出错: ${error instanceof Error ? error.message : String(error)}`,
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
}
};
/**
* Handle other sections (问答, 树洞, 随手拍, 无聊图)
*/
const handleCommentSection = async (rootUrl, category) => {
const currentUrl = `${rootUrl}/${category}`;
try {
const pageId = await extractPageId(currentUrl, rootUrl);
const $ = load(await ofetch_default(currentUrl, { headers: {
"User-Agent": USER_AGENT,
Referer: rootUrl,
Accept: "application/json, text/plain, */*"
} }));
const title = String($("title").text().trim()) || `煎蛋 - ${category}`;
if (!pageId) return {
title,
items: [{
title: `无法解析: ${title}`,
description: "无法从页面中获取到帖子ID,可能网站结构已变更",
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
const commentsData = await ofetch_default(`${rootUrl}/api/comment/post/${pageId}?order=desc&page=1`, { headers: {
"User-Agent": USER_AGENT,
Referer: currentUrl,
Accept: "application/json, text/plain, */*"
} });
if (commentsData.code === 0 && commentsData.data && commentsData.data.list && Array.isArray(commentsData.data.list)) return {
title,
items: commentsData.data.list.map((comment) => {
const content = comment.content.replaceAll(/img src="(.*?)"/g, (match, src) => match.replace(src, src.replace(/^https?:\/\/(\w+)\.moyu\.im/, "https://$1.sinaimg.cn")));
return {
author: comment.author,
title: `${comment.author}: ${content.replaceAll(/<[^>]+>/g, "")}`,
description: content,
pubDate: parseDate(comment.date_gmt || comment.date),
link: `${rootUrl}/t/${comment.id}`
};
})
};
return {
title,
items: [{
title: `暂无内容: ${title || category}`,
description: "没有获取到内容,可能需要更新解析规则",
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
} catch {
return {
title: `煎蛋 - ${category}`,
items: [{
title: `解析错误: ${category}`,
description: "解析页面时出错",
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
}
};
//#endregion
//#region lib/routes/jandan/section.ts
const route = {
path: "/:category/:type?",
example: "/jandan/top",
name: "Section",
maintainers: ["nczitzk", "pseudoyu"],
parameters: {
category: {
description: "板块",
options: [
{
label: "热榜",
value: "top"
},
{
label: "问答",
value: "qa"
},
{
label: "树洞",
value: "treehole"
},
{
label: "随手拍",
value: "ooxx"
},
{
label: "无聊图",
value: "pic"
},
{
label: "鱼塘",
value: "bbs"
}
]
},
type: {
description: "热榜类型,仅当 category 选择 `top` 时有效",
default: "4hr",
options: [
{
label: "4小时热门",
value: "4hr"
},
{
label: "3天内无聊图",
value: "pic3days"
},
{
label: "7天内无聊图",
value: "pic7days"
}
]
}
},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["i.jandan.net/:category"],
target: "/jandan/:category?"
}],
handler
};
async function handler(ctx) {
let category = ctx.req.param("category") ?? "top";
category = category.replace(/#.*$/, "");
const type = ctx.req.param("type") ?? "4hr";
const rootUrl = "http://i.jandan.net";
const currentUrl = `${rootUrl}/${category}`;
let result;
try {
if (category === "top") result = await handleTopSection(rootUrl, type);
else if (category === "bbs") result = await handleForumSection(rootUrl);
else result = await handleCommentSection(rootUrl, category);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
result = {
title: `煎蛋 - ${category}`,
items: [{
title: `抓取出错: ${category}`,
description: `抓取 ${category} 分区时出现错误: ${errorMessage}`,
link: currentUrl,
pubDate: /* @__PURE__ */ new Date()
}]
};
}
return {
title: result.title,
link: currentUrl,
item: result.items
};
}
//#endregion
export { route };