def __C_MENU(C_ID): #0: Refresh #1: Delete menuItems = [AddonString(30031), AddonString(30039)] try: ret = xbmcgui.Dialog().select( 'Manage: ' + CONFIG['channels'][C_ID]['channel_name'], menuItems) if ret == 0: __parse_uploads(False, CONFIG['channels'][C_ID]['playlist_id']) elif ret == 1: cname = CONFIG['channels'][C_ID]['channel_name'] cdir = CHANNELS + '\\' + C_ID __logger(cdir) #Are you sure to remove X... ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30036).format(cname)) if ret == True: local_index_file = CHANNELS + '\\' + C_ID + '\\index.json' __Remove_from_index(local_index_file) CONFIG['channels'].pop(C_ID) __save() #Remove from library? ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30037).format(cname)) if ret: success = recursive_delete_dir(cdir) if success: xbmc.executebuiltin("CleanLibrary(video)") else: pass except KeyError: pass
def __MUSIC_MENU(C_ID): #0: Refresh #1: Delete menuItems = [AddonString(30031), AddonString(30039)] try: ret = xbmcgui.Dialog().select( 'Manage: ' + CONFIG['music_videos'][C_ID]['channel_name'], menuItems) if ret == 0: __parse_music(False, CONFIG['music_videos'][C_ID]['playlist_id']) elif ret == 1: cname = CONFIG['music_videos'][C_ID]['channel_name'] cdir = MUSIC_VIDEOS + '\\' + C_ID __logger(cdir) #Are you sure to remove X... ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30036).format(cname)) if ret == True: CONFIG['music_videos'].pop(C_ID) __save() #Remove from library? ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30037).format(cname)) if ret: success = recursive_delete_dir(cdir) if success: xbmc.executebuiltin("CleanLibrary(video)") except KeyError: pass
def __PLAYLIST_MENU(C_ID): #0: Refresh #1: Delete menuItems = [ AddonString(30031), 'add/remove playlist items', AddonString(30039) ] try: ret = xbmcgui.Dialog().select( 'Manage: ' + CONFIG['playlists'][C_ID]['channel_name'], menuItems) if ret == 0: __parse_playlists(False, CONFIG['playlists'][C_ID]['playlist_id'], C_ID) elif ret == 1: playlists = __get_playlists( CONFIG['playlists'][C_ID]['original_channel_id']) data_set = __select_playlists(playlists, C_ID) if data_set: __logger(data_set) __logger('playlists follows:') CONFIG['playlists'][C_ID].pop('playlist_id') CONFIG['playlists'][C_ID]['playlist_id'] = data_set __save() elif ret == 2: cname = CONFIG['playlists'][C_ID]['channel_name'] cdir = CHANNELS + '\\' + C_ID __logger(cdir) #Are you sure to remove X... ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30036).format(cname)) if ret == True: local_index_file = CHANNELS + '\\' + C_ID + '\\index.json' __Remove_from_index(local_index_file) CONFIG['playlists'].pop(C_ID) __save() #Remove from library? ret = xbmcgui.Dialog().yesno( AddonString(30035).format(cname), AddonString(30037).format(cname)) if ret: success = recursive_delete_dir(cdir) if success: xbmc.executebuiltin("CleanLibrary(video)") else: pass except KeyError: pass
def __refresh(): # Updating channels... xbmcgui.Dialog().notification(addonname, AddonString(30026), addon_resources + '/icon.png', 2500) for items in CONFIG['playlists']: try: VIDEOS.clear() VIDEO_DURATION = {} except AttributeError: del VIDEOS[:] VIDEO_DURATION = {} LOCAL_CONF['update'] = True pl_items = CONFIG['playlists'][items]['playlist_id'] __parse_playlists(False, pl_items, items) for items in CONFIG['channels']: try: VIDEOS.clear() VIDEO_DURATION = {} except AttributeError: del VIDEOS[:] VIDEO_DURATION = {} LOCAL_CONF['update'] = True __parse_uploads(False, CONFIG['channels'][items]['playlist_id'], None, update=True) for items in CONFIG['music_videos']: try: VIDEOS.clear() VIDEO_DURATION = {} except AttributeError: del VIDEOS[:] VIDEO_DURATION = {} LOCAL_CONF['update'] = True __parse_music(False, CONFIG['music_videos'][items]['playlist_id'], None, update=True) __save() CONFIG['last_scan'] = int(time.time()) __save() #Update finished. xbmcgui.Dialog().notification(addonname, AddonString(30027), addon_resources + '/icon.png', 2500)
def __add_music(channel_id): data = {} channel_url = "https://www.googleapis.com/youtube/v3/channels?part=brandingSettings,contentDetails,contentOwnerDetails,id,localizations,snippet,statistics,status,topicDetails&id=" + channel_id + "&key=" + addon.getSetting( 'API_key') reply = c_download(channel_url) if 'items' not in reply: __print(AddonString(30015)) #No Such channel return "no such channel" data['channel_id'] = channel_id data['title'] = reply['items'][0]['brandingSettings']['channel']['title'] if 'description' in reply['items'][0]['brandingSettings']['channel']: data['plot'] = reply['items'][0]['brandingSettings']['channel'][ 'description'] else: data['plot'] = data['title'] data['aired'] = reply['items'][0]['snippet']['publishedAt'] if 'high' in reply['items'][0]['snippet']['thumbnails']: data['thumb'] = reply['items'][0]['snippet']['thumbnails']['high'][ 'url'] else: data['thumb'] = reply['items'][0]['snippet']['thumbnails']['default'][ 'url'] # data['banner'] = reply['items'][0]['brandingSettings']['image']['bannerImageUrl'] # if 'bannerTvHighImageUrl' in reply['items'][0]['brandingSettings']['image']: # data['fanart'] = reply['items'][0]['brandingSettings']['image']['bannerTvHighImageUrl'] # else: # data['fanart'] = reply['items'][0]['brandingSettings']['image']['bannerImageUrl'] data['banner'] = data['thumb'] data['fanart'] = data['thumb'] uploads = reply['items'][0]['contentDetails']['relatedPlaylists'][ 'uploads'] xbmcvfs.mkdirs(MUSIC_VIDEOS + '\\' + data['channel_id']) if channel_id not in CONFIG['music_videos']: CONFIG['music_videos'][channel_id] = {} CONFIG['music_videos'][channel_id]['channel_name'] = data['title'] CONFIG['music_videos'][channel_id]['branding'] = {} CONFIG['music_videos'][channel_id]['branding']['thumbnail'] = data['thumb'] CONFIG['music_videos'][channel_id]['branding']['fanart'] = data['fanart'] CONFIG['music_videos'][channel_id]['branding']['banner'] = data['banner'] CONFIG['music_videos'][channel_id]['branding']['description'] = data[ 'plot'] CONFIG['music_videos'][channel_id]['playlist_id'] = uploads __save() __parse_music(True, uploads, None)
def __Remove_from_index(a): index_file = addon_path + '\\index.json' if xbmcvfs.exists(index_file): if PY_V >= 3: with xbmcvfs.File(index_file) as f: # PYTHON 3 v19+ INDEX = json.load(f) # else: f = xbmcvfs.File(index_file) # PYTHON 2 v18+ INDEX = json.loads(f.read()) f.close() local_index_file = a if PY_V >= 3: with xbmcvfs.File(local_index_file) as f: # PYTHON 3 v19+ LOCAL_INDEX = json.load(f) # else: f = xbmcvfs.File(local_index_file) # PYTHON 2 v18+ LOCAL_INDEX = f.read() f.close() res = list(filter(lambda i: i not in LOCAL_INDEX, INDEX)) INDEX = res __logger(INDEX) __save(data=INDEX, file=index_file)
def __render(type, render_style='Full'): #RENDER MUSIC if type == 'music': if len(VIDEOS) <= 0: return if LOCAL_CONF['update'] == False: #Importing channel, plz wait. PDIALOG.create(AddonString(30024), AddonString(30025)) year = 0 episode = 0 l_count = 0 channelId = VIDEOS[0]['snippet']['channelId'] VIDEOS.reverse() if 'last_video' in CONFIG['music_videos'][VIDEOS[0]['snippet'] ['channelId']]: latest_aired = int(CONFIG['music_videos'][ VIDEOS[0]['snippet']['channelId']]['last_video']['aired']) last_video_id = CONFIG['music_videos'][ VIDEOS[0]['snippet']['channelId']]['last_video']['video_id'] for item in VIDEOS: data = {} data['video_id'] = item['snippet']['resourceId']['videoId'] aired = item['snippet']['publishedAt'].split('T')[0] ttime = item['snippet']['publishedAt'].split('T')[1] data['aired'] = aired aired_datetime = datetime.datetime(int(aired.split('-')[0]), int(aired.split('-')[1]), int(aired.split('-')[2]), int(ttime.split(':')[0]), int(ttime.split(':')[1]), 0, 0) # pylint: disable=line-too-long aired_timestamp = int( (aired_datetime - datetime.datetime(1970, 1, 1)).total_seconds()) try: if latest_aired > aired_timestamp or last_video_id == data[ 'video_id']: PARSER['steps'] += 2 continue except NameError: pass #Determine ARTIST - TITLE pattern: #FAILSAFE data[u'title'] = item['snippet'][u'title'] data[u'artist'] = item['snippet']['channelTitle'] #__logger(data[u'artist'] +' :::: ' +data[u'title']) # ARTIST - TITLE if '-' in data['title']: data[u'title'] = item['snippet'][u'title'].split('-')[1] data[u'artist'] = item['snippet'][u'title'].split('-')[0] # EXACTLY THE SAME AS ABOVE BUT WITH HYPHEN MINUS # (*angrily stares at Kælan Mikla*) elif ':' in data['title']: data[u'title'] = item['snippet'][u'title'].split(':')[1] data[u'artist'] = item['snippet'][u'title'].split(':')[0] elif '|' in data['title']: data[u'title'] = item['snippet'][u'title'].split('|')[1] data[u'artist'] = item['snippet'][u'title'].split('|')[0] data['channelId'] = item['snippet']['channelId'] data['plot'] = item['snippet']['description'] season = int(aired.split('-')[0]) data['video_duration'] = VIDEO_DURATION[data['video_id']] if 'maxres' in item['snippet']['thumbnails']: data['thumb'] = item['snippet']['thumbnails']['maxres']['url'] elif item['snippet']['thumbnails']['high']: data['thumb'] = item['snippet']['thumbnails']['high']['url'] elif item['snippet']['thumbnails']['standard']: data['thumb'] = item['snippet']['thumbnails']['standard'][ 'url'] else: data['thumb'] = item['snippet']['thumbnails']['default']['url'] l_count += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) output = u"""<? xml version = "1.0" encoding = "UTF-8" standalone = "yes"?> <musicvideo> <title>{title}</title> <plot>{plot}</plot> <runtime>{video_duration}</runtime> <thumb>{thumb}</thumb> <thumb>{thumb}</thumb> <thumb>{thumb}</thumb> <thumb>{thumb}</thumb> <artist>{artist}</artist> </musicvideo> """.format(**data) file_location = MUSIC_VIDEOS + '\\' + channelId + '\\' + data[ 'video_id'] write_file = file_location + '.nfo' if PY_V >= 3: with xbmcvfs.File(write_file, 'w') as f: result = f.write(output) else: f = xbmcvfs.File(write_file, 'w') f.write(bytearray(output.encode('utf-8'))) f.close() PARSER['steps'] += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) write_file = file_location + '.strm' if (addon.getSetting('YT_client') == "0"): youtube_client = 'plugin://plugin.video.youtube/play/?video_id=' elif (addon.getSetting('YT_client') == "1"): youtube_client = 'plugin://plugin.video.tubed/?mode=play&video_id=' if PY_V >= 3: with xbmcvfs.File(write_file, 'w') as f: f.write(youtube_client + data['video_id']) else: f = xbmcvfs.File(write_file, 'w') # Python 2 f.write( bytearray(youtube_client + data['video_id'].encode('utf-8'))) f.close() PARSER['steps'] += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) CONFIG['music_videos'][data['channelId']]['last_video'] = { 'video_id': data['video_id'], 'aired': aired_timestamp } __save() if addon.getSetting('refresh_after_add' ) == 'true' and LOCAL_CONF['update'] == False: time.sleep(1)
def __add_channel_playlist(channel_id): if 'playlists' not in CONFIG: CONFIG['playlists'] = {} data = {} custom_uuid = 'PL_' + uuid.uuid4().hex channel_url = "https://www.googleapis.com/youtube/v3/channels?part=brandingSettings,contentDetails,contentOwnerDetails,id,localizations,snippet,statistics,status,topicDetails&id=" + channel_id + "&key=" + addon.getSetting( 'API_key') reply = c_download(channel_url) if 'items' not in reply: __print(AddonString(30015)) #No Such channel return "no such channel" playlists = __get_playlists(channel_id) data_set = __select_playlists(playlists) data['channel_id_original'] = channel_id data['channel_id'] = custom_uuid data['title'] = data_set['title'] if 'description' in reply['items'][0]['brandingSettings']['channel']: data['plot'] = reply['items'][0]['brandingSettings']['channel'][ 'description'] else: data['plot'] = data['title'] data['aired'] = reply['items'][0]['snippet']['publishedAt'] if 'high' in reply['items'][0]['snippet']['thumbnails']: data['thumb'] = reply['items'][0]['snippet']['thumbnails']['high'][ 'url'] else: data['thumb'] = reply['items'][0]['snippet']['thumbnails']['default'][ 'url'] data['banner'] = data['thumb'] # # #reply['items'][0]['brandingSettings']['image']['bannerImageUrl'] #if 'bannerTvHighImageUrl' in reply['items'][0]['brandingSettings']['image']: # data['fanart'] = data['thumb'] # #reply['items'][0]['brandingSettings']['image']['bannerTvHighImageUrl'] #else: # data['fanart'] = data['thumb'] # reply['items'][0]['brandingSettings']['image']['bannerImageUrl'] data['fanart'] = data['thumb'] data['banner'] = data['thumb'] uploads = data_set['items'] data['uploader_stripped'] = re.sub(r'[^\w\s]', '', data['title']).replace(" ", "_") xbmcvfs.mkdirs(CHANNELS + '\\' + data['channel_id']) if custom_uuid not in CONFIG['playlists']: CONFIG['playlists'][custom_uuid] = {} CONFIG['playlists'][custom_uuid]['channel_name'] = data['title'] CONFIG['playlists'][custom_uuid][ 'channel_type'] = 'series' #temporarily until music videos and movies are implemented CONFIG['playlists'][custom_uuid]['branding'] = {} CONFIG['playlists'][custom_uuid]['branding']['thumbnail'] = data['thumb'] CONFIG['playlists'][custom_uuid]['branding']['fanart'] = data['fanart'] CONFIG['playlists'][custom_uuid]['branding']['banner'] = data['banner'] CONFIG['playlists'][custom_uuid]['branding']['description'] = data['plot'] CONFIG['playlists'][custom_uuid]['original_channel_id'] = channel_id CONFIG['playlists'][custom_uuid]['playlist_id'] = uploads output = u""" <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n <tvshow> <title>{title}</title> <showtitle>{title}</showtitle> <plot>{plot}</plot> <genre>None</genre> <premiered>{aired}</premiered> <aired>{aired}</aired> <studio>{title}</studio> <thumb>{thumb}</thumb> <thumb aspect="poster">{fanart}</thumb> <thumb aspect="banner">{banner}</thumb> <fanart> <thumb>{fanart}</thumb> </fanart> <tag>Youtube</tag> </tvshow> """.format(**data) tvshow_file = CHANNELS + '\\' + data['channel_id'] + '\\' + 'tvshow.nfo' if PY_V >= 3: with xbmcvfs.File(tvshow_file, 'w') as f: result = f.write(output) else: f = xbmcvfs.File(tvshow_file, 'w') # Python 2 result = f.write(bytearray(output.encode('utf-8'))) # f.close() local_index_file = CHANNELS + '\\' + data['channel_id'] + '\\index.json' if xbmcvfs.exists(index_file) == False: __save(data=[], file=local_index_file) __save() __parse_playlists(True, uploads, custom_uuid, None)
def __render(type, render_style='Full'): if type == 'tv' or type == 'tv_playlist': if len(VIDEOS) <= 0: return if LOCAL_CONF['update'] == False: #Importing channel, plz wait. PDIALOG.create(AddonString(30024), AddonString(30025)) year = 0 episode = 0 l_count = 0 channelId = VIDEOS[0]['snippet']['channelId'] local_index_file = CHANNELS + '\\' + channelId + '\\index.json' LOCAL_INDEX = [] if xbmcvfs.exists(local_index_file): if PY_V >= 3: with xbmcvfs.File(local_index_file) as f: # PYTHON 3 v19+ LOCAL_INDEX = json.load(f) # else: f = xbmcvfs.File(local_index_file) # PYTHON 2 v18+ LOCAL_INDEX = json.loads(f.read()) f.close() if type == 'tv' and 'last_video' in CONFIG['channels'][ VIDEOS[0]['snippet']['channelId']]: year = int(CONFIG['channels'][VIDEOS[0]['snippet']['channelId']] ['last_video']['season']) episode = int(CONFIG['channels'][VIDEOS[0]['snippet']['channelId']] ['last_video']['episode']) latest_aired = int(CONFIG['channels'][ VIDEOS[0]['snippet']['channelId']]['last_video']['aired']) last_video_id = CONFIG['channels'][ VIDEOS[0]['snippet']['channelId']]['last_video']['video_id'] for item in sorted(VIDEOS, key=lambda i: i["snippet"]["publishedAt"], reverse=False): data = {} data['video_id'] = item['snippet']['resourceId']['videoId'] aired = item['snippet']['publishedAt'].split('T')[0] ttime = item['snippet']['publishedAt'].split('T')[1] data['aired'] = aired aired_datetime = datetime.datetime(int(aired.split('-')[0]), int(aired.split('-')[1]), int(aired.split('-')[2]), int(ttime.split(':')[0]), int(ttime.split(':')[1]), 0, 0) # pylint: disable=line-too-long aired_timestamp = int( (aired_datetime - datetime.datetime(1970, 1, 1)).total_seconds()) try: if latest_aired > aired_timestamp or last_video_id == data[ 'video_id']: PARSER['steps'] += 2 continue except NameError: pass data['author'] = item['snippet']['channelTitle'] data['channelId'] = item['snippet']['channelId'] data['title'] = item['snippet']['title'] data['plot'] = item['snippet']['description'] season = int(aired.split('-')[0]) if year != season: year = season season = year episode = 0 try: data['video_duration'] = VIDEO_DURATION[data['video_id']] except KeyError: data['video_duration'] = 0 # NO F***ING IDEA WHAT IS GOING ON if 'maxres' in item['snippet']['thumbnails']: data['thumb'] = item['snippet']['thumbnails']['maxres']['url'] elif 'high' in item['snippet']['thumbnails']: data['thumb'] = item['snippet']['thumbnails']['high']['url'] elif 'standard' in item['snippet']['thumbnails']: data['thumb'] = item['snippet']['thumbnails']['standard'][ 'url'] else: data['thumb'] = item['snippet']['thumbnails']['default']['url'] episode += 1 data['episode'] = episode data['season'] = season l_count += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) xbmcvfs.mkdirs(CHANNELS + '\\' + data['channelId'] + '\\' + str(data['season'])) LOCAL_INDEX.append(data['video_id']) output = u"""<? xml version = \"1.0\" encoding = \"UTF-8\" standalone = \"yes\"?> <episodedetails> <title>{title}</title> <season>{season}</season> <episode>{episode}</episode> <plot>{plot}</plot> <aired>{aired}</aired> <studio>{author}</studio> <credits>{author}</credits> <director>{author}</director> <thumb>{thumb}</thumb> <runtime>{video_duration}</runtime> <fileinfo> <streamdetails> <durationinseconds>{video_duration}</durationinseconds> </streamdetails> </fileinfo> </episodedetails> """.format(**data) file_location = CHANNELS + '\\' + data['channelId'] + '\\' + str( data['season']) + '\\s' + str(data['season']) + 'e' + str( data['episode']) write_file = file_location + '.nfo' if PY_V >= 3: with xbmcvfs.File(write_file, 'w') as f: result = f.write(output) else: f = xbmcvfs.File(write_file, 'w') f.write(bytearray(output.encode('utf-8'))) f.close() PARSER['steps'] += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) write_file = file_location + '.strm' if (addon.getSetting('YT_client') == "0"): youtube_client = 'plugin://plugin.video.youtube/play/?video_id=' elif (addon.getSetting('YT_client') == "1"): youtube_client = 'plugin://plugin.video.tubed/?mode=play&video_id=' if PY_V >= 3: with xbmcvfs.File(write_file, 'w') as f: f.write(youtube_client + data['video_id']) else: f = xbmcvfs.File(write_file, 'w') # Python 2 f.write( bytearray(youtube_client + data['video_id'].encode('utf-8'))) f.close() PARSER['steps'] += 1 if LOCAL_CONF['update'] == False: PDIALOG.update( int(100 * PARSER['steps'] / PARSER['total_steps']), data['title']) if type == 'tv': CONFIG['channels'][data['channelId']]['last_video'] = { 'video_id': data['video_id'], 'aired': aired_timestamp, 'season': str(data['season']), 'episode': str(data['episode']) } __save() __save(data=INDEX, file=index_file) __save(data=LOCAL_INDEX, file=local_index_file) if addon.getSetting('refresh_after_add' ) == 'true' and LOCAL_CONF['update'] == False: time.sleep(1)