mirror of
https://github.com/NohamR/OqeeRewind.git
synced 2026-01-11 08:38:21 +00:00
Add CLI mode and refactor Oqee downloader workflow
Introduces a command-line interface to main.py for Oqee TV downloads, supporting argument parsing for channel, date, quality, and keys. Refactors stream selection, segment download, decryption, and merging logic for both CLI and interactive modes. Adds new utility modules for DRM key retrieval, segment merging, and decryption. Cleans up and simplifies Oqee client, input, stream, and time utilities for improved maintainability and usability.
This commit is contained in:
72
utils/downloader.py
Normal file
72
utils/downloader.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import os
|
||||
import base64
|
||||
import requests
|
||||
from uuid import UUID
|
||||
from pywidevine.cdm import Cdm
|
||||
from pywidevine.device import Device
|
||||
from pywidevine.pssh import PSSH
|
||||
|
||||
|
||||
def fetch_drm_keys(kid: str, api_url: str, api_key: str) -> str:
|
||||
"""Fetch DRM keys for a given KID.
|
||||
|
||||
Args: kid: The key identifier string.
|
||||
Returns: The DRM key as a string.
|
||||
"""
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Api-Key': api_key,
|
||||
}
|
||||
data = {"service": "oqee", "kid": kid}
|
||||
response = requests.post(
|
||||
api_url, headers=headers, json=data, timeout=10
|
||||
)
|
||||
return response.json()["key"]
|
||||
|
||||
|
||||
def generate_pssh(kids: list[str]) -> PSSH:
|
||||
"""Generate a PSSH box for given KIDs.
|
||||
|
||||
Args: kids: List of key identifier strings.
|
||||
Returns: The PSSH object.
|
||||
"""
|
||||
default_pssh = (
|
||||
"AAAAiHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAGgIARIQrKzUjhLvvbqkebbW2/EQtBIQ"
|
||||
"WxKIsxtqP3iaIFYUu9f6xxIQXn4atxoopds39jbUXbiFVBIQUUJpv9uuzWKv4ccKTtooMRIQ"
|
||||
"ocf9FUFCoGm775zPIBr3HRoAKgAyADgASABQAA=="
|
||||
)
|
||||
pssh = PSSH(default_pssh)
|
||||
pssh.set_key_ids([UUID(kid.replace("-", "").lower()) for kid in kids])
|
||||
return pssh
|
||||
|
||||
|
||||
def get_keys(kids: list[str], method: dict) -> list[str]:
|
||||
"""Retrieve DRM keys using the specified method."""
|
||||
if method["method"] == 'api':
|
||||
print("Fetching DRM keys via API...")
|
||||
keys = []
|
||||
for kid in kids:
|
||||
key = fetch_drm_keys(kid, method["api_url"], method["api_key"])
|
||||
keys.append(f"{kid}:{key}")
|
||||
return keys
|
||||
else:
|
||||
print("Fetching DRM keys via Widevine CDM...")
|
||||
client = method["client_class"]
|
||||
|
||||
device = Device.load(method["device_file"])
|
||||
cdm = Cdm.from_device(device)
|
||||
session_id = cdm.open()
|
||||
certificate = client.certificate()
|
||||
cdm.set_service_certificate(session_id, certificate)
|
||||
|
||||
pssh_data = generate_pssh(kids)
|
||||
challenge = cdm.get_license_challenge(session_id, pssh_data, privacy_mode=True)
|
||||
license_data = client.license(challenge)
|
||||
|
||||
cdm.parse_license(session_id, license_data)
|
||||
keys = []
|
||||
for key in cdm.get_keys(session_id):
|
||||
if key.type=='CONTENT':
|
||||
keys.append(f"{key.kid.hex}:{key.key.hex()}")
|
||||
cdm.close(session_id)
|
||||
return keys
|
||||
Reference in New Issue
Block a user