CI / build-and-test (push) Successful in 13m34s
- 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
52 lines
1.6 KiB
Python
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)
|