bep40 commited on
Commit
b37dc7b
·
verified ·
1 Parent(s): 395e02a

Upload static/shorts_fresh.js

Browse files
Files changed (1) hide show
  1. static/shorts_fresh.js +25 -56
static/shorts_fresh.js CHANGED
@@ -1,6 +1,7 @@
1
  /**
2
- * VNEWS Fresh Shorts Fetcher v6 - YouTube RSS + Invidious API
3
- * No CORS proxy needed, uses public APIs
 
4
  */
5
  (function() {
6
  'use strict';
@@ -34,8 +35,8 @@
34
  return url;
35
  }
36
 
37
- // Fetch via server-side proxy (our own /api/shorts endpoint)
38
- async function fetchShortsFromServer() {
39
  try {
40
  const r = await fetch('/api/shorts?t=' + Date.now());
41
  if (r.ok) {
@@ -52,55 +53,25 @@
52
  }
53
  }
54
  } catch(e) {
55
- console.warn('Server fetch failed:', e);
56
  }
57
  return [];
58
  }
59
 
60
- // Fetch from YouTube RSS (no CORS issue when proxied)
61
- async function fetchShortsFromRSS(channel) {
62
  try {
63
- const rssUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${channel.id}`;
64
- const r = await fetch('/api/proxy/rss?url=' + encodeURIComponent(rssUrl));
65
- if (!r.ok) return [];
66
- const text = await r.text();
67
-
68
- const shorts = [];
69
- const parser = new DOMParser();
70
- const doc = parser.parseFromString(text, 'text/xml');
71
- const entries = doc.querySelectorAll('entry');
72
-
73
- for (const entry of entries) {
74
- const title = entry.querySelector('title')?.textContent || '';
75
- const link = entry.querySelector('link')?.getAttribute('href') || '';
76
- const vidEl = entry.querySelector('videoId');
77
- const vid = vidEl?.textContent || link.match(/(?:v=|shorts\/)([A-Za-z0-9_-]{11})/)?.[1] || '';
78
-
79
- if (!vid) continue;
80
-
81
- // Filter shorts only
82
- const isShort = title.toLowerCase().includes('#shorts') ||
83
- title.toLowerCase().includes('#short') ||
84
- link.includes('/shorts/');
85
-
86
- if (!isShort && shorts.length < 15) continue;
87
-
88
- shorts.push({
89
- id: vid,
90
- title: title.replace(/#shorts?/gi, '').trim().substring(0, 120) || 'YouTube Short',
91
- img: `https://i.ytimg.com/vi/${vid}/hqdefault.jpg`,
92
- link: `https://www.youtube.com/shorts/${vid}`,
93
- channel: channel.handle,
94
- source: 'yt'
95
- });
96
-
97
- if (shorts.length >= 20) break;
98
  }
99
- return shorts;
100
  } catch(e) {
101
- console.warn('RSS fetch failed for', channel.handle, e);
102
- return [];
103
  }
 
104
  }
105
 
106
  function interleaveShorts(shorts) {
@@ -156,17 +127,15 @@
156
  try {
157
  toast('🔄 Đang tải shorts mới...');
158
 
159
- // Method 1: Try server-side API first (uses yt-dlp/scraping on server)
160
- let all = await fetchShortsFromServer();
161
 
162
- // Method 2: If server returns old data, try RSS
163
- if (all.length === 0) {
164
- for (const ch of CHANNELS) {
165
- const shorts = await fetchShortsFromRSS(ch);
166
- if (shorts.length > 0) {
167
- all.push(...shorts);
168
- }
169
- await new Promise(r => setTimeout(r, 500));
170
  }
171
  }
172
 
@@ -211,5 +180,5 @@
211
  // Fetch fresh after delay
212
  setTimeout(() => { window.refreshShorts().catch(() => {}); }, 3000);
213
 
214
- console.log('[Shorts] Fresh fetcher v6 loaded (RSS + server API)');
215
  })();
 
1
  /**
2
+ * VNEWS Fresh Shorts Fetcher v7 - Final
3
+ * Uses server-side /api/shorts endpoint (which has yt-dlp fallback)
4
+ * + YouTube RSS as backup
5
  */
6
  (function() {
7
  'use strict';
 
35
  return url;
36
  }
37
 
38
+ // Method 1: Server-side API (uses yt-dlp on server)
39
+ async function fetchFromServer() {
40
  try {
41
  const r = await fetch('/api/shorts?t=' + Date.now());
42
  if (r.ok) {
 
53
  }
54
  }
55
  } catch(e) {
56
+ console.warn('Server API failed:', e);
57
  }
58
  return [];
59
  }
60
 
61
+ // Method 2: Server-side RSS proxy
62
+ async function fetchFromRSS() {
63
  try {
64
+ const r = await fetch('/api/shorts/rss?t=' + Date.now());
65
+ if (r.ok) {
66
+ const data = await r.json();
67
+ if (data.shorts && data.shorts.length > 0) {
68
+ return data.shorts;
69
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
 
71
  } catch(e) {
72
+ console.warn('RSS fetch failed:', e);
 
73
  }
74
+ return [];
75
  }
76
 
77
  function interleaveShorts(shorts) {
 
127
  try {
128
  toast('🔄 Đang tải shorts mới...');
129
 
130
+ // Try server API first
131
+ let all = await fetchFromServer();
132
 
133
+ // If server returns old/fallback data, try RSS
134
+ if (all.length === 0 || (all.length > 0 && all[0].id === 'Lu_iCQ5YwNM')) {
135
+ console.log('[Shorts] Server returned fallback, trying RSS...');
136
+ const rssShorts = await fetchFromRSS();
137
+ if (rssShorts.length > 0) {
138
+ all = rssShorts;
 
 
139
  }
140
  }
141
 
 
180
  // Fetch fresh after delay
181
  setTimeout(() => { window.refreshShorts().catch(() => {}); }, 3000);
182
 
183
+ console.log('[Shorts] Fresh fetcher v7 loaded (server API + RSS)');
184
  })();