fix(shorts): embeds DM/PT/Rumble/Twitch + flux Pour toi multi-fournisseurs
CI / build-and-test (push) Successful in 14m16s
CI / build-and-test (push) Successful in 14m16s
This commit is contained in:
+39
-10
@@ -346,21 +346,29 @@ function parseDurationToSeconds(text) {
|
||||
return 0; // Par défaut si aucun format n'est reconnu
|
||||
}
|
||||
|
||||
async function scrapeRumbleList({ q, page = 1, limit = 24, sort = 'viral' }) {
|
||||
async function scrapeRumbleList({ q, page = 1, limit = 24, sort = 'viral', mode = 'videos' }) {
|
||||
try {
|
||||
const url = q
|
||||
? `https://rumble.com/search/video?q=${encodeURIComponent(q)}&page=${page}`
|
||||
: `https://rumble.com/videos?sort=${encodeURIComponent(sort)}&page=${page}`;
|
||||
// Mode "shorts" : le flux natif rumble.com/shorts (vertical ≤ 90 s).
|
||||
// Les liens sont de la forme /shorts/vXXXX (plus éventuellement ?tracking).
|
||||
const isShortsMode = mode === 'shorts';
|
||||
const url = isShortsMode
|
||||
? `https://rumble.com/shorts?page=${page}`
|
||||
: q
|
||||
? `https://rumble.com/search/video?q=${encodeURIComponent(q)}&page=${page}`
|
||||
: `https://rumble.com/videos?sort=${encodeURIComponent(sort)}&page=${page}`;
|
||||
|
||||
const html = await httpGet(url);
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const found = [];
|
||||
// 1) Cartes "vidéos" standards (li/article/div)
|
||||
$('a[href^="/v"], a[href^="/video/"]').each((_, el) => {
|
||||
const href = $(el).attr('href') || '';
|
||||
// On préfère STRICTEMENT l’ID /vXXXX
|
||||
let m = /^\/(v[0-9A-Za-z]+)(?:[-/.]|$)/.exec(href);
|
||||
const linkSelector = isShortsMode
|
||||
? 'a[href*="/shorts/v"], a[href^="/v"], a[href^="/video/"]'
|
||||
: 'a[href^="/v"], a[href^="/video/"]';
|
||||
$(linkSelector).each((_, el) => {
|
||||
const href = ($(el).attr('href') || '').split('?')[0];
|
||||
// On préfère STRICTEMENT l’ID /vXXXX (aussi après /shorts/).
|
||||
let m = /\/(v[0-9A-Za-z]+)(?:[-/.]|$)/.exec(href);
|
||||
let id = m?.[1] || null;
|
||||
|
||||
// Fallback minimaliste pour /video/123 → on ne convertit pas ici; on laissera /video/:id passer au détails qui normalise par parse de la page.
|
||||
@@ -460,9 +468,11 @@ async function scrapeRumbleList({ q, page = 1, limit = 24, sort = 'viral' }) {
|
||||
uploaderName,
|
||||
views,
|
||||
duration: durationSeconds,
|
||||
// Indicateur natif pour le front : une vidéo ≤ 75 s est un Short probable.
|
||||
// Indicateur natif pour le front. En mode "shorts", tout ce qui sort
|
||||
// du flux rumble.com/shorts (vertical ≤ 90 s) est un Short, même si
|
||||
// le badge de durée est absent du HTML.
|
||||
// (Rumble n'expose pas de flag natif ; la durée reste la source de vérité.)
|
||||
isShort: durationSeconds > 0 && durationSeconds <= 75,
|
||||
isShort: isShortsMode ? (durationSeconds <= 0 || durationSeconds <= 90) : (durationSeconds > 0 && durationSeconds <= 75),
|
||||
uploadedDate: '',
|
||||
url,
|
||||
type: 'video'
|
||||
@@ -517,6 +527,25 @@ router.get('/browse', async (req, res) => {
|
||||
return res.json(data);
|
||||
});
|
||||
|
||||
/* ---------------- Route "shorts" natifs (rumble.com/shorts) -------------- */
|
||||
/**
|
||||
* GET /api/rumble/shorts?page=&limit=
|
||||
* Scrape le flux natif des Shorts Rumble (vertical ≤ 90 s) : IDs /vXXXX
|
||||
* propres, compatibles avec l'embed officiel /embed/vXXXX/.
|
||||
*/
|
||||
router.get('/shorts', async (req, res) => {
|
||||
const page = Math.max(1, parseInt(String(req.query.page || '1'), 10) || 1);
|
||||
const limit = Math.min(50, Math.max(1, parseInt(String(req.query.limit || '24'), 10) || 24));
|
||||
|
||||
const key = cacheKey('/shorts', { page, limit });
|
||||
const cached = getCache(key);
|
||||
if (cached) return res.json(cached);
|
||||
|
||||
const data = await scrapeRumbleList({ page, limit, mode: 'shorts' });
|
||||
setCache(key, data);
|
||||
return res.json(data);
|
||||
});
|
||||
|
||||
router.get('/search', async (req, res) => {
|
||||
const q = String(req.query.q || '').trim();
|
||||
if (!q) return res.status(400).json({ error: 'Query parameter required' });
|
||||
|
||||
Reference in New Issue
Block a user