def get_user_jwt_token(): #get the Gigya token for the current user #TOFIX should be cached in a way or another so we don't always call a new session ? if not user_has_account(): common.plugin.log("get_user_jwt_token - missing email or password") raise ValueError( "Veuillez configurer votre compte dans les options de l'addon.") else: user_login = Addon().get_setting('email') user_pwd = Addon().get_setting('password') session = gigya.get_user_session(user_login, user_pwd) uid = session['UID'] #user_datas = gigya.get_account_info(uid) user_token = gigya.get_jwt(uid) if not user_token: common.plugin.log("get_user_jwt_token - unable to get user token") raise ValueError("Impossible de récupérer le token utilisateur.") return #TOFIX TOCHECK do we need a to return here ? else: return user_token
def browse_indexes(params): connection = get_connection() if connection is False: return listing = [] # Get items # optional folder ID folder_id = params.get('folder_id') items = connection.walk_index(folder_id) # Iterate through items for item in items: coverartsrc = 'coverArt' if 'coverArt' in item else 'id' if Addon().get_setting('coverart_from_server'): image = connection.getCoverArtUrl(item.get(coverartsrc)) else: image = None entry = { 'icon': 'DefaultArtist.png', 'thumb': image, 'label': item.get('name'), 'url': plugin.get_url( action='list_directory', id=item.get('id'), menu_id=params.get('menu_id'), ), 'info': { 'music': { 'artist': item.get('name'), 'mediatype': 'artist', 'rating': item.get('starred'), } } } ####TO FIX #context menu actions context_actions = [] if can_star('artist', item.get('id')): action_star = context_action_star('artist', item.get('id')) context_actions.append(action_star) if len(context_actions) > 0: entry['context_menu'] = context_actions listing.append(entry) return plugin.create_listing(listing, cache_to_disk=True, sort_methods=get_sort_methods( 'artists', params), view_mode=Addon().get_setting('view_artist'), content='artists')
def user_has_account(): user_login = Addon().get_setting('email') user_pwd = Addon().get_setting('password') if user_login and user_pwd: return True else: return False
def __init__(self, headers=None, cookie_file=None): super(WebClient, self).__init__() if cookie_file is not None: self.cookies = cookielib.LWPCookieJar(cookie_file) if os.path.exists(cookie_file): self.cookies.load(ignore_discard=True, ignore_expires=True) if headers is not None: self.headers.update(headers) self._addon = Addon()
def menu_tracks(params): # get connection connection = get_connection() if connection is False: return listing = [] menus = { 'tracks_starred': { 'name': Addon().get_localized_string(30036), 'thumb': None }, 'tracks_random': { 'name': Addon().get_localized_string(30037), 'thumb': None } } # Iterate through categories for menu_id in menus: menu = menus.get(menu_id) # image if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), # Item thumbnail 'fanart': menu.get('thumb'), # Item thumbnail 'url': plugin.get_url(action='list_tracks', menu_id=menu_id) }) # Item label return plugin.create_listing( listing, #succeeded = True, #if False Kodi won’t open a new listing and stays on the current level. #update_listing = False, #if True, Kodi won’t open a sub-listing but refresh the current one. #cache_to_disk = True, #cache this view to disk. #sort_methods = None, #he list of integer constants representing virtual folder sort methods. #view_mode = None, #a numeric code for a skin view mode. View mode codes are different in different skins except for 50 (basic listing). #content = None #string - current plugin content, e.g. ‘movies’ or ‘episodes’. )
def get_connection(): global connection if connection == None: connected = False # Create connection try: connection = libsonic.Connection( baseUrl=Addon().get_setting('subsonic_url'), username=Addon().get_setting('username', convert=False), password=Addon().get_setting('password', convert=False), port=Addon().get_setting('port'), apiVersion=Addon().get_setting('apiversion'), insecure=Addon().get_setting('insecure'), legacyAuth=Addon().get_setting('legacyauth'), useGET=Addon().get_setting('useget'), ) connected = connection.ping() except: pass if connected == False: popup('Connection error') return False return connection
def search(params): dialog = xbmcgui.Dialog() d = dialog.input(Addon().get_localized_string(30039), type=xbmcgui.INPUT_ALPHANUM) if not d: d = " " # get connection connection = get_connection() if connection is False: return listing = [] # Get items items = connection.search2(query=d) # Iterate through items for item in items.get('searchResult2').get('song'): entry = get_entry_track(item, params) listing.append(entry) if len(listing) == 1: plugin.log( 'One single Media Folder found; do return listing from browse_indexes()...' ) return browse_indexes(params) else: return plugin.create_listing(listing)
def get_program_medias(id, page=1): """ Get a list of recent medias by show ID or IDs, from the API """ items = [] limit = int(Addon().get_setting('medias_per_page')) url_args = { 'program_id': id, 'target_site': 'mediaz', 'offset': (page - 1) * limit, 'limit': limit, } url = generic_api_url('media', 'objectlist', url_args) json_data = utils.request_url(url) if not json_data: return nodes = json.loads(json_data) common.plugin.log('api.get_program_medias: found %d nodes' % len(nodes)) return nodes
def download_item(params): id = params.get('id') #can be single or lists of IDs type = params.get('type') #validate path download_folder = Addon().get_setting('download_folder') if not download_folder: popup("Please set a directory for your downloads") plugin.log_error("No directory set for downloads") #validate capability if not can_download(type, id): return if type == 'track': did_action = download_tracks(id) elif type == 'album': did_action = download_album(id) if did_action: plugin.log('Downloaded %s #%s' % (type, id)) popup('Item has been downloaded!') else: plugin.log_error('Unable to downloaded %s #%s' % (type, id)) return did_action
def get_entry_playlist(item, params): image = connection.getCoverArtUrl(item.get('coverArt')) genre_setting = item.get('genre') if ( Addon().get_setting('view_genre')) else None return { 'label': item.get('name'), 'thumb': image, 'icon': 'DefaultMusicPlaylists.png', 'url': plugin.get_url(action='list_tracks', playlist_id=item.get('id'), menu_id=params.get('menu_id')), 'info': { 'music': { 'mediatype': 'album', 'title': item.get('name'), 'count': item.get('songCount'), 'duration': item.get('duration'), 'date': convert_date_from_iso8601(item.get('created')), 'genre': genre_setting, 'rating': item.get('starred'), } } }
def play_track(params): id = params['id'] plugin.log('play_track #' + id) connection = get_connection() if connection is False: return url = connection.streamUrl( sid=id, maxBitRate=Addon().get_setting('bitrate_streaming'), tformat=Addon().get_setting('transcode_format_streaming')) return url
def list_directory(params): # get connection connection = get_connection() merge_artist = Addon().get_setting('merge') if connection == False: return listing = [] # Get items id = params.get('id') items = walk_directory(id, merge_artist) # Iterate through items for item in items: #is a directory if (item.get('isDir') == True): entry = { 'label': item.get('title'), 'url': plugin.get_url(action='list_directory', id=item.get('id'), menu_id=params.get('menu_id')) } else: entry = get_entry_track(item, params) listing.append(entry) add_directory_items(create_listing(listing))
def get_live_videos(page=1): # parse live video streams items = [] limit = int(Addon().get_setting('medias_per_page')) url = common.cryo_base_url + 'live/planninglist' url_params = { 'target_site': 'mediaz', #'offset': (page - 1) * limit, #'limit': limit, 'partner_key': common.cryo_partner_key, 'v': 8, } #API request json_data = None json_data = utils.request_url(url, url_params) #handle datas if not json_data: return else: nodes = json.loads(json_data) common.plugin.log('api.get_live_videos: found %d nodes' % len(nodes)) return nodes
def browse_folders(params): connection = get_connection() if connection is False: return listing = [] # Get items items = connection.walk_folders() # Iterate through items for item in items: entry = { 'label': item.get('name'), 'url': plugin.get_url(action='browse_indexes', folder_id=item.get('id'), menu_id=params.get('menu_id')) } listing.append(entry) # Merge folders if setting == True or if there is only 1 media folder. if len(listing) == 1 or Addon().get_setting('merge_folders') == True: plugin.log( 'One single Media Folder found; do return listing from browse_indexes()...' ) return browse_indexes(params) else: return plugin.create_listing(listing, cache_to_disk=True, sort_methods=None, view_mode=None, content='files')
def get_live_videos(page=1): """ parse live video streams """ items = [] limit = int(Addon().get_setting('medias_per_page')) url_args = { 'target_site': 'media', 'origin_site': 'media', 'category_id': 0, 'start_date': '', 'offset': (page - 1) * limit, 'limit': limit, } url = generic_api_url('live', 'planninglist', url_args) json_data = utils.request_url(url) if not json_data: return nodes = json.loads(json_data) common.plugin.log('api.get_live_videos: found %d nodes' % len(nodes)) return nodes
def search(params): dialog = xbmcgui.Dialog() d = dialog.input(Addon().get_localized_string(30039), type=xbmcgui.INPUT_ALPHANUM) if not d: return False lmenu = [] types = [ { 'type': "artist", 'locstr': 30085, 'image': "DefaultMusicArtists.png" }, { 'type': "album", 'locstr': 30086, 'image': "DefaultMusicAlbums.png" }, { 'type': "track", 'locstr': 30087, 'image': "DefaultMusicSongs.png" }, ] for props in types: lmenu.append({ 'label': Addon().get_localized_string(props['locstr']), 'url': plugin.get_url( action='get_search_results', page=1, query_args=json.dumps({ 'query': d, 'type': props['type'], }), firstEntry=True, ), 'thumb': props['image'], 'fanart': None, }) return plugin.create_listing(lmenu, cache_to_disk=True, content='mixed')
def test_icon_fanart_properties(self): addon = Addon() self.assertEqual(addon.icon, '') self.assertEqual(addon.fanart, '') open('icon.png', 'w').close() open('fanart.jpg', 'w').close() self.assertTrue('icon.png' in addon.icon) self.assertTrue('fanart.jpg' in addon.fanart)
def play_track(params): id = params['id'] plugin.log('play_track #' + id) # get connection connection = get_connection() if connection == False: return url = connection.streamUrl( sid=id, maxBitRate=Addon().get_setting('bitrate_streaming'), tformat=Addon().get_setting('transcode_format_streaming')) #return url _set_resolved_url(resolve_url(url))
def test_addon_set_setting(self): """ Test saving addon settings """ addon = Addon() addon.set_setting('test', True) self.assertEqual(addon.addon.getSetting('test'), 'true') addon.set_setting('test', False) self.assertEqual(addon.addon.getSetting('test'), 'false') addon.set_setting('test', 10) self.assertEqual(addon.addon.getSetting('test'), '10')
def context_action_star(type, id): starred = is_starred(id) if not starred: label = Addon().get_localized_string(30093) else: #Should be available only in the stars lists; #so we don't have to fetch the starred status for each item #(since it is not available into the XML response from the server) label = Addon().get_localized_string(30094) return ( label, 'XBMC.RunPlugin(%s)' % plugin.get_url(action='star_item', type=type, ids=id, unstar=starred))
def menu_tracks(params): # get connection connection = get_connection() if connection == False: return listing = [] menus = { 'tracks_starred': { 'name': Addon().get_localized_string(30036), 'thumb': None }, 'tracks_random': { 'name': Addon().get_localized_string(30037), 'thumb': None } } # Iterate through categories for menu_id in menus: menu = menus.get(menu_id) # image if 'thumb' in menu: thumb = menu.get('thumb') listing.append({ 'label': menu.get('name'), 'thumb': menu.get('thumb'), # Item thumbnail 'fanart': menu.get('thumb'), # Item thumbnail 'url': plugin.get_url(action='list_tracks', menu_id=menu_id) }) # Item label add_directory_items(create_listing(listing, ))
def get_entry_track(item, params): menu_id = params.get('menu_id') coverartsrc = 'coverArt' if 'coverArt' in item else 'id' image = connection.getCoverArtUrl(item.get(coverartsrc)) genre_setting = item.get('genre') if ( Addon().get_setting('view_genre')) else None entry = { 'label': get_entry_album_label(item, params.get('hide_artist', False)), 'tracknumber': item.get('track'), 'thumb': image, 'url': plugin.get_url(action='play_track', id=item.get('id'), menu_id=menu_id), 'is_playable': True, 'mimetype': item.get("contentType"), 'info': { 'music': { 'mediatype': 'song', 'title': item.get('title'), 'album': item.get('album'), 'tracknumber': item.get('track'), 'artist': item.get('artist'), 'year': item.get('year'), 'genre': genre_setting, 'size': item.get('size'), 'duration': item.get('duration'), 'date': item.get('created'), 'rating': item.get('starred'), } } } #context menu actions context_actions = [] if can_star('track', item.get('id')): action_star = context_action_star('track', item.get('id')) context_actions.append(action_star) if can_download('track', item.get('id')): action_download = context_action_download('track', item.get('id')) context_actions.append(action_download) if len(context_actions) > 0: entry['context_menu'] = context_actions return entry
def test_cached_decorator(self): addon = Addon() @addon.cached() def tester(*args): return str(time.time()) test1 = tester('arg1') time.sleep(0.5) self.assertEqual(tester('arg1'), test1) self.assertNotEqual(tester('arg2'), test1)
def test_mem_cached_decorator(self): with mock.patch.object(Addon, 'get_mem_storage', return_value={}): addon = Addon() @addon.mem_cached() def tester(*args): return str(time.time()) test1 = tester('arg1') time.sleep(0.5) self.assertEqual(tester('arg1'), test1) self.assertNotEqual(tester('arg2'), test1)
def get_connection(): global connection if connection is None: connected = False # Create connection try: connection = libsonic_extra.SubsonicClient( Addon().get_setting('subsonic_url'), Addon().get_setting('username', convert=False), Addon().get_setting('password', convert=False), Addon().get_setting('apiversion'), Addon().get_setting('insecure') == 'true', Addon().get_setting('legacyauth') == 'true', ) connected = connection.ping() except: pass if connected is False: popup('Connection error') return False return connection
def get_entry_album(item, params): coverartsrc = 'coverArt' if 'coverArt' in item else 'id' image = connection.getCoverArtUrl(item.get(coverartsrc)) genre_setting = item.get('genre') if ( Addon().get_setting('view_genre')) else None entry = { 'label': get_entry_album_label(item, params.get('hide_artist', False)), 'thumb': image, 'icon': 'DefaultMusicAlbums.png', 'url': plugin.get_url(action='list_directory', id=item.get('id'), hide_artist=item.get('hide_artist'), menu_id=params.get('menu_id')), 'info': { 'music': { 'mediatype': 'album', #'count': item.get('songCount'), 'date': convert_date_from_iso8601(item.get('created')), #date added #'duration': item.get('duration'), 'artist': item.get('artist'), 'album': item.get('name'), 'year': item.get('year'), 'genre': genre_setting, 'rating': item.get('starred'), } } } #context menu actions context_actions = [] if can_star('album', item.get('id')): action_star = context_action_star('album', item.get('id')) context_actions.append(action_star) if can_download('album', item.get('id')): action_download = context_action_download('album', item.get('id')) context_actions.append(action_download) if len(context_actions) > 0: entry['context_menu'] = context_actions return entry
def navigate_next(params): page = int(params.get('page', 1)) page += 1 title = Addon().get_localized_string(30090) + " (%d)" % (page) return { 'label': title, 'url': plugin.get_url(action=params.get('action', None), page=page, query_args=params.get('query_args', None)) }
def test_addon_get_setting(self): """ Test addon settings normalization """ addon = Addon() addon.addon.setSetting('test', 'true') self.assertEqual(addon.get_setting('test'), True) addon.addon.setSetting('test', 'false') self.assertEqual(addon.get_setting('test'), False) addon.addon.setSetting('test', '10') self.assertEqual(addon.get_setting('test'), 10) addon.addon.setSetting('test', '1.0') self.assertEqual(addon.get_setting('test'), 1.0) addon.addon.setSetting('test', 'foo') self.assertEqual(addon.get_setting('test'), 'foo')
def get_entry_artist(item, params): coverartsrc = 'coverArt' if 'coverArt' in item else 'id' if Addon().get_setting('coverart_from_server'): image = connection.getCoverArtUrl(item.get(coverartsrc)) else: image = None return { 'label': item.get('name'), 'icon': 'DefaultArtist.png', 'thumb': image, 'url': plugin.get_url( action='list_directory', id=item.get('id'), ), 'info': { 'music': { 'mediatype': 'artist', 'artist': item.get('name') } } }
def get_category_medias(id, page=1): items = [] limit = int(Addon().get_setting('medias_per_page')) url_args = { 'target_site': 'mediaz', 'category_id': id, 'offset': (page - 1) * limit, 'limit': limit, } url = generic_api_url('media', 'objectlist', url_args) json_data = utils.request_url(url) if not json_data: return nodes = json.loads(json_data) common.plugin.log('api.get_category_medias: found %d nodes' % len(nodes)) return nodes
# coding: utf-8 # Module: commands # Created on: 28.07.2015 # Author: Roman Miroshnychenko aka Roman V.M. ([email protected]) # Licence: GPL v.3: http://www.gnu.org/copyleft/gpl.html """ Context menu commands """ import sys import xbmc import xbmcgui import json_requests as jsonrq from simpleplugin import Addon addon = Addon('plugin.video.yatp') _ = addon.initialize_gettext() def show_torrent_info(info_hash): """ Display current torrent info :param info_hash: :return: """ torr_info = jsonrq.get_torrent_info(info_hash) info_dialog = xbmcgui.DialogProgress() info_dialog.create(torr_info['name']) while not info_dialog.iscanceled(): info_dialog.update(torr_info['progress'],
# Author: Roman V.M. # Created on: 12.05.2015 # License: GPL v.3 https://www.gnu.org/copyleft/gpl.html """ Buffering torrent """ import os from urllib import quote import xbmc import xbmcgui import json_requests as jsonrq from simpleplugin import Addon addon = Addon() _ = addon.initialize_gettext() media_url = 'http://127.0.0.1:{0}/stream/'.format(addon.server_port) MEDIAFILES = ('.avi', '.mkv', '.mp4', '.ts', '.m2ts', '.mov', '.m4v', '.wmv') def get_videofiles(files): """ Get a sorted list of videofiles from all files in a torrent :param files: :return: the sorted list of 3-item tuples (file_index, file_name, file_size) """ videofiles = [] for file_index, file_ in enumerate(files): if os.path.splitext(file_[0].lower())[1] in MEDIAFILES:
def test_gettext_initialized(self): addon = Addon() _ = addon.initialize_gettext() self.assertEqual(_('Hello World!'), u'Привет, мир!'.encode('utf-8')) self.assertEqual(_('I love you.'), u'Я тебя люблю.'.encode('utf-8')) self.assertRaises(SimplePluginError, _, 'Foo Bar')