# -*- coding: utf-8 -*-
# Module: widevine_keys
# Created on: 10.12.2021
# Authors: medvm
# Version: 2.1.0

import base64, requests, sys, xmltodict
import headers
# import cookies
import json
from cdm import cdm, deviceconfig
from base64 import b64encode
from getPSSH import get_pssh
from wvdecryptcustom import WvDecrypt
from cdm.formats import wv_proto2_pb2 as wv_proto2
from urllib.parse import urlparse
import logging
# logging.basicConfig(level=logging.DEBUG)
MDP_URL = input('\nInput MPD URL: ')
lic_url = input('License URL: ')
# hardcoded for kinopoisk.ru
# lic_url = 'https://widevine-proxy.ott.yandex.ru/proxy'
responses = []
license_b64 = ''
pssh = get_pssh(MDP_URL)
params = None
params = urlparse(lic_url).query
# pssh = 'AAAAXHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADwIARIQ7iYSc3cNGm7XKPe3hSn3MhoIdXNwLWNlbmMiGDdpWVNjM2NOR203WEtQZTNoU24zTWc9PSoAMgA='
# params from mdp_url:
# ottsession=5945048d6f844d1699054cc5d44548f1&
# puid=339572866&
# video_content_id=4315082489d87677b21f7c83593fcb73&

print(f'{chr(10)}PSSH obtained.\n{pssh}')

def WV_Function(pssh, lic_url, cert_b64=None):
	"""main func, emulates license request and then decrypt obtained license
	fileds that changes every new request is signature, expirationTimestamp, watchSessionId, puid, and rawLicenseRequestBase64 """
	wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64=cert_b64, device=deviceconfig.device_android_generic)                   
	raw_request = wvdecrypt.get_challenge()
	request = b64encode(raw_request)
	signature = cdm.hash_object
# basic, mostly sites works
	responses.append(requests.post(url=lic_url, headers=headers.headers, data=raw_request, params=params))
# some another sites support
	responses.append(requests.post(url=lic_url, headers=headers.headers, params=params, 
		json={
		"rawLicenseRequestBase64": str(request, "utf-8" ), 
		}))
# kakaotv support
	responses.append(requests.post(url=lic_url, headers=headers.headers, params=params, 
		data=f'token={headers.token}&provider={headers.provider}&payload={str(request, "utf-8" )}'
		))
# xfinity.com support
	headers.headers['licenseRequest'] = str(request, "utf-8" )
	responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
		))
	del headers.headers['licenseRequest']
# rte.ie support
	responses.append(requests.post(url=lic_url, headers=headers.headers, params=params, 
		json={
		"getWidevineLicense": 
			{
			'releasePid': headers.releasePid,
			'widevineChallenge': str(request, "utf-8" )
			}, 
			}))
# kinopoisk support
	responses.append(requests.post(url=lic_url, headers=headers.headers, params=params, 
			json={
			"rawLicenseRequestBase64": str(request, "utf-8" ), 
			"puid": 				'339572866',
			"watchSessionId": 		'ed0e355063ac48b783130a390dc27ba6',
			"contentId": 			'4315082489d87677b21f7c83593fcb73',
			"contentTypeId": 		'21',
			"serviceName": 			'ott-kp',
			"productId": 			'2',
			"monetizationModel": 	'SVOD',
			"expirationTimestamp": 	'1639009453',
			"verificationRequired": 'false',
			"signature": 			str(signature), 
			"version":				'V4'
			}))
	for idx, response in enumerate(responses):
		try:
			str(response.content, "utf-8")
		except UnicodeDecodeError:
			widevine_license = response
			print(f'{chr(10)}license response status: {widevine_license}{chr(10)}')
			break	
		else:
			if len(str(response.content, "utf-8")) > 500:
				widevine_license = response
				print(f'{chr(10)}license response status: {widevine_license}{chr(10)}')
				break
		if idx == len(responses) - 1:
			print(f'{chr(10)}license response status: {response}')
			print(f'server reports: {str(response.content, "utf-8")}')
			print(f'server did not issue license, make sure you have correctly pasted all the required headers in the headers.py. Also check json/raw params of POST request.{chr(10)}')
			exit() 	
		
	lic_field_names = ['license', 'payload', 'getWidevineLicenseResponse']
	lic_field_names2 = ['license']
	
	open('license_content.bin', 'wb').write(widevine_license.content)

	try:
		if str(widevine_license.content, 'utf-8').find(':'):
			for key in lic_field_names:
				try: 
					license_b64 = json.loads(widevine_license.content.decode())[key]
				except:
					pass			
				else:
					for key2 in lic_field_names2:
						try: 
							license_b64 = json.loads(widevine_license.content.decode())[key][key2]
						except:
							pass
		else:
			license_b64 = widevine_license.content								
	except:
		license_b64 = b64encode(widevine_license.content)

	wvdecrypt.update_license(license_b64)
	Correct, keyswvdecrypt = wvdecrypt.start_process()
	if Correct:
		return Correct, keyswvdecrypt   

correct, keys = WV_Function(pssh, lic_url)

for key in keys:
	print('KID:KEY -> ' + key)
