import sys
import o11
import requests
import base64
import json
import os
from uuid import uuid4
import glob
from pyplayready import Cdm, Device, PSSH

cdm=o11.parse_params(sys.argv, 'cdm')
drm=o11.parse_params(sys.argv, 'drm')
kid=o11.parse_params(sys.argv, 'kid')
pssh=o11.parse_params(sys.argv, 'pssh')
base64Challenge=o11.parse_params(sys.argv, 'challenge')
action=o11.parse_params(sys.argv, 'action')
drm=o11.parse_params(sys.argv, 'drm')
pssh=o11.parse_params(sys.argv, 'pssh')
proxy=o11.parse_params(sys.argv, 'proxy')
channelId = o11.parse_params(sys.argv, 'channelId')
country = o11.parse_params(sys.argv, "country").upper()

if not country:
    print("Missing country!")
    exit(1)

PATH = os.getcwd() + f"/discovery+{country}"


proxies = {
    "http": proxy,
    "https": proxy
}

headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
}

def getEpg(token):
    url = "https://eu1-prod-direct.discoveryplus.com/cms/routes/home"

    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
        "cookie": f"st={token}"
    }

    params = {
        "include": "default",
        "decorators": "playbackAllowed"
    }

    response = requests.get(url, headers=headers, params=params, proxies=proxies)

    if not response.ok:
        raise RuntimeError("Error while getting channels!")
    
    items = response.json()['included']

    channels = []

    for item in items:
        if item['type'] == "channel" :
            if "Free" in item.get('attributes', {}).get('packages', []) and item.get('attributes',{}).get('hasLiveStream', ''):
                channels.append({
                    "name": item['attributes']['name'],
                    "id": item['id']
                })
        else:
            continue


    return channels

def getLiveResources(channelId:str):

    url = "https://eu1-prod-direct.discoveryplus.com/playback/v3/channelPlaybackInfo"

    payload = {'channelId': channelId,
            'deviceInfo': {
                'adBlocker': 'true',
                'drmSupported': 'true',
                'hwDecodingCapabilities': [],
                'screen':{
                    'width':1920,
                    'height':1080
                },
                'player':{
                    'width':1920,
                    'height':1080
                }
            },
            'wisteriaProperties':{
                'advertiser': {
                    'firstPlay': 0,
                    'fwIsLat': 0
                },
                'device':{
                    'browser':{
                        'name': 'chrome',
                        'version': "138.0.7204.98"
                    },
                    'type': 'desktop'
                },
                'platform': 'desktop',
                'product': 'dplus_emea',
                'sessionId': str(uuid4()),
                'streamProvider': {
                    'suspendBeaconing': 0,
                    'hlsVersion': 6,
                    'pingConfig': 1
                }
            }
    }

    response = requests.post(url, json=payload, headers=headers, proxies=proxies)

    if not response.ok:
        raise Exception("\nErrore durante il recupero del playback!")
    

    content = response.json()

    return {
        "mpd": content['data']['attributes']['streaming'][0]['url'],
        "licenseUrl": content['data']['attributes']['streaming'][0]['protection']['schemes']['widevine']['licenseUrl']
    }

def getKeys(psshs:list, licenseUrl:str)->list:
    
    prds = glob.glob(f"*.prd")

    if len(prds) < 1:
        print("No .PRD found in o11 folder!")
        exit(1)

    device = Device.load(prds[0])
    cdm = Cdm.from_device(device)

    session = cdm.open()

    keys = []

    for pssh in psshs:
        pssh = PSSH(pssh)

        challenge = cdm.get_license_challenge(session, pssh.wrm_headers[0])
        response = requests.post(licenseUrl, data=challenge, proxies=proxies)

        if not response.ok:
            print(response.text)
            exit(1)

        cdm.parse_license(session, response.text)

        for key in cdm.get_keys(session):
            if not f"{key.key_id.hex}:{key.key.hex()}" in keys:
                keys.append(f"{key.key_id.hex}:{key.key.hex()}")
    cdm.close(session)
    return keys


""" def getToken():
    with open(PATH + "/token.txt", "r") as f:
        token = f.read().strip("\n")
        f.close()
    return token """

#Anonymous token retrival
def getToken():

    url =  "https://eu1-prod-direct.discoveryplus.com/token"

    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
    }

    params = {
        "deviceId": str(uuid4().hex),
        "realm": "dplay",
        "shortlived": "true"
    }

    response = requests.get(url, headers=headers, params=params, proxies=proxies)

    if not response.ok:
        print(response.text)
        raise RuntimeError("Error while getting token!")

    return response.json()['data']['attributes']['token']


def main():
    global headers
    token = getToken()
    headers['cookie'] = f"countryCode={country}; st={token}"

    if action == "channels":
        items = getEpg(token)
        channels = []
        for item in items:
            channels.append({
                "Name": item['name'],
                "SessionManifest": True,
                "ManifestScript": f"channelId={item['id']}",
                "Autostart": False,
                "CdmType": "playready",
                "CdmMode": "external",
                "Cdm": f"channelId={item['id']}",
                "UseCdm": True,
                #"LogoUrl": "https://raw.githubusercontent.com/Stream4me/media/refs/heads/master/resources/thumb/discoveryplus.png",
                "Video": "best",
            })

        print(json.dumps(
            {
                "Channels": channels
            },
            indent=2
        ))
        
    if action == "manifest":
        resources = getLiveResources(channelId)

        print(json.dumps(
            {
                "ManifestUrl": resources['mpd']
            }
        , indent=2))


    if action == "cdm" and drm == "widevine":
        global base64Challenge
        licenseUrl = getLiveResources(channelId)['licenseUrl']
        if base64Challenge == "cert":
            exit(0)

        challenge = base64.b64decode(base64Challenge)

        response = requests.post(licenseUrl, data=challenge, proxies=proxies)
        encodedResponse = base64.b64encode(response.content).decode()

        print(encodedResponse)

    elif action == "cdm" and drm == "playready":

        licenseUrl = getLiveResources(channelId)['licenseUrl'].replace("/widevine?", "/play-ready?")

        keys = getKeys([pssh], licenseUrl)

        for key in keys:
            print(key)



if __name__ == "__main__":
    main()
