diff --git a/addon.xml b/addon.xml index ac39b45..59cb3e5 100644 --- a/addon.xml +++ b/addon.xml @@ -1,13 +1,14 @@ + diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index dadde39..da515a8 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -268,3 +268,7 @@ msgstr "" msgctxt "#30203" msgid "Format not supported" msgstr "" + +msgctxt "#30204" +msgid "Video not available" +msgstr "" diff --git a/resources/language/resource.language.es_es/strings.po b/resources/language/resource.language.es_es/strings.po index 6146d44..daf5534 100644 --- a/resources/language/resource.language.es_es/strings.po +++ b/resources/language/resource.language.es_es/strings.po @@ -268,3 +268,7 @@ msgstr "Inputstream.adaptive no está disponible" msgctxt "#30203" msgid "Format not supported" msgstr "Formato no soportado" + +msgctxt "#30204" +msgid "Video not available" +msgstr "Vídeo no disponible" diff --git a/resources/lib/movistar.py b/resources/lib/movistar.py index cd15b60..9cd6f88 100644 --- a/resources/lib/movistar.py +++ b/resources/lib/movistar.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals, absolute_import, division import sys -import base64 import json import requests import io @@ -31,6 +30,8 @@ class Movistar(object): 'ssp_token': '', 'demarcation': 0} + add_extra_info = True + def __init__(self, config_directory, reuse_devices=False): self.logged = False @@ -69,9 +70,10 @@ class Movistar(object): if not data or 'ofertas' not in data: return self.cache.save_file('account.json', json.dumps(data, ensure_ascii=False)) self.account['id'] = data['ofertas'][0]['accountNumber'] - self.account['pid'] = data['ofertas'][0]['cod_persona'] + #self.account['pid'] = data['ofertas'][0]['cod_persona'] self.account['encoded_user'] = data['cod_usuario_cifrado'] self.account['platform'] = data['ofertas'][0]['@id_perfil'] + #self.account['platform'] = 'OTT' # Profile ID content = self.cache.load_file('profile_id.conf') @@ -145,6 +147,7 @@ class Movistar(object): self.account['session_token'] = data['token'] self.account['ssp_token'] = data['sspToken'] self.account['demarcation'] = data['demarcation'] + self.account['pid'] = data['pid'] self.entitlements['activePurchases'] = data['activePurchases'] self.entitlements['partners'] = data['partners'] @@ -155,6 +158,10 @@ class Movistar(object): #print_json(self.entitlements) self.logged = True + # Search + data = self.cache.load_file('searchs.json') + self.search_list = json.loads(data) if data else [] + def get_token(self): data = {"accountNumber": self.account['id'], "userProfile": self.account['profile_id'], @@ -197,7 +204,7 @@ class Movistar(object): headers = self.net.headers.copy() headers['Content-Type'] = 'application/json' headers['X-Hzid'] = session_token - url = self.endpoints['setUpStream'].format(PID=self.account['id'], deviceCode='WP_OTT', PLAYREADYID=self.account['device_id']) + url = self.endpoints['setUpStream'].format(PID=self.account['pid'], deviceCode='WP_OTT', PLAYREADYID=self.account['device_id']) if session_id != None: url += '/' + session_id #LOG('open_session: url: {}'.format(url)) @@ -407,8 +414,9 @@ class Movistar(object): data = json.loads(content) else: today = datetime.today() - str_now = today.strftime('%Y-%m-%dT%H:00:00') + str_now = today.strftime('%Y-%m-%dT00:00:00') url = self.endpoints['rejilla'].format(deviceType='webplayer', profile=self.account['platform'], UTCDATETIME=str_now, DURATION=2, CHANNELS='', NETWORK='movistarplus', mdrm='true', demarcation=self.account['demarcation']) + #print(url) data = self.net.load_data(url) self.cache.save_file('epg2.json', json.dumps(data, ensure_ascii=False)) @@ -422,10 +430,13 @@ class Movistar(object): pr['end'] = int(p['FechaHoraFin']) pr['start_str'] = timestamp2str(pr['start']) pr['end_str'] = timestamp2str(pr['end']) + pr['date_str'] = timestamp2str(pr['start'], '%a %d %H:%M') pr['desc1'] = p['Titulo'] pr['desc2'] = '' if 'TituloHorLinea2' in p: pr['desc2'] = p['TituloHorLinea2'] + pr['show_id'] = p['ShowId'] + if 'links' in p: pr['links'] = p['links'] epg[id].append(pr) return epg @@ -451,13 +462,23 @@ class Movistar(object): if stype == 'u7d': s += ' (U7D)' elif stype == 'rec': s += ' (REC)' - if title['subscribed'] == True: - color1 = 'yellow' - color2 = 'red' - else: + color1 = 'yellow' + color2 = 'red' + + available = True + if 'subscribed' in title and title['subscribed'] == False: available = False + if 'url' in title and title['url'] == '': available = False + + if not available: color1 = 'gray' color2 = 'gray' s = '[COLOR gray]' + s +'[/COLOR]' + elif 'start' in title: + aired = (title['start'] <= (time.time() * 1000)) + if not aired: + color1 = 'blue' + color2 = 'blue' + s = '[COLOR blue]' + s +'[/COLOR]' if title.get('desc1', '') != '': s += ' - [COLOR {}]{}[/COLOR]'.format(color1, title['desc1']) if title.get('desc2', '') != '': @@ -467,14 +488,21 @@ class Movistar(object): def add_epg_info(self, channels, epg, timestamp): for ch in channels: programs = self.find_program_epg(epg, ch['id'], timestamp) - ch['info']['plot'] = '' + plot = '' for i in range(len(programs)): desc1 = programs[i]['desc1'] desc2 = programs[i]['desc2'] if i == 0: ch['desc1'] = desc1 ch['desc2'] = desc2 - ch['info']['plot'] += "[B]{}[/B] {} {}\n".format(programs[i]['start_str'], desc1, desc2) + plot += "[B]{}[/B] {} {}\n".format(programs[i]['start_str'], desc1, desc2) + if self.add_extra_info: + ch['art'] = {'poster': None, 'fanart': None} + self.add_video_extra_info(programs[i]['show_id'], ch, catalog='events') + if 'plot' in ch['info']: + plot = plot + ch['info']['plot'] + break + ch['info']['plot'] = plot def is_subscribed_channel(self, products): for e in self.entitlements['activePackages']: @@ -519,9 +547,7 @@ class Movistar(object): t['desc2'] = '' t['dial'] = c['Dial'] t['url'] = c['PuntoReproduccion'] - t['art']['icon'] = c['Logo'] - t['art']['thumb'] = c['Logo'] - t['art']['poster'] = c['Logo'] + t['art']['icon'] = t['art']['thumb'] = t['art']['poster'] = c['Logo'] t['session_request'] = '{"contentID":"'+ t['id'] +'", "streamType":"CHN"}' t['subscribed'] = self.is_subscribed_channel(c['Productos']) t['info']['playcount'] = 1 # Set as watched @@ -571,9 +597,28 @@ class Movistar(object): url = self.endpoints['grabaciones'].format( deviceType='webplayer', DIGITALPLUSUSERIDC=self.account['encoded_user'], PROFILE=self.account['platform'], idsOnly='false', start=1, end=30, mdrm='true', demarcation=self.account['demarcation']) - url += '&state=Completed&_='+ str(int(time.time()*1000)) + #url += '&state=Completed&_='+ str(int(time.time()*1000)) + url += '&_='+ str(int(time.time()*1000)) return url + def get_search_url(self, search_term): + url = self.endpoints['buscar_best'].format( + ACCOUNTNUMBER=self.account['id'], + profile=self.account['platform'], + texto=search_term, + linearSubscription=','.join(self.entitlements['linearSubscription']), + vodSubscription=','.join(self.entitlements['vodSubscription']), + mdrm='true', demarcation=self.account['demarcation']) + return url + + def add_search(self, search_term): + self.search_list.append(search_term) + self.cache.save_file('searchs.json', json.dumps(self.search_list, ensure_ascii=False)) + + def delete_search(self, search_term): + self.search_list = [s for s in self.search_list if s != search_term] + self.cache.save_file('searchs.json', json.dumps(self.search_list, ensure_ascii=False)) + def get_title(self, data): t = {} t['info'] = {} @@ -584,6 +629,7 @@ class Movistar(object): t['art']['poster'] = ed['Imagen'].replace('ywcatalogov', 'dispficha') t['art']['thumb'] = t['art']['poster'] t['info']['genre'] = ed['GeneroComAntena'] + if ed.get('TipoComercial') == 'Impulsivo': return None # Alquiler if ed['TipoContenido'] in ['Individual', 'Episodio']: t['type'] = 'movie' t['stream_type'] = 'vod' @@ -604,6 +650,16 @@ class Movistar(object): elif video['AssetType'] == 'NPVR': t['stream_type'] = 'rec' t['session_request'] = '{"contentID":' + str(t['id']) + ', "streamType":"NPVR"}' + if self.add_extra_info: + self.add_video_extra_info(t['id'], t) + if 'Recording' in data: + t['stream_type'] = 'rec' + t['rec'] = {'id': data['Recording']['id'], + 'name': data['Recording']['name'], + 'start': data['Recording']['beginTime'], + 'end': data['Recording']['endTime']} + if t['url'] == '': t['info']['title'] += ' (' + isodate2str(t['rec']['start']) + ')' + if t['url'] == '' and t['stream_type'] == 'vod': t['subscribed'] = False if ed['TipoContenido'] == 'Serie': t['type'] = 'series' t['info']['mediatype'] = 'tvshow' @@ -624,6 +680,39 @@ class Movistar(object): res.append(t) return res + def add_video_extra_info(self, id, t, catalog=''): + try: + url = self.endpoints['ficha'].format(deviceType='webplayer', id=id, profile=self.account['platform'], mediatype='FOTOV', version='7.1', mode='GLOBAL', catalog=catalog, channels='', state='', mdrm='true', demarcation=self.account['demarcation'], legacyBoxOffice='') + #print(url) + data = self.net.load_data(url) + if data.get('Sinopsis'): + t['info']['plot'] = data['Sinopsis'] + if data.get('Actores'): + t['info']['cast'] = data['Actores'].split(', ') + if data.get('Directores'): + t['info']['director'] = data['Directores'].split(', ') + if data.get('Anno'): + t['info']['year'] = data['Anno'] + if data.get('Nacionalidad'): + t['info']['country'] = data['Nacionalidad'] + im_thumb = im_default = im_season = im_fanart = None + for im in data['Imagenes']: + if im['id'] == 'horizontal': im_thumb = im['uri'] + elif im['id'] == 'default': im_default = im['uri'] + elif im['id'] == 'watch2tgr-end': im_fanart = im['uri'] + elif im['id'] == 'temporada': im_season = im['uri'] + if im_thumb and not t['art'].get('thumb'): t['art']['thumb'] = im_thumb + if im_season: + if not t['art'].get('poster'): t['art']['poster'] = im_season + if im_fanart: + if not t['art'].get('fanart'): t['art']['fanart'] = im_fanart + if im_default: + if not t['art'].get('poster'): t['art']['poster'] = im_default + if not t['art'].get('icon'): t['art']['icon'] = im_default + if not t['art'].get('fanart'): t['art']['fanart'] = im_default + except: + pass + def get_seasons(self, id): url = self.endpoints['ficha'].format(deviceType='webplayer', id=id, profile=self.account['platform'], mediatype='FOTOV', version='7.1', mode='GLOBAL', catalog='', channels='', state='', mdrm='true', demarcation=self.account['demarcation'], legacyBoxOffice='') data = self.net.load_data(url) @@ -653,6 +742,7 @@ class Movistar(object): #print(url) data = self.net.load_data(url) #print_json(data) + #self.cache.save_file('episodes.json', json.dumps(data, ensure_ascii=False)) res = [] for d in data['Episodios']: ed = d['DatosEditoriales'] @@ -666,7 +756,8 @@ class Movistar(object): t['info']['title'] = ed['TituloEpisodio'] t['info']['episode'] = ed['NumeroEpisodio'] t['info']['duration'] = ed['DuracionEnSegundos'] - t['art']['thumb'] = ed['Imagen'] + t['info']['tvshowtitle'] = data.get('TituloSerie', '') + t['art']['poster'] = data['Imagen'] for im in ed['Imagenes']: if im['id'] == 'horizontal': t['art']['thumb'] = im['uri'] m = re.search(r'T(\d+)', ed['Temporada']) @@ -682,7 +773,8 @@ class Movistar(object): elif video['AssetType'] == 'U7D': t['stream_type'] = 'u7d' t['session_request'] = '{"contentID":' + str(t['id']) + ', "streamType":"CUTV"}' - + if self.add_extra_info: + self.add_video_extra_info(t['id'], t) res.append(t) return res @@ -694,6 +786,65 @@ class Movistar(object): data = self.net.load_data(url, headers) return data + def order_recording(self, program_id): + headers = self.net.headers.copy() + headers['Content-Type'] = 'application/json' + headers['X-Hzid'] = self.account['session_token'] + url = self.endpoints['grabarprograma'] + data = '{"tvProgramID":"' + str(program_id) +'"}' + response = self.net.session.post(url, data=data, headers=headers) + content = response.content.decode('utf-8') + try: + data = json.loads(content) + return data + except: + return None + + def delete_recording(self, program_id): + headers = self.net.headers.copy() + headers['Content-Type'] = 'application/json' + headers['X-Hzid'] = self.account['session_token'] + url = self.endpoints['borrargrabacionindividual'].format(showId=program_id) + response = self.net.session.delete(url, headers=headers) + content = response.content.decode('utf-8') + try: + data = json.loads(content) + return data + except: + return None + + def epg_to_movies(self, channel_id): + epg = self.get_epg() + res = [] + for p in epg[channel_id]: + if sys.version_info[0] < 3: + p['date_str'] = unicode(p['date_str'], 'utf-8') + name = '[B]' + p['date_str'] + '[/B] ' + p['desc1'] + if p['desc2']: name += ' - '+ p['desc2'] + plot = name +"\n" + p['desc2'] + t = {'info': {}, 'art': {}} + t['info']['title'] = name + t['info']['plot'] = plot + t['type'] = 'movie' + t['stream_type'] = 'u7d' + t['info']['mediatype'] = 'movie' + t['url'] = '' + t['id'] = p['show_id'] + t['session_request'] = '{"contentID":' + str(t['id']) +',"streamType":"CUTV"}' + t['info']['playcount'] = 1 # Set as watched + t['start'] = p['start'] + t['end'] = p['end'] + t['aired'] = (p['end'] <= (time.time() * 1000)) + t['subscribed'] = True # Fix me + if 'links' in p: + for link in p['links']: + if link['rel'] == 'start-over': + t['url'] = link['href'] + if self.add_extra_info: + self.add_video_extra_info(t['id'], t, catalog='events') + res.append(t) + return res + def get_subtitles(self, manifest_url): base_url = os.path.dirname(manifest_url) content = self.net.load_url(manifest_url) @@ -730,6 +881,7 @@ class Movistar(object): sort = 'MA' url = self.endpoints['consultar'].format(deviceType='webplayer', profile=self.account['platform'], sort=sort, start=1, end=50, mdrm='true', demarcation=self.account['demarcation']) filter = '&filter=AC-OM,AC-MA,MA-GBLCICLO59,TD-CUP,RG-SINCAT,AC-PREPUB,' + self.entitlements['suscripcion'] + #filter = '&filter=AC-OM,AC-MA,MA-GBLCICLO59,TD-CUP,RG-SINCAT,AC-PREPUB' url += '&mode=VOD' + filter if cat == 'tvshows': url += '&topic=SR&showSeries=series' @@ -767,3 +919,19 @@ class Movistar(object): def save_key_file(self, d): data = {'timestamp': int(time.time()*1000), 'response': d} self.cache.save_file('auth.key', json.dumps(data, ensure_ascii=False)) + + def get_profile_image_url(self, img_id): + content = self.cache.load_file('avatars.json') + if content: + data = json.loads(content) + else: + url = self.endpoints['avatares'] + data = self.net.load_data(url) + self.cache.save_file('avatars.json', json.dumps(data, ensure_ascii=False)) + #print_json(data) + for avatar in data: + if avatar['id'] == img_id: + for link in avatar['links']: + if link['sizes'] == '512x512': + return link['href'] + return None diff --git a/resources/lib/plugin.py b/resources/lib/plugin.py index d7a76b7..0c7031c 100644 --- a/resources/lib/plugin.py +++ b/resources/lib/plugin.py @@ -33,19 +33,18 @@ _url = sys.argv[0] # Get the plugin handle as an integer number. _handle = int(sys.argv[1]) -try: # Kodi >= 19 - from xbmcvfs import translatePath -except ImportError: # Kodi 18 - from xbmc import translatePath - - def get_url(**kwargs): + for key, value in kwargs.items(): + if isinstance(value, unicode): + kwargs[key] = value.encode('utf-8') return '{0}?{1}'.format(_url, urlencode(kwargs)) def play(params): LOG('play - params: {}'.format(params)) - if not 'url' in params: return + if not 'url' in params: + show_notification(addon.getLocalizedString(30204)) + return url = params['url'] channel_id = params['id'] @@ -70,7 +69,7 @@ def play(params): d = m.open_session(params['session_request'], session_token) LOG('Open session: d: {}'.format(d)) if d['resultCode'] != 0: - dialog = xbmcgui.Dialog().notification('Error', d['resultText'], xbmcgui.NOTIFICATION_ERROR, 5000) + show_notification(d['resultText']) return if 'resultData' in d and 'cToken' in d['resultData']: token = d['resultData']['cToken'] @@ -85,7 +84,11 @@ def play(params): if stype in ['u7d', 'rec']: d = m.get_u7d_url(url) - url = d['url'] + if 'resultText' in d: + show_notification(d['resultText']) + return + else: + url = d['url'] proxy = m.cache.load_file('proxy.conf') if addon.getSettingBool('manifest_modification') and proxy: @@ -136,6 +139,9 @@ def play(params): #play_item.setProperty('inputstream.adaptive.license_flags', 'persistent_storage') #play_item.setProperty('inputstream.adaptive.license_flags', 'force_secure_decoder') + if stype == 'u7d': + play_item.setProperty('inputstream.adaptive.play_timeshift_buffer', 'true') + if sys.version_info[0] < 3: play_item.setProperty('inputstreamaddon', 'inputstream.adaptive') else: @@ -214,20 +220,25 @@ def add_videos(category, ctype, videos, ref=None, url_next=None, url_prev=None): #LOG("*** TEST t: {}".format(t)) if 'subscribed' in t: if addon.getSettingBool('only_subscribed') and t['subscribed'] == False: continue - t['info']['title'] = m.colorize_title(t) - title_name = t['info']['title'].encode('utf-8') + t['info']['title'] = m.colorize_title(t) + title_name = t['info']['title'] if not 'type' in t: continue if t['type'] == 'movie': list_item = xbmcgui.ListItem(label = title_name) - #if t['stream_type'] == 'tv': - # action = get_url(action='epg', id=t['id'], name=t['name'].encode('utf-8')) - # LOG('action: {}'.format(action)) - # list_item.addContextMenuItems([('EPG', "RunPlugin(" + action + ")")]) - if t['url'] == '': - t['info']['title'] = '[COLOR gray]' + t['info']['title'] +'[/COLOR]' + #if t['url'] == '': + # t['info']['title'] = '[COLOR gray]' + t['info']['title'] +'[/COLOR]' list_item.setProperty('IsPlayable', 'true') list_item.setInfo('video', t['info']) list_item.setArt(t['art']) + + if t.get('stream_type') == 'u7d' and not t.get('aired', False): + record_program_action = (addon.getLocalizedString(30171), "RunPlugin(" + get_url(action='add_recording', id=t['id']) + ")") + list_item.addContextMenuItems([record_program_action]) + + if 'rec' in t: + action = get_url(action='delete_recording', id=t['rec']['id'], name=t['rec']['name']) + list_item.addContextMenuItems([(addon.getLocalizedString(30173), "RunPlugin(" + action + ")")]) + url = get_url(action='play', id=t['id'], url=t['url'], session_request=t['session_request'], stype=t['stream_type']) xbmcplugin.addDirectoryItem(_handle, url, list_item, False) elif t['type'] == 'series': @@ -314,24 +325,16 @@ def list_profiles(params): name = p['name'] if p['id'] == m.account['profile_id']: name = '[B][COLOR blue]' + name + '[/COLOR][/B]' + img_url = m.get_profile_image_url(p['image_id']) + art = {'icon': img_url} if img_url else None select_action = get_url(action='profiles', id=p['id'], name='select') - add_menu_option(name, select_action) + add_menu_option(name, select_action, art=art) close_folder(cacheToDisc=False) def list_epg(params): LOG('list_epg: {}'.format(params)) if 'id' in params: - epg = m.get_epg() - xbmcplugin.setPluginCategory(_handle, params['name']) - xbmcplugin.setContent(_handle, 'files') - for p in epg[params['id']]: - name = '[B]' + p['start_str'] + '[/B] ' + p['desc1'] - if p['desc2']: name += ' - '+ p['desc2'] - plot = name +"\n" + p['desc2'] - list_item = xbmcgui.ListItem(label=name) - list_item.setInfo('video', {'name':name, 'plot':plot}) - xbmcplugin.addDirectoryItem(_handle, '', list_item, False) - xbmcplugin.endOfDirectory(_handle) + add_videos(params['name'], 'movies', m.epg_to_movies(params['id'])) else: channels = m.get_channels() open_folder(addon.getLocalizedString(30107)) # EPG @@ -369,6 +372,53 @@ def list_vod(): add_menu_option(name, get_url(action='listing', name=name, url=m.get_vod_list_url(cat='kids'))) # Kids close_folder() +def search(params): + search_term = params.get('search_term', None) + if search_term: + if sys.version_info[0] < 3: + search_term = search_term.decode('utf-8') + if params.get('name', None) == 'delete': + m.delete_search(search_term) + xbmc.executebuiltin("Container.Refresh") + else: + url = m.get_search_url(search_term) + listing_hz(addon.getLocalizedString(30117), url) + return + + if params.get('name', None) == 'new': + search_term = input_window(addon.getLocalizedString(30116)) # Search term + if search_term: + if sys.version_info[0] < 3: + search_term = search_term.decode('utf-8') + m.add_search(search_term) + xbmc.executebuiltin("Container.Refresh") + return + + open_folder(addon.getLocalizedString(30113)) # Search + add_menu_option(addon.getLocalizedString(30113), get_url(action='search', name='new')) # New search + + for i in m.search_list: + remove_action = get_url(action='search', search_term=i, name='delete') + cm = [(addon.getLocalizedString(30114), "RunPlugin(" + remove_action + ")")] + add_menu_option(i.encode('utf-8'), get_url(action='search', search_term=i), cm) + + close_folder(cacheToDisc=False) + +def order_recording(program_id): + data = m.order_recording(program_id) + if data and 'resultText' in data: + show_notification(data['resultText']) + else: + show_notification(addon.getLocalizedString(30172), xbmcgui.NOTIFICATION_INFO) + +def delete_recording(id, name): + if sys.version_info[0] < 3: + name = name.decode('utf-8') + res = xbmcgui.Dialog().yesno(addon.getLocalizedString(30173), addon.getLocalizedString(30174).format(name)) + if res == True: + m.delete_recording(id) + xbmc.executebuiltin("Container.Refresh") + def clear_session(): m.cache.remove_file('access_token.conf') m.cache.remove_file('account.json') @@ -453,6 +503,10 @@ def router(paramstring): logout() elif params['action'] == 'epg': list_epg(params) + elif params['action'] == 'add_recording': + order_recording(params['id']) + elif params['action'] == 'delete_recording': + delete_recording(params['id'], params['name']) elif params['action'] == 'wishlist': # Wishlist listing_hz(addon.getLocalizedString(30102), m.get_wishlist_url()) @@ -469,6 +523,8 @@ def router(paramstring): add_videos(params['name'], 'episodes', m.get_episodes(params['id'])) elif params['action'] == 'vod': list_vod() + elif params['action'] == 'search': + search(params) else: # Main open_folder(addon.getLocalizedString(30101)) # Menu @@ -480,6 +536,7 @@ def router(paramstring): add_menu_option(addon.getLocalizedString(30102), get_url(action='wishlist')) # My list add_menu_option(addon.getLocalizedString(30103), get_url(action='recordings')) # Recordings add_menu_option(addon.getLocalizedString(30111), get_url(action='vod')) # VOD + add_menu_option(addon.getLocalizedString(30112), get_url(action='search')) # Search add_menu_option(addon.getLocalizedString(30180), get_url(action='profiles')) # Profiles add_menu_option(addon.getLocalizedString(30108), get_url(action='devices')) # Devices @@ -520,6 +577,7 @@ def run(): LOG('profile_dir: {}'.format(profile_dir)) LOG('reuse_devices: {}'.format(reuse_devices)) m = Movistar(profile_dir, reuse_devices=reuse_devices) + m.add_extra_info = addon.getSettingBool('add_extra_info') global player player = Player() diff --git a/resources/lib/timeconv.py b/resources/lib/timeconv.py index 011c84d..e1e9704 100644 --- a/resources/lib/timeconv.py +++ b/resources/lib/timeconv.py @@ -5,27 +5,31 @@ from __future__ import unicode_literals, absolute_import, division -from datetime import datetime, timedelta +from datetime import datetime +import pytz +from dateutil import parser -def timestamp2str(timestamp): +weekdays = ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab'] + +def timestamp2str(timestamp, format='%H:%M'): time = datetime.fromtimestamp(timestamp / 1000) - return time.strftime("%H:%M") + if '%a' in format: + w = int(time.strftime('%w')) + format = format.replace('%a', weekdays[w]) + return time.strftime(format).capitalize() -def isodate2str(iso_str): - iso_str = iso_str[0:19] +def isodate2date(date_string): + date_object = parser.parse(date_string) + if date_object.tzinfo is None: + madrid_tz = pytz.timezone("Europe/Madrid") + madrid_time = madrid_tz.localize(date_object) + else: + madrid_time = date_object.astimezone(pytz.timezone("Europe/Madrid")) + return madrid_time + +def isodate2str(date_string): try: - dt = datetime.strptime(iso_str, "%Y-%m-%dT%H:%M:%S") + date_object = isodate2date(date_string) + return date_object.strftime("%d/%m/%Y %H:%M:%S") except: - return iso_str - - try: - import pytz - utc_tz = pytz.timezone('UTC') - dt = utc_tz.localize(dt) - dt = dt.astimezone(pytz.timezone('Europe/Madrid')) - except: - pass - - dt = dt.strftime('%d/%m/%Y %H:%M:%S') - return dt - + return date_string diff --git a/resources/settings.xml b/resources/settings.xml index 6f58744..f1d4ede 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -2,11 +2,11 @@ - + - +