fix(twitch,rumble,shorts): replis serveur, embed Rumble autoritaire, refonte UX Shorts
CI / build-and-test (push) Successful in 14m15s

This commit is contained in:
2026-09-29 10:39:03 -04:00
parent 3fe05b3c30
commit f76a3795c2
6 changed files with 530 additions and 90 deletions
+13
View File
@@ -3014,6 +3014,19 @@ app.get('/api/twitch-token', async (_req, res) => {
}
});
// Top streams Twitch via le token serveur (repli fiable pour Home/Explore
// quand les appels Helix directs du navigateur échouent).
app.get('/api/twitch/top-streams', async (req, res) => {
try {
const first = Math.min(50, Math.max(1, parseInt(String(req.query.first || '24'), 10) || 24));
const { default: twitch } = await import('./providers/twitch.mjs');
const items = await twitch.topStreams(first);
return res.json({ items });
} catch (e) {
return res.status(502).json({ items: [], error: e?.message || 'twitch_top_streams_failed' });
}
});
// -------------------- Gemini summarize (server-side) --------------------
// Keeps GEMINI_API_KEY on the server. Client calls POST /api/ai/summarize.
app.get('/api/ai/status', (_req, res) => {
+18
View File
@@ -302,6 +302,24 @@ async function searchChannelsMulti(queries, first, auth, after = '') {
const handler = {
id: 'tw',
label: 'Twitch',
/**
* Top streams via le token serveur (retries inclus).
* Utilisé par la route /api/twitch/top-streams : repli fiable quand les
* appels Helix directs du navigateur échouent (proxy, CORS, 429...).
* @param {number} limit
*/
async topStreams(limit = 24) {
try {
const appToken = await getAppAccessToken();
const auth = { token: appToken.token, clientId: appToken.clientId };
const first = String(Math.min(100, Math.max(1, Number(limit) || 24)));
const data = await helixGet('/streams', new URLSearchParams({ first }), auth, { retries: 2 });
return Array.isArray(data?.data) ? data.data.map(mapStream) : [];
} catch (e) {
console.error('Twitch topStreams error:', e?.message || e);
return [];
}
},
/**
* Recherche mixte : lives + VODs + clips + chaînes.
* @param {string} q