Files
bruno 97e5de74f5
CI / build-and-test (push) Successful in 13m34s
feat(channel): page details chaine multi-providers avec onglets et infinite scroll
- Strategy Pattern front: ChannelProviderInterface + 6 providers (yt/dm/tw/pt/od/ru) + factory (ids longs/courts)
- ChannelContentService: cache par onglet/tri/recherche (TTL 5min), pagination nextPage
- ChannelPage: header (banniere/avatar/subs/description ...plus), tabs dynamiques par capabilities, grilles videos/shorts 9:16/playlists/live, recherche debounced, tri recent/populaire, infinite scroll IntersectionObserver, skeletons/empty/error
- Backend: GET /api/channels/:provider/:id/content (videos/shorts/playlists/live) natif par provider
2026-09-25 10:15:12 -04:00

52 lines
1.6 KiB
Python

#!/usr/bin/env python3
"""
Rumble Cloudflare bypass fetcher.
Node's TLS fingerprint (OpenSSL) is blocked by Rumble's Cloudflare config, while
curl_cffi's browser impersonation passes. This helper fetches a URL with
curl_cffi impersonating a Chrome client and prints the raw HTML to stdout.
Usage: python3 rumble_fetch.py <url> [timeout_seconds]
Exit codes: 0 = ok (stdout = html), 2 = HTTP error / challenge, 3 = curl_cffi missing.
"""
import sys
URL = sys.argv[1] if len(sys.argv) > 1 else ""
TIMEOUT = int(sys.argv[2]) if len(sys.argv) > 2 else 15
try:
from curl_cffi import requests as curl_requests
except ImportError:
sys.stderr.write("curl_cffi not installed\n")
sys.exit(3)
if not URL:
sys.stderr.write("url required\n")
sys.exit(2)
IMPERSONATE_CANDIDATES = ["chrome131", "chrome124", "chrome120", "safari18_0"]
for target in IMPERSONATE_CANDIDATES:
try:
resp = curl_requests.get(
URL,
impersonate=target,
timeout=TIMEOUT,
allow_redirects=True,
headers={
"Accept-Language": "en-US,en;q=0.9",
},
)
body = resp.text or ""
if resp.status_code == 200 and "Just a moment" not in body[:4000]:
sys.stdout.write(body)
sys.exit(0)
# challenge or error: try next impersonation target
last_status = resp.status_code
except Exception as exc: # noqa: BLE001
sys.stderr.write(f"{target}: {exc}\n")
last_status = 0
sys.stderr.write(f"all impersonation targets failed (last={last_status})\n")
sys.exit(2)