rsshub
Version:
Make RSS Great Again!
112 lines (111 loc) • 4.18 kB
JavaScript
import { t as rofetch } from "./ofetch-W1aeTHCo.mjs";
import "./types-DNj6Etbg.mjs";
import { t as parseDate } from "./parse-date-CjhZE69i.mjs";
import { t as cache_default } from "./cache-CiDoUSLo.mjs";
import { load } from "cheerio";
import pMap from "p-map";
//#region lib/routes/rumble/channel.ts
const rootUrl = "https://rumble.com";
const route = {
path: "/c/:channel/:embed?",
categories: ["multimedia"],
view: 3,
name: "Channel",
maintainers: ["luckycold"],
example: "/rumble/c/MikhailaPeterson",
parameters: {
channel: "Channel slug from `https://rumble.com/c/<channel>`",
embed: "Default to not embed the video, set to `embed` to enable embedding"
},
description: "Fetches full Rumble video descriptions without embedding the player by default.",
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: true,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["rumble.com/c/:channel", "rumble.com/c/:channel/videos"],
target: "/c/:channel"
}],
handler
};
function parseDescription($, fallback) {
return $("div[data-js=\"media_long_description_container\"] > p.media-description").toArray().map((element) => $.html(element)).filter(Boolean).join("") || $("meta[name=\"description\"]").attr("content") || fallback || void 0;
}
function parseStructuredVideoObject($) {
const elements = $("script[type=\"application/ld+json\"]").toArray();
for (const element of elements) try {
const parsed = JSON.parse($(element).text());
const videoObject = Array.isArray(parsed) ? parsed.find((item) => item?.["@type"] === "VideoObject") : parsed;
if (videoObject?.["@type"] === "VideoObject") return videoObject;
} catch {
continue;
}
}
function parseListVideos($) {
const content = $("rum-videos-grid script[type=\"application/json\"]").text();
if (!content) return [];
try {
return JSON.parse(content).items;
} catch {
return [];
}
}
function parseImage($, videoObject) {
return videoObject?.thumbnailUrl || $("meta[property=\"og:image\"]").attr("content") || void 0;
}
function renderDescription(image, description, embedUrl, includeEmbed) {
let descriptionHtml = "";
if (includeEmbed && embedUrl) descriptionHtml += `<iframe src="${embedUrl}" width="640" height="360" frameborder="0" allowfullscreen></iframe>`;
else if (image) descriptionHtml += `<p><img src="${image}"></p>`;
if (description) descriptionHtml += description;
return descriptionHtml || void 0;
}
function getMedia(image) {
return image ? {
thumbnail: { url: image },
content: {
url: image,
medium: "image"
}
} : void 0;
}
async function buildItem(link, title, listImage, pubDate, includeEmbed) {
const cookies = ((await rofetch.raw(link, { ignoreResponseError: true })).headers.getSetCookie?.() || []).map((cookie) => cookie.split(";", 1)[0]).join("; ");
if (!cookies) throw new Error(`Failed to get Rumble page cookie from ${link}`);
const $ = load(await rofetch(link, { headers: { Cookie: cookies } }));
const videoObject = parseStructuredVideoObject($);
const image = listImage || parseImage($, videoObject);
return {
title,
image,
link,
description: renderDescription(image, parseDescription($, videoObject?.description), videoObject?.embedUrl, includeEmbed),
itunes_item_image: image,
media: getMedia(image),
pubDate
};
}
async function handler(ctx) {
const channel = ctx.req.param("channel");
const includeEmbed = ctx.req.param("embed") === "embed";
const videosUrl = `${new URL(`/c/${encodeURIComponent(channel)}`, rootUrl).href}/videos`;
const $ = load(await rofetch(videosUrl));
const title = $("title").first().text() || "Rumble";
const items = await pMap(parseListVideos($), (video) => {
const link = new URL(video.url || video.relative_url, rootUrl).href;
const listImage = new URL(video.thumb, rootUrl).href;
const pubDate = parseDate(video.upload_date);
return cache_default.tryGet(`${link}:${includeEmbed ? "embed" : "noembed"}`, () => buildItem(link, video.title, listImage, pubDate, includeEmbed));
}, { concurrency: 5 });
return {
title: `Rumble - ${title}`,
link: videosUrl,
item: items
};
}
//#endregion
export { route };