Skip to content

feat(route/rumble): add channel feed - #21545

Open
luckycold wants to merge 9 commits into
DIYgod:masterfrom
luckycold:rumble-route
Open

feat(route/rumble): add channel feed#21545
luckycold wants to merge 9 commits into
DIYgod:masterfrom
luckycold:rumble-route

Conversation

@luckycold

@luckycold luckycold commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Involved Issue / 该 PR 相关 Issue

No issue involved. This was just something I wanted and thought others might like too.

Example for the Proposed Route(s) / 路由地址示例

/rumble/c/MikhailaPeterson
/rumble/c/MikhailaPeterson/noembed

New RSS Route Checklist / 新 RSS 路由检查表

  • New Route / 新的路由
  • Anti-bot or rate limit / 反爬/频率限制
    • If yes, do your code reflect this sign? / 如果有, 是否有对应的措施?
  • Date and time / 日期和时间
    • Parsed / 可以解析
    • Correct time zone / 时区正确
  • New package added / 添加了新的包
  • Puppeteer

Note / 说明

This adds a Rumble route that keeps the channel listing on server-rendered markup while using structured detail-page data for fallback descriptions and thumbnails. It also adds standard image output and limits detail-page fetch concurrency to reduce anti-bot risk.

@github-actions github-actions Bot added the route label Mar 29, 2026
@luckycold luckycold changed the title fix(route/rumble): improve feed metadata feat(route/rumble): add channel feed Mar 29, 2026
@github-actions github-actions Bot added the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: f31972f0
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: f31972f0

@luckycold

Copy link
Copy Markdown
Contributor Author

I tested this route locally and it returns valid results there, but the GitHub Actions fails on the request to https://rumble.com/c/MikhailaPeterson with 403 Forbidden. That seems to be Rumble / Cloudflare blocking the GitHub-hosted runner IP instead of any actual error on the route.
This route is marked with antiCrawler: true because of the high likelihood of that on large facing instances. In local testing, both /rumble/c/MikhailaPeterson and /rumble/c/MikhailaPeterson/noembed worked as expected.

@github-actions github-actions Bot removed the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 29, 2026
@github-actions

github-actions Bot commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Auto Review

No clear rule violations found in the current diff.

@github-actions github-actions Bot added the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: f31972f0
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: f31972f0

@github-actions github-actions Bot added auto: not ready to review Users can't get the RSS feed output according to automated testing results and removed auto: not ready to review Users can't get the RSS feed output according to automated testing results labels Mar 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 4b482c11
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 4b482c11

@github-actions github-actions Bot removed the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 4b482c11
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 4b482c11

@github-actions github-actions Bot added the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 29, 2026
@luckycold

Copy link
Copy Markdown
Contributor Author

Tested with and without embed (and thumbnails instead) for the feeds and descriptions work as well:
image
image
image

@luckycold

luckycold commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

I realize, I should also clarify. The reason for no API usage is because Rumble doesn't seem to offer a web API for listing all the videos reliably. If it comes to my attention an area where it does I'd love to rewrite this since the site does often update their formatting. I'm happy to fix it if it does in the mean time though.

@github-actions github-actions Bot removed the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 5d5b9e26
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 5d5b9e26

@github-actions github-actions Bot added the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Mar 31, 2026
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
Comment thread lib/routes/rumble/channel.ts Outdated
@github-actions github-actions Bot added auto: not ready to review Users can't get the RSS feed output according to automated testing results and removed auto: not ready to review Users can't get the RSS feed output according to automated testing results labels Apr 8, 2026
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: bfed6d11
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: bfed6d11

Comment thread lib/routes/rumble/channel.ts Fixed
@github-actions github-actions Bot added auto: not ready to review Users can't get the RSS feed output according to automated testing results and removed auto: not ready to review Users can't get the RSS feed output according to automated testing results labels Apr 8, 2026
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 05f64989
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 05f64989

@github-actions github-actions Bot added auto: not ready to review Users can't get the RSS feed output according to automated testing results and removed auto: not ready to review Users can't get the RSS feed output according to automated testing results labels Apr 8, 2026
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 01ee062e
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 01ee062e

Comment thread lib/routes/rumble/channel.ts Outdated
videoElements,
(element: Element) => {
const $video = $(element);
const $link = $video.find('.videostream__link[href]').first();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide the URL where you do found multiple occurrences of .videostream__link[href] within a single .videostream.thumbnail__grid--item[data-video-id] which makes you used first().

Comment thread lib/routes/rumble/channel.ts Outdated
const url = new URL(href, rootUrl);
url.search = '';

const $title = $video.find('.thumbnail__title').first();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide the URL where you do found multiple occurrences of .thumbnail__title within a single .videostream.thumbnail__grid--item[data-video-id] which makes you used first().

Comment thread lib/routes/rumble/channel.ts Outdated
return null;
}

const imageRaw = $video.find('img.thumbnail__image, .thumbnail__thumb img').first().attr('src');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not enumerate different combination of selectors of the same element. Beside that, provide the URL where you do found multiple occurrences of img.thumbnail__image or .thumbnail__thumb img within a single .videostream.thumbnail__grid--item[data-video-id] which makes you used first().

Comment thread lib/routes/rumble/channel.ts Outdated

const imageRaw = $video.find('img.thumbnail__image, .thumbnail__thumb img').first().attr('src');
const listImage = imageRaw ? new URL(imageRaw, rootUrl).href : undefined;
const pubDateRaw = $video.find('time.videostream__time[datetime]').first().attr('datetime')?.trim();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide the URL where you do found multiple occurrences of time.videostream__time[datetime] within a single .videostream.thumbnail__grid--item[data-video-id] which makes you used first().

Comment thread lib/routes/rumble/channel.ts Outdated
}

function parseStructuredVideoObject($: ReturnType<typeof load>): RumbleVideoObject | undefined {
const content = $('script[type="application/ld+json"]').first().text().trim();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#21545 (comment) is marked as resolved so please provide the URL where you do found multiple occurrences of script[type="application/ld+json"] which makes you used .toArray() and first().

Comment thread lib/routes/rumble/channel.ts Outdated
return;
}

try {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#21545 (comment) is marked as resolved so please provide the URL where you do found a malformed JSON in script[type="application/ld+json"] that can't be parsed.

Comment thread lib/routes/rumble/channel.ts Outdated

try {
const parsed = JSON.parse(content);
const entries = Array.isArray(parsed) ? parsed : [parsed];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide the URL where you didn’t find the JSON-LD as an array which requires [parsed].

Comment thread lib/routes/rumble/channel.ts Outdated
const videoObject = parseStructuredVideoObject($);
const image = listImage || parseImage($, videoObject);
const description = renderDescription(image, parseDescription($, videoObject?.description?.trim()), videoObject?.embedUrl, includeEmbed);
const author = videoObject?.author?.name || $('.channel-header--title').first().text().trim() || undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#21545 (comment) is marked as resolved so please provide the URL where you do found multiple occurrences of .channel-header--title which makes you used first().

@github-actions github-actions Bot removed the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Apr 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.14.1
Git Hash: 4193cf8e
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.14.1
Git Hash: 4193cf8e

@github-actions github-actions Bot added the auto: not ready to review Users can't get the RSS feed output according to automated testing results label Apr 10, 2026
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

This PR is stale because it has been opened for more than 3 weeks with no activity. Comment or this will be closed in 7 days.

@github-actions github-actions Bot added the Stale No feedback from OP label May 7, 2026
@luckycold

Copy link
Copy Markdown
Contributor Author

Going to work on this soon. Bought a house recently. Haven't had time to finish this out yet.

@github-actions github-actions Bot removed the Stale No feedback from OP label May 13, 2026
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

This PR is stale because it has been opened for more than 3 weeks with no activity. Comment or this will be closed in 7 days.

@github-actions github-actions Bot added the Stale No feedback from OP label Jun 5, 2026
@data-dag

data-dag commented Jun 9, 2026

Copy link
Copy Markdown

I'm going attempt to address this soon.

@github-actions github-actions Bot removed the Stale No feedback from OP label Jun 9, 2026
luckycold and others added 9 commits July 2, 2026 15:50
Add a Rumble channel route so channel videos can be subscribed to through RSSHub. Use stable server-rendered selectors and normalized item URLs to keep feed entries consistent.
Add full Rumble video descriptions to channel feeds and expose an /embed route variant for readers that support iframe players. Keep the default route image-based while deriving stable embed URLs from each video page.
Match YouTube's optional embed parameter behavior so the default feed includes embedded players and any trailing path segment disables embedding. Keep full Rumble video descriptions in both output modes.
Use structured detail-page data for Rumble descriptions and fallback thumbnails while keeping the channel listing on stable server-rendered markup. Limit detail fetch concurrency so the route is less likely to trip anti-bot protections.
@github-actions github-actions Bot added auto: not ready to review Users can't get the RSS feed output according to automated testing results and removed auto: not ready to review Users can't get the RSS feed output according to automated testing results labels Jul 3, 2026
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Successfully generated as following:

http://localhost:1200/rumble/c/MikhailaPeterson - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson
Node Version: v24.18.0
Git Hash: b5e6a988
http://localhost:1200/rumble/c/MikhailaPeterson/noembed - Failed ❌
HTTPError: Response code 503 (Service Unavailable)

Error Message:<br/>FetchError: [GET] &quot;https://rumble.com/c/MikhailaPeterson/videos&quot;: 403 Forbidden
Route: /rumble/c/:channel/:embed?
Full Route: /rumble/c/MikhailaPeterson/noembed
Node Version: v24.18.0
Git Hash: b5e6a988

@TonyRL TonyRL left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove all redundant trim().


const response = await ofetch(videosUrl, {
headers: {
'user-agent': config.trueUA,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the site only work with this specific UA instead of RSSHub's default UA which is a randomised version of Chrome on mac?

headers: {
'user-agent': config.trueUA,
},
retryStatusCodes: [403],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not override the default

retryStatusCodes: [400, 408, 409, 425, 429, 500, 502, 503, 504],


const $ = load(response);

const title = parseChannelTitle($);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline this function instead of spliting it to a function that called only once.

}

const parsed = JSON.parse(content);
return Array.isArray(parsed?.items) ? parsed.items : [];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide the site URL where you found parsed.items is not an array which requires Array.isArray() check.

Comment on lines +177 to +180
const videoUrl = video.url || video.relative_url;
if (!videoUrl) {
return null;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide the site URL where you found the embedded video data JSON does not contain url and relative_url which requires using

if (!videoUrl) {
return null;
}

headers: {
'user-agent': config.trueUA,
},
retryStatusCodes: [403],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not override the default

retryStatusCodes: [400, 408, 409, 425, 429, 500, 502, 503, 504],

retryStatusCodes: [403],
});

const $ = load(response);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The video detail page requires RNSC cookie and it will provide one if the request does not have it.

Comment on lines +79 to +80
const type = parsed?.['@type'];
return type === 'VideoObject' ? (parsed as RumbleVideoObject) : undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure these can parse the VideoObject?

Comment on lines +94 to +96
const image = videoObject?.thumbnailUrl || $('meta[property="og:image"]').attr('content')?.trim();

return image ? new URL(image, rootUrl).href : undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does any of the videoObject?.thumbnailUrl or $('meta[property="og:image"]').attr('content') start with relative path which requires URL normalisation?

const videoObject = parseStructuredVideoObject($);
const image = listImage || parseImage($, videoObject);
const description = renderDescription(image, parseDescription($, videoObject?.description?.trim()), videoObject?.embedUrl, includeEmbed);
const author = videoObject?.author?.name;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide the site URL where VideoObject has author attribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto: not ready to review Users can't get the RSS feed output according to automated testing results route

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants