o11v4-podman/example.py
2026-02-22 17:02:56 -05:00

184 lines
5.9 KiB
Python

#!/usr/bin/python3
import sys
import os
import base64
import json
import requests
import jwt
import logging
from logging.handlers import RotatingFileHandler # Import RotatingFileHandler
from typing import Any, Dict, Optional
# Utility function for parameter parsing
def parse_params(params: list[str], name: str, default: str = "") -> str:
return next((p.split('=')[1] for p in params if p.startswith(f"{name}=")), default)
# Fetch parameters from sys.argv
user = parse_params(sys.argv, 'user')
password = parse_params(sys.argv, 'password')
id = parse_params(sys.argv, 'id')
action = parse_params(sys.argv, 'action')
pssh = parse_params(sys.argv, 'pssh')
# Dynamically set the log filename based on the 'id' parameter
log_filename = f"{id}.log" if id else f"default.log"
# Setup logging to a dynamically named file
logging.basicConfig(
level=logging.DEBUG, # Capture all log messages
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
RotatingFileHandler(log_filename, maxBytes=5*1024*1024, backupCount=3),
logging.StreamHandler()
]
)
# Constants for URLs
CHANNELS_API_URL = 'https://cbd46b77.cdn.cms.movetv.com/cms/publish3/domain/summary/ums/1.json'
PLAYBACK_API_URL = 'https://cbd46b77.cdn.cms.movetv.com/playermetadata/sling/v1/api/channels/{id}/schedule/now/playback_info.qvt'
# API headers
api_headers = {"ccdodlad-api-key": "bluechip_studio_696223755_api_and_extension_unlimited"}
# CDM process
def do_cdm(pssh: str, id: str) -> Optional[Dict[str, Any]]:
try:
# Use f-string for URL formatting
sling_key_api = f"id={id}&pssh={pssh}"
# Make the request
response = requests.get(sling_key_api)
response.raise_for_status() # Raise an error for bad HTTP status codes
try:
key_data = response.json() # Attempt to parse JSON
except ValueError:
logging.error(f"Invalid JSON response: {response.content}")
return None
# Check if 'status' is present in the response and handle 'false' status
if key_data.get('status') == 'false':
logging.error("Failed to Grab Key: Status is false")
return None
# Return the 'keys' field from the response if present
keys = key_data.get('keys', None)
if keys is None or not keys: # Check if keys is None or an empty list
logging.error("Keys are empty or not present")
return None
list = "\n".join(keys)
print(list)
except requests.exceptions.RequestException as e:
logging.error(f"RequestException: {e}")
except Exception as e:
logging.error(f"Unexpected error in do_cdm: {e}")
return None
# Function to process channels and fetch playback manifest
def process_channel(id: str) -> Optional[str]:
try:
response = requests.get(PLAYBACK_API_URL.format(id=id))
response.raise_for_status()
data = response.json()
dash_manifest_url = data.get('playback_info', {}).get('dash_manifest_url')
if dash_manifest_url:
return dash_manifest_url
else:
logging.error("dash_manifest_url not found in the response")
return None
except requests.exceptions.RequestException as e:
logging.error(f"API request error: {e}")
except KeyError as e:
logging.error(f"KeyError: {e}")
except Exception as e:
logging.error(f"Unexpected error: {e}")
return None
# Function to handle the channels action
def handle_channels() -> None:
output = {"Channels": []}
try:
response = requests.get(CHANNELS_API_URL).json()
channels = response.get('channels', [])
for channel_data in channels:
channelid = str(channel_data['channel_guid'])
channel_info = {
"Name": channel_data['metadata']['channel_name'],
"Mode": "live",
"SessionManifest": True,
"ManifestScript": f'id={channelid}',
"CdmType": "widevine",
"UseCdm": True,
"Cdm": f'id={channelid}',
"Video": "best",
"OnDemand": True,
"SpeedUp": True,
"CdmMode": "external"
}
output['Channels'].append(channel_info)
print(json.dumps(output, indent=2))
except (KeyError, ValueError, requests.RequestException) as e:
logging.error(f"Error while handling channels: {e}")
# Function to handle the manifest action
def handle_manifest(id: str) -> None:
try:
manifest_url = process_channel(id)
output = {
"ManifestUrl": manifest_url,
"Headers": {
"Manifest": {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
},
"Media": {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
}
},
"Heartbeat": {
"Url": '',
"Params": '',
"PeriodMs": 5 * 60 * 1000
}
}
print(json.dumps(output, indent=4))
except Exception as e:
logging.error(f"Error while handling manifest: {e}")
def fix_base64(encoded_str):
# Add necessary padding if needed
missing_padding = len(encoded_str) % 4
if missing_padding:
encoded_str += '=' * (4 - missing_padding) # Add '=' padding
return encoded_str
# Main control flow
logging.error("Running with action : " + action)
if action == "cdm":
logging.error("Requesting keys")
do_cdm(pssh, id)
elif action == "channels":
logging.error("Reloading channels")
handle_channels()
elif action == "manifest":
logging.error("Requesting manifest")
handle_manifest(id)