chore: update Angular cache and TypeScript build info
This commit is contained in:
+128
-17
@@ -1,3 +1,5 @@
|
||||
import { load } from 'cheerio';
|
||||
|
||||
/**
|
||||
* Minimal Rumble provider handler
|
||||
*/
|
||||
@@ -10,30 +12,139 @@ const handler = {
|
||||
* @returns {Promise<Array<any>>}
|
||||
*/
|
||||
async search(q, opts) {
|
||||
const { limit = 10 } = opts;
|
||||
const { limit = 10, page = 1 } = opts || {};
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://rumble.com/api/search/videos?` +
|
||||
new URLSearchParams({
|
||||
q: q,
|
||||
size: Math.min(limit, 50).toString()
|
||||
})
|
||||
);
|
||||
const perPage = Math.min(Math.max(1, Number(limit || 10)), 50);
|
||||
const pageNum = Math.max(1, Number(page || 1));
|
||||
const params = new URLSearchParams({ q: q });
|
||||
if (pageNum > 1) params.set('page', pageNum.toString());
|
||||
|
||||
const response = await fetch(`https://rumble.com/search/video?${params.toString()}` , {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Rumble API error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const html = await response.text();
|
||||
const $ = load(html);
|
||||
const items = [];
|
||||
|
||||
return (data.videos || []).map(item => ({
|
||||
title: item.title,
|
||||
id: item.id,
|
||||
url: `https://rumble.com${item.url}`,
|
||||
thumbnail: item.thumbnail,
|
||||
uploaderName: item.author.name,
|
||||
type: 'video'
|
||||
}));
|
||||
const parseDurationToSeconds = (raw) => {
|
||||
if (raw == null) return undefined;
|
||||
const value = String(raw).trim();
|
||||
if (!value) return undefined;
|
||||
|
||||
// Plain numeric seconds
|
||||
const numeric = Number(value);
|
||||
if (Number.isFinite(numeric) && numeric > 0) return Math.floor(numeric);
|
||||
|
||||
// ISO-8601 style: PT#H#M#S
|
||||
const isoMatch = value.match(/^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/i);
|
||||
if (isoMatch) {
|
||||
const hours = Number(isoMatch[1] || 0);
|
||||
const minutes = Number(isoMatch[2] || 0);
|
||||
const seconds = Number(isoMatch[3] || 0);
|
||||
const totalIso = (hours * 3600) + (minutes * 60) + seconds;
|
||||
if (totalIso > 0) return totalIso;
|
||||
}
|
||||
|
||||
// Text formats like "1h 2m 3s" or "15m13s"
|
||||
const textMatch = value.match(/^(?:(\d+)\s*h(?:ours?)?)?\s*(?:(\d+)\s*m(?:in(?:utes)?)?)?\s*(?:(\d+)\s*s(?:ec(?:onds)?)?)?$/i);
|
||||
if (textMatch && (textMatch[1] || textMatch[2] || textMatch[3])) {
|
||||
const hours = Number(textMatch[1] || 0);
|
||||
const minutes = Number(textMatch[2] || 0);
|
||||
const seconds = Number(textMatch[3] || 0);
|
||||
const totalText = (hours * 3600) + (minutes * 60) + seconds;
|
||||
if (totalText > 0) return totalText;
|
||||
}
|
||||
|
||||
// Colon separated HH:MM:SS or MM:SS
|
||||
const colonCandidate = value.replace(/[^0-9:]/g, '');
|
||||
if (colonCandidate.includes(':')) {
|
||||
const segments = colonCandidate.split(':').filter(Boolean).map(s => Number(s));
|
||||
if (segments.length >= 2 && segments.every(n => Number.isFinite(n))) {
|
||||
while (segments.length < 3) segments.unshift(0);
|
||||
const [hours, minutes, seconds] = segments.slice(-3);
|
||||
const totalColon = (hours * 3600) + (minutes * 60) + seconds;
|
||||
if (totalColon > 0) return totalColon;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: first integer found, assume seconds if >0
|
||||
const fallbackDigits = value.match(/(\d+)/);
|
||||
if (fallbackDigits) {
|
||||
const seconds = Number(fallbackDigits[1]);
|
||||
if (Number.isFinite(seconds) && seconds > 0) return seconds;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
$('li.video-listing-entry').each((_idx, el) => {
|
||||
if (items.length >= perPage) return false;
|
||||
const $el = $(el);
|
||||
const anchor = ($el.find('a.video-item--a').attr('href') || '').trim();
|
||||
if (!anchor) return;
|
||||
|
||||
const img = $el.find('img.video-item--img');
|
||||
const rawThumbnail =
|
||||
img.attr('data-src') ||
|
||||
img.attr('data-original') ||
|
||||
img.attr('src') ||
|
||||
'';
|
||||
const normalizedThumb = rawThumbnail.replace(/\s+/g, '').trim();
|
||||
const title = $el.find('h3.video-item--title').text().replace(/\s+/g, ' ').trim();
|
||||
const uploaderName = $el.find('.ellipsis-1').text().replace(/\s+/g, ' ').trim();
|
||||
|
||||
const url = anchor.startsWith('http') ? anchor : `https://rumble.com${anchor}`;
|
||||
|
||||
const id =
|
||||
$el.attr('data-id') ||
|
||||
url.split('/').filter(Boolean).pop() ||
|
||||
String(Math.random());
|
||||
|
||||
const thumbnail = normalizedThumb
|
||||
? normalizedThumb.startsWith('//')
|
||||
? `https:${normalizedThumb}`
|
||||
: normalizedThumb
|
||||
: undefined;
|
||||
|
||||
const durationCandidates = [
|
||||
$el.attr('data-duration'),
|
||||
$el.attr('data-video-duration'),
|
||||
$el.data('duration'),
|
||||
$el.find('[data-duration]').attr('data-duration'),
|
||||
$el.find('[data-video-duration]').attr('data-video-duration'),
|
||||
$el.find('time[datetime]').attr('datetime'),
|
||||
$el.find('.video-item--duration, .video-item--meta time, .video-item--meta .duration, .video-item--meta-duration, .video-item--length').first().text(),
|
||||
];
|
||||
|
||||
let durationSeconds;
|
||||
for (const candidate of durationCandidates) {
|
||||
const parsed = parseDurationToSeconds(candidate);
|
||||
if (typeof parsed === 'number' && parsed > 0) {
|
||||
durationSeconds = parsed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
title: title || url,
|
||||
id,
|
||||
url,
|
||||
thumbnail,
|
||||
uploaderName: uploaderName || undefined,
|
||||
type: 'video',
|
||||
duration: durationSeconds
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
} catch (error) {
|
||||
console.error('Rumble search error:', error);
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user