def reddit_get_access_token(url="", name="", type_=""): try: log( "Requesting a reddit 1-hour token" ) req = urllib2.Request('https://www.reddit.com/api/v1/access_token') data = urllib.urlencode({'grant_type' : 'refresh_token' ,'refresh_token' : reddit_refresh_token }) import base64 base64string = base64.encodestring('%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization',"Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response=page.read();page.close() status=reddit_set_addon_setting_from_response(response) if status=='ok': return True else: r2="Requesting 1-hour token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( status, r2) ) except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
def playURLRVideo(url, name, type_): dialog_progress_title = 'URL Resolver' dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title) dialog_progress_YTDL.update(10, dialog_progress_title, translation(32014)) import urlresolver from urlparse import urlparse parsed_uri = urlparse(url) domain = '{uri.netloc}'.format(uri=parsed_uri) #hmf = urlresolver.HostedMediaFile(url) dialog_progress_YTDL.update(20, dialog_progress_title, translation(32012)) try: media_url = urlresolver.resolve(url) dialog_progress_YTDL.update(80, dialog_progress_title, translation(32013)) if media_url: log(' URLResolver stream url=' + repr(media_url)) pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) pl.clear() pl.add(media_url, xbmcgui.ListItem(name)) xbmc.Player().play(pl, windowed=False) #scripts play video like this. else: log(" Can't URL Resolve:" + repr(url)) xbmc_notify('URLresolver', translation(32192)) #Failed to get playable url except Exception as e: xbmc_notify('URLresolver:' + domain, str(e)) dialog_progress_YTDL.close()
def playURLRVideo(url, name, type_): dialog_progress_title = 'URL Resolver' dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title) dialog_progress_YTDL.update(10, dialog_progress_title, translation(30024)) import urlresolver #from urlparse import urlparse #parsed_uri = urlparse( url ) #domain = '{uri.netloc}'.format(uri=parsed_uri) #hmf = urlresolver.HostedMediaFile(url) dialog_progress_YTDL.update(20, dialog_progress_title, translation(30022)) try: media_url = urlresolver.resolve(url) dialog_progress_YTDL.update(80, dialog_progress_title, translation(30023)) if media_url: log(' URLResolver stream url=' + repr(media_url)) listitem = xbmcgui.ListItem(path=media_url) xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: log(" Can't URL Resolve:" + repr(url)) xbmc_notify('URLresolver', translation(30192)) except Exception as e: xbmc_notify('URLresolver', str(e)) dialog_progress_YTDL.close()
def reddit_revoke_refresh_token(url, name, type_): global reddit_access_token #specify "global" if you wanto to change the value of a global variable global reddit_refresh_token try: log( "Revoking refresh token " ) req = urllib2.Request('https://www.reddit.com/api/v1/revoke_token') data = urllib.urlencode({'token' : reddit_refresh_token ,'token_type_hint': 'refresh_token' }) import base64 base64string = base64.encodestring('%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization',"Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response=page.read();page.close() log( "response:" + response ) addon.setSetting('reddit_refresh_token', "") addon.setSetting('reddit_access_token', "") addon.setSetting('reddit_access_token_scope', "") addon.setSetting('reddit_access_token_expires', "") reddit_refresh_token="" reddit_access_token="" r2="Revoking refresh token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( 'Token revoked', r2) ) except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
def playURLRVideo(url, name, type_): dialog_progress_title='URL Resolver' dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title ) dialog_progress_YTDL.update(10,dialog_progress_title,translation(32014) ) from urlparse import urlparse parsed_uri = urlparse( url ) domain = '{uri.netloc}'.format(uri=parsed_uri) try: import urlresolver #hmf = urlresolver.HostedMediaFile(url) dialog_progress_YTDL.update(20,dialog_progress_title,translation(32012) ) media_url = urlresolver.resolve(url) dialog_progress_YTDL.update(80,dialog_progress_title,translation(32013) ) if media_url: log( ' URLResolver stream url=' + repr(media_url )) pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) pl.clear() pl.add(media_url, xbmcgui.ListItem(name)) xbmc.Player().play(pl, windowed=False) #scripts play video like this. else: log( " Can't URL Resolve:" + repr(url)) xbmc_notify('URLresolver', translation(32192),icon="type_urlr.png" ) #Failed to get playable url except Exception as e: xbmc_notify('URLresolver:'+domain, str(e),icon="type_urlr.png" ) dialog_progress_YTDL.close()
def playURLRVideo(url, name, type_): dialog_progress_title='URL Resolver' dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title ) dialog_progress_YTDL.update(10,dialog_progress_title,translation(30024) ) import urlresolver #from urlparse import urlparse #parsed_uri = urlparse( url ) #domain = '{uri.netloc}'.format(uri=parsed_uri) #hmf = urlresolver.HostedMediaFile(url) dialog_progress_YTDL.update(20,dialog_progress_title,translation(30022) ) try: media_url = urlresolver.resolve(url) dialog_progress_YTDL.update(80,dialog_progress_title,translation(30023) ) if media_url: log( ' URLResolver stream url=' + repr(media_url )) listitem = xbmcgui.ListItem(path=media_url) xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: log( " Can't URL Resolve:" + repr(url)) xbmc_notify('URLresolver',translation(30192)) except Exception as e: xbmc_notify('URLresolver', str(e) ) dialog_progress_YTDL.close()
def reddit_get_access_token(url="", name="", type_=""): try: log("Requesting a reddit 1-hour token") req = urllib2.Request('https://www.reddit.com/api/v1/access_token') #http://stackoverflow.com/questions/6348499/making-a-post-call-instead-of-get-using-urllib2 data = urllib.urlencode({ 'grant_type': 'refresh_token', 'refresh_token': reddit_refresh_token }) #http://stackoverflow.com/questions/2407126/python-urllib2-basic-auth-problem import base64 base64string = base64.encodestring( '%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization', "Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response = page.read() page.close() status = reddit_set_addon_setting_from_response(response) if status == 'ok': return True else: r2 = "Requesting 1-hour token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" % (status, r2)) except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
def addtoKodiFavorites(command, name, thumbnail): import xml.etree.ElementTree from utils import unescape #adding to favorites involve 3 steps: # 1.) add the favorite via jsonrpc (script params not included) # 2.) modify the favourites.xml to include script params <-- (kodi18 leia alpha1) i think there is another favourites file or this file is cached until another favorite is added # 3.) ??? <-- adding another favorite will delete the first one (until kodi is restarted) need to find a way for kodi to reload the modified favourite.xml #http://kodi.wiki/view/JSON-RPC_API/v8#Favourites #schema=xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "JSONRPC.Introspect", "id": 1}') #log(repr(schema)) favorite_was_found=False #add_dummy_favorite() temp_command='script.reddit.reader' #can't add script favorites with parameter using jsonrpc saved_command='RunScript("script.reddit.reader")' json_rpc_command={"jsonrpc": "2.0", "method": "Favourites.AddFavourite", 'params': { 'title': name, 'type': 'script', 'path': temp_command, 'thumbnail':thumbnail, }, 'id': '1' } a=xbmc.executeJSONRPC(json.dumps(json_rpc_command)) #log(repr(a)) a=json.loads(a) if a.get('result','')=="OK": log('Favourite added') #now that we've created the favorite, we edit it to add parameters favorites_xml = xbmc.translatePath(os.path.join(addon.getAddonInfo('profile'), '..','..','favourites.xml')) if os.path.exists(favorites_xml): #log('{0} exists'.format(favorites_xml) ) et = xml.etree.ElementTree.parse(favorites_xml) root=et.getroot() for f in root.findall('favourite'): #the name attribute is escape encoded the xml file. fav_name=unescape( f.get('name') ) #replaces & to & etc. fav_cmd=f.text #log('*a*'+repr(name) + ' ' + saved_command) #log('*b*'+repr(fav_name) + ' ' + fav_cmd ) #log('---') if (fav_name==name) and (fav_cmd==saved_command): log('Favourite entry found {0}'.format(fav_name) ) favorite_was_found=True f.text=command if favorite_was_found: et.write(favorites_xml) xbmc_notify(translation(32028), fav_name, icon=thumbnail)
def playYTDLVideo(url, name, type_): if pluginhandle==-1: xbmc_notify("Error","Attempt to use invalid handle -1") #saves the user from waiting return dialog_progress_title='Youtube_dl' #.format(ytdl_get_version_info()) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title ) dialog_progress_YTDL.update(10,dialog_progress_title,translation(30024) ) from YoutubeDLWrapper import YoutubeDLWrapper, _selectVideoQuality from urlparse import urlparse, parse_qs import pprint o = urlparse(url) query = parse_qs(o.query) video_index=0 if 'index' in query: try:video_index=int(query['index'][0]) except (TypeError, ValueError): video_index=0 dialog_progress_YTDL.update(20,dialog_progress_title,translation(30025) ) else: dialog_progress_YTDL.update(20,dialog_progress_title,translation(30022) ) ytdl=YoutubeDLWrapper() try: ydl_info=ytdl.extract_info(url, download=False) video_infos=_selectVideoQuality(ydl_info, quality=ytdl_quality, disable_dash=(not ytdl_DASH)) dialog_progress_YTDL.update(80,dialog_progress_title,translation(30023) ) if len(video_infos)>1: log(' ***ytdl link resolved to %d streams. playing #%d' %(len(video_infos), video_index)) li=ytdl_video_info_to_listitem(video_infos, video_index, name) xbmcplugin.setResolvedUrl(pluginhandle, True, li) except Exception as e: ytdl_ver=dialog_progress_title+' v'+ytdl_get_version_info('local') err_msg=str(e)+';' #ERROR: No video formats found; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest vers.... short_err=err_msg.split(';')[0] log( "playYTDLVideo Exception:" + str( sys.exc_info()[0]) + " " + str(e) ) xbmc_notify(ytdl_ver, short_err) log(' trying urlresolver...') playURLRVideo(url, name, type_) dialog_progress_YTDL.update(100,dialog_progress_title ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def reddit_save(api_method, post_id, type_): url=urlMain+api_method data = urllib.urlencode({'id' : post_id }) response=reddit_request( url,data ) log(repr(response)) if response=='{}': xbmc_notify(api_method, 'Success') if api_method=='/api/unsave/': xbmc.executebuiltin('XBMC.Container.Refresh') else: xbmc_notify(api_method, response)
def reddit_save(api_method, post_id, type_): #api_method either /api/save/ or /api/unsave/ url = urlMain + api_method data = urllib.urlencode({'id': post_id}) response = reddit_request(url, data) log(repr(response)) if response == '{}': xbmc_notify(api_method, 'Success') if api_method == '/api/unsave/': xbmc.executebuiltin('XBMC.Container.Refresh') else: xbmc_notify(api_method, response)
def delete_setting_file(url, name, action_type): #log( "delete setting file:" + action_type) if action_type == 'requests_cache': file_to_delete = CACHE_FILE + '.sqlite' elif action_type == 'icons_cache': file_to_delete = subredditsPickle elif action_type == 'subreddits_setting': file_to_delete = subredditsFile try: os.remove(file_to_delete) xbmc_notify("Deleting", '..' + file_to_delete[-30:]) except OSError as e: xbmc_notify("Error:", str(e))
def delete_setting_file(url,name,action_type): #log( "delete setting file:" + action_type) if action_type=='requests_cache': file_to_delete=CACHE_FILE+'.sqlite' elif action_type=='icons_cache': file_to_delete=subredditsPickle elif action_type=='subreddits_setting': file_to_delete=subredditsFile try: os.remove(file_to_delete) xbmc_notify("Deleting", '..'+file_to_delete[-30:]) except OSError as e: xbmc_notify("Error:", str(e))
def listRelatedVideo(url,name,type_): #type_: 'channel' -other videos in the channel # 'related' -related videos #only youtube is supported for now from domains import ClassYoutube from domains import parse_reddit_link, build_DirectoryItem_url_based_on_media_type match=re.compile( ClassYoutube.regex, re.I).findall( url ) if match: #log('***** isYouTubeable' + repr(link_url)) yt=ClassYoutube(url) links_dictList=yt.ret_album_list(type_) #returns a list of dict same as one used for albums if links_dictList: #log(pprint.pformat(links_dictList)) for _, d in enumerate(links_dictList): label=d.get('li_label') label2=d.get('li_label2') #li_iconImage=d.get('li_iconImage') ti=d.get('li_thumbnailImage') media_url=d.get('DirectoryItem_url') #media_type=d.get('type') #media_thumb=d.get('thumb') #isPlayable=d.get('isPlayable') #link_action=d.get('link_action') #channel_id=d.get('channel_id') #video_id=d.get('video_id') liz=xbmcgui.ListItem(label,label2) liz.setInfo( type='video', infoLabels=d['infoLabels'] ) #this tricks the skin to show the plot. where we stored the descriptions liz.setArt({"thumb": ti,'icon': ti, "poster":ti, "banner":ti, "fanart":ti, "landscape":ti }) #a little overkill considering we're only matching for youtube ld=parse_reddit_link(media_url) DirectoryItem_url, setProperty_IsPlayable, isFolder, _ = build_DirectoryItem_url_based_on_media_type(ld, media_url, '', '', script_to_call="") #directory_items.append( (url_for_DirectoryItem, liz, False,) ) liz.setProperty('IsPlayable', setProperty_IsPlayable) xbmcplugin.addDirectoryItem(pluginhandle, DirectoryItem_url, liz, isFolder) xbmcplugin.endOfDirectory(handle=pluginhandle, succeeded=True, updateListing=False, #setting this to True causes the ".." entry to quit the plugin cacheToDisc=True) else: xbmc_notify('Nothing to list', url) else: xbmc_notify('cannot identify youtube url', url)
def listMoreVideo(google_api_request_url,label_name,type_): from domains import ClassYoutube from utils import safe_cast #https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&type=video&maxResults=50&key=AIzaSyCqvYW8NI-OpMPaWR1DuZYW_llpmFdHRBI&playlistId=PLJ8cMiYb3G5eJquaiw6Xlyt3Qhe-3e7Xh yt=ClassYoutube(google_api_request_url)#this will be a broken class because it won't be able to parse just_numbers_from_label=re.sub("[^0-9]", "", label_name) #Removes all non-numeric characters "Page 2" becomes "2" page_indicator=safe_cast(just_numbers_from_label,int,default=0) links=yt.get_video_list(None,None,google_api_request_url,page_indicator) yt.assemble_images_dictList(links) links_dictList=yt.dictList if links_dictList: dictlist_to_RelatedVideo_gui(links_dictList, google_api_request_url, 'more', label_name, type_) else: xbmc_notify('Nothing to list', google_api_request_url)
def reddit_get_refresh_token(url, name, type_): code = addon.getSetting("reddit_code") if reddit_refresh_token and code: dialog = xbmcgui.Dialog() if dialog.yesno(translation(30411), translation(30412), translation(30413), translation(30414) ): pass else: return try: log( "Requesting a reddit permanent token with code=" + code ) req = urllib2.Request('https://www.reddit.com/api/v1/access_token') data = urllib.urlencode({'grant_type' : 'authorization_code' ,'code' : code #'woX9CDSuw7XBg1MiDUnTXXQd0e4' ,'redirect_uri': reddit_redirect_uri}) #http://localhost:8090/ import base64 base64string = base64.encodestring('%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization',"Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response=page.read();page.close() log( response ) status=reddit_set_addon_setting_from_response(response) if status=='ok': r1="Click 'OK' when done" r2="Settings will not be saved" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( r1, r2) ) else: r2="Requesting a reddit permanent token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( status, r2) ) except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
def addSubreddit(subreddit, name, type_): from utils import colored_subreddit from reddit import this_is_a_multireddit, format_multihub alreadyIn = False with open(subredditsFile, 'r') as fh: content = fh.readlines() if subreddit: for line in content: if line.lower() == subreddit.lower(): alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit + '\n') get_subreddit_entry_info(subreddit) xbmc_notify(colored_subreddit(subreddit), translation(30019)) else: #dialog = xbmcgui.Dialog() #ok = dialog.ok('Add subreddit', 'Add a subreddit (videos)','or Multiple subreddits (music+listentothis)','or Multireddit (/user/.../m/video)') #would be great to have some sort of help to show first time user here keyboard = xbmc.Keyboard('', translation(30001)) keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): subreddit = keyboard.getText() #cleanup user input. make sure /user/ and /m/ is lowercase if this_is_a_multireddit(subreddit): subreddit = format_multihub(subreddit) else: get_subreddit_entry_info(subreddit) for line in content: if line.lower() == subreddit.lower() + "\n": alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit + '\n') xbmc.executebuiltin("Container.Refresh")
def addSubreddit(subreddit, name, type_): from utils import colored_subreddit from reddit import this_is_a_multireddit, format_multihub alreadyIn = False with open(subredditsFile, 'r') as fh: content = fh.readlines() if subreddit: for line in content: if line.lower()==subreddit.lower(): alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit+'\n') get_subreddit_entry_info(subreddit) xbmc_notify(colored_subreddit(subreddit), translation(32019) ) else: #dialog = xbmcgui.Dialog() #ok = dialog.ok('Add subreddit', 'Add a subreddit (videos)','or Multiple subreddits (music+listentothis)','or Multireddit (/user/.../m/video)') #would be great to have some sort of help to show first time user here keyboard = xbmc.Keyboard('', translation(32001)) keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): subreddit = keyboard.getText() #cleanup user input. make sure /user/ and /m/ is lowercase if this_is_a_multireddit(subreddit): subreddit = format_multihub(subreddit) else: get_subreddit_entry_info(subreddit) for line in content: if line.lower()==subreddit.lower()+"\n": alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit+'\n') xbmc.executebuiltin("Container.Refresh")
def listAlbum(album_url, name, type_): from slideshow import slideshowAlbum from domains import sitesManager log(" listAlbum:"+album_url) hoster = sitesManager( album_url ) #log( ' %s %s ' %(hoster.__class__.__name__, album_url ) ) if hoster: dictlist=hoster.ret_album_list(album_url) if type_=='return_dictlist': #used in autoSlideshow return dictlist if not dictlist: xbmc_notify(translation(32200), translation(32055)) #slideshow, no playable items return #log(pprint.pformat(dictlist)) if addon.getSetting('use_slideshow_for_album') == 'true': slideshowAlbum( dictlist, name ) else: display_album_from( dictlist, name )
def listAlbum(album_url, name, type_): from slideshow import slideshowAlbum from domains import sitesManager log(" listAlbum:"+album_url) hoster = sitesManager( album_url ) if hoster: dictlist=hoster.ret_album_list(album_url) if type_=='return_dictlist': #used in autoSlideshow return dictlist if not dictlist: xbmc_notify(translation(32200),translation(32055)) #slideshow, no playable items return if addon.getSetting('use_slideshow_for_album') == 'true': slideshowAlbum( dictlist, name ) else: display_album_from( dictlist, name )
def listRelatedVideo(url,name,type_): from domains import ClassYoutube from domains import parse_reddit_link, build_DirectoryItem_url_based_on_media_type match=re.compile( ClassYoutube.regex, re.I).findall( url ) if match: yt=ClassYoutube(url) links_dictList=yt.ret_album_list(type_) #returns a list of dict same as one used for albums if links_dictList: for _, d in enumerate(links_dictList): label=d.get('li_label') label2=d.get('li_label2') ti=d.get('li_thumbnailImage') media_url=d.get('DirectoryItem_url') liz=xbmcgui.ListItem(label,label2) liz.setInfo( type='video', infoLabels=d['infoLabels'] ) #this tricks the skin to show the plot. where we stored the descriptions liz.setArt({"thumb": ti,'icon': ti, "poster":ti, "banner":ti, "fanart":ti, "landscape":ti }) ld=parse_reddit_link(media_url) DirectoryItem_url, setProperty_IsPlayable, isFolder, _ = build_DirectoryItem_url_based_on_media_type(ld, media_url, '', '', script_to_call="") liz.setProperty('IsPlayable', setProperty_IsPlayable) xbmcplugin.addDirectoryItem(pluginhandle, DirectoryItem_url, liz, isFolder) xbmcplugin.endOfDirectory(handle=pluginhandle, succeeded=True, updateListing=False, #setting this to True causes the ".." entry to quit the plugin cacheToDisc=True) else: xbmc_notify('Nothing to list', url) else: xbmc_notify('cannot identify youtube url', url)
def addSubreddit(subreddit, name, type_): from utils import colored_subreddit from reddit import this_is_a_multireddit, format_multihub alreadyIn = False with open(subredditsFile, 'r') as fh: content = fh.readlines() if subreddit: for line in content: if line.lower()==subreddit.lower(): alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit+'\n') get_subreddit_entry_info(subreddit) xbmc_notify(colored_subreddit(subreddit), translation(30019)) else: keyboard = xbmc.Keyboard('', translation(30001)) keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): subreddit = keyboard.getText() if this_is_a_multireddit(subreddit): subreddit = format_multihub(subreddit) else: get_subreddit_entry_info(subreddit) for line in content: if line.lower()==subreddit.lower()+"\n": alreadyIn = True if not alreadyIn: with open(subredditsFile, 'a') as fh: fh.write(subreddit+'\n') xbmc.executebuiltin("Container.Refresh")
def playYTDLVideoOLD(url, name, type_): from urlparse import urlparse parsed_uri = urlparse( url ) domain = '{uri.netloc}'.format(uri=parsed_uri) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create('YTDL' ) dialog_progress_YTDL.update(10,'YTDL','Checking link...' ) try: from domains import ydtl_get_playable_url stream_url = ydtl_get_playable_url(url) if stream_url: dialog_progress_YTDL.update(80,'YTDL', 'Playing' ) listitem = xbmcgui.ListItem(path=stream_url[0]) #plugins play video like this. xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: dialog_progress_YTDL.update(40,'YTDL', 'Trying URLResolver' ) log('YTDL Unable to get playable URL, Trying UrlResolver...' ) media_url = urlresolver.resolve(url) if media_url: dialog_progress_YTDL.update(88,'YTDL', 'Playing' ) listitem = xbmcgui.ListItem(path=media_url) xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: log('UrlResolver cannot get a playable url' ) xbmc_notify(translation(30192), domain) except Exception as e: xbmc_notify("%s(YTDL)"% domain,str(e)) finally: dialog_progress_YTDL.update(100,'YTDL' ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def listRelatedVideo(url,name,type_): #type_: 'channel' -other videos in the channel # 'related' -related videos #only youtube is supported for now from domains import ClassYoutube import requests #log('*****name='+repr(name)) links_dictList=[] match=re.compile( ClassYoutube.regex, re.I).findall( url ) if match: #log('***** isYouTubeable' + repr(url)) yt=ClassYoutube(url) try: yt.get_thumb_url() poster=yt.poster_url #log(' thung:'+yt.thumb_url) url_type,_=yt.get_video_channel_user_or_playlist_id_from_url(url) #log(' listRelatedVideo:type_:{0} url_type:{1} url:{2}'.format(type_,url_type,url) ) xbmc_busy(True) if type_=='links_in_description': links_dictList=yt.get_links_in_description(return_channelID_only=False) elif type_=='search': keyboard = xbmc.Keyboard(name, translation(32529)) keyboard.doModal() if keyboard.isConfirmed() and keyboard.getText(): search_string=keyboard.getText() if search_string: links_dictList=yt.ret_album_list(type_,search_string) name=search_string #this shows up on the top of screen else: # 'channel' 'related default links_dictList=yt.ret_album_list(type_) #returns a list of dict same as one used for albums xbmc_busy(False) if links_dictList: dictlist_to_RelatedVideo_gui(links_dictList, url, url_type, name, type_, poster) else: xbmc_notify('Nothing to list', url) except (ValueError, requests.exceptions.RequestException) as e: xbmc_notify('Error', str(e)) finally: xbmc_busy(False) else: xbmc_notify('cannot identify youtube url', url)
def playYTDLVideoOLD(url, name, type_): #url = "http://www.youtube.com/watch?v=_yVv9dx88x0" #a youtube ID will work as well and of course you could pass the url of another site #url='https://www.youtube.com/shared?ci=W8n3GMW5RCY' #url='http://burningcamel.com/video/waster-blonde-amateur-gets-f****d' #url='http://www.3sat.de/mediathek/?mode=play&obj=51264' #url='http://www.4tube.com/videos/209271/hurry-f**k-i-bored' #url='http://www.pbs.org/newshour/rundown/cubas-elian-gonzalez-now-college-graduate/' #these checks done in around May 2016 #does not work: yourlust porntube xpornvid.com porndig.com thumbzilla.com eporner.com yuvutu.com p**n.com pornerbros.com f*x.com flyflv.com xstigma.com sexu.com 5min.com alphaporno.com # stickyxtube.com xxxbunker.com bdsmstreak.com jizzxman.com pornwebms.com pornurl.pw porness.tv openload.online pornworms.com fapgod.com porness.tv hvdporn.com pornmax.xyz xfig.net yobt.com # eroshare.com kalporn.com hdvideos.p**n dailygirlscute.com desianalporn.com indianxxxhd.com onlypron.com sherloxxx.com hdvideos.p**n x1xporn.com pornhvd.com lxxlx.com xrhub.com shooshtime.com # pornvil.com lxxlx.com redclip.xyz younow.com aniboom.com gotporn.com virtualtaboo.com 18porn.xyz vidshort.net fapxl.com vidmega.net freudbox.com bigtits.com xfapzap.com o****m.com # userporn.com hdpornstar.com moviesand.com chumleaf.com fucktube.com fookgle.com pornative.com dailee.com pornsharia.com f*x.com sluttyred.com pk5.net kuntfutube.com youpunish.com # vidxnet.com jizzbox.com bondagetube.tv spankingtube.tv pornheed.com pornwaiter.com lubetube.com porncor.com maxjizztube.com asianxtv.com analxtv.com yteenporn.com nurglestube.com yporn.tv # asiantubesex.com zuzandra.com moviesguy.com bustnow.com dirtydirtyangels.com yazum.com watchersweb.com voyeurweb.com zoig.com flingtube.com yourfreeporn.us foxgay.com goshgay.com # player.moviefap.com(www.moviefap.com works) nosvideo.com # also does not work (non p**n) # rutube.ru mail.ru afreeca.com nicovideo.jp videos.sapo.pt(many but not all) sciencestage.com vidoosh.tv metacafe.com vzaar.com videojug.com trilulilu.ro tudou.com video.yahoo.com blinkx.com blip.tv # blogtv.com brainpop.com crackle.com engagemedia.org expotv.com flickr.com fotki.com hulu.com lafango.com mefeedia.com motionpictur.com izlesene.com sevenload.com patas.in myvideo.de # vbox7.com 1tv.ru 1up.com 220.ro 24video.xxx 3sat.de 56.com adultswim.com atresplayer.com techchannel.att.com v.baidu.com azubu.tv www.bbc.co.uk/iplayer bet.com biobiochile.cl biqle.com # bloomberg.com/news/videos bpb.de bravotv.com byutv.org cbc.ca chirbit.com cloudtime.to(almost) cloudyvideos.com cracked.com crackle.com criterion.com ctv.ca culturebox.francetvinfo.fr # cultureunplugged.com cwtv.com daum.net dctp.tv democracynow.org douyutv.com dumpert.nl eitb.tv ex.fm fc-zenit.ru ikudonsubs.com akb48ma.com Flipagram.com ft.dk Formula1.com # fox.com/watch(few works) video.foxnews.com foxsports.com france2.fr franceculture.fr franceinter.fr francetv.fr/videos francetvinfo.fr giantbomb.com hbo.com History.com hitbox.tv # howcast.com HowStuffWorks.com hrt.hr iconosquare.com infoq.com ivi.ru kamcord.com/v video.kankan.com karrierevideos.at KrasView.ru hlamer.ru kuwo.cn la7.it laola1.tv le.com # media.ccc.de metacritic.com mitele.es moevideo.net,playreplay.net,videochart.net vidspot.net(might work, can't find recent post) movieclips.com mtv.de mtviggy.com muenchen.tv myspace.com # myvi.ru myvideo.de myvideo.ge 163.com netzkino.de nfb.ca nicovideo.jp videohive.net normalboots.com nowness.com ntr.nl nrk.no ntv.ru/video ocw.mit.edu odnoklassniki.ru/video # onet.tv onionstudios.com/videos openload.co orf.at parliamentlive.tv pbs.org # news site (can't find sample to test) # bleacherreport.com crooksandliars.com DailyMail.com channel5.com Funimation.com gamersyde.com gamespot.com gazeta.pl helsinki.fi hotnewhiphop.com lemonde.fr mnet.com motorsport.com MSN.com # n-tv.de ndr.de NDTV.com NextMedia.com noz.de # these sites have mixed media. can handle the video in these sites: # 20min.ch 5min.com archive.org Allocine.fr(added) br.de bt.no buzzfeed.com condenast.com firstpost.com gameinformer.com gputechconf.com heise.de HotStar.com(some play) lrt.lt natgeo.com # nbcsports.com patreon.com # 9c9media.com(no posts) #ytdl plays this fine but no video? #coub.com #supported but is an audio only site #acast.com AudioBoom.com audiomack.com bandcamp.com clyp.it democracynow.org? freesound.org hark.com hearthis.at hypem.com libsyn.com mixcloud.com #Minhateca.com.br(direct mp3) # # ytdl also supports these sites: # myvideo.co.za ? #bluegartr.com (gif) # behindkink.com (not sure) # facebook.com (need to work capturing only videos) # features.aol.com (inconsistent) # livestream.com (need to work capturing only videos) # mail.ru inconsistent(need to work capturing only videos) # miomio.tv(some play but most won't) # ooyala.com(some play but most won't) # # extractors=[] # from youtube_dl.extractor import gen_extractors # for ie in gen_extractors(): # #extractors.append(ie.IE_NAME) # try: # log("[%s] %s " %(ie.IE_NAME, ie._VALID_URL) ) # except Exception as e: # log( "zz " + str(e) ) # extractors.sort() # for n in extractors: log("'%s'," %n) from urlparse import urlparse parsed_uri = urlparse( url ) domain = '{uri.netloc}'.format(uri=parsed_uri) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create('YTDL' ) dialog_progress_YTDL.update(10,'YTDL','Checking link...' ) try: from domains import ydtl_get_playable_url stream_url = ydtl_get_playable_url(url) if stream_url: dialog_progress_YTDL.update(80,'YTDL', 'Playing' ) listitem = xbmcgui.ListItem(path=stream_url[0]) #plugins play video like this. xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: dialog_progress_YTDL.update(40,'YTDL', 'Trying URLResolver' ) log('YTDL Unable to get playable URL, Trying UrlResolver...' ) #ytdl seems better than urlresolver for getting the playable url... media_url = urlresolver.resolve(url) if media_url: dialog_progress_YTDL.update(88,'YTDL', 'Playing' ) #log( '------------------------------------------------urlresolver stream url ' + repr(media_url )) listitem = xbmcgui.ListItem(path=media_url) xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: log('UrlResolver cannot get a playable url' ) xbmc_notify(translation(30192), domain) except Exception as e: xbmc_notify("%s(YTDL)"% domain,str(e)) finally: dialog_progress_YTDL.update(100,'YTDL' ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def playYTDLVideo(url, name, type_): dialog_progress_title = 'Youtube_dl' #.format(ytdl_get_version_info()) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title) dialog_progress_YTDL.update(10, dialog_progress_title, translation(32014)) from YoutubeDLWrapper import YoutubeDLWrapper, _selectVideoQuality import pprint pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) pl.clear() dialog_progress_YTDL.update(20, dialog_progress_title, translation(32012)) #use YoutubeDLWrapper by ruuk to avoid bad file error ytdl = YoutubeDLWrapper() try: ydl_info = ytdl.extract_info(url, download=False) #in youtube_dl utils.py def unified_timestamp(date_str, day_first=True): # there was an error playing https://vimeo.com/14652586 # on line 1195: # change except ValueError: # to except (ValueError,TypeError): # this already fixed by ruuk magic. in YoutubeDLWrapper #log( "YoutubeDL extract_info:\n" + pprint.pformat(ydl_info, indent=1) ) #log('quality============='+repr(ytdl_quality)) #log('ytdl_DASH==========='+repr(ytdl_DASH)) video_infos = _selectVideoQuality(ydl_info, quality=ytdl_quality, disable_dash=(not ytdl_DASH)) #log( "video_infos:\n" + pprint.pformat(video_infos, indent=1, depth=5) ) dialog_progress_YTDL.update(80, dialog_progress_title, translation(32013)) for video_info in video_infos: url = video_info.get( 'xbmc_url' ) #there is also video_info.get('url') url without the |useragent... #url="d://mp4-live-mpd-AV-BS.mpd.xml" title = video_info.get('title') or name ytdl_format = video_info.get('ytdl_format') if ytdl_format: description = ytdl_format.get('description') #check if there is a time skip code try: start_time = ytdl_format.get( 'start_time', 0) #int(float(ytdl_format.get('start_time'))) except (ValueError, TypeError): start_time = 0 li = xbmcgui.ListItem(label=title, label2='', iconImage=video_info.get('thumbnail'), thumbnailImage=video_info.get('thumbnail'), path=url) li.setInfo(type="Video", infoLabels={ "Title": title, "plot": description }) li.setProperty('StartOffset', str(start_time)) pl.add(url, li) xbmc.Player().play(pl, windowed=False) #only use the time skip code if there is only one item in the playlist #if start_time and pl.size()==1: # xbmc.Player().seekTime(start_time) except Exception as e: ytdl_ver = dialog_progress_title + ' v' + ytdl_get_version_info( 'local') err_msg = str( e ) + ';' #ERROR: No video formats found; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest vers.... short_err = err_msg.split(';')[0] log("playYTDLVideo Exception:" + str(sys.exc_info()[0]) + " " + str(e)) xbmc_notify(ytdl_ver, short_err) #try urlresolver log(' trying urlresolver...') playURLRVideo(url, name, type_) finally: dialog_progress_YTDL.update( 100, dialog_progress_title ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def error_message(message, name, type_): if name: sub_msg = name #name is usually the title of the post else: sub_msg = translation(32021) #Parsing error xbmc_notify(message, sub_msg)
def error_message(message, name, type_): if name: sub_msg=name #name is usually the title of the post else: sub_msg=translation(32021) #Parsing error xbmc_notify(message, sub_msg)
def playYTDLVideo(url, name, type_): dialog_progress_title='Youtube_dl' #.format(ytdl_get_version_info()) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title ) dialog_progress_YTDL.update(10,dialog_progress_title,translation(32014) ) from YoutubeDLWrapper import YoutubeDLWrapper, _selectVideoQuality o = urlparse.urlparse(url) query = urlparse.parse_qs(o.query) video_index=0 #note that in domains.py youtube class will send a simplified url to avoid sending # https://www.youtube.com/watch?v=R6_dZhE-4bk&index=22&list=PLGJ6ezwqAB2a4RP8hWEWAGB9eT2bmaBsy (ytdl will parse around 90+ videos, takes a very long time) # http://youtube.com/v/R6_dZhE-4bk (will be faster) if 'index' in query: try:video_index=int(query['index'][0]) except (TypeError, ValueError): video_index=0 #log( repr(video_index) ) dialog_progress_YTDL.update(20,dialog_progress_title,translation(32017) ) else: #if there is index, link is likely a playlist, parsing will take a looooong time. # we move progress dialog here to differentiate dialog_progress_YTDL.update(20,dialog_progress_title,translation(32012) ) pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) pl.clear() #use YoutubeDLWrapper by ruuk to avoid bad file error ytdl=YoutubeDLWrapper() try: ydl_info=ytdl.extract_info(url, download=False) #in youtube_dl utils.py def unified_timestamp(date_str, day_first=True): # there was an error playing https://vimeo.com/14652586 # on line 1195: # change except ValueError: # to except (ValueError,TypeError): # this already fixed by ruuk magic. in YoutubeDLWrapper #log( "YoutubeDL extract_info:\n" + pprint.pformat(ydl_info, indent=1, depth=3) ) #log('quality============='+repr(ytdl_quality)) #log('ytdl_DASH==========='+repr(ytdl_DASH)) #link_type=ydl_info.get("_type") #entries=ydl_info.get('entries') video_infos=_selectVideoQuality(ydl_info, quality=ytdl_quality, disable_dash=(not ytdl_DASH) ) log( "video_infos:\n" + pprint.pformat(video_infos, indent=1, depth=3) ) dialog_progress_YTDL.update(80,dialog_progress_title,translation(32013) ) if video_index > 0: add_ytdl_video_info_to_playlist(video_infos[video_index-1], pl, name) else: for video_info in video_infos: add_ytdl_video_info_to_playlist(video_info, pl, name) if len(pl)>1: xbmc_notify("Multiple video", "{0} videos in playlist".format(len(pl))) xbmc.Player().play(pl, windowed=False) #only use the time skip code if there is only one item in the playlist #if start_time and pl.size()==1: # xbmc.Player().seekTime(start_time) except Exception as e: ytdl_ver=dialog_progress_title+' v'+ytdl_get_version_info('local') err_msg=str(e)+';' #ERROR: No video formats found; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest vers.... short_err=err_msg.split(';')[0] log( "playYTDLVideo Exception:" + str( sys.exc_info()[0]) + " " + str(e) ) xbmc_notify(ytdl_ver, short_err,icon='type_ytdl.png') #try urlresolver log(' trying urlresolver...') playURLRVideo(url, name, type_) finally: dialog_progress_YTDL.update(100,dialog_progress_title ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def listSubReddit(url, subreddit_key, type_): from guis import progressBG from utils import post_is_filtered_out, build_script, compose_list_item, xbmc_notify,prettify_reddit_query, set_query_field from reddit import reddit_request, has_multiple, assemble_reddit_filter_string, subreddit_icoheader_banner global GCXM_hasmultiplesubreddit, GCXM_actual_url_used_to_generate_these_posts,GCXM_reddit_query_of_this_gui,GCXM_hasmultipledomain,GCXM_hasmultipleauthor #the +'s got removed by url conversion title_bar_name=subreddit_key.replace(' ','+') if title_bar_name.startswith('?'): title_bar_name=prettify_reddit_query(title_bar_name) #log(" title_bar_name %s " %(title_bar_name) ) log("listSubReddit r/%s\n %s" %(title_bar_name,url) ) currentUrl = url icon=banner=header=None xbmc_busy() loading_indicator=progressBG('Loading...') loading_indicator.update(0,'Retrieving '+subreddit_key) content = reddit_request(url) loading_indicator.update(10,subreddit_key ) if not content: xbmc_busy(False) loading_indicator.end() #it is important to close xbmcgui.DialogProgressBG return threads = [] q_liz = Queue() #output queue (listitem) content = json.loads(content) #log("query returned %d items " % len(content['data']['children']) ) posts_count=len(content['data']['children']) filtered_out_posts=0 hms=has_multiple('subreddit', content['data']['children']) if hms==False: #r/random and r/randnsfw returns a random subreddit. we need to use the name of this subreddit for the "next page" link. try: g=content['data']['children'][0]['data']['subreddit'] except ValueError: g="" except IndexError: xbmc_busy(False) loading_indicator.end() #it is important to close xbmcgui.DialogProgressBG xbmc_notify("List Subreddit",translation(32022)) return if g: title_bar_name=g #preserve the &after string so that functions like play slideshow and play all videos can 'play' the correct page # extract the &after string from currentUrl -OR- send it with the 'type' argument when calling this function. currentUrl=assemble_reddit_filter_string('',g) + '&after=' + type_ #put subreddit icon/header in the GUI icon,banner,header=subreddit_icoheader_banner(g) GCXM_hasmultiplesubreddit=hms GCXM_hasmultipledomain=has_multiple('domain', content['data']['children']) GCXM_hasmultipleauthor=has_multiple('author', content['data']['children']) GCXM_actual_url_used_to_generate_these_posts=url GCXM_reddit_query_of_this_gui=currentUrl for idx, entry in enumerate(content['data']['children']): try: if post_is_filtered_out( entry.get('data') ): filtered_out_posts+=1 continue domain,domain_count=count_links_from_same_domain( entry ) #count how many same domains we're hitting delay=compute_anti_dos_delay(domain,domain_count) #have threads process each reddit post t = threading.Thread(target=reddit_post_worker, args=(idx, entry,q_liz,delay), name='#t%.2d'%idx) threads.append(t) t.start() except Exception as e: log(" EXCEPTION:="+ str( sys.exc_info()[0]) + " " + str(e) ) log( repr(domains_d) ) #check the queue to determine progress break_counter=0 #to avoid infinite loop expected_listitems=(posts_count-filtered_out_posts) if expected_listitems>0: loading_indicator.set_tick_total(expected_listitems) last_queue_size=0 while q_liz.qsize() < expected_listitems: if break_counter>=500: #log('break counter reached limit') break #each change in the queue size gets a tick on our progress track if last_queue_size < q_liz.qsize(): items_added=q_liz.qsize()-last_queue_size loading_indicator.tick(items_added) else: break_counter+=1 last_queue_size=q_liz.qsize() xbmc.sleep(100) #wait for all threads to finish before collecting the list items for idx, t in enumerate(threads): #log(' joining %s' %t.getName()) t.join(timeout=20) #<-- does not seem to work xbmc_busy(False) #compare the number of entries to the returned results #log( "queue:%d entries:%d" %( q_liz.qsize() , len(content['data']['children'] ) ) ) if q_liz.qsize() != expected_listitems: #some post might be filtered out. log('some threads did not return a listitem') #for t in threads: log('isAlive %s %s' %(t.getName(), repr(t.isAlive()) ) ) #liu=[ qi for qi in sorted(q_liz.queue) ] li=[ liz for idx,liz in sorted(q_liz.queue) ] #empty the queue. with q_liz.mutex: q_liz.queue.clear() loading_indicator.end() #it is important to close xbmcgui.DialogProgressBG try: #this part makes sure that you load the next page instead of just the first after=content['data']['after'] o = urlparse.urlparse(currentUrl) current_url_query = urlparse.parse_qs(o.query) count=current_url_query.get('count') if current_url_query.get('count')==None: #firsttime it is none count=itemsPerPage else: #nexttimes it will be kept incremented with itemsPerPage try: count=int(current_url_query.get('count')[0]) + int(itemsPerPage) except ValueError: count=itemsPerPage nextUrl=set_query_field(currentUrl,'count', count, True) #log('$$$ nextUrl: ' +nextUrl) nextUrl=set_query_field(nextUrl, field='after', value=after, replace=True) #(url, field, value, replace=False): #log('$$$currenturl: ' +currentUrl) #log('$$$ nextUrl: ' +nextUrl) liz = compose_list_item( translation(32024), "", "DefaultFolderNextSquare.png", "script", build_script("listSubReddit",nextUrl,title_bar_name,after) ) #for items at the bottom left corner liz.setArt({ "clearart": "DefaultFolderNextSquare.png" }) liz.setInfo(type='video', infoLabels={"Studio":translation(32024)}) liz.setProperty('link_url', nextUrl ) li.append(liz) except Exception as e: log(" EXCEPTzION:="+ str( sys.exc_info()[0]) + " " + str(e) ) xbmc_busy(False) title_bar_name=urllib.unquote_plus(title_bar_name) ui=skin_launcher('listSubReddit', title_bar_name=title_bar_name, listing=li, subreddits_file=subredditsFile, currentUrl=currentUrl, icon=icon, banner=banner, header=header) ui.doModal() del ui
def playYTDLVideo(url, name, type_): if pluginhandle==-1: xbmc_notify("Error","Attempt to use invalid handle -1") #saves the user from waiting return dialog_progress_title='Youtube_dl' #.format(ytdl_get_version_info()) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title ) dialog_progress_YTDL.update(10,dialog_progress_title,translation(30024) ) from YoutubeDLWrapper import YoutubeDLWrapper, _selectVideoQuality from urlparse import urlparse, parse_qs import pprint o = urlparse(url) query = parse_qs(o.query) video_index=0 #note that in domains.py youtube class will send a simplified url to avoid sending # https://www.youtube.com/watch?v=R6_dZhE-4bk&index=22&list=PLGJ6ezwqAB2a4RP8hWEWAGB9eT2bmaBsy (ytdl will parse around 90+ videos, takes a very long time) # http://youtube.com/v/R6_dZhE-4bk (will be faster) if 'index' in query: try:video_index=int(query['index'][0]) except (TypeError, ValueError): video_index=0 #log( repr(video_index) ) dialog_progress_YTDL.update(20,dialog_progress_title,translation(30025) ) else: #if there is index, link is likely a playlist, parsing will take a looooong time. # we move progress dialog here to differentiate dialog_progress_YTDL.update(20,dialog_progress_title,translation(30022) ) #use YoutubeDLWrapper by ruuk to avoid bad file error ytdl=YoutubeDLWrapper() try: ydl_info=ytdl.extract_info(url, download=False) #in youtube_dl utils.py def unified_timestamp(date_str, day_first=True): # there was an error playing https://vimeo.com/14652586 # on line 1195: # change except ValueError: # to except (ValueError,TypeError): # this already fixed by ruuk magic. in YoutubeDLWrapper #log( "YoutubeDL extract_info:\n" + pprint.pformat(ydl_info, indent=1) ) video_infos=_selectVideoQuality(ydl_info, quality=ytdl_quality, disable_dash=(not ytdl_DASH)) #log( "video_infos:\n" + pprint.pformat(video_infos, indent=1, depth=3) ) dialog_progress_YTDL.update(80,dialog_progress_title,translation(30023) ) if len(video_infos)>1: log(' ***ytdl link resolved to %d streams. playing #%d' %(len(video_infos), video_index)) #xbmc_notify("Multiple video", "{} videos in playlist".format(len(pl))) li=ytdl_video_info_to_listitem(video_infos, video_index, name) xbmcplugin.setResolvedUrl(pluginhandle, True, li) except Exception as e: ytdl_ver=dialog_progress_title+' v'+ytdl_get_version_info('local') err_msg=str(e)+';' #ERROR: No video formats found; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest vers.... short_err=err_msg.split(';')[0] log( "playYTDLVideo Exception:" + str( sys.exc_info()[0]) + " " + str(e) ) xbmc_notify(ytdl_ver, short_err) #try urlresolver log(' trying urlresolver...') playURLRVideo(url, name, type_) # finally: dialog_progress_YTDL.update(100,dialog_progress_title ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def listRelatedVideo(url, name, type_): #type_: 'channel' -other videos in the channel # 'related' -related videos #only youtube is supported for now from domains import ClassYoutube from domains import parse_reddit_link, build_DirectoryItem_url_based_on_media_type match = re.compile(ClassYoutube.regex, re.I).findall(url) if match: #log('***** isYouTubeable' + repr(link_url)) yt = ClassYoutube(url) links_dictList = yt.ret_album_list( type_) #returns a list of dict same as one used for albums if links_dictList: #log(pprint.pformat(links_dictList)) for _, d in enumerate(links_dictList): label = d.get('li_label') label2 = d.get('li_label2') #li_iconImage=d.get('li_iconImage') ti = d.get('li_thumbnailImage') media_url = d.get('DirectoryItem_url') #media_type=d.get('type') #media_thumb=d.get('thumb') #isPlayable=d.get('isPlayable') #link_action=d.get('link_action') #channel_id=d.get('channel_id') #video_id=d.get('video_id') liz = xbmcgui.ListItem(label, label2) liz.setInfo( type='video', infoLabels=d['infoLabels'] ) #this tricks the skin to show the plot. where we stored the descriptions liz.setArt({ "thumb": ti, 'icon': ti, "poster": ti, "banner": ti, "fanart": ti, "landscape": ti }) #a little overkill considering we're only matching for youtube ld = parse_reddit_link(media_url) DirectoryItem_url, setProperty_IsPlayable, isFolder, _ = build_DirectoryItem_url_based_on_media_type( ld, media_url, '', '', script_to_call="") #directory_items.append( (url_for_DirectoryItem, liz, False,) ) liz.setProperty('IsPlayable', setProperty_IsPlayable) xbmcplugin.addDirectoryItem(pluginhandle, DirectoryItem_url, liz, isFolder) xbmcplugin.endOfDirectory( handle=pluginhandle, succeeded=True, updateListing= False, #setting this to True causes the ".." entry to quit the plugin cacheToDisc=True) else: xbmc_notify('Nothing to list', url) else: xbmc_notify('cannot identify youtube url', url)
req.add_header('Authorization','bearer '+ reddit_access_token ) try: log(" 2nd attempt:"+ url) page = urllib2.urlopen(req) #it has to be https:// not http:// response=page.read();page.close() return response except urllib2.HTTPError, err: xbmc.executebuiltin('XBMC.Notification("%s %s", "%s" )' %( err.code, err.msg, url) ) log( err.reason ) except urllib2.URLError, err: log( err.reason ) else: log( "*** failed to get new access token - don't know what to do " ) xbmc_notify("%s %s" %( err.code, err.msg), url) except urllib2.URLError, err: # Not an HTTP-specific error (e.g. connection refused) xbmc_notify(err.reason, url) except : pass def reddit_get_refresh_token(url, name, type_): code = addon.getSetting("reddit_code") if reddit_refresh_token and code: dialog = xbmcgui.Dialog() if dialog.yesno(translation(30411), translation(30412), translation(30413), translation(30414) ): pass
def playYTDLVideoOLD(url, name, type_): #url = "http://www.youtube.com/watch?v=_yVv9dx88x0" #a youtube ID will work as well and of course you could pass the url of another site #url='https://www.youtube.com/shared?ci=W8n3GMW5RCY' #url='http://burningcamel.com/video/waster-blonde-amateur-gets-f****d' #url='http://www.3sat.de/mediathek/?mode=play&obj=51264' #url='http://www.4tube.com/videos/209271/hurry-f**k-i-bored' #url='http://www.pbs.org/newshour/rundown/cubas-elian-gonzalez-now-college-graduate/' #these checks done in around May 2016 #does not work: yourlust porntube xpornvid.com porndig.com thumbzilla.com eporner.com yuvutu.com p**n.com pornerbros.com f*x.com flyflv.com xstigma.com sexu.com 5min.com alphaporno.com # stickyxtube.com xxxbunker.com bdsmstreak.com jizzxman.com pornwebms.com pornurl.pw porness.tv openload.online pornworms.com fapgod.com porness.tv hvdporn.com pornmax.xyz xfig.net yobt.com # eroshare.com kalporn.com hdvideos.p**n dailygirlscute.com desianalporn.com indianxxxhd.com onlypron.com sherloxxx.com hdvideos.p**n x1xporn.com pornhvd.com lxxlx.com xrhub.com shooshtime.com # pornvil.com lxxlx.com redclip.xyz younow.com aniboom.com gotporn.com virtualtaboo.com 18porn.xyz vidshort.net fapxl.com vidmega.net freudbox.com bigtits.com xfapzap.com o****m.com # userporn.com hdpornstar.com moviesand.com chumleaf.com fucktube.com fookgle.com pornative.com dailee.com pornsharia.com f*x.com sluttyred.com pk5.net kuntfutube.com youpunish.com # vidxnet.com jizzbox.com bondagetube.tv spankingtube.tv pornheed.com pornwaiter.com lubetube.com porncor.com maxjizztube.com asianxtv.com analxtv.com yteenporn.com nurglestube.com yporn.tv # asiantubesex.com zuzandra.com moviesguy.com bustnow.com dirtydirtyangels.com yazum.com watchersweb.com voyeurweb.com zoig.com flingtube.com yourfreeporn.us foxgay.com goshgay.com # player.moviefap.com(www.moviefap.com works) nosvideo.com # also does not work (non p**n) # rutube.ru mail.ru afreeca.com nicovideo.jp videos.sapo.pt(many but not all) sciencestage.com vidoosh.tv metacafe.com vzaar.com videojug.com trilulilu.ro tudou.com video.yahoo.com blinkx.com blip.tv # blogtv.com brainpop.com crackle.com engagemedia.org expotv.com flickr.com fotki.com hulu.com lafango.com mefeedia.com motionpictur.com izlesene.com sevenload.com patas.in myvideo.de # vbox7.com 1tv.ru 1up.com 220.ro 24video.xxx 3sat.de 56.com adultswim.com atresplayer.com techchannel.att.com v.baidu.com azubu.tv www.bbc.co.uk/iplayer bet.com biobiochile.cl biqle.com # bloomberg.com/news/videos bpb.de bravotv.com byutv.org cbc.ca chirbit.com cloudtime.to(almost) cloudyvideos.com cracked.com crackle.com criterion.com ctv.ca culturebox.francetvinfo.fr # cultureunplugged.com cwtv.com daum.net dctp.tv democracynow.org douyutv.com dumpert.nl eitb.tv ex.fm fc-zenit.ru ikudonsubs.com akb48ma.com Flipagram.com ft.dk Formula1.com # fox.com/watch(few works) video.foxnews.com foxsports.com france2.fr franceculture.fr franceinter.fr francetv.fr/videos francetvinfo.fr giantbomb.com hbo.com History.com hitbox.tv # howcast.com HowStuffWorks.com hrt.hr iconosquare.com infoq.com ivi.ru kamcord.com/v video.kankan.com karrierevideos.at KrasView.ru hlamer.ru kuwo.cn la7.it laola1.tv le.com # media.ccc.de metacritic.com mitele.es moevideo.net,playreplay.net,videochart.net vidspot.net(might work, can't find recent post) movieclips.com mtv.de mtviggy.com muenchen.tv myspace.com # myvi.ru myvideo.de myvideo.ge 163.com netzkino.de nfb.ca nicovideo.jp videohive.net normalboots.com nowness.com ntr.nl nrk.no ntv.ru/video ocw.mit.edu odnoklassniki.ru/video # onet.tv onionstudios.com/videos openload.co orf.at parliamentlive.tv pbs.org # news site (can't find sample to test) # bleacherreport.com crooksandliars.com DailyMail.com channel5.com Funimation.com gamersyde.com gamespot.com gazeta.pl helsinki.fi hotnewhiphop.com lemonde.fr mnet.com motorsport.com MSN.com # n-tv.de ndr.de NDTV.com NextMedia.com noz.de # these sites have mixed media. can handle the video in these sites: # 20min.ch 5min.com archive.org Allocine.fr(added) br.de bt.no buzzfeed.com condenast.com firstpost.com gameinformer.com gputechconf.com heise.de HotStar.com(some play) lrt.lt natgeo.com # nbcsports.com patreon.com # 9c9media.com(no posts) #ytdl plays this fine but no video? #coub.com #supported but is an audio only site #acast.com AudioBoom.com audiomack.com bandcamp.com clyp.it democracynow.org? freesound.org hark.com hearthis.at hypem.com libsyn.com mixcloud.com #Minhateca.com.br(direct mp3) # # ytdl also supports these sites: # myvideo.co.za ? #bluegartr.com (gif) # behindkink.com (not sure) # facebook.com (need to work capturing only videos) # features.aol.com (inconsistent) # livestream.com (need to work capturing only videos) # mail.ru inconsistent(need to work capturing only videos) # miomio.tv(some play but most won't) # ooyala.com(some play but most won't) # # extractors=[] # from youtube_dl.extractor import gen_extractors # for ie in gen_extractors(): # #extractors.append(ie.IE_NAME) # try: # log("[%s] %s " %(ie.IE_NAME, ie._VALID_URL) ) # except Exception as e: # log( "zz " + str(e) ) # extractors.sort() # for n in extractors: log("'%s'," %n) from urlparse import urlparse parsed_uri = urlparse(url) domain = '{uri.netloc}'.format(uri=parsed_uri) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create('YTDL') dialog_progress_YTDL.update(10, 'YTDL', 'Checking link...') try: from domains import ydtl_get_playable_url stream_url = ydtl_get_playable_url(url) if stream_url: dialog_progress_YTDL.update(80, 'YTDL', 'Playing') listitem = xbmcgui.ListItem( path=stream_url[0]) #plugins play video like this. xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: dialog_progress_YTDL.update(40, 'YTDL', 'Trying URLResolver') log('YTDL Unable to get playable URL, Trying UrlResolver...') #ytdl seems better than urlresolver for getting the playable url... media_url = urlresolver.resolve(url) if media_url: dialog_progress_YTDL.update(88, 'YTDL', 'Playing') #log( '------------------------------------------------urlresolver stream url ' + repr(media_url )) listitem = xbmcgui.ListItem(path=media_url) xbmcplugin.setResolvedUrl(pluginhandle, True, listitem) else: log('UrlResolver cannot get a playable url') xbmc_notify(translation(30192), domain) except Exception as e: xbmc_notify("%s(YTDL)" % domain, str(e)) finally: dialog_progress_YTDL.update( 100, 'YTDL' ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def reddit_get_refresh_token(url, name, type_): #this function gets a refresh_token from reddit and keep it in our addon. this refresh_token is used to get 1-hour access tokens. # getting a refresh_token is a one-time step #1st: use any webbrowser to # https://www.reddit.com/api/v1/authorize?client_id=hXEx62LGqxLj8w&response_type=code&state=RS&redirect_uri=http://localhost:8090/&duration=permanent&scope=read,mysubreddits #2nd: click allow and copy the code provided after reddit redirects the user # save this code in add-on settings. A one-time use code that may be exchanged for a bearer token. code = addon.getSetting("reddit_code") #log(" user refresh token:"+reddit_refresh_token) #log(" user code:"+code) if reddit_refresh_token and code: #log(" user already have refresh token:"+reddit_refresh_token) dialog = xbmcgui.Dialog() if dialog.yesno(translation(30411), translation(30412), translation(30413), translation(30414) ): pass else: return try: log( "Requesting a reddit permanent token with code=" + code ) req = urllib2.Request('https://www.reddit.com/api/v1/access_token') #http://stackoverflow.com/questions/6348499/making-a-post-call-instead-of-get-using-urllib2 data = urllib.urlencode({'grant_type' : 'authorization_code' ,'code' : code #'woX9CDSuw7XBg1MiDUnTXXQd0e4' ,'redirect_uri': reddit_redirect_uri}) #http://localhost:8090/ #http://stackoverflow.com/questions/2407126/python-urllib2-basic-auth-problem import base64 base64string = base64.encodestring('%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization',"Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response=page.read();page.close() log( response ) status=reddit_set_addon_setting_from_response(response) if status=='ok': r1="Click 'OK' when done" r2="Settings will not be saved" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( r1, r2) ) else: r2="Requesting a reddit permanent token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" %( status, r2) ) # This is a 2nd option reddit oauth. user needs to request access token every hour # #user enters this on their webbrowser. note that there is no duration=permanent response_type=token instead of code # request_url='https://www.reddit.com/api/v1/authorize?client_id=hXEx62LGqxLj8w&response_type=token&state=RS&redirect_uri=http://localhost:8090/&scope=read,identity' # #click on "Allow" # #copy the redirect url code #enters it on settings. e.g.: LVQu8vitbEXfMPcK1sGlVVQZEpM # # #u='https://oauth.reddit.com/new.json' # u='https://oauth.reddit.com//api/v1/me.json' # # req = urllib2.Request(u) # #req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14') # req.add_header('User-Agent', reddit_userAgent) # req.add_header('Authorization','bearer LVQu8vitbEXfMPcK1sGlVVQZEpM') # page = read,identity.urlopen(req) # response=page.read();page.close() except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
req) #it has to be https:// not http:// response = page.read() page.close() return response except urllib2.HTTPError, err: xbmc.executebuiltin('XBMC.Notification("%s %s", "%s" )' % (err.code, err.msg, url)) log(err.reason) except urllib2.URLError, err: log(err.reason) else: log("*** failed to get new access token - don't know what to do " ) xbmc_notify("%s %s" % (err.code, err.msg), url) except urllib2.URLError, err: # Not an HTTP-specific error (e.g. connection refused) xbmc_notify(err.reason, url) except: pass def reddit_get_refresh_token(url, name, type_): #this function gets a refresh_token from reddit and keep it in our addon. this refresh_token is used to get 1-hour access tokens. # getting a refresh_token is a one-time step #1st: use any webbrowser to # https://www.reddit.com/api/v1/authorize?client_id=hXEx62LGqxLj8w&response_type=code&state=RS&redirect_uri=http://localhost:8090/&duration=permanent&scope=read,mysubreddits #2nd: click allow and copy the code provided after reddit redirects the user # save this code in add-on settings. A one-time use code that may be exchanged for a bearer token. code = addon.getSetting("reddit_code")
def autoPlay(url, name, type_): from domains import sitesBase, parse_reddit_link, ydtl_get_playable_url from utils import unescape, post_is_filtered_out, strip_emoji,xbmc_busy, translation, xbmc_notify from reddit import reddit_request, determine_if_video_media_from_reddit_json from actions import setting_gif_repeat_count #collect a list of title and urls as entries[] from the j_entries obtained from reddit #then create a playlist from those entries #then play the playlist gif_repeat_count=setting_gif_repeat_count() entries = [] watchdog_counter=0 playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist.clear() xbmc_busy() content = reddit_request(url) if not content: return #log( str(content) ) #content = json.loads(content.replace('\\"', '\'')) content = json.loads(content) log("Autoplay %s - Parsing %d items" %( type_, len(content['data']['children']) ) ) for j_entry in content['data']['children']: try: title=unescape(j_entry['data']['title'].encode('utf-8')) title=strip_emoji(title) try: media_url = j_entry['data']['url'] except (AttributeError,TypeError,ValueError): media_url = j_entry['data']['media']['oembed']['url'] is_a_video = determine_if_video_media_from_reddit_json(j_entry) log(" %cTITLE:%s" %( ("v" if is_a_video else " "), title ) ) ld=parse_reddit_link(link_url=media_url, assume_is_video=False, needs_preview=False, get_playable_url=True ) if ld: log(' type:%s %s' %( ld.media_type, ld.link_action) ) if ld.media_type in [sitesBase.TYPE_VIDEO, sitesBase.TYPE_GIF, sitesBase.TYPE_VIDS, sitesBase.TYPE_MIXED]: if ld.media_type==sitesBase.TYPE_GIF: entries.append([title,ld.playable_url, sitesBase.DI_ACTION_PLAYABLE]) for _ in range( 0, gif_repeat_count ): entries.append([title,ld.playable_url, sitesBase.DI_ACTION_PLAYABLE]) else: entries.append([title,ld.playable_url, ld.link_action]) else: #log(' checking if ytdl supports %s' %media_url ) playable_video_url=ydtl_get_playable_url(media_url) if playable_video_url: for u in playable_video_url: entries.append([title, u, sitesBase.DI_ACTION_PLAYABLE]) except Exception as e: log( ' autoPlay exception:' + str(e) ) #for i,e in enumerate(entries): log(' e1-%d %s:' %(i, e[1]) ) #def k2(x): return x[1] #entries=remove_duplicates(entries, k2) #***disable removal of duplicates because it will also remove looping for gif videos #for i,e in enumerate(entries): log(' e2-%d %s:' %(i, e[1]) ) for i,e in enumerate(entries): try: log(' possible playable items(%.2d) %s...%s (%s)' %(i, e[0].ljust(15)[:15], e[1],e[2]) ) except: continue if len(entries)==0: xbmc_notify(translation(32025), translation(32026)) #Play All No playable items xbmc_busy(False) return entries_to_buffer=4 #log(' entries:%d buffer:%d' %( len(entries), entries_to_buffer ) ) if len(entries) < entries_to_buffer: entries_to_buffer=len(entries) #log('entries to buffer reduced to %d' %entries_to_buffer ) #for title, url in entries: # log(" added to playlist:"+ title + " " + url ) log("**********autoPlay*************") #play_list=[] ev = threading.Event() t = Worker(entries, q, ev) t.daemon = True t.start() #t.run() #wait for worker to finish processing 1st item #e.wait(200) while True: #log( ' c-wait+get buffer(%d) wdt=%d ' %(playlist.size(), watchdog_counter) ) try: #playable_url = q.get(True, 10) playable_entry = q.get(True, 10) #playable_url=playable_entry[1] q.task_done() #play_list.append(playable_entry[1]) playlist.add(playable_entry[1], xbmcgui.ListItem(playable_entry[0])) log( ' c-buffered(%d):%s...%s' %(playlist.size(), playable_entry[0].ljust(15)[:15], playable_entry[1]) ) except: watchdog_counter+=1 if ev.is_set():#p is done producing break #if got 3 empty from queue. pass watchdog_counter+=1 #log(' playlist:%d buffer:%d' %( playlist.size(), entries_to_buffer ) ) if playlist.size() >= entries_to_buffer: #q.qsize() log(' c-buffer count met') break if watchdog_counter > entries_to_buffer: break log(' c-buffering done') xbmc_busy(False) xbmc.Player().play(playlist) watchdog_counter=0 while True: #log( ' c-get buffer(%d) wdt=%d ' %(playlist.size(), watchdog_counter) ) #q.join() #log( ' c- join-ed, get... ' ) try: #playable_url = q.get(True,10) playable_entry = q.get(True,10) q.task_done() #log( ' c- got next item... ' + playable_entry[1] ) #play_list.append(playable_entry[1]) playlist.add(playable_entry[1], xbmcgui.ListItem(playable_entry[0])) log( ' c-got next item(%d):%s...%s' %(playlist.size(), playable_entry[0].ljust(15)[:15], playable_entry[1]) ) except: watchdog_counter+=1 if ev.isSet(): #p is done producing break pass #xbmc.PlayList(1).add(playable_url) if ev.isSet() and q.empty(): log( ' c- ev is set and q.empty --> break ' ) break if watchdog_counter > 2: break log( ' c-all done ' )
def error_message(message, name, type_): if name: sub_msg = name else: sub_msg = translation(30021) #Parsing error xbmc_notify(message, sub_msg)
def playYTDLVideo(url, name, type_): if pluginhandle == -1: xbmc_notify( "Error", "Attempt to use invalid handle -1") #saves the user from waiting return dialog_progress_title = 'Youtube_dl' #.format(ytdl_get_version_info()) dialog_progress_YTDL = xbmcgui.DialogProgressBG() dialog_progress_YTDL.create(dialog_progress_title) dialog_progress_YTDL.update(10, dialog_progress_title, translation(30024)) from YoutubeDLWrapper import YoutubeDLWrapper, _selectVideoQuality from urlparse import urlparse, parse_qs import pprint o = urlparse(url) query = parse_qs(o.query) video_index = 0 #note that in domains.py youtube class will send a simplified url to avoid sending # https://www.youtube.com/watch?v=R6_dZhE-4bk&index=22&list=PLGJ6ezwqAB2a4RP8hWEWAGB9eT2bmaBsy (ytdl will parse around 90+ videos, takes a very long time) # http://youtube.com/v/R6_dZhE-4bk (will be faster) if 'index' in query: try: video_index = int(query['index'][0]) except (TypeError, ValueError): video_index = 0 #log( repr(video_index) ) dialog_progress_YTDL.update(20, dialog_progress_title, translation(30025)) else: #if there is index, link is likely a playlist, parsing will take a looooong time. # we move progress dialog here to differentiate dialog_progress_YTDL.update(20, dialog_progress_title, translation(30022)) #use YoutubeDLWrapper by ruuk to avoid bad file error ytdl = YoutubeDLWrapper() try: ydl_info = ytdl.extract_info(url, download=False) #in youtube_dl utils.py def unified_timestamp(date_str, day_first=True): # there was an error playing https://vimeo.com/14652586 # on line 1195: # change except ValueError: # to except (ValueError,TypeError): # this already fixed by ruuk magic. in YoutubeDLWrapper #log( "YoutubeDL extract_info:\n" + pprint.pformat(ydl_info, indent=1) ) video_infos = _selectVideoQuality(ydl_info, quality=ytdl_quality, disable_dash=(not ytdl_DASH)) #log( "video_infos:\n" + pprint.pformat(video_infos, indent=1, depth=3) ) dialog_progress_YTDL.update(80, dialog_progress_title, translation(30023)) if len(video_infos) > 1: log(' ***ytdl link resolved to %d streams. playing #%d' % (len(video_infos), video_index)) #xbmc_notify("Multiple video", "{} videos in playlist".format(len(pl))) li = ytdl_video_info_to_listitem(video_infos, video_index, name) xbmcplugin.setResolvedUrl(pluginhandle, True, li) except Exception as e: ytdl_ver = dialog_progress_title + ' v' + ytdl_get_version_info( 'local') err_msg = str( e ) + ';' #ERROR: No video formats found; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest vers.... short_err = err_msg.split(';')[0] log("playYTDLVideo Exception:" + str(sys.exc_info()[0]) + " " + str(e)) xbmc_notify(ytdl_ver, short_err) #try urlresolver log(' trying urlresolver...') playURLRVideo(url, name, type_) # finally: dialog_progress_YTDL.update( 100, dialog_progress_title ) #not sure if necessary to set to 100 before closing dialogprogressbg dialog_progress_YTDL.close()
def error_message(message, name, type_): if name: sub_msg=name else: sub_msg=translation(30021) #Parsing error xbmc_notify(message,sub_msg)
def reddit_get_refresh_token(url, name, type_): #this function gets a refresh_token from reddit and keep it in our addon. this refresh_token is used to get 1-hour access tokens. # getting a refresh_token is a one-time step #1st: use any webbrowser to # https://www.reddit.com/api/v1/authorize?client_id=hXEx62LGqxLj8w&response_type=code&state=RS&redirect_uri=http://localhost:8090/&duration=permanent&scope=read,mysubreddits #2nd: click allow and copy the code provided after reddit redirects the user # save this code in add-on settings. A one-time use code that may be exchanged for a bearer token. code = addon.getSetting("reddit_code") #log(" user refresh token:"+reddit_refresh_token) #log(" user code:"+code) if reddit_refresh_token and code: #log(" user already have refresh token:"+reddit_refresh_token) dialog = xbmcgui.Dialog() if dialog.yesno(translation(30411), translation(30412), translation(30413), translation(30414)): pass else: return try: log("Requesting a reddit permanent token with code=" + code) req = urllib2.Request('https://www.reddit.com/api/v1/access_token') #http://stackoverflow.com/questions/6348499/making-a-post-call-instead-of-get-using-urllib2 data = urllib.urlencode({ 'grant_type': 'authorization_code', 'code': code #'woX9CDSuw7XBg1MiDUnTXXQd0e4' , 'redirect_uri': reddit_redirect_uri }) #http://localhost:8090/ #http://stackoverflow.com/questions/2407126/python-urllib2-basic-auth-problem import base64 base64string = base64.encodestring( '%s:%s' % (reddit_clientID, '')).replace('\n', '') req.add_header('Authorization', "Basic %s" % base64string) req.add_header('User-Agent', reddit_userAgent) page = urllib2.urlopen(req, data=data) response = page.read() page.close() log(response) status = reddit_set_addon_setting_from_response(response) if status == 'ok': r1 = "Click 'OK' when done" r2 = "Settings will not be saved" xbmc.executebuiltin("XBMC.Notification(%s, %s)" % (r1, r2)) else: r2 = "Requesting a reddit permanent token" xbmc.executebuiltin("XBMC.Notification(%s, %s)" % (status, r2)) # This is a 2nd option reddit oauth. user needs to request access token every hour # #user enters this on their webbrowser. note that there is no duration=permanent response_type=token instead of code # request_url='https://www.reddit.com/api/v1/authorize?client_id=hXEx62LGqxLj8w&response_type=token&state=RS&redirect_uri=http://localhost:8090/&scope=read,identity' # #click on "Allow" # #copy the redirect url code #enters it on settings. e.g.: LVQu8vitbEXfMPcK1sGlVVQZEpM # # #u='https://oauth.reddit.com/new.json' # u='https://oauth.reddit.com//api/v1/me.json' # # req = urllib2.Request(u) # #req.add_header('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14') # req.add_header('User-Agent', reddit_userAgent) # req.add_header('Authorization','bearer LVQu8vitbEXfMPcK1sGlVVQZEpM') # page = read,identity.urlopen(req) # response=page.read();page.close() except urllib2.HTTPError, err: xbmc_notify(err.code, err.msg)
def listSubReddit(url, subreddit_key, type_): from guis import progressBG from utils import post_is_filtered_out, build_script, compose_list_item, xbmc_notify from reddit import reddit_request, has_multiple, assemble_reddit_filter_string global GCXM_hasmultiplesubreddit, GCXM_actual_url_used_to_generate_these_posts, GCXM_reddit_query_of_this_gui, GCXM_hasmultipledomain, GCXM_hasmultipleauthor #the +'s got removed by url conversion title_bar_name = subreddit_key.replace(' ', '+') #log(" title_bar_name %s " %(title_bar_name) ) log("listSubReddit r/%s\n %s" % (title_bar_name, url)) currentUrl = url icon = banner = header = None xbmc_busy() loading_indicator = progressBG('Loading...') loading_indicator.update(0, 'Retrieving ' + subreddit_key) content = reddit_request(url) loading_indicator.update(10, subreddit_key) if not content: xbmc_busy(False) loading_indicator.end( ) #it is important to close xbmcgui.DialogProgressBG return threads = [] q_liz = Queue() #output queue (listitem) content = json.loads(content) #log("query returned %d items " % len(content['data']['children']) ) posts_count = len(content['data']['children']) filtered_out_posts = 0 hms = has_multiple('subreddit', content['data']['children']) if hms == False: #r/random and r/randnsfw returns a random subreddit. we need to use the name of this subreddit for the "next page" link. try: g = content['data']['children'][0]['data']['subreddit'] except ValueError: g = "" except IndexError: xbmc_busy(False) loading_indicator.end( ) #it is important to close xbmcgui.DialogProgressBG xbmc_notify("List Subreddit", translation(32022)) return if g: title_bar_name = g #preserve the &after string so that functions like play slideshow and play all videos can 'play' the correct page # extract the &after string from currentUrl -OR- send it with the 'type' argument when calling this function. currentUrl = assemble_reddit_filter_string('', g) + '&after=' + type_ #put subreddit icon/header in the GUI icon, banner, header = subreddit_icoheader_banner(g) GCXM_hasmultiplesubreddit = hms GCXM_hasmultipledomain = has_multiple('domain', content['data']['children']) GCXM_hasmultipleauthor = has_multiple('author', content['data']['children']) GCXM_actual_url_used_to_generate_these_posts = url GCXM_reddit_query_of_this_gui = currentUrl for idx, entry in enumerate(content['data']['children']): try: #if entry.get('kind')!='t3': # filtered_out_posts+=1 # continue if post_is_filtered_out(entry.get('data')): filtered_out_posts += 1 continue #have threads process each reddit post t = threading.Thread(target=reddit_post_worker, args=(idx, entry, q_liz), name='#t%.2d' % idx) threads.append(t) t.start() except Exception as e: log(" EXCEPTION:=" + str(sys.exc_info()[0]) + " " + str(e)) #check the queue to determine progress break_counter = 0 #to avoid infinite loop expected_listitems = (posts_count - filtered_out_posts) if expected_listitems > 0: loading_indicator.set_tick_total(expected_listitems) last_queue_size = 0 while q_liz.qsize() < expected_listitems: if break_counter >= 100: break #each change in the queue size gets a tick on our progress track if last_queue_size < q_liz.qsize(): items_added = q_liz.qsize() - last_queue_size loading_indicator.tick(items_added) else: break_counter += 1 last_queue_size = q_liz.qsize() xbmc.sleep(100) #wait for all threads to finish before collecting the list items for idx, t in enumerate(threads): #log(' joining %s' %t.getName()) t.join(timeout=20) xbmc_busy(False) #compare the number of entries to the returned results #log( "queue:%d entries:%d" %( q_liz.qsize() , len(content['data']['children'] ) ) ) if q_liz.qsize() != expected_listitems: #some post might be filtered out. log('some threads did not return a listitem') #for t in threads: log('isAlive %s %s' %(t.getName(), repr(t.isAlive()) ) ) #liu=[ qi for qi in sorted(q_liz.queue) ] li = [liz for idx, liz in sorted(q_liz.queue)] #empty the queue. with q_liz.mutex: q_liz.queue.clear() loading_indicator.end() #it is important to close xbmcgui.DialogProgressBG try: #this part makes sure that you load the next page instead of just the first after = "" after = content['data']['after'] if after: if "&after=" in currentUrl: nextUrl = currentUrl[:currentUrl.find("&after=" )] + "&after=" + after else: nextUrl = currentUrl + "&after=" + after liz = compose_list_item( translation(32004), "", "DefaultFolderNextSquare.png", "script", build_script("listSubReddit", nextUrl, title_bar_name, after)) #for items at the bottom left corner liz.setArt({"clearart": "DefaultFolderNextSquare.png"}) liz.setInfo(type='video', infoLabels={"Studio": translation(32004)}) liz.setProperty('link_url', nextUrl) li.append(liz) except Exception as e: log(" EXCEPTzION:=" + str(sys.exc_info()[0]) + " " + str(e)) xbmc_busy(False) title_bar_name = urllib.unquote_plus(title_bar_name) ui = skin_launcher('listSubReddit', title_bar_name=title_bar_name, listing=li, subreddits_file=subredditsFile, currentUrl=currentUrl, icon=icon, banner=banner, header=header) ui.doModal() del ui