chore: update Angular cache and TypeScript build info files
This commit is contained in:
parent
41255a8126
commit
709b2e55c2
2
.angular/cache/20.2.2/app/.tsbuildinfo
vendored
2
.angular/cache/20.2.2/app/.tsbuildinfo
vendored
File diff suppressed because one or more lines are too long
BIN
db/newtube.db
BIN
db/newtube.db
Binary file not shown.
@ -60,7 +60,27 @@ async function scrapeRumbleVideo(videoId) {
|
|||||||
const duration = durationText ? parseInt(durationText) : 0;
|
const duration = durationText ? parseInt(durationText) : 0;
|
||||||
const uploadedDate = $('meta[property="article:published_time"]').attr('content') || '';
|
const uploadedDate = $('meta[property="article:published_time"]').attr('content') || '';
|
||||||
const description = $('meta[property="og:description"]').attr('content') || '';
|
const description = $('meta[property="og:description"]').attr('content') || '';
|
||||||
return { videoId, title: title || 'Untitled Video', thumbnail, uploaderName: uploaderName || 'Unknown Uploader', views, duration, uploadedDate, description, url: `https://rumble.com/${videoId}`, type: 'video' };
|
// Try to extract the official embed URL
|
||||||
|
let embedUrl = $('meta[property="og:video"], meta[name="twitter:player"]').attr('content') || '';
|
||||||
|
if (!embedUrl) {
|
||||||
|
const iframeSrc = $('iframe[src*="/embed/"]').attr('src') || '';
|
||||||
|
embedUrl = iframeSrc || '';
|
||||||
|
}
|
||||||
|
// Normalize protocol-less URLs
|
||||||
|
if (embedUrl && embedUrl.startsWith('//')) embedUrl = 'https:' + embedUrl;
|
||||||
|
// Detect canonical URL to extract stable ID
|
||||||
|
const canonicalUrl = $('link[rel="canonical"]').attr('href') || $('meta[property="og:url"]').attr('content') || '';
|
||||||
|
// Normalize/derive the stable Rumble ID (e.g., v464efu)
|
||||||
|
let stableId = videoId;
|
||||||
|
const mEmbed = /\/embed\/(v[0-9A-Za-z]+)/.exec(embedUrl || '');
|
||||||
|
const mCanon = /\/(v[0-9A-Za-z]+)(?:[\-./]|$)/.exec(canonicalUrl || '');
|
||||||
|
if (mEmbed && mEmbed[1]) stableId = mEmbed[1];
|
||||||
|
else if (mCanon && mCanon[1]) stableId = mCanon[1];
|
||||||
|
// If embedUrl is a page URL, convert to embed path as a fallback
|
||||||
|
if (!/\/embed\//.test(embedUrl)) {
|
||||||
|
embedUrl = `https://rumble.com/embed/${stableId}/?autoplay=2&muted=1`;
|
||||||
|
}
|
||||||
|
return { videoId: stableId, title: title || 'Untitled Video', thumbnail, uploaderName: uploaderName || 'Unknown Uploader', views, duration, uploadedDate, description, url: `https://rumble.com/${stableId}`, embedUrl, type: 'video' };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('scrapeRumbleVideo error:', e.message);
|
console.error('scrapeRumbleVideo error:', e.message);
|
||||||
return { videoId, error: 'Scraping failed' };
|
return { videoId, error: 'Scraping failed' };
|
||||||
|
@ -208,6 +208,9 @@ export class WatchComponent implements OnDestroy, AfterViewInit {
|
|||||||
private providerSel = signal<string>('');
|
private providerSel = signal<string>('');
|
||||||
provider = computed(() => this.providerSel() || this.instances.selectedProvider());
|
provider = computed(() => this.providerSel() || this.instances.selectedProvider());
|
||||||
private twitchChannel = signal<string | null>(null);
|
private twitchChannel = signal<string | null>(null);
|
||||||
|
// Backend-provided embed URL for providers that need it (e.g., Rumble)
|
||||||
|
private rumbleEmbed = signal<string | null>(null);
|
||||||
|
|
||||||
embedUrl = computed<SafeResourceUrl | null>(() => {
|
embedUrl = computed<SafeResourceUrl | null>(() => {
|
||||||
const id = this.videoId();
|
const id = this.videoId();
|
||||||
const p = this.provider();
|
const p = this.provider();
|
||||||
@ -261,8 +264,11 @@ export class WatchComponent implements OnDestroy, AfterViewInit {
|
|||||||
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
||||||
}
|
}
|
||||||
if (p === 'rumble') {
|
if (p === 'rumble') {
|
||||||
// Best-effort: Rumble embed path may vary depending on the id format
|
// Prefer backend-provided embed URL (includes required pub/query params)
|
||||||
const u = `https://rumble.com/embed/${encodeURIComponent(id)}/?autoplay=2&muted=1`;
|
const fromBackend = this.rumbleEmbed();
|
||||||
|
const u = fromBackend && /^https?:\/\//i.test(fromBackend)
|
||||||
|
? fromBackend
|
||||||
|
: `https://rumble.com/embed/${encodeURIComponent(id)}/?autoplay=2&muted=1`;
|
||||||
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
@ -348,6 +354,8 @@ export class WatchComponent implements OnDestroy, AfterViewInit {
|
|||||||
loadVideo(id: string) {
|
loadVideo(id: string) {
|
||||||
console.log('[Watch] Loading video', { id });
|
console.log('[Watch] Loading video', { id });
|
||||||
this.loading.set(true);
|
this.loading.set(true);
|
||||||
|
// Clear any previous Rumble embed URL to avoid stale iframes during fast navigation
|
||||||
|
this.rumbleEmbed.set(null);
|
||||||
// Prepare placeholder from router state if available for richer UI
|
// Prepare placeholder from router state if available for richer UI
|
||||||
const stateVideo = (history.state && (history.state as any).video) as Video | undefined;
|
const stateVideo = (history.state && (history.state as any).video) as Video | undefined;
|
||||||
this.video.set({
|
this.video.set({
|
||||||
@ -385,13 +393,28 @@ export class WatchComponent implements OnDestroy, AfterViewInit {
|
|||||||
const provider = this.provider();
|
const provider = this.provider();
|
||||||
if (provider === 'rumble') {
|
if (provider === 'rumble') {
|
||||||
// Validate and enrich Rumble video via backend scraping (may also normalize id)
|
// Validate and enrich Rumble video via backend scraping (may also normalize id)
|
||||||
this.http.get<any>(`/api/rumble/video/${encodeURIComponent(id)}`).subscribe({
|
const handle = (data: any) => {
|
||||||
next: (data) => {
|
|
||||||
const newId = (data && (data.videoId || data.id)) ? String(data.videoId || data.id) : id;
|
const newId = (data && (data.videoId || data.id)) ? String(data.videoId || data.id) : id;
|
||||||
|
// If route changed while request was in-flight, ignore this response
|
||||||
|
const current = this.videoId();
|
||||||
|
if (current && current !== id && current !== newId) {
|
||||||
|
console.warn('[Watch] Ignoring out-of-date Rumble response', { requested: id, newId, current });
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Update id if backend provided a more accurate one
|
// Update id if backend provided a more accurate one
|
||||||
if (newId && newId !== id) {
|
if (newId && newId !== current) {
|
||||||
this.videoId.set(newId);
|
this.videoId.set(newId);
|
||||||
}
|
}
|
||||||
|
// Store backend-provided embed url if present, but only if it matches the expected id
|
||||||
|
try {
|
||||||
|
const eurl = (data && data.embedUrl) ? String(data.embedUrl) : '';
|
||||||
|
const match = /\/embed\/([A-Za-z0-9]+)/.exec(eurl || '');
|
||||||
|
if (eurl && match && match[1] && (match[1] === newId.replace(/^v/, 'v'))) {
|
||||||
|
this.rumbleEmbed.set(eurl);
|
||||||
|
} else {
|
||||||
|
this.rumbleEmbed.set(null);
|
||||||
|
}
|
||||||
|
} catch { this.rumbleEmbed.set(null); }
|
||||||
// Merge enriched fields
|
// Merge enriched fields
|
||||||
this.video.update(v => v ? {
|
this.video.update(v => v ? {
|
||||||
...v,
|
...v,
|
||||||
@ -434,11 +457,19 @@ export class WatchComponent implements OnDestroy, AfterViewInit {
|
|||||||
error: () => {}
|
error: () => {}
|
||||||
});
|
});
|
||||||
} catch {}
|
} catch {}
|
||||||
},
|
};
|
||||||
|
this.http.get<any>(`/api/rumble/video/${encodeURIComponent(id)}`).subscribe({
|
||||||
|
next: handle,
|
||||||
error: () => {
|
error: () => {
|
||||||
// Even if details fail, try to display embed with the original id
|
// Fallback to dev proxy alias if /api is not available in dev
|
||||||
this.loading.set(false);
|
this.http.get<any>(`/proxy/api/rumble/video/${encodeURIComponent(id)}`).subscribe({
|
||||||
this.loadRelatedSuggestions();
|
next: handle,
|
||||||
|
error: () => {
|
||||||
|
// Even if details fail, try to display embed with the original id
|
||||||
|
this.loading.set(false);
|
||||||
|
this.loadRelatedSuggestions();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user