rsshub
Version:
Make RSS Great Again!
77 lines (73 loc) • 3.13 kB
JavaScript
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs";
import { t as config } from "./config-CCmw1BNE.mjs";
import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs";
import { t as processContent } from "./utils-BXldxNVQ.mjs";
import { load } from "cheerio";
//#region lib/routes/f95zone/thread.ts
const route = {
path: "/thread/:thread",
name: "Thread",
maintainers: ["wsmbsbbz"],
example: "/f95zone/thread/ubermation-collection-2026-01-19-uebermation-uebermation.231247",
categories: ["game"],
description: `Track replies in a thread. Fetches the first page and the last page.
URL format: \`https://f95zone.to/threads/{thread}/\` → use \`{thread}\` as the parameter.
Example: \`https://f95zone.to/threads/ubermation-collection-2026-01-19-uebermation-uebermation.231247/\` → \`/f95zone/thread/ubermation-collection-2026-01-19-uebermation-uebermation.231247\`
Note: If you want to track a specific post's content changes (e.g., first post with download links), use the \`/f95zone/post\` route instead.`,
parameters: { thread: "Thread slug with ID, copy from browser URL after `/threads/`" },
features: {
requireConfig: [{
name: "F95ZONE_COOKIE",
optional: true,
description: "F95zone cookie for accessing restricted content."
}],
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
nsfw: true
},
radar: [{
source: ["f95zone.to/threads/:thread/*"],
target: "/thread/:thread"
}],
handler: async (ctx) => {
const { thread } = ctx.req.param();
const threadLink = `https://f95zone.to/threads/${thread}/`;
const headers = { ...config.f95zone.cookie && { cookie: config.f95zone.cookie } };
const $firstPage = load(await rofetch(threadLink, { headers }));
const title = $firstPage("h1.p-title-value").text();
const lastPageLink = $firstPage("ul.pageNav-main li.pageNav-page:last-child a").attr("href");
const totalPages = lastPageLink ? Number(lastPageLink.match(/page-(\d+)/)?.[1] || "1") : 1;
const extractPosts = ($) => $("article.message").toArray().map((article) => {
const $article = $(article);
const postId = $article.attr("data-content")?.replace("post-", "");
if (!postId) return;
const author = $article.find(".message-name a").text();
const postDate = $article.find("time.u-dt").attr("datetime");
const content = $article.find(".bbWrapper").html() || "";
const postLink = `${threadLink}post-${postId}`;
return {
title: `#${$article.find(".message-attribution-opposite--list li:last-child a").text().trim().replace("#", "") || postId} by ${author}`,
link: postLink,
guid: postLink,
description: processContent(content),
pubDate: postDate ? parseDate(postDate) : void 0,
author
};
}).filter(Boolean);
const allPosts = [...extractPosts($firstPage)];
if (totalPages > 1) {
const lastPageResponse = await rofetch(`${threadLink}page-${totalPages}`, { headers });
allPosts.push(...extractPosts(load(lastPageResponse)));
}
return {
title: `[F95zone] ${title}`,
link: threadLink,
item: allPosts
};
}
};
//#endregion
export { route };