Add DRM support for all streams (#121)

This commit is contained in:
mediaminister 2023-07-21 22:16:07 +02:00 committed by GitHub
parent dc446332ab
commit c9ae78f83b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 70 deletions

View File

@ -12,11 +12,6 @@ from resources.lib.viervijfzes.auth import AuthApi
from resources.lib.viervijfzes.aws.cognito_idp import AuthenticationException, InvalidLoginException
from resources.lib.viervijfzes.content import CACHE_PREVENT, ContentApi, GeoblockedException, UnavailableException
try: # Python 3
from urllib.parse import quote, urlencode
except ImportError: # Python 2
from urllib import quote, urlencode
_LOGGER = logging.getLogger(__name__)
@ -79,18 +74,9 @@ class Player:
if resolved_stream:
titleitem = Menu.generate_titleitem(episode)
if resolved_stream.license_url:
# Generate license key
license_key = self.create_license_key(resolved_stream.license_url,
key_headers=dict(
customdata=resolved_stream.auth,
))
else:
license_key = None
kodiutils.play(resolved_stream.url,
resolved_stream.stream_type,
license_key,
resolved_stream.license_key,
info_dict=titleitem.info_dict,
art_dict=titleitem.art_dict,
prop_dict=titleitem.prop_dict)
@ -106,15 +92,7 @@ class Player:
# Lookup the stream
resolved_stream = self._resolve_stream(uuid, islongform)
if resolved_stream.license_url:
# Generate license key
license_key = self.create_license_key(resolved_stream.license_url, key_headers=dict(
customdata=resolved_stream.auth,
))
else:
license_key = None
kodiutils.play(resolved_stream.url, resolved_stream.stream_type, license_key)
kodiutils.play(resolved_stream.url, resolved_stream.stream_type, resolved_stream.license_key)
@staticmethod
def _resolve_stream(uuid, islongform):
@ -153,26 +131,3 @@ class Player:
except UnavailableException:
kodiutils.ok_dialog(message=kodiutils.localize(30712)) # The video is unavailable...
return None
@staticmethod
def create_license_key(key_url, key_type='R', key_headers=None, key_value=None):
""" Create a license key string that we need for inputstream.adaptive.
:param str key_url:
:param str key_type:
:param dict[str, str] key_headers:
:param str key_value:
:rtype: str
"""
header = ''
if key_headers:
header = urlencode(key_headers)
if key_type in ('A', 'R', 'B'):
key_value = key_type + '{SSM}'
elif key_type == 'D':
if 'D{SSM}' not in key_value:
raise ValueError('Missing D{SSM} placeholder')
key_value = quote(key_value)
return '%s|%s|%s|' % (key_url, header, key_value)

View File

@ -79,19 +79,17 @@ STREAM_DICT = {
class ResolvedStream:
""" Defines a stream that we can play"""
def __init__(self, uuid=None, url=None, stream_type=None, license_url=None, auth=None):
def __init__(self, uuid=None, url=None, stream_type=None, license_key=None):
"""
:type uuid: str
:type url: str
:type stream_type: str
:type license_url: str
:type auth: str
:type license_key: str
"""
self.uuid = uuid
self.url = url
self.stream_type = stream_type
self.license_url = license_url
self.auth = auth
self.license_key = license_key
def __repr__(self):
return "%r" % self.__dict__

View File

@ -351,10 +351,10 @@ class ContentApi:
return None
def get_stream_by_uuid(self, uuid, islongform):
""" Get the stream URL to use for this video.
""" Return a ResolvedStream for this video.
:type uuid: str
:type islongform: bool
:rtype str
:rtype: ResolvedStream
"""
mode = 'long-form' if islongform else 'short-form'
response = self._get_url(self.API_GOPLAY + '/web/v1/videos/%s/%s' % (mode, uuid), authentication='Bearer %s' % self._auth.get_token())
@ -363,34 +363,35 @@ class ContentApi:
if not data:
raise UnavailableException
if data.get('manifestUrls'):
# Get DRM license
license_key = None
if data.get('drmXml'):
# DRM protected stream
# BuyDRM format
# See https://docs.unified-streaming.com/documentation/drm/buydrm.html#setting-up-the-client
# DRM protected DASH stream
return ResolvedStream(
uuid=uuid,
url=data['manifestUrls']['dash'],
stream_type=STREAM_DASH,
license_url='https://wv-keyos.licensekeyserver.com/',
auth=data['drmXml'],
)
# Generate license key
license_key = self.create_license_key('https://wv-keyos.licensekeyserver.com/', key_headers=dict(
customdata=data['drmXml'],
))
# Get manifest url
if data.get('manifestUrls'):
if data.get('manifestUrls').get('dash'):
# Unprotected DASH stream
# DASH stream
return ResolvedStream(
uuid=uuid,
url=data['manifestUrls']['dash'],
stream_type=STREAM_DASH,
license_key=license_key,
)
# Unprotected HLS stream
# HLS stream
return ResolvedStream(
uuid=uuid,
url=data['manifestUrls']['hls'],
stream_type=STREAM_HLS,
license_key=license_key,
)
# No manifest url found, get manifest from Server-Side Ad Insertion service
@ -398,11 +399,12 @@ class ContentApi:
url = 'https://pubads.g.doubleclick.net/ondemand/dash/content/%s/vid/%s/streams' % (data.get('ssai').get('contentSourceID'), data.get('ssai').get('videoID'))
ad_data = json.loads(self._post_url(url, data=''))
# Unprotected DASH stream
# Server-Side Ad Insertion DASH stream
return ResolvedStream(
uuid=uuid,
url=ad_data['stream_manifest'],
stream_type=STREAM_DASH,
license_key=license_key,
)
raise UnavailableException
@ -733,6 +735,34 @@ class ContentApi:
)
return episode
@staticmethod
def create_license_key(key_url, key_type='R', key_headers=None, key_value='', response_value=''):
""" Create a license key string that we need for inputstream.adaptive.
:type key_url: str
:type key_type: str
:type key_headers: dict[str, str]
:type key_value: str
:type response_value: str
:rtype str
"""
try: # Python 3
from urllib.parse import quote, urlencode
except ImportError: # Python 2
from urllib import quote, urlencode
header = ''
if key_headers:
header = urlencode(key_headers)
if key_type in ('A', 'R', 'B'):
key_value = key_type + '{SSM}'
elif key_type == 'D':
if 'D{SSM}' not in key_value:
raise ValueError('Missing D{SSM} placeholder')
key_value = quote(key_value)
return '%s|%s|%s|%s' % (key_url, header, key_value, response_value)
def _get_url(self, url, params=None, authentication=None):
""" Makes a GET request for the specified URL.
:type url: str