import base64

from pywidevine.cdm import Cdm
from pywidevine.device import Device
from pywidevine.pssh import PSSH
from base64 import b64encode
import time
import requests
from lxml import etree
import json
import uuid
import httpx
import sys
import re
import binascii
import urllib.request
from urllib.error import HTTPError
from urllib import request as urlrequest
 
proxy_url = "" #add a http proxy url if you need it
MyWVD = "2.wvd" #insert WVD filename

def get_pssh_from_url(url):
    mpd_headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }

    try:
        pssh_list = []
        if proxy_url:
           proxy_support = urllib.request.ProxyHandler({'http': '%s' % proxy_url, 'https': '%s' % proxy_url})
           opener = urllib.request.build_opener(proxy_support)
           urllib.request.install_opener(opener)
           request = urllib.request.Request(url)
           mpd_data = urllib.request.urlopen(request).read().decode('utf-8') 
        else:
           mpd_data = urllib.request.urlopen(url).read().decode('utf-8') 
        baseurl = url.rstrip("/") + "/"
        psshs = re.findall(">([\S]+)</cenc:pssh", mpd_data)
        if psshs:
            for pssh in psshs:
                pesx = binascii.hexlify(base64.b64decode(pssh)).decode('utf-8')
                if "edef8ba9" in pesx:
                    if pssh not in pssh_list:
                        pssh_list.append(pssh)
        
        if pssh_list:
            return pssh_list[0]
        else:
            psshs = re.findall('urn:mpeg:cenc:2013">([\S]+)</pssh', mpd_data)
            if psshs:
               for pssh in psshs:
                   pesx = binascii.hexlify(base64.b64decode(pssh)).decode('utf-8')
                   if "edef8ba9" in pesx:
                       if pssh not in pssh_list:
                           pssh_list.append(pssh)
            
               if pssh_list:
                  return pssh_list[0]
               else:
                  return ''
     
    except HTTPError as e:
        return ''

    except ValueError as e:
        if "unknown url type" in str(e):
            return ''
        else:
            raise e

def getKeys(url, urlLicence, token):
           
   response = requests.get(url)
   
   if response.status_code == 200:    
   
      pssh = get_pssh_from_url(url)
         
      if (pssh):
         pssh_stream = PSSH(str(pssh))
         device = Device.load(MyWVD)
         cdm = Cdm.from_device(device)
         session_id = cdm.open()
         challenge = cdm.get_license_challenge(session_id, pssh_stream)
         ilicurl = str(urlLicence)
         token = str(token)
         headers = {
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0',
           'authorization':f"Bearer {token}", 
         }
         
         if proxy_url:
            proxies = {
                    'http': proxy_url,
                    'https': proxy_url
            }
            licence = requests.post(ilicurl, data=challenge, headers=headers, proxies=proxies)
         else:
            licence = requests.post(ilicurl, data=challenge, headers=headers)
            
         licence.raise_for_status()
         cdm.parse_license(session_id, licence.content)
         fkeys = ""
         for key in cdm.get_keys(session_id):
           if key.type != 'SIGNING':
             fkeys += key.kid.hex + ":" + key.key.hex()
        
         return fkeys
         cdm.close(session_id)
      else:
         return 'key:nofound'
         cdm.close(session_id)
   else:
      return 'key:nofound'