diff options
Diffstat (limited to 'plugin.video.eurosportplayer/resources/lib')
14 files changed, 928 insertions, 0 deletions
diff --git a/plugin.video.eurosportplayer/resources/lib/__init__.py b/plugin.video.eurosportplayer/resources/lib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/__init__.py diff --git a/plugin.video.eurosportplayer/resources/lib/client.py b/plugin.video.eurosportplayer/resources/lib/client.py new file mode 100644 index 0000000..ff534d5 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/client.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +import simple_requests as requests + +class Client: + + def __init__(self, plugin): + self.plugin = plugin + + self.API_KEY = '2I84ZDjA2raVJ3hyTdADwdwxgDz7r62J8J0W8bE8N8VVILY446gDlrEB33fqLaXD' + + self.IDENTITY_URL = self.plugin.global_base + 'v2/user/identity' + self.USER_URL = self.plugin.global_base + 'v2/user/profile' + self.TOKEN_URL = self.plugin.global_base + 'token' + self.GRAPHQL_URL = self.plugin.search_base + 'svc/search/v2/graphql' + + self.DEVICE_ID = self.plugin.get_setting('device_id') + self.ACCESS_TOKEN = self.plugin.get_setting('access_token') + self.REFRESH_TOKEN = self.plugin.get_setting('refresh_token') + self.LANGUAGE = self.plugin.get_language() + + if not plugin.startup: + self.refresh_token() + + def graphql_request(self, url, query='', variables=None): + if variables is None: + variables = {} + headers = { + 'accept': 'application/json', + 'content-type': 'application/json', + 'authorization': self.ACCESS_TOKEN + } + variables.update( + { + 'language': self.LANGUAGE, + 'mediaRights': ['GeoMediaRight'], + 'preferredLanguages': [self.LANGUAGE, 'en'] + } + ) + post_data = { + 'query': query, + 'operationName': '', + 'variables': variables + } + return requests.post(url, headers=headers, json=post_data).json() + + def channels(self): + return self.graphql_request(self.GRAPHQL_URL + '/persisted/query/eurosport/web/Airings/onAir') + + def categories(self): + return self.graphql_request(self.GRAPHQL_URL + '/persisted/query/eurosport/ListByTitle/sports_filter') + + def category_all(self): + return self.graphql_request(self.GRAPHQL_URL + '/persisted/query/eurosport/CategoryAll') + + def events(self): + return self.graphql_request(self.GRAPHQL_URL + '/persisted/query/eurosport/EventPageByLanguage') + + def event(self, id_): + return self.graphql_request( + url = self.GRAPHQL_URL + '/persisted/query/eurosport/web/EventPageByContentId', + variables = { + 'contentId': id_, + 'include_media': True, + 'include_images': True + } + ) + + def videos(self, id_): + return self.graphql_request( + url = self.GRAPHQL_URL, + query = '{ sport_%s:query (index: "eurosport_global",sort: new,page: 1,page_size: 1000,type: ["Video","Airing"],must: {termsFilters: [{attributeName: "category", values: ["%s"]}]},must_not: {termsFilters: [{attributeName: "mediaConfigState", values: ["OFF"]}]},should: {termsFilters: [{attributeName: "mediaConfigProductType", values: ["VOD"]},{attributeName: "type", values: ["Video"]}]}) @context(uiLang: "%s") { ... on QueryResponse { ...queryResponse }} }fragment queryResponse on QueryResponse {meta { hits }hits {hit { ... on Airing { ... airingData } ... on Video { ... videoData } }}}fragment airingData on Airing {type contentId mediaId liveBroadcast linear partnerProgramId programId runTime startDate endDate expires genres playbackUrls { href rel templated } channel { id parent callsign partnerId } photos { id uri width height } mediaConfig { state productType type } titles { language title descriptionLong descriptionShort episodeName } }fragment videoData on Video {type contentId epgPartnerProgramId programId appears releaseDate expires runTime genres media { playbackUrls { href rel templated } } titles { title titleBrief episodeName summaryLong summaryShort tags { type value displayName } } photos { rawImage width height photos { imageLocation width height } } }' % (id_, id_, self.LANGUAGE) + ) + + def epg(self, prev_date, date): + return self.graphql_request( + url = self.GRAPHQL_URL + '/persisted/query/eurosport/web/Airings/DateRange', + variables = { + 'startDate': prev_date+'T23:59:59.000Z', + 'endDate': date+'T23:59:59.999Z' + } + ) + + def license_key(self): + return '|authorization='+self.ACCESS_TOKEN+'|||plugin://'+self.plugin.addon_id+'/?mode=license_renewal' + + def streams(self, url): + headers = { + 'accept': 'application/vnd.media-service+json; version=1', + 'authorization': self.ACCESS_TOKEN + } + data = requests.get(url.format(scenario='browser'), headers=headers).json() + if data.get('errors', ''): + self.plugin.log('[{0}] {1}'.format(self.plugin.addon_id, self.plugin.utfenc(data['errors'][0][:100]))) + data['license_key'] = self.license_key() + return data + + def authorization(self, grant_type='refresh_token', token=''): + if token == '': + token = self.DEVICE_ID + headers = { + 'accept': 'application/json', + 'content-type': 'application/x-www-form-urlencoded', + 'authorization': 'Bearer ' + self.API_KEY + } + post_data = { + 'grant_type': grant_type, + 'platform': 'browser', + 'token': token + } + return requests.post(self.TOKEN_URL, headers=headers, data=post_data).json() + + def authentication(self, credentials): + headers = { + 'accept': 'application/vnd.identity-service+json; version=1.0', + 'content-type': 'application/json', + 'authorization': self.authorization(grant_type='client_credentials')['access_token'] + } + post_data = { + "type": "email-password", + "email": { + "address": credentials['email'] + }, + "password": { + "value": credentials['password'] + } + } + return requests.post(self.IDENTITY_URL, headers=headers, json=post_data).json() + + def user(self): + headers = { + 'accept': 'application/vnd.identity-service+json; version=1.0', + 'content-type': 'application/json', + 'authorization': self.ACCESS_TOKEN + } + return requests.get(self.USER_URL, headers=headers).json() + + def user_settings(self, data): + self.ACCESS_TOKEN = data.get('access_token', '') + self.REFRESH_TOKEN = data.get('refresh_token', '') + self.plugin.set_setting('access_token', self.ACCESS_TOKEN) + self.plugin.set_setting('refresh_token', self.REFRESH_TOKEN) + + def refresh_token(self): + if self.REFRESH_TOKEN: + self.user_settings(self.authorization(token=self.REFRESH_TOKEN)) + elif self.DEVICE_ID: + self.login() + + def profile(self): + data = self.user() + properties = data['profile']['profileProperty'] + for i in properties: + name = i['name'] + if name == 'country': + self.plugin.set_setting('country', i['value']) + if name == 'language': + self.plugin.set_setting('language', i['value']) + + def login(self): + code = None + credentials = self.plugin.get_credentials() + if credentials: + data = self.authentication(credentials) + if data.get('message'): + msg = self.plugin.utfenc(data['message'][:100]) + else: + msg = 'logged in' + code = data['code'] + self.plugin.log('[{0}] {1}'.format(self.plugin.addon_id, msg)) + if code: + self.user_settings(self.authorization(grant_type='urn:mlbam:params:oauth:grant_type:token', token=code)) + self.profile() + else: + self.plugin.dialog_ok(30004) diff --git a/plugin.video.eurosportplayer/resources/lib/common.py b/plugin.video.eurosportplayer/resources/lib/common.py new file mode 100644 index 0000000..af50b9a --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/common.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- + +import datetime +import hashlib +import time +import urllib +import uuid +import xbmc +import xbmcaddon +import xbmcgui +from inputstreamhelper import Helper +from resources import resources + +class Common: + + def __init__(self, addon_handle=None, addon_url=None): + self.base_url = 'http://www.eurosportplayer.com' + self.global_base = 'https://global-api.svcs.eurosportplayer.com/' + self.search_base = 'https://search-api.svcs.eurosportplayer.com/' + self.time_format = '%Y-%m-%dT%H:%M:%SZ' + self.date_format = '%Y-%m-%d' + + addon = self.get_addon() + self.addon_handle = addon_handle + self.addon_url = addon_url + self.addon_id = addon.getAddonInfo('id') + self.addon_name = addon.getAddonInfo('name') + self.addon_version = addon.getAddonInfo('version') + self.addon_icon = addon.getAddonInfo('icon') + self.addon_fanart = addon.getAddonInfo('fanart') + self.content = addon.getSetting('content') + self.view_id = addon.getSetting('view_id') + self.force_view = addon.getSetting('force_view') == 'true' + self.startup = addon.getSetting('startup') == 'true' + + def utfenc(self, text): + result = text + if isinstance(text, unicode): + result = text.encode('utf-8') + return result + + def get_addon(self): + return xbmcaddon.Addon() + + def get_dialog(self): + return xbmcgui.Dialog() + + def set_setting(self, key, value): + return self.get_addon().setSetting(key, value) + + def get_setting(self, key): + return self.get_addon().getSetting(key) + + def get_string(self, id_): + return self.utfenc(self.get_addon().getLocalizedString(id_)) + + def dialog_ok(self, id_): + self.get_dialog().ok(self.addon_name, self.get_string(id_)) + + def get_resource(self, string): + result = self.utfenc(string) + id_ = resources(string) + if id_ != 0: + result = self.get_string(id_) + return result + + def get_credentials(self): + email = self.get_dialog().input(self.addon_name + self.get_string(30002), type=xbmcgui.INPUT_ALPHANUM) + if '@' in email: + password = self.get_dialog().input(self.addon_name + self.get_string(30003), type=xbmcgui.INPUT_ALPHANUM, option=xbmcgui.ALPHANUM_HIDE_INPUT) + if len(password) > 4: + return { + 'email': email, + 'password': password + } + return None + + def log(self, msg): + xbmc.log(str(msg), xbmc.LOGDEBUG) + + def build_url(self, query): + return self.addon_url + '?' + urllib.urlencode(query) + + def get_language(self): + language = xbmc.getLanguage().split(' (')[0] + return xbmc.convertLanguage(language, xbmc.ISO_639_1) + + def time_now(self): + return datetime.datetime.now().strftime(self.time_format) + + def time_stamp(self, str_date): + return datetime.datetime.fromtimestamp(time.mktime(time.strptime(str_date, self.time_format))) + + def timedelta_total_seconds(self, timedelta): + return ( + timedelta.microseconds + 0.0 + + (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6 + + def utc2local(self, date_string): + if str(date_string).startswith('2'): + utc = datetime.datetime(*(time.strptime(date_string, self.time_format)[0:6])) + epoch = time.mktime(utc.timetuple()) + offset = datetime.datetime.fromtimestamp(epoch) - datetime.datetime.utcfromtimestamp(epoch) + return (utc + offset).strftime(self.time_format) + + def uniq_id(self): + device_id = '' + mac_addr = xbmc.getInfoLabel('Network.MacAddress') + if not ":" in mac_addr: + mac_addr = xbmc.getInfoLabel('Network.MacAddress') + # hack response busy + i = 0 + while not ":" in mac_addr and i < 3: + i += 1 + time.sleep(1) + mac_addr = xbmc.getInfoLabel('Network.MacAddress') + if ":" in mac_addr: + device_id = str(uuid.UUID(hashlib.md5(str(mac_addr.decode("utf-8"))).hexdigest())) + else: + self.log("[{0}] error: failed to get device id ({1})".format(self.addon_id, str(mac_addr))) + self.dialog_ok(30051) + self.set_setting('device_id', device_id) + return device_id + + def open_is_settings(self): + xbmcaddon.Addon(id='inputstream.adaptive').openSettings() + + def start_is_helper(self): + helper = Helper(protocol='hls') + return helper.check_inputstream() + + def get_duration(self, end, now): + return self.timedelta_total_seconds(self.time_stamp(end)-self.time_stamp(now)) + + def plot_time(self, date_string, event): + if event: + return datetime.datetime(*(time.strptime(date_string, self.time_format)[0:6])).strftime('%a, %d %b, %H:%M') + else: + return datetime.datetime(*(time.strptime(date_string, self.time_format)[0:6])).strftime('%H:%M') + + def add_zero(self, s): + s = s.strip() + if not len(s) == 2: + s = '0'+s + return s + + def remove_zero(self, s): + if s.startswith('0'): + s = s[1:] + return s + + def runtime_to_seconds(self, runtime): + spl = runtime.split(':') + seconds = 0 + seconds += int(self.remove_zero(spl[0]))*60*60 + seconds += int(self.remove_zero(spl[1]))*60 + seconds += int(self.remove_zero(spl[2])) + return seconds + + def epg_date(self, date=False): + if not date: + date = datetime.datetime.now().strftime(self.date_format) + return datetime.datetime.fromtimestamp(time.mktime(time.strptime(date, self.date_format))) + + def get_prev_day(self, date): + return (date - datetime.timedelta(days=1)) + + def get_next_day(self, date): + return (date + datetime.timedelta(days=1)) + + def get_date(self): + date = self.epg_date().strftime(self.date_format) + dlg = self.get_dialog().numeric(1, self.get_string(30230)) + if dlg: + spl = dlg.split('/') + date = '%s-%s-%s' % (spl[2], self.add_zero(spl[1]), self.add_zero(spl[0])) + prev_date = self.get_prev_day(self.epg_date(date)) + return prev_date.strftime(self.date_format), date diff --git a/plugin.video.eurosportplayer/resources/lib/context.py b/plugin.video.eurosportplayer/resources/lib/context.py new file mode 100755 index 0000000..644d0bb --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/context.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +class Context: + + def __init__(self, plugin): + self.cm = [] + self.plugin = plugin + + def epg_date(self): + d = { + 'mode': 'epg', + 'id': 'date' + } + self.cm.append((self.plugin.get_string(30230), 'ActivateWindow(Videos, {0})'.format(self.plugin.build_url(d)))) + return self.cm diff --git a/plugin.video.eurosportplayer/resources/lib/events.py b/plugin.video.eurosportplayer/resources/lib/events.py new file mode 100644 index 0000000..1d17575 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/events.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +class Events: + + def __init__(self, plugin, i): + self.item = {} + self.plugin = plugin + self.item['mode'] = 'event' + self.item['title'] = self.plugin.utfenc(i['title']) + self.item['id'] = i['contentId'] + self.item['thumb'] = i['heroImage'][0]['rawImage'] + self.item['fanart'] = i['heroImage'][0]['rawImage'] + self.item['plot'] = '{0} - {1}'.format(i['startDate'][:10], i['endDate'][:10]) +
\ No newline at end of file diff --git a/plugin.video.eurosportplayer/resources/lib/hits.py b/plugin.video.eurosportplayer/resources/lib/hits.py new file mode 100644 index 0000000..2eabc87 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/hits.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- + +class Hits: + + def __init__(self, plugin, i, epg=False, event=False): + self.item = {} + self.plugin = plugin + self.epg = epg + self.event = event + self.type = i['type'] + self.now = self.plugin.time_now() + self.titles = i['titles'] + self.photos = i['photos'] + self.appears = i.get('appears', '') + self.start = self.plugin.utc2local(i.get('startDate', '')) + self.end = self.plugin.utc2local(i.get('endDate', '')) + self.duration = self.plugin.runtime_to_seconds(i['runTime']) + self.linear = False + self.language = self.plugin.get_language() + if self.type == 'Airing': + self.airing(i) + elif self.type == 'Video': + self.video(i) + + def airing(self, i): + self.channel = i['channel'] + self.playback = i['playbackUrls'] + self.config = i['mediaConfig'] + self.livebroadcast = i['liveBroadcast'] + self.linear = i['linear'] + self.airing_item() + + def airing_info(self): + for i in self.titles: + self.title = i['title'] + self.plot = i['descriptionLong'] + if i['language'] == self.language: + break + if not self.title: + self.title = self.plot + + def airing_images(self): + for i in self.photos: + if i['width'] == 770 and i['height'] == 432: + self.item['thumb'] = i['uri'] + if i['width'] == 1600: + self.item['fanart'] = i['uri'] + + def airing_item(self): + self.airing_info() + name = self.channel['callsign'] + producttype = self.config['productType'] + start = self.plugin.plot_time(self.start, self.event) + end = self.plugin.plot_time(self.end, self.event) + if producttype == 'LIVE' and self.livebroadcast and not self.epg and not self.event: + self.title = '{0} [COLOR red]LIVE[/COLOR] [I]{1}[/I]'.format(self.plugin.utfenc(name), self.plugin.utfenc(self.title)) + elif self.epg or self.event: + if not self.playback: + self.title = '{0} [COLOR dimgray]{1} {2}[/COLOR]'.format(start, self.plugin.utfenc(name), self.plugin.utfenc(self.title)) + else: + self.title = '{0} [COLOR dimgray]{1}[/COLOR] {2}'.format(start, self.plugin.utfenc(name), self.plugin.utfenc(self.title)) + else: + self.title = '{0} [I]{1}[/I]'.format(self.plugin.utfenc(name), self.plugin.utfenc(self.title)) + if producttype == 'LIVE': + self.plot = '{0} - {1}\n{2}'.format(start, end, self.plugin.utfenc(self.plot)) + if not self.epg: + self.duration = self.plugin.get_duration(self.end, self.now) + else: + self.plot = self.plugin.utfenc(self.plot) + self.airing_images() + self.create_item() + + def video(self, i): + media = i['media'] + self.playback = media[0]['playbackUrls'] + if self.appears and not self.start: + self.start = self.plugin.utc2local(self.appears[:19] + 'Z') + self.video_item() + + def video_info(self): + for i in self.titles: + self.title = i['title'] + self.plot = i['summaryLong'] + tags = i.get('tags', []) + for t in tags: + if t['type'] == 'language': + if t['value'] == self.language: + break + if not self.title: + self.title = self.plot + + def video_images(self): + photos = self.photos[0]['photos'] + for i in photos: + if i['width'] == 770 and i['height'] == 432: + self.item['thumb'] = i['imageLocation'] + if i['width'] == 1600: + self.item['fanart'] = i['imageLocation'] + + def video_item(self): + self.video_info() + self.title = self.plugin.utfenc(self.title) + self.plot = self.plugin.utfenc(self.plot) + self.create_item() + if self.photos: + self.video_images() + + def playback_id(self): + id_ = '' + for i in self.playback: + id_ = i['href'] + if self.linear and not self.epg and i['rel'] == 'linear': + break + elif self.epg and i['rel'] == 'video': + break + return id_ + + def create_item(self): + self.item['mode'] = 'play' + self.item['title'] = self.title + self.item['id'] = self.playback_id() + self.item['plot'] = self.plot + self.item['duration'] = self.duration + if self.start: + self.item['date'] = self.start[:10] diff --git a/plugin.video.eurosportplayer/resources/lib/items.py b/plugin.video.eurosportplayer/resources/lib/items.py new file mode 100644 index 0000000..78cf396 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/items.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- + +import xbmc +import xbmcgui +import xbmcplugin + +class Items: + + def __init__(self, plugin): + self.cache = True + self.video = False + self.plugin = plugin + + def list_items(self, sort=False, upd=False): + if self.video: + xbmcplugin.setContent(self.plugin.addon_handle, self.plugin.content) + if sort: + xbmcplugin.addSortMethod(self.plugin.addon_handle, 1) + xbmcplugin.endOfDirectory(self.plugin.addon_handle, cacheToDisc=self.cache, updateListing=upd) + + if self.plugin.force_view: + xbmc.executebuiltin('Container.SetViewMode({0})'.format(self.plugin.view_id)) + + def add_item(self, item): + data = { + 'mode': item['mode'], + 'title': item['title'], + 'id': item.get('id', ''), + 'params': item.get('params', '') + } + + art = { + 'thumb': item.get('thumb', self.plugin.addon_fanart), + 'poster': item.get('thumb', self.plugin.addon_fanart), + 'fanart': item.get('fanart', self.plugin.addon_fanart) + } + + labels = { + 'title': item['title'], + 'plot': item.get('plot', item['title']), + 'premiered': item.get('date', ''), + 'episode': item.get('episode', 0) + } + + listitem = xbmcgui.ListItem(item['title']) + listitem.setArt(art) + listitem.setInfo(type='Video', infoLabels=labels) + + if 'play' in item['mode']: + self.cache = False + self.video = True + folder = False + listitem.addStreamInfo('video', {'duration':item.get('duration', 0)}) + listitem.setProperty('IsPlayable', 'true') + else: + folder = True + + if item.get('cm', None): + listitem.addContextMenuItems( item['cm'] ) + + xbmcplugin.addDirectoryItem(self.plugin.addon_handle, self.plugin.build_url(data), listitem, folder) + + def play_item(self, path, license_key): + listitem = xbmcgui.ListItem() + listitem.setContentLookup(False) + listitem.setMimeType('application/x-mpegURL') + listitem.setProperty('inputstreamaddon', 'inputstream.adaptive') + listitem.setProperty('inputstream.adaptive.manifest_type', 'hls') + listitem.setProperty('inputstream.adaptive.license_key', license_key) + listitem.setPath(path) + xbmcplugin.setResolvedUrl(self.plugin.addon_handle, True, listitem) + + def add_token(self, license_key): + listitem = xbmcgui.ListItem() + xbmcplugin.addDirectoryItem(self.plugin.addon_handle, license_key, listitem) + xbmcplugin.endOfDirectory(self.plugin.addon_handle, cacheToDisc=False)
\ No newline at end of file diff --git a/plugin.video.eurosportplayer/resources/lib/parser.py b/plugin.video.eurosportplayer/resources/lib/parser.py new file mode 100644 index 0000000..f56a128 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/parser.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- + +from items import Items +from hits import Hits +from sports import Sports +from events import Events +from context import Context + +class Parser: + + def __init__(self, plugin): + self.plugin = plugin + self.items = Items(self.plugin) + + def channel(self, data): + hits = data['data']['Airings'] + for i in hits: + item = Hits(self.plugin, i).item + if item.get('id'): + self.items.add_item(item) + date = self.plugin.epg_date() + prev_date = self.plugin.get_prev_day(date) + self.items.add_item( + { + 'mode': 'epg', + 'title': self.plugin.get_string(30103), + 'plot': self.plugin.get_string(30103), + 'id': date.strftime(self.plugin.date_format), + 'params': prev_date.strftime(self.plugin.date_format) + } + ) + self.items.add_item( + { + 'mode': 'sports', + 'title': self.plugin.get_string(30101), + 'plot': self.plugin.get_string(30102) + } + ) + self.items.add_item( + { + 'mode': 'events', + 'title': self.plugin.get_string(30104), + 'plot': self.plugin.get_string(30104) + } + ) + self.items.list_items(sort=True) + + def sport(self, data): + self.items.add_item( + { + 'mode': 'all_sports', + 'title': self.plugin.get_string(30105).upper(), + 'plot': self.plugin.get_string(30105) + } + ) + hits = data['data']['sports_filter']['list'] + for i in hits: + self.items.add_item(Sports(self.plugin, i).item) + self.items.list_items(sort=True) + + def all_sports(self, data): + hits = data['data']['CategoryAll'] + for i in hits: + item = Sports(self.plugin, i).item + if item.get('thumb') and item.get('id'): + self.items.add_item(item) + self.items.list_items(sort=True) + + def events(self, data): + hits = data['data']['EventPageByLanguage'] + for i in hits: + self.items.add_item(Events(self.plugin, i).item) + self.items.list_items() + + def event(self, data): + media = data['data']['EventPageByContentId']['media'] + for m in media: + hits = m['videos'] + for i in hits: + self.items.add_item(Hits(self.plugin, i, event=True).item) + self.items.list_items() + + def video(self, data, id_): + sport_id = 'sport_{0}'.format(id_) + hits = data['data'][sport_id]['hits'] + for i in hits: + hit = i['hit'] + item = Hits(self.plugin, hit).item + if item.get('id'): + self.items.add_item(item) + self.items.list_items() + + def epg(self, data, prev_date, date): + + def date_item(params, id_): + return { + 'mode': 'epg', + 'title': '{0} {1}'.format(self.plugin.get_resource(id_.strftime('%A')), id_.strftime(self.plugin.date_format)), + 'plot': '{0} {1}'.format(self.plugin.get_resource(self.plugin.epg_date(date).strftime('%A')), self.plugin.epg_date(date).strftime(self.plugin.date_format)), + 'id': id_.strftime(self.plugin.date_format), + 'params': params.strftime(self.plugin.date_format), + 'cm': cm + } + + update = False if date == self.plugin.epg_date().strftime(self.plugin.date_format) else True + cm = Context(self.plugin).epg_date() + + self.items.add_item(date_item(self.plugin.get_prev_day(self.plugin.epg_date(prev_date)), self.plugin.epg_date(prev_date))) + hits = data['data']['Airings'] + hits = sorted(hits, key=lambda k: k.get('startDate')) + for i in hits: + self.items.add_item(Hits(self.plugin, i, epg=True).item) + self.items.add_item(date_item(self.plugin.epg_date(date), self.plugin.get_next_day(self.plugin.epg_date(date)))) + self.items.list_items(upd=update) + + def play(self, data): + if data.get('stream'): + for i in data['stream']: + path = data['stream'][i].replace('desktop','wired50') + break + key = data['license_key'] + self.items.play_item(path, key) + + def license_renewal(self, license_key): + self.items.add_token(license_key) diff --git a/plugin.video.eurosportplayer/resources/lib/resources.py b/plugin.video.eurosportplayer/resources/lib/resources.py new file mode 100755 index 0000000..3204053 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/resources.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +def resources(string): + if string == 'Today': + return 30221 + elif string == 'Tomorrow': + return 30222 + elif string == 'Monday': + return 30223 + elif string == 'Tuesday': + return 30224 + elif string == 'Wednesday': + return 30225 + elif string == 'Thursday': + return 30226 + elif string == 'Friday': + return 30227 + elif string == 'Saturday': + return 30228 + elif string == 'Sunday': + return 30229 + else: + return string diff --git a/plugin.video.eurosportplayer/resources/lib/simple_requests/__init__.py b/plugin.video.eurosportplayer/resources/lib/simple_requests/__init__.py new file mode 100644 index 0000000..fa1fd74 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/simple_requests/__init__.py @@ -0,0 +1,6 @@ +__author__ = 'bromix' + +__ALL__ = ['get', 'post', 'put', 'delete', 'head', 'codes'] + +from .constants import codes +from api import get, post, put, delete, head diff --git a/plugin.video.eurosportplayer/resources/lib/simple_requests/api.py b/plugin.video.eurosportplayer/resources/lib/simple_requests/api.py new file mode 100644 index 0000000..42b01b8 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/simple_requests/api.py @@ -0,0 +1,170 @@ +__author__ = 'bromix' + +import urllib +import urllib2 +from StringIO import StringIO +import gzip + +import json as real_json + +class ErrorHandler(urllib2.HTTPDefaultErrorHandler): + def http_error_default(self, req, fp, code, msg, hdrs): + infourl = urllib.addinfourl(fp, hdrs, req.get_full_url()) + infourl.status = code + infourl.code = code + return infourl + + +class NoRedirectHandler(urllib2.HTTPRedirectHandler): + def http_error_302(self, req, fp, code, msg, headers): + infourl = urllib.addinfourl(fp, headers, req.get_full_url()) + infourl.status = code + infourl.code = code + return infourl + + http_error_300 = http_error_302 + http_error_301 = http_error_302 + http_error_303 = http_error_302 + http_error_307 = http_error_302 + + +class Response(): + def __init__(self): + self.headers = {} + self.code = -1 + self.text = u'' + self.status_code = -1 + + def read(self): + return self.text + + def json(self): + return real_json.loads(self.text) + + +def _request(method, url, + params=None, + data=None, + headers=None, + cookies=None, + files=None, + auth=None, + timeout=None, + allow_redirects=False, + proxies=None, + hooks=None, + stream=None, + verify=None, + cert=None, + json=None): + if not headers: + headers = {} + + url = urllib.quote(url, safe="%/:=&?~#+!$,;'@()*[]") + handlers = [] + + import sys + # starting with python 2.7.9 urllib verifies every https request + if False == verify and sys.version_info >= (2, 7, 9): + import ssl + + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + handlers.append(urllib2.HTTPSHandler(context=ssl_context)) + + # handlers.append(urllib2.HTTPCookieProcessor()) + # handlers.append(ErrorHandler) + if not allow_redirects: + handlers.append(NoRedirectHandler) + opener = urllib2.build_opener(*handlers) + + query = '' + if params: + for key in params: + value = params[key] + if isinstance(value, str): + value = value.decode('utf-8') + params[key] = value.encode('utf-8') + query = urllib.urlencode(params) + if query: + url += '?%s' % query + request = urllib2.Request(url) + if headers: + for key in headers: + request.add_header(key, str(unicode(headers[key]).encode('utf-8'))) + if data or json: + if headers.get('Content-Type', '').startswith('application/x-www-form-urlencoded') or data: + # transform a string into a map of values + if isinstance(data, basestring): + _data = data.split('&') + data = {} + for item in _data: + name, value = item.split('=') + data[name] = value + + # encode each value + for key in data: + data[key] = data[key] + if isinstance(data[key], unicode): + data[key] = data[key].encode('utf-8') + + # urlencode + request.data = urllib.urlencode(data) + elif headers.get('Content-Type', '').startswith('application/json') and data: + request.data = real_json.dumps(data).encode('utf-8') + elif json: + request.data = real_json.dumps(json).encode('utf-8') + else: + if not isinstance(data, basestring): + data = str(data) + + if isinstance(data, str): + data = data.encode('utf-8') + request.data = data + elif method.upper() in ['POST', 'PUT']: + request.data = "null" + request.get_method = lambda: method + result = Response() + response = None + try: + response = opener.open(request, timeout=timeout) + except urllib2.HTTPError as e: + # HTTPError implements addinfourl, so we can use the exception to construct a response + if isinstance(e, urllib2.addinfourl): + response = e + + # process response + result.headers.update(response.headers) + result.status_code = response.getcode() + if response.headers.get('Content-Encoding', '').startswith('gzip'): + buf = StringIO(response.read()) + f = gzip.GzipFile(fileobj=buf) + result.text = f.read() + elif stream: + return result + else: + result.text = response.read() + return result + + +def get(url, **kwargs): + kwargs.setdefault('allow_redirects', True) + return _request('GET', url, **kwargs) + + +def post(url, data=None, json=None, **kwargs): + kwargs.setdefault('allow_redirects', True) + return _request('POST', url, data=data, json=json, **kwargs) + + +def put(url, data=None, json=None, **kwargs): + return _request('PUT', url, data=data, json=json, **kwargs) + + +def delete(url, **kwargs): + return _request('DELETE', url, **kwargs) + + +def head(url, **kwargs): + return _request('HEAD', url, **kwargs)
\ No newline at end of file diff --git a/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/__init__.py b/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/__init__.py new file mode 100644 index 0000000..50f773a --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/__init__.py @@ -0,0 +1 @@ +__author__ = 'bromix' diff --git a/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/codes.py b/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/codes.py new file mode 100644 index 0000000..5536a63 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/simple_requests/constants/codes.py @@ -0,0 +1,5 @@ +__author__ = 'bromix' + +ok = 200 + +unauthorized = 401
\ No newline at end of file diff --git a/plugin.video.eurosportplayer/resources/lib/sports.py b/plugin.video.eurosportplayer/resources/lib/sports.py new file mode 100644 index 0000000..72fc221 --- /dev/null +++ b/plugin.video.eurosportplayer/resources/lib/sports.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +class Sports: + + def __init__(self, plugin, i): + self.item = {} + self.plugin = plugin + self.item['mode'] = 'videos' + self.item['title'] = self.plugin.utfenc(i['tags'][0]['displayName']) + sport = i['sport'] + logo = i['logoImage'] + if logo and sport: + if sport.isdigit(): + self.item['id'] = sport + self.item['thumb'] = logo[0]['rawImage'] |