def playYoutubeVid(id, meta=None, poster=None):
    if meta is None:
        #Create an empty meta, so we can fill it with the information grabbed from youtube
        meta = {}
    if 'title' not in meta:
        meta['title'] = v.title  #Store the youtube title in the meta
    if poster is None:
        poster = 'Default.png'

    #YDStreamExtractor.disableDASHVideo(True) #Kodi (XBMC) only plays the video for DASH streams, so you don't want these normally. Of course these are the only 1080p streams on YouTube
    try:
        #url = id #a youtube ID will work as well and of course you could pass the url of another site
        vid = YDStreamExtractor.getVideoInfo(
            id, quality=1)  #quality is 0=SD, 1=720p, 2=1080p and is a maximum
        stream_url = vid.streamURL()  #This is what Kodi (XBMC) will play
    except:
        dev.log('Failed to get a valid stream_url!')
        return False  #Failed to grab a video title

    #xbmc.Player().play(v.getbest().url) #Play this video
    liz = xbmcgui.ListItem(meta['title'],
                           iconImage=poster,
                           thumbnailImage=poster)
    liz.setInfo(type="Video", infoLabels=meta)
    liz.setPath(stream_url)
    return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
def delete_playlist(id, type=''):
    #Grab the settings from this playlist
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist
    if settings is None:
        dev.log('deletePlaylist: Could not find playlist '+id+' in the '+dev.typeXml(type)+' file', True)
        return False
    else:         
        i = xbmcgui.Dialog().yesno("Delete Playlist", "Are you sure you want to delete this playlist?")
        if i == 0:
            editPlaylist(id, type=type)
        else:
            if m_xml.xml_remove_playlist(id, type=type) is True:
                #Remove the episodenr xml file to
                file = os.path.join(vars.settingsPath+dev.typeEpnr(type), id+'.xml' )
                if os.path.isfile(file):
                    success = os.remove(file) #Remove the episodenr xml file
                
                xbmcgui.Dialog().ok('Removed Playlist', 'Succesfully removed playlist '+id)
                i = xbmcgui.Dialog().yesno('Delete from library', 'Do you also want to delete the videos from your library?')
                if i != 0:
                    #Check in which folder the show resides
                    folder = settings.find('overwritefolder').text
                    if folder is None or folder == '':
                        folder = dev.legal_filename(settings.find('title').text) #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
                    else:
                        folder = dev.legal_filename(folder)
                    movieLibrary = vars.tv_folder #Use the directory from the addon settings
                    if type == 'musicvideo':
                        movieLibrary = vars.musicvideo_folder
                    elif type == 'movies':
                        movieLibrary = vars.movies_folder
                    dir = os.path.join(movieLibrary, folder) #Set the folder to the maindir/dir
                    
                    success = shutil.rmtree(dir, ignore_errors=True) #Remove the directory
                    xbmcgui.Dialog().ok('Removed from library', 'Deleted the videos from your library (You should clean your library, otherwise they will still show in your library)')
def refresh_artwork(id, type=''):
    response = ytube.yt_get_playlist_info(id)
    res = response['items'][0]['snippet']
    
    thumbnail = dev.best_thumbnail(res)
    #Grab the channel information 
    response = ytube.yt_get_channel_info(res['channelId'])
    snippet = response['items'][0]['snippet']
    brand = response['items'][0]['brandingSettings']
    
    #Check if we can do a better thumbnail
    better_thumbnail = dev.best_thumbnail(snippet)
    if(better_thumbnail != False):
        thumbnail = better_thumbnail
    if thumbnail == False:
        thumbnail = ''
        
    dev.log('The thumbnail now: '+thumbnail)
    
    bannerTv = brand['image']['bannerImageUrl']
    if 'bannerTvImageUrl' in brand['image']:
        bannerTv = brand['image']['bannerTvImageUrl']
    
    m_xml.xml_update_playlist_setting(id, 'thumb', thumbnail, type=type) #Save the new setting
    m_xml.xml_update_playlist_setting(id, 'banner', brand['image']['bannerImageUrl'], type=type) #Save the new setting
    m_xml.xml_update_playlist_setting(id, 'fanart', bannerTv, type=type) #Save the new setting
    
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist

    id = vars.args['id'][0]
    update_playlist(id, type=type)
def playlist_add_episode(playlist, season, id, season_tag='season', type=''):
    dev.log('playlist_add_episode(' + season + ',' + id + ', type=' + type +
            ')')
    #Check if this playlist isnt in the xml file yet
    #if xml_get_elem('season', 'episode', {'id' : id}, playlist=playlist) is None:
    #Build the playlist
    #doc = playlist_xml_get(playlist)

    #s = doc.find("season[@number='"+season+"']")
    s = xml_get_elem(season_tag,
                     season_tag, {'number': season},
                     playlist=playlist,
                     type=type)
    if s is None:
        playlist_add_season(playlist, season, type=type)
        #doc = playlist_xml_get(playlist)
        #s = doc.find("season[@number='"+season+"']")
        s = xml_get_elem(season_tag,
                         season_tag, {'number': season},
                         playlist=playlist,
                         type=type)

    #doc = playlist_xml_get(playlist)
    global playlistdocument
    attr = {'id': id}
    elem = Element('episode', attr)

    s.insert(0, elem)
    root = playlistdocument.getroot()

    write_xml(root, dir=dev.typeEpnr(type), output=playlist + '.xml')
    dev.log('Added the episode ' + id + ' to ' + season_tag + ': ' + season +
            ' in ' + dev.typeEpnr(type) + '/' + playlist + '.xml')
def number_of_episodes(playlist, season, season_tag='season', type=''):
    s = xml_get_elem(season_tag, season_tag, {'number': season}, playlist=playlist, type=type)
    if s == None:
        dev.log('number_of_episodes('+type+'): Could not find '+season_tag+' '+season+' in playlist '+playlist)
        return None
    dev.log('number_of_episodes('+type+'): Found '+str(len(s))+' episodes in '+season_tag+' '+season)
    return len(s)
Example #6
0
def hms_to_sec(hms):
    hms = hms.strip(' \t\n\r')
    #dev.log('hms_to_sec('+hms+')')
    m = re.search(r'(?i)((\d+)h)?((\d+)m)?((\d+)s)?', hms)
    if m:
        if m.group(2) is None and m.group(4) is None and m.group(6) == None:
            #if hms.count(':') == 2:
            m = re.search(r'(?i)((\d)+:)?((\d+))?(:(\d)+)?', hms)
            #else:
            #m = re.search(r'(?i)((\d)+:)?((\d+))?(:(\d)+)?', hms)
        hours = m.group(2)
        minutes = m.group(4)
        seconds = m.group(6)
        #dev.log(str(hours)+', '+str(minutes)+', '+str(seconds))
        if seconds is None:
            seconds = '0' #Seconds was not set in the setting, so we start with 0 seconds
        seconds = int(seconds)
        #dev.log('Seconds is '+str(seconds))
        if minutes is not None: #If minutes are specified
            #dev.log('minutes is '+minutes)
            sm = int(minutes) * 60
            seconds = seconds + sm
        if hours is not None:
            #dev.log('hours is '+hours)
            sh = int(hours) * 60 * 60
            seconds = seconds + sh
        return seconds
    else:
        dev.log('Could not extract seconds from hms format: '+hms, True)
        return None
def delete_playlist(id, type=''):
    #Grab the settings from this playlist
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist
    if settings is None:
        dev.log('deletePlaylist: Could not find playlist '+id+' in the '+dev.typeXml(type)+' file', True)
        return False
    else:         
        i = xbmcgui.Dialog().yesno("Delete Playlist", "Are you sure you want to delete this playlist?")
        if i == 0:
            editPlaylist(id, type=type)
        else:
            if m_xml.xml_remove_playlist(id, type=type) is True:
                #Remove the episodenr xml file to
                file = os.path.join(vars.settingsPath+dev.typeEpnr(type), id+'.xml' )
                if os.path.isfile(file):
                    success = os.remove(file) #Remove the episodenr xml file
                
                xbmcgui.Dialog().ok('Removed Playlist', 'Succesfully removed playlist '+id)
                i = xbmcgui.Dialog().yesno('Delete from library', 'Do you also want to delete the videos from your library?')
                if i != 0:
                    #Check in which folder the show resides
                    folder = settings.find('overwritefolder').text
                    if folder is None or folder == '':
                        folder = dev.legal_filename(settings.find('title').text) #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
                    else:
                        folder = dev.legal_filename(folder)
                    movieLibrary = vars.tv_folder #Use the directory from the addon settings
                    if type == 'musicvideo':
                        movieLibrary = vars.musicvideo_folder
                    elif type == 'movies':
                        movieLibrary = vars.movies_folder
                    dir = os.path.join(movieLibrary, folder) #Set the folder to the maindir/dir
                    
                    success = shutil.rmtree(dir, ignore_errors=True) #Remove the directory
                    xbmcgui.Dialog().ok('Removed from library', 'Deleted the videos from your library (You should clean your library, otherwise they will still show in your library)')
Example #8
0
def write_strm(name, fold, videoid, show=None, season=None, episode=None, startpoint = None, endpoint = None, artist='', album='', song='', year='', type=''):
    #dev.log('strm('+name+', '+fold+', '+videoid+')')
    movieLibrary = vars.tv_folder #The path we should save in is the vars.tv_folder setting from the addon settings
    if type=='musicvideo':
        movieLibrary = vars.musicvideo_folder
    sysname = urllib.quote_plus(videoid) #Escape strings in the videoid if needed
    enc_name = dev.legal_filename(name) #Encode the filename to a legal filename
    
    if vars.__settings__.getSetting("strm_link") == "Youtube Library":
        if type == 'musicvideo':
            content = 'plugin://plugin.video.youtubelibrary/?mode=playmusicvideo'
            if startpoint != None:
                content += '&startpoint='+startpoint
            if endpoint != None:
                content += '&endpoint='+endpoint
            content += '&id=%s&artist=%s&song=%s&album=%s&year=%s&filename=%s' % (sysname, artist, song, album, year, enc_name) #Set the content of the strm file with a link back to this addon for playing the video 
        else:
            content = 'plugin://plugin.video.youtubelibrary/?mode=play&id=%s&show=%s&season=%s&episode=%s&filename=%s' % (sysname, show, season, episode, enc_name) #Set the content of the strm file with a link back to this addon for playing the video
    else:
        content = vars.KODI_ADDONLINK+'%s' % ( sysname) #Set the content of the strm file with a link to the official Kodi Youtube Addon

    xbmcvfs.mkdir(movieLibrary) #Create the maindirectory if it does not exists yet
    
    folder = os.path.join(movieLibrary, fold) #Set the folder to the maindir/dir
    xbmcvfs.mkdir(folder) #Create this subfolder if it does not exist yet

    stream = os.path.join(folder, enc_name + '.strm') #Set the file to maindir/name/name.strm
    file = xbmcvfs.File(stream, 'w') #Open / create this file for writing
    file.write(str(content.encode('UTF-8'))) #Write the content in the file
    file.close() #Close the file
    dev.log('write_strm: Written strm file: '+fold+'/'+enc_name+'.strm')
    return enc_name
def refresh_artwork(id, type=''):
    response = ytube.yt_get_playlist_info(id)
    res = response['items'][0]['snippet']
    
    thumbnail = dev.best_thumbnail(res)
    #Grab the channel information 
    response = ytube.yt_get_channel_info(res['channelId'])
    snippet = response['items'][0]['snippet']
    brand = response['items'][0]['brandingSettings']
    
    #Check if we can do a better thumbnail
    better_thumbnail = dev.best_thumbnail(snippet)
    if(better_thumbnail != False):
        thumbnail = better_thumbnail
    if thumbnail == False:
        thumbnail = ''
        
    dev.log('The thumbnail now: '+thumbnail)
    
    bannerTv = brand['image']['bannerImageUrl']
    if 'bannerTvImageUrl' in brand['image']:
        bannerTv = brand['image']['bannerTvImageUrl']
    
    m_xml.xml_update_playlist_setting(id, 'thumb', thumbnail, type=type) #Save the new setting
    m_xml.xml_update_playlist_setting(id, 'banner', brand['image']['bannerImageUrl'], type=type) #Save the new setting
    m_xml.xml_update_playlist_setting(id, 'fanart', bannerTv, type=type) #Save the new setting
    
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist

    id = vars.args['id'][0]
    update_playlist(id, type=type)
Example #10
0
def playYoutubeVid(id, meta=None, poster=None):
    '''
    from resources.lib import pafy
    pafy.set_api_key(vars.API_KEY)
    #Resolve the youtube video url for ourselves
    v = pafy.new(id)
    stream_url = v.getbest().url
    '''
    if meta is None:
        #Create an empty meta, so we can fill it with the information grabbed from youtube
        meta = {}
    if 'title' not in meta:
        meta['title'] = v.title #Store the youtube title in the meta  
    if poster is None:
        poster = 'Default.png'
    
    
    #YDStreamExtractor.disableDASHVideo(True) #Kodi (XBMC) only plays the video for DASH streams, so you don't want these normally. Of course these are the only 1080p streams on YouTube
    try:
        #url = id #a youtube ID will work as well and of course you could pass the url of another site
        vid = YDStreamExtractor.getVideoInfo(id,quality=1) #quality is 0=SD, 1=720p, 2=1080p and is a maximum
        stream_url = vid.streamURL() #This is what Kodi (XBMC) will play
    except:
        dev.log('Failed to get a valid stream_url!')
        return False #Failed to grab a video title
    
    
    #xbmc.Player().play(v.getbest().url) #Play this video
    liz = xbmcgui.ListItem(meta['title'], iconImage=poster, thumbnailImage=poster)
    liz.setInfo( type="Video", infoLabels=meta )
    liz.setPath(stream_url)
    return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
Example #11
0
def add_playlist(id, type=''):
    if type == '' or type == 'tv':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/tv/' + id + '?api_token=' + vars.__settings__.getSetting(
            'api_token')
    if type == 'musicvideo':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/musicvideos/' + id + '?api_token=' + vars.__settings__.getSetting(
            'api_token')
    if type == 'movies':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/movies/' + id + '?api_token=' + vars.__settings__.getSetting(
            'api_token')
    dev.log('Adding the Api playlist to the config: ' + api_url)
    data = json.load(urllib2.urlopen(api_url))

    if 'data' not in data:
        url = dev.build_url({'mode': 'ApiIndex'})
        dev.adddir(
            'Something went wrong',
            url,
            description=
            'There was an error getting the playlist from the youtubelibrary.nl API.'
        )
        return False

    playlist = data['data']

    return playlist

    url = dev.build_url({'mode': 'ApiAddPlaylist', 'type': type})
    dev.adddir(playlist['title'], url, description=playlist['description'])
def downloadYoutubeVid(name, fold, videoid, settings, type='', season=None):
    #youtube-dl command to download best quality: -f bestvideo[ext!=webm]‌​+bestaudio[ext!=webm]‌​/best[ext!=webm]
    #YDStreamExtractor.disableDASHVideo(True)

    movieLibrary = vars.tv_folder  #The path we should save in is the vars.tv_folder setting from the addon settings
    if type == 'musicvideo':
        movieLibrary = vars.musicvideo_folder
    if type == 'movies':
        movieLibrary = vars.movies_folder

    folder = os.path.join(movieLibrary,
                          fold)  #Set the folder to the maindir/dir
    enc_name = dev.legal_filename(
        name)  #Encode the filename to a legal filename

    xbmcvfs.mkdir(
        movieLibrary)  #Create the maindirectory if it does not exist yet
    xbmcvfs.mkdir(folder)  #Create this subfolder if it does not exist yet

    xbmcvfs.mkdir(folder)  #Create this subfolder if it does not exist yet
    if type == '' or type == 'tv':
        folder = os.path.join(folder, 'Season ' +
                              season)  #Set the folder to the maindir/dir
        xbmcvfs.mkdir(folder)  #Create this subfolder if it does not exist yet

    full_file_path = os.path.join(folder,
                                  enc_name)  #Set the file to maindir/name/name

    dev.log('Downloading ' + videoid, 1)
    #vid = YDStreamExtractor.getVideoInfo(videoid,quality=1)
    path = os.path.join(movieLibrary, fold)  #Set the folder to the maindir/dir

    #url = "https://www.youtube.com/watch?v=YKSU82afy1w" #ducktales intro to test
    url = "https://www.youtube.com/watch?v=" + videoid
    vid = YDStreamExtractor.getVideoInfo(url, quality=1)

    if vid == None:
        dev.log('Failed to retrieve video from url: ' + url)
        return False

    if settings.find('download_videos').text == '720p':
        dev.log('%%%%%%% QUALITY: 720p quality selected')
        format = 'bestvideo[height<=?720]+bestaudio/best[height<=?720]'
    elif settings.find('download_videos').text == '1080p':
        dev.log('%%%%%%% QUALITY: 1080p quality selected')
        format = 'bestvideo[height<=?1080]+bestaudio/best[height<=?1080]'
    else:
        dev.log('%%%%%%% QUALITY: best quality selected')
        format = 'bestvideo+bestaudio/best'

    ydl_opts = {
        'format': format,
        'logger': MyLogger(),
        'progress_hooks': [my_hook],
        'outtmpl': full_file_path + '.%(ext)s',
        #'-o' : enc_name+'.%(ext)s',
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        return ydl.download(['https://www.youtube.com/watch?v=' + videoid])
    """
Example #13
0
def addBookmark(currentTime, name, imdb='0'):
    import hashlib
    dev.log('addBookmark(%s)' % name)
    try:
        idFile = hashlib.md5()
        for i in name:
            idFile.update(str(i))
        for i in imdb:
            idFile.update(str(i))
        idFile = str(idFile.hexdigest())
        dev.log('addBookmark: idFile calculated: %s' % idFile)
        timeInSeconds = str(currentTime)
        xbmcvfs.mkdir(
            xbmc.translatePath(vars.addonInfo('profile')).decode(
                'utf-8'))  #Create the directory if it does not yet exist
        dbcon = database.connect(os.path.join(vars.dataPath, 'settings.db'))
        dbcur = dbcon.cursor()
        dbcur.execute("CREATE TABLE IF NOT EXISTS bookmark ("
                      "idFile TEXT, "
                      "timeInSeconds TEXT, "
                      "UNIQUE(idFile)"
                      ");")
        dbcur.execute("DELETE FROM bookmark WHERE idFile = '%s'" % idFile)
        dbcur.execute("INSERT INTO bookmark Values (?, ?)",
                      (idFile, timeInSeconds))
        dbcon.commit()
    except:
        pass
Example #14
0
def update_playlist(id, type=''):
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist
    if settings is None:
        dev.log('Could not find playlist '+id+' in the '+dev.typeXml(type)+' file', True)
        return False
    else:
        dev.log('Updating playlist %s (Id: %s)' % (settings.find('title').text.encode('utf-8'), id))
        #Check in which folder the show should be added
        folder = settings.find('overwritefolder').text
        if folder is None or folder == '':
            folder = dev.legal_filename(settings.find('title').text) #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
        else:
            folder = dev.legal_filename(folder)
        
        #Create the tvshow.nfo
        writenfo = settings.find('writenfo').text
        if writenfo != 'no':
            if type == '' or type == 'tv':
                generators.write_tvshow_nfo(folder, settings)
        
        update_playlist_vids(id, folder, settings, type=type)
        
        #Save the time this playlist got updated in the xml
        import datetime
        d=datetime.datetime.now()
        m_xml.xml_update_playlist_attr(id, 'scansince', d.strftime("%d/%m/%Y %H:%M:%S"), type=type)
    
        return True
def write_xml(elem, dir='', output='', type=''):
    if output == '':
        output = dev.typeXml(type)
    dev.log('write_xml('+type+','+output+').')
    
    
    xbmcvfs.mkdir(vars.settingsPath) #Create the settings dir if it does not exist already
    if dir is not '': xbmcvfs.mkdir(vars.settingsPath+dir) #Create the settings dir if it does not exist already
    #Write these settings to a .xml file in the addonfolder
    output_file = os.path.join(vars.settingsPath+dir, output) #Set the outputfile to settings.xml
    
    #Creating a backup of the .xml file (in case it gets corrupted)
    backupfile = os.path.join(vars.settingsPath+dir, output+'.backup')
    if xbmcvfs.exists(output_file):
        if xbmcvfs.copy(output_file, backupfile):
            dev.log('Created a backup of the xml file at: '+backupfile)
        else:
            dev.log('Failed to create a backup of the xml file at: '+backupfile)
    else:
        dev.log(output_file+' could not be found, so not able to create a backup')
    
    
    indent( elem ) #Prettify the xml so its not on one line
    tree = ElementTree.ElementTree( elem ) #Convert the xml back to an element
    tree.write(output_file) #Save the XML in the settings file
    
    #For backup purposes, check if the xml got corrupted by writing just now
    if xml_get(type) is False:
        dev.log('corrupt .xml file')
def hms_to_sec(hms):
    hms = hms.strip(' \t\n\r')
    #dev.log('hms_to_sec('+hms+')')
    m = re.search(r'(?i)((\d+)h)?((\d+)m)?((\d+)s)?', hms)
    if m:
        if m.group(2) is None and m.group(4) is None and m.group(6) == None:
            #if hms.count(':') == 2:
            m = re.search(r'(?i)((\d)+:)?((\d+))?(:(\d)+)?', hms)
            #else:
            #m = re.search(r'(?i)((\d)+:)?((\d+))?(:(\d)+)?', hms)
        hours = m.group(2)
        minutes = m.group(4)
        seconds = m.group(6)
        #dev.log(str(hours)+', '+str(minutes)+', '+str(seconds))
        if seconds is None:
            seconds = '0'  #Seconds was not set in the setting, so we start with 0 seconds
        seconds = int(seconds)
        #dev.log('Seconds is '+str(seconds))
        if minutes is not None:  #If minutes are specified
            #dev.log('minutes is '+minutes)
            sm = int(minutes) * 60
            seconds = seconds + sm
        if hours is not None:
            #dev.log('hours is '+hours)
            sh = int(hours) * 60 * 60
            seconds = seconds + sh
        return seconds
    else:
        dev.log('Could not extract seconds from hms format: ' + hms, True)
        return None
def write_xml(elem, dir='', output='', type=''):
    if output == '':
        output = dev.typeXml(type)
    dev.log('write_xml(' + type + ',' + output + ').')

    xbmcvfs.mkdir(vars.settingsPath
                  )  #Create the settings dir if it does not exist already
    if dir is not '':
        xbmcvfs.mkdir(
            vars.settingsPath +
            dir)  #Create the settings dir if it does not exist already
    #Write these settings to a .xml file in the addonfolder
    output_file = os.path.join(vars.settingsPath + dir,
                               output)  #Set the outputfile to settings.xml

    #Creating a backup of the .xml file (in case it gets corrupted)
    backupfile = os.path.join(vars.settingsPath + dir, output + '.backup')
    if xbmcvfs.exists(output_file):
        if xbmcvfs.copy(output_file, backupfile):
            dev.log('Created a backup of the xml file at: ' + backupfile)
        else:
            dev.log('Failed to create a backup of the xml file at: ' +
                    backupfile)
    else:
        dev.log(output_file +
                ' could not be found, so not able to create a backup')

    indent(elem)  #Prettify the xml so its not on one line
    tree = ElementTree.ElementTree(elem)  #Convert the xml back to an element
    tree.write(output_file)  #Save the XML in the settings file

    #For backup purposes, check if the xml got corrupted by writing just now
    if xml_get(type) is False:
        dev.log('corrupt .xml file')
def playlist_add_episode(playlist, season, id, season_tag='season', type=''):
    dev.log('playlist_add_episode('+season+','+id+', type='+type+')')
    #Check if this playlist isnt in the xml file yet
    #if xml_get_elem('season', 'episode', {'id' : id}, playlist=playlist) is None:
    #Build the playlist
    #doc = playlist_xml_get(playlist)
    
    #s = doc.find("season[@number='"+season+"']")
    s = xml_get_elem(season_tag, season_tag, {'number': season}, playlist=playlist, type=type)
    if s is None:
        playlist_add_season(playlist, season, type=type)
        #doc = playlist_xml_get(playlist)
        #s = doc.find("season[@number='"+season+"']")
        s = xml_get_elem(season_tag, season_tag, {'number': season}, playlist=playlist, type=type)
        
    #doc = playlist_xml_get(playlist)
    global playlistdocument
    attr = { 'id' : id}
    elem = Element('episode', attr)
    
    s.insert(0, elem)
    root = playlistdocument.getroot()
    
    write_xml(root, dir=dev.typeEpnr(type), output=playlist+'.xml')
    dev.log('Added the episode '+id+' to '+season_tag+': '+season+' in '+dev.typeEpnr(type)+'/'+playlist+'.xml')
    #else:
        #dev.log('playlist_add_episode: not added episode '+id+' since the episode already exists')    
Example #19
0
def refresh_playlist(id, type=''):
    #Grab the settings from this playlist
    settings = m_xml.xml_get_elem(
        'playlists/playlist', 'playlist', {'id': id},
        type=type)  #Grab the xml settings for this playlist
    if settings is None:
        dev.log(
            'refreshPlaylist: Could not find playlist ' + id + ' in the ' +
            typeXml(type) + ' file', True)
        return False
    else:
        i = xbmcgui.Dialog().yesno(
            "Refresh Playlist",
            "Are you sure you want to refresh this playlist?")
        if i != 0:
            m_xml.xml_update_playlist_setting(id, 'lastvideoId', '', type=type)
            #Delete the .xml containing all scanned videoId's as well
            file = os.path.join(vars.settingsPath, dev.typeEpnr(type))
            file = os.path.join(file, id + '.xml')
            if os.path.isfile(file):
                success = os.remove(file)  #Remove the episodenr xml file

            xbmcgui.Dialog().ok('Refreshed Playlist',
                                'Succesfully refreshed playlist ' + id)
            i = xbmcgui.Dialog().yesno(
                'Delete from library',
                'Do you also want to delete the previous videos from your library?'
            )
            if i != 0:
                #Check in which folder the show resides
                folder = settings.find('overwritefolder').text
                if folder is None or folder == '':
                    folder = dev.legal_filename(
                        settings.find('title').text
                    )  #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
                else:
                    folder = dev.legal_filename(folder)
                movieLibrary = vars.tv_folder  #Use the directory from the addon settings
                if type == 'musicvideo':
                    movieLibrary = vars.musicvideo_folder
                elif type == 'movies':
                    movieLibrary = vars.movies_folder
                dir = os.path.join(movieLibrary,
                                   folder)  #Set the folder to the maindir/dir

                success = shutil.rmtree(
                    dir, ignore_errors=True)  #Remove the directory
                #if vars.update_videolibrary == "true" and type=='':
                #    update_dir = vars.tv_folder_path
                #    if type == 'musicvideo':
                #        update_dir = vars.musicvideo_folder_path
                #    dev.log('Updating video library is enabled. Cleaning librarys directory %s' % update_dir, True)
                #    xbmc.executebuiltin('xbmc.updatelibrary(Video,'+update_dir+')')

                xbmcgui.Dialog().ok(
                    'Removed from library',
                    'Deleted the previous videos from your library (You should clean your library, otherwise they will still show in your library)'
                )
            editPlaylist(id, type=type)  #Load the editplaylist view
def playlist_xml_get(playlist, type=''):
    dev.log('playlist_XML_get('+type+')')
    if xbmcvfs.exists(os.path.join(vars.settingsPath,dev.typeEpnr(type)+"/"+playlist+".xml")) == False: #If the episodes.xml file can't be found, we should create this file
        playlist_create_xml(playlist, type=type)
    
    global playlistdocument #Set the document variable as global, so every function can reach it
    playlistdocument = ElementTree.parse( vars.settingsPath+dev.typeEpnr(type)+'/'+playlist+'.xml' )
    return playlistdocument
def manage_playlists(type=''):
    dev.log('manage_playlists(' + type + ')')
    #pl = m_xml.xml_get_elem('playlists', 'playlists') #Grab <playlists>
    m_xml.xml_get(type)
    pl = m_xml.document.findall('playlists/playlist')
    if pl is not None:
        for child in pl:  #Loop through each playlist
            url = dev.build_url({
                'mode': 'editPlaylist',
                'id': child.attrib['id'],
                'type': type
            })
            #Build the contextmenu item to force the updating of one playlist
            context_url = dev.build_url({
                'mode': 'updateplaylist',
                'id': child.attrib['id'],
                'type': type
            })
            context_url2 = dev.build_url({
                'mode': 'deletePlaylist',
                'id': child.attrib['id'],
                'type': type
            })
            context_url3 = dev.build_url({
                'mode': 'refreshPlaylist',
                'id': child.attrib['id'],
                'type': type
            })
            context_url4 = dev.build_url({
                'mode': 'refreshArtwork',
                'id': child.attrib['id'],
                'type': type
            })
            commands = []
            commands.append((
                dev.lang(31006),
                'XBMC.RunPlugin(' + context_url + ')',
            ))
            commands.append((
                dev.lang(31007),
                'XBMC.RunPlugin(' + context_url2 + ')',
            ))
            commands.append((
                dev.lang(31029),
                'XBMC.RunPlugin(' + context_url3 + ')',
            ))
            commands.append((
                dev.lang(31030),
                'XBMC.RunPlugin(' + context_url4 + ')',
            ))
            dev.adddir(child.find('title').text,
                       url,
                       child.find('thumb').text,
                       child.find('fanart').text,
                       child.find('description').text,
                       context=commands)
    xbmcplugin.endOfDirectory(vars.addon_handle)
def downloadYoutubeVid(name, fold, videoid, settings, type='', season=None):
    #youtube-dl command to download best quality: -f bestvideo[ext!=webm]‌​+bestaudio[ext!=webm]‌​/best[ext!=webm]
    #YDStreamExtractor.disableDASHVideo(True)
    
    movieLibrary = vars.tv_folder #The path we should save in is the vars.tv_folder setting from the addon settings
    if type=='musicvideo':
        movieLibrary = vars.musicvideo_folder
    if type=='movies':
        movieLibrary = vars.movies_folder
    
    folder = os.path.join(movieLibrary, fold) #Set the folder to the maindir/dir
    enc_name = dev.legal_filename(name) #Encode the filename to a legal filename
    
    xbmcvfs.mkdir(movieLibrary) #Create the maindirectory if it does not exist yet
    xbmcvfs.mkdir(folder) #Create this subfolder if it does not exist yet
    
    xbmcvfs.mkdir(folder) #Create this subfolder if it does not exist yet
    if type == '' or type == 'tv':
        folder = os.path.join(folder, 'Season '+season) #Set the folder to the maindir/dir
        xbmcvfs.mkdir(folder) #Create this subfolder if it does not exist yet

    full_file_path = os.path.join(folder, enc_name) #Set the file to maindir/name/name
    
    dev.log('Downloading '+videoid, 1)
    #vid = YDStreamExtractor.getVideoInfo(videoid,quality=1)
    path = os.path.join(movieLibrary, fold) #Set the folder to the maindir/dir
    
    
    #url = "https://www.youtube.com/watch?v=YKSU82afy1w" #ducktales intro to test
    url = "https://www.youtube.com/watch?v="+videoid
    vid = YDStreamExtractor.getVideoInfo(url,quality=1)
    
    if vid == None:
        dev.log('Failed to retrieve video from url: '+url)
        return False
    
    if settings.find('download_videos').text  == '720p':
        dev.log('%%%%%%% QUALITY: 720p quality selected')
        format = 'bestvideo[height<=?720]+bestaudio/best[height<=?720]'
    elif settings.find('download_videos').text == '1080p':
        dev.log('%%%%%%% QUALITY: 1080p quality selected')
        format = 'bestvideo[height<=?1080]+bestaudio/best[height<=?1080]'
    else:
        dev.log('%%%%%%% QUALITY: best quality selected')
        format = 'bestvideo+bestaudio/best'
    
    ydl_opts = {
    'format': format,
    'logger': MyLogger(),
    'progress_hooks': [my_hook],
    'outtmpl' : full_file_path+'.%(ext)s',
    #'-o' : enc_name+'.%(ext)s',
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        return ydl.download(['https://www.youtube.com/watch?v='+videoid])
    
    """
Example #23
0
def find_year(text):
    regex = "(\(?()c(opyright)?\)?)?\s*(\d{4})"
    m = re.search(regex, text, re.IGNORECASE)
    if m:
        if len(m.group(4)) == 4:
            #Found a year!
            dev.log(u'Found a year!: '+m.group(4)+ ' Whole match: '+m.group(0))
            text = text.replace(m.group(0), '') #Remove the copyright / year notice from the title
            return m.group(4), text
    return False, text
def number_of_episodes(playlist, season, season_tag='season', type=''):
    s = xml_get_elem(season_tag,
                     season_tag, {'number': season},
                     playlist=playlist,
                     type=type)
    if s == None:
        dev.log('number_of_episodes(' + type + '): Could not find ' +
                season_tag + ' ' + season + ' in playlist ' + playlist)
        return None
    dev.log('number_of_episodes(' + type + '): Found ' + str(len(s)) +
            ' episodes in ' + season_tag + ' ' + season)
    return len(s)
Example #25
0
def update_playlist(type=''):
    id = vars.args['id'][0]
    xbmcgui.Dialog().notification(vars.__addonname__, 'Updating '+dev.typeName(type)+' Playlist '+id, vars.__icon__, 3000)
    service.update_playlist(id, type=type)
    xbmcgui.Dialog().notification(vars.__addonname__, 'Done updating '+dev.typeName(type)+' Playlist '+id, vars.__icon__, 3000)
    #Should we also update the video library?
    if vars.update_videolibrary == "true":
        update_dir = vars.tv_folder_path
        if type == 'musicvideo':
            update_dir = vars.musicvideo_folder_path
        dev.log('Updating video library is enabled. Updating librarys directory %s' % update_dir, True)
        xbmc.executebuiltin('xbmc.updatelibrary(Video,'+update_dir+')')
def xml_get(type=''):
    file=dev.typeXml(type)
    dev.log('XML_get('+type+','+file+')')
    global document #Set the document variable as global, so every function can reach it
    try:
        document = ElementTree.parse( vars.settingsPath+file )
    except Exception:
        xbmcgui.Dialog().ok("ERROR: "+file+" got corrupted", "ERROR!: "+file+" got corrupted. Please report this error to the addon developer on youtubelibrary.nl or the kodi forums. Luckily a backup has been created automatically before.")
        dev.log('ERROR: '+file+' got corrupted.', 1)
        raise ValueError(output_file+' got corrupted! Best to quit here')
        return False
    return document
def update_playlist(id, type=''):
    xbmcgui.Dialog().notification(vars.__addonname__, 'Updating '+dev.typeName(type)+' Playlist '+id, vars.__icon__, 3000)
    service.update_playlist(id, type=type)
    xbmcgui.Dialog().notification(vars.__addonname__, 'Done updating '+dev.typeName(type)+' Playlist '+id, vars.__icon__, 3000)
    #Should we also update the video library?
    if vars.update_videolibrary == "true":
        update_dir = vars.tv_folder_path
        if type == 'musicvideo':
            update_dir = vars.musicvideo_folder_path
        elif type == 'movies':
            update_dir = vars.movies_folder_path
        dev.log('Updating video library is enabled. Updating librarys directory %s' % update_dir, True)
        xbmc.executebuiltin('xbmc.updatelibrary(Video,'+update_dir+')')
def yt_get_channel_info(Channelid):
    #Connect to youtube API
    youtube = build_youtube()
    dev.log('GET yt_get_channel_info: https://www.googleapis.com/youtube/v3/channels?part=snippet%2C+contentDetails%2C+brandingSettings&maxResults=50&id='+Channelid+'&key='+vars.API_KEY)

    #Search for the channels with the following parameters
    search_response = youtube.channels().list(
      part="brandingSettings,snippet,contentDetails",
      id=Channelid,
      maxResults=50
    ).execute()
    
    return search_response
def playlist_xml_get(playlist, type=''):
    dev.log('playlist_XML_get(' + type + ')')
    if xbmcvfs.exists(
            os.path.join(vars.settingsPath,
                         dev.typeEpnr(type) + "/" + playlist + ".xml")
    ) == False:  #If the episodes.xml file can't be found, we should create this file
        playlist_create_xml(playlist, type=type)

    global playlistdocument  #Set the document variable as global, so every function can reach it
    playlistdocument = ElementTree.parse(vars.settingsPath +
                                         dev.typeEpnr(type) + '/' + playlist +
                                         '.xml')
    return playlistdocument
def playlist_add_season(playlist, season, season_tag='season', type=''):
    dev.log('playlist_add_season('+season+')')
    #Check if this playlist isnt in the xml file yet
    #if xml_get_elem('season', 'episode', {'id' : id}, playlist=playlist) is None:
    #Build the playlist
    doc = playlist_xml_get(playlist, type=type)
    
    attr = { 'number' : season}
    elem = Element(season_tag, attr)
    root = doc.getroot()
    root.insert(0, elem)
    write_xml(root, dir=dev.typeEpnr(type), output=playlist+'.xml')
    dev.log('Added '+season_tag+': '+season+' in '+dev.typeEpnr(type)+'/'+playlist+'.xml')
def create_xml(file='settings.xml'):
    dev.log('Create_xml')

    #<playlists>
    root = Element('config')
    newxml = SubElement(root, 'playlists')

    example = {
        'id': 'PUTPLAYLISTIDHERE',
        'enabled': 'no',
        'settings': {
            'type': 'TV',
            'title': 'Exampleplaylist',
            'description':
            'This is an example of a youtube playlist xml config for use with Youtube Library',
            'genre': 'Action/Comedy',
            'published': '2010',
            #Art
            'thumb': 'thumbimgurl',
            'fanart': 'fanarturl',
            'banner': 'bannerurl',
            'epsownfanart': 'No',
            # STRM & NFO Settings
            'writenfo': 'Yes',
            'delete': '168',
            'keepvideos': '500',
            'overwritefolder': 'Z:/MEDIA/TV Shows/Example show',
            #Filters
            'minlength': '12:00',
            'maxlength': '25:00',
            'excludewords': 'trailer|commercial',
            'onlyinclude': 'review',
            #Strip Stuff from NFO information
            'striptitle': 'Brought to you by',
            'removetitle':
            'Example Youtube Channels|Always annoying part of title',
            'stripdescription':
            'See our other channels|Subscribe to our channel',
            'removedescription': 'Brought to you by our sponsors',
            #Scan Settings
            'lastvideoId': 'Wixi28loswo',
            'scansince': '29 jun 2015 18:23:21'
        }
    }

    playlist = xml_create_playlist(example)
    #Append this playlist to the new created xml file
    #newxml.append(playlist)
    #Write this new xml to the settings.xml file
    write_xml(root, output=file)
    dev.log('Create_xml: Created new ' + file + ' file')
def xml_update_playlist_attr(id, attr, val, type=''):
    dev.log('XML: Updating playlist id ' + id + ' with attr ' + attr + ' : ' +
            val + ' (' + type + ')')

    #Grab this playlist from the xml file
    playlist = xml_get_elem('playlists/playlist',
                            'playlist', {'id': id},
                            type=type)

    #Check if we have succesfully retrieved the playlist
    if playlist == None:
        dev.log('XML_update_playlist: could not find playlist ' + id)
    else:
        dev.log('XML_update_playlist_: found playlist ' + id)

        #Update this attribute to the new val
        try:
            del playlist.attrib[attr]
        except:
            pass
        playlist.attrib[attr] = val
        #playlist.set(attr, val)
        #Write this to the xml
        root = document.getroot()
        write_xml(root, type=type)
        dev.log('XML_update_playlist_attr: written XML')
def playlist_add_season(playlist, season, season_tag='season', type=''):
    dev.log('playlist_add_season(' + season + ')')
    #Check if this playlist isnt in the xml file yet
    #if xml_get_elem('season', 'episode', {'id' : id}, playlist=playlist) is None:
    #Build the playlist
    doc = playlist_xml_get(playlist, type=type)

    attr = {'number': season}
    elem = Element(season_tag, attr)
    root = doc.getroot()
    root.insert(0, elem)
    write_xml(root, dir=dev.typeEpnr(type), output=playlist + '.xml')
    dev.log('Added ' + season_tag + ': ' + season + ' in ' +
            dev.typeEpnr(type) + '/' + playlist + '.xml')
Example #34
0
def yt_get_playlist_info(id):
    #Connect to youtube API
    youtube = build_youtube()
    #Retrieve the information from the youtube API
    dev.log(
        'GET yt_get_playlist_info: https://www.googleapis.com/youtube/v3/playlists?part=snippet%2C+id%2C+contentDetails&maxResults=50&channelId='
        + id + '&key=' + vars.API_KEY)

    response = youtube.playlists().list(part="contentDetails,id,snippet",
                                        id=id,
                                        maxResults=50).execute()

    return response
    '''
def yt_get_channel_info(Channelid):
    #Connect to youtube API
    youtube = build_youtube()
    dev.log(
        'GET yt_get_channel_info: https://www.googleapis.com/youtube/v3/channels?part=snippet%2C+contentDetails%2C+brandingSettings&maxResults=50&id='
        + Channelid + '&key=' + vars.API_KEY)

    #Search for the channels with the following parameters
    search_response = youtube.channels().list(
        part="brandingSettings,snippet,contentDetails",
        id=Channelid,
        maxResults=50).execute()

    return search_response
def vids_by_playlist(id, nextpage=False):
    youtube = build_youtube()
    if nextpage == False:
        dev.log(
            'GET vids_by_playlist: https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2C+contentDetails&maxResults=50&playlistId='
            + id + '&key=' + vars.API_KEY)
        try:
            search_response = youtube.playlistItems().list(
                part="snippet,contentDetails", maxResults=50,
                playlistId=id).execute()
        except KeyboardInterrupt:
            raise
        except:
            dev.log('Playlist ' + id + ' could not be retrieved!')
            return False
    else:
        dev.log(
            'GET vids_by_playlist: https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2C+contentDetails&maxResults=50&playlistId='
            + id + '&pageToken=' + nextpage + '&key=' + vars.API_KEY)
        try:
            search_response = youtube.playlistItems().list(
                part="snippet,contentDetails",
                maxResults=50,
                playlistId=id,
                pageToken=nextpage).execute()
        except KeyboardInterrupt:
            raise
        except:
            dev.log('Playlist ' + id + ' could not be retrieved!')
            return False
    return search_response
def create_xml(file='settings.xml'):
    dev.log('Create_xml')
    
    #<playlists>
    root = Element('config')
    newxml = SubElement(root, 'playlists')
    
    example = {
        'id'    : 'PUTPLAYLISTIDHERE',
        'enabled'      : 'no',
        'settings'      : {
            'type'                  : 'TV',
            'title'                   : 'Exampleplaylist',
            
            'description'        : 'This is an example of a youtube playlist xml config for use with Youtube Library',
            'genre'                : 'Action/Comedy',
            'published'          : '2010',
            #Art
            'thumb'               : 'thumbimgurl',
            'fanart'                : 'fanarturl',
            'banner'              : 'bannerurl',
            'epsownfanart'    : 'No',
            # STRM & NFO Settings
            'writenfo'             : 'Yes',
            'delete'                : '168',
            'keepvideos'        : '500',
            'overwritefolder'   : 'Z:/MEDIA/TV Shows/Example show',
            #Filters
            'minlength'         : '12:00',
            'maxlength'         : '25:00',
            'excludewords'    : 'trailer|commercial',
            'onlyinclude'       : 'review',
            #Strip Stuff from NFO information
            'striptitle'            : 'Brought to you by',
            'removetitle'       : 'Example Youtube Channels|Always annoying part of title',
            'stripdescription' : 'See our other channels|Subscribe to our channel',
            'removedescription' : 'Brought to you by our sponsors',
            #Scan Settings
            'lastvideoId'       : 'Wixi28loswo',
            'scansince'        : '29 jun 2015 18:23:21'
        }
    }

    
    playlist = xml_create_playlist(example)
    #Append this playlist to the new created xml file
    #newxml.append(playlist)
    #Write this new xml to the settings.xml file
    write_xml(root, output=file)
    dev.log('Create_xml: Created new '+file+' file')
def yt_get_playlist_info(id):
    #Connect to youtube API
    youtube = build_youtube()
    #Retrieve the information from the youtube API
    dev.log('GET yt_get_playlist_info: https://www.googleapis.com/youtube/v3/playlists?part=snippet%2C+id%2C+contentDetails&maxResults=50&channelId='+id+'&key='+vars.API_KEY)

    response = youtube.playlists().list(
      part="contentDetails,id,snippet",
      id=id,
      maxResults=50
    ).execute()
    
    return response
    '''
def vids_by_playlist(id, nextpage = False):
    youtube = build_youtube()
    if nextpage == False:
        dev.log('GET vids_by_playlist: https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2C+contentDetails&maxResults=50&playlistId='+id+'&key='+vars.API_KEY)
        try:
            search_response = youtube.playlistItems().list(
              part="snippet,contentDetails",
              maxResults=50,
              playlistId=id
            ).execute()
        except KeyboardInterrupt:
            raise
        except:
            dev.log('Playlist '+id+' could not be retrieved!')
            return False
    else:
        dev.log('GET vids_by_playlist: https://www.googleapis.com/youtube/v3/playlistItems?part=snippet%2C+contentDetails&maxResults=50&playlistId='+id+'&pageToken='+nextpage+'&key='+vars.API_KEY)
        try:
            search_response = youtube.playlistItems().list(
              part="snippet,contentDetails",
              maxResults=50,
              playlistId=id,
              pageToken=nextpage
            ).execute()
        except KeyboardInterrupt:
            raise
        except:
            dev.log('Playlist '+id+' could not be retrieved!')
            return False
    return search_response
def xml_get(type=''):
    file = dev.typeXml(type)
    dev.log('XML_get(' + type + ',' + file + ')')
    global document  #Set the document variable as global, so every function can reach it
    try:
        document = ElementTree.parse(vars.settingsPath + file)
    except Exception:
        xbmcgui.Dialog().ok(
            "ERROR: " + file + " got corrupted", "ERROR!: " + file +
            " got corrupted. Please report this error to the addon developer on youtubelibrary.nl or the kodi forums. Luckily a backup has been created automatically before."
        )
        dev.log('ERROR: ' + file + ' got corrupted.', 1)
        raise ValueError(output_file + ' got corrupted! Best to quit here')
        return False
    return document
Example #41
0
def find_artist_song(text, hardcoded_artist):
    regex = "^([^-\n]+)(-|by|\|)\s*([^-:\n]+)$"
    m = re.search(regex, text, re.IGNORECASE)
    if m:
        dev.log('find_artist_song() Found Artist - Song: '+str(m.group(1).encode('UTF-8'))+' - '+str(m.group(3).encode('UTF-8')))
        artist = remove_extra_spaces(m.group(1))
        song = remove_extra_spaces(m.group(3))
        if m.group(2) == 'by' or artist.lower() == hardcoded_artist.lower():
            #Turn artist and song around
            artist = m.group(3)
            song = m.group(1)
        if '(' in artist and ')' not in artist or ')' in artist and '(' not in artist:
            return False, False
        return artist, song
    return False, False
def yt_get_playlists_by_channel(id, pagetoken='default'):
    if pagetoken == 'default':
        pagetoken = ''
    #Connect to youtube API
    youtube = build_youtube()
    dev.log(
        'GET yt_get_playlists_by_channel: https://www.googleapis.com/youtube/v3/playlists?part=snippet%2C+contentDetails&maxResults=50&channelId='
        + id + '&key=' + vars.API_KEY + '&pageToken=' + pagetoken)

    #Retrieve the information from the youtube API
    response = youtube.playlists().list(part="contentDetails,snippet",
                                        channelId=id,
                                        maxResults=50,
                                        pageToken=pagetoken).execute()

    return response
def deleteBookmark(name, imdb='0'):
    dev.log('deleteBookmark(%s)' % name)
    import hashlib
    try:
        idFile = hashlib.md5()
        for i in name: idFile.update(str(i))
        for i in imdb: idFile.update(str(i))
        idFile = str(idFile.hexdigest())
        control.makeFile(control.vars.dataPath)
        dbcon = database.connect(os.path.join(vars.dataPath, 'settings.db'))
        dbcur = dbcon.cursor()
        dbcur.execute("CREATE TABLE IF NOT EXISTS bookmark (""idFile TEXT, ""timeInSeconds TEXT, ""UNIQUE(idFile)"");")
        dbcur.execute("DELETE FROM bookmark WHERE idFile = '%s'" % idFile)
        dbcon.commit()
    except:
        pass
def yt_get_playlists_by_channel(id, pagetoken='default'):
    if pagetoken == 'default':
        pagetoken = ''
    #Connect to youtube API
    youtube = build_youtube()
    dev.log('GET yt_get_playlists_by_channel: https://www.googleapis.com/youtube/v3/playlists?part=snippet%2C+contentDetails&maxResults=50&channelId='+id+'&key='+vars.API_KEY+'&pageToken='+pagetoken)

    #Retrieve the information from the youtube API
    response = youtube.playlists().list(
      part="contentDetails,snippet",
      channelId=id,
      maxResults=50,
      pageToken=pagetoken
    ).execute()
    
    return response
Example #45
0
def manage_playlists(type=''):
    dev.log('manage_playlists('+type+')')
    #pl = m_xml.xml_get_elem('playlists', 'playlists') #Grab <playlists>
    m_xml.xml_get(type)
    pl = m_xml.document.findall('playlists/playlist')
    if pl is not None: 
        for child in pl: #Loop through each playlist
            url = dev.build_url({'mode': 'editPlaylist', 'id': child.attrib['id'], 'type': type})
            #Build the contextmenu item to force the updating of one playlist
            context_url = dev.build_url({'mode': 'updateplaylist', 'id': child.attrib['id'], 'type': type})
            context_url2 = dev.build_url({'mode': 'deletePlaylist', 'id': child.attrib['id'], 'type': type})
            commands = []
            commands.append(( dev.lang(31006), 'XBMC.RunPlugin('+context_url+')', ))
            commands.append(( dev.lang(31007), 'XBMC.RunPlugin('+context_url2+')', ))
            dev.adddir(child.find('title').text, url, child.find('thumb').text, child.find('fanart').text, child.find('description').text, context=commands)
    xbmcplugin.endOfDirectory(vars.addon_handle)
def playlist_create_xml(playlist, type=''):
    dev.log('playlist_create_xml('+type+')')
    
    #<playlists>
    root = Element('seasons')
    #attr = { 'number' : season }
    #newxml = SubElement(root, 'season', attr)
    #attr = { 'id' : videoId}
    #elem = SubElement(newxml, 'episode', attr)
    
    #playlist = xml_create_playlist(example)
    #Append this playlist to the new created xml file
    #newxml.append(playlist)
    #Write this new xml to the settings.xml file
    write_xml(root, dev.typeEpnr(type), playlist+'.xml')
    dev.log('playlist_create_xml: Created new '+dev.typeEpnr(type)+'/'+playlist+'.xml')
def playlist_create_xml(playlist, type=''):
    dev.log('playlist_create_xml(' + type + ')')

    #<playlists>
    root = Element('seasons')
    #attr = { 'number' : season }
    #newxml = SubElement(root, 'season', attr)
    #attr = { 'id' : videoId}
    #elem = SubElement(newxml, 'episode', attr)

    #playlist = xml_create_playlist(example)
    #Append this playlist to the new created xml file
    #newxml.append(playlist)
    #Write this new xml to the settings.xml file
    write_xml(root, dev.typeEpnr(type), playlist + '.xml')
    dev.log('playlist_create_xml: Created new ' + dev.typeEpnr(type) + '/' +
            playlist + '.xml')
def addBookmark(currentTime, name, imdb='0'):
    import hashlib
    dev.log('addBookmark(%s)' % name)
    try:
        idFile = hashlib.md5()
        for i in name: idFile.update(str(i))
        for i in imdb: idFile.update(str(i))
        idFile = str(idFile.hexdigest())
        dev.log('addBookmark: idFile calculated: %s' % idFile)
        timeInSeconds = str(currentTime)
        xbmcvfs.mkdir(xbmc.translatePath(vars.addonInfo('profile')).decode('utf-8')) #Create the directory if it does not yet exist
        dbcon = database.connect(os.path.join(vars.dataPath, 'settings.db'))
        dbcur = dbcon.cursor()
        dbcur.execute("CREATE TABLE IF NOT EXISTS bookmark (""idFile TEXT, ""timeInSeconds TEXT, ""UNIQUE(idFile)"");")
        dbcur.execute("DELETE FROM bookmark WHERE idFile = '%s'" % idFile)
        dbcur.execute("INSERT INTO bookmark Values (?, ?)", (idFile, timeInSeconds))
        dbcon.commit()
    except:
        pass
def xml_get_elem(path,
                 tag,
                 whereAttrib=False,
                 whereTxt=False,
                 playlist=False,
                 type=''):
    dev.log('XML_get_elem(' + type + ')')
    if playlist == False:
        xml_get(type)  # Grab the xml file
        doc = document
    else:
        doc = playlist_xml_get(
            playlist, type=type)  #Grab the episodes.xml file of this playlist

    for child in doc.findall(path):
        check = True  # Use this var to check if this element meets all requirements. Set it by default to true, so it can be set to False if it fails some requirement
        #Check if this element has the tag we are looking for
        if child.tag == tag:
            #Should we also check that the element has a certain attribute with a certain value?
            if whereAttrib != False:
                # Check if this element meets all the requirements of the attributes
                for key, value in whereAttrib.iteritems():
                    if child.attrib[key] != value:
                        #This element does not meet all requirements, so quit this for loop, since checking for others ones has no use, since it already does meet this requirement
                        check = False
                        break

            if check == False:  #It has already failed to meet a requirement, so skip to the next xml element
                continue

            #Should we check if the element has the given text?
            if whereTxt != False:
                # Check if this element has the same text as required
                if child.text != whereTxt:
                    #This XML element does not meet te requirement of holding the same text, so we will skip to the next xml element
                    continue

            #If check is still true, we have found the correct element, so return this element
            return child
            break

    #If the code has made it here, that means it has failed to find the xml element, so return None
    return None
def refresh_playlist(id, type=''):
    #Grab the settings from this playlist
    settings = m_xml.xml_get_elem('playlists/playlist', 'playlist', {'id': id}, type=type) #Grab the xml settings for this playlist
    if settings is None:
        dev.log('refreshPlaylist: Could not find playlist '+id+' in the '+typeXml(type)+' file', True)
        return False
    else:         
        i = xbmcgui.Dialog().yesno("Refresh Playlist", "Are you sure you want to refresh this playlist?")
        if i != 0:
            m_xml.xml_update_playlist_setting(id, 'lastvideoId', '', type=type)
            #Delete the .xml containing all scanned videoId's as well
            file = os.path.join(vars.settingsPath, dev.typeEpnr(type))
            file = os.path.join(file, id+'.xml')
            if os.path.isfile(file):
                success = os.remove(file) #Remove the episodenr xml file
            
            xbmcgui.Dialog().ok('Refreshed Playlist', 'Succesfully refreshed playlist '+id)
            i = xbmcgui.Dialog().yesno('Delete from library', 'Do you also want to delete the previous videos from your library?')
            if i != 0:
                #Check in which folder the show resides
                folder = settings.find('overwritefolder').text
                if folder is None or folder == '':
                    folder = dev.legal_filename(settings.find('title').text) #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
                else:
                    folder = dev.legal_filename(folder)
                movieLibrary = vars.tv_folder #Use the directory from the addon settings
                if type == 'musicvideo':
                    movieLibrary = vars.musicvideo_folder
                elif type == 'movies':
                    movieLibrary = vars.movies_folder
                dir = os.path.join(movieLibrary, folder) #Set the folder to the maindir/dir
                
                success = shutil.rmtree(dir, ignore_errors=True) #Remove the directory
                #if vars.update_videolibrary == "true" and type=='':
                #    update_dir = vars.tv_folder_path
                #    if type == 'musicvideo':
                #        update_dir = vars.musicvideo_folder_path
                #    dev.log('Updating video library is enabled. Cleaning librarys directory %s' % update_dir, True)
                #    xbmc.executebuiltin('xbmc.updatelibrary(Video,'+update_dir+')')

                xbmcgui.Dialog().ok('Removed from library', 'Deleted the previous videos from your library (You should clean your library, otherwise they will still show in your library)')
            editPlaylist(id, type=type) #Load the editplaylist view
def build_youtube():
    try:
        youtube = build(vars.YOUTUBE_API_SERVICE_NAME,
                        vars.YOUTUBE_API_VERSION,
                        developerKey=vars.API_KEY)
    except:
        dev.log(
            'ERROR: Could not connect to Youtube API! Will try again in 15 seconds with SSL disabled',
            2)
        import xbmc
        #Wait 15 seconds before trying again
        xbmc.Monitor().waitForAbort(15)
        #Try again with SSL disabled
        import ssl
        ssl._create_default_https_context = ssl._create_unverified_context
        youtube = build(vars.YOUTUBE_API_SERVICE_NAME,
                        vars.YOUTUBE_API_VERSION,
                        developerKey=vars.API_KEY)

    return youtube
Example #52
0
def update_playlist(id, type=''):
    settings = m_xml.xml_get_elem(
        'playlists/playlist', 'playlist', {'id': id},
        type=type)  #Grab the xml settings for this playlist
    if settings is None:
        dev.log(
            'Could not find playlist ' + id + ' in the ' + dev.typeXml(type) +
            ' file', True)
        return False
    else:
        dev.log('Updating playlist %s (Id: %s)' %
                (settings.find('title').text.encode('utf-8'), id))
        #Check in which folder the show should be added
        folder = settings.find('overwritefolder').text
        if folder is None or folder == '':
            folder = dev.legal_filename(
                settings.find('title').text
            )  #Overwrite folder is not set in settings.xml, so set the folder to the title of the show
        else:
            folder = dev.legal_filename(folder)

        #Create the tvshow.nfo
        writenfo = settings.find('writenfo').text
        if writenfo != 'no':
            if type == '' or type == 'tv':
                generators.write_tvshow_nfo(folder, settings)
            elif type == 'musicvideo':
                generators.write_artist_nfo(folder, settings)

        if update_playlist_vids(id, folder, settings, type=type) == False:
            return False  #something failed while updating the videos of the playlist

        #Save the time this playlist got updated in the xml
        import datetime
        d = datetime.datetime.now()
        m_xml.xml_update_playlist_attr(id,
                                       'scansince',
                                       d.strftime("%d/%m/%Y %H:%M:%S"),
                                       type=type)

        return True
def add_playlist(id, type=''):
    if type=='' or type=='tv':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/tv/'+id+'?api_token='+vars.__settings__.getSetting('api_token')
    if type=='musicvideo':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/musicvideos/'+id+'?api_token='+vars.__settings__.getSetting('api_token')
    if type=='movies':
        api_url = 'http://youtubelibrary.nl/api/v1/playlists/movies/'+id+'?api_token='+vars.__settings__.getSetting('api_token')
    dev.log('Adding the Api playlist to the config: '+api_url)
    data = json.load(urllib2.urlopen(api_url))
    
    if 'data' not in data:
        url = dev.build_url({'mode': 'ApiIndex'})
        dev.adddir('Something went wrong', url, description='There was an error getting the playlist from the youtubelibrary.nl API.')
        return False;
    
    playlist = data['data']
    
    return playlist
    
    url = dev.build_url({'mode': 'ApiAddPlaylist', 'type': type})
    dev.adddir(playlist['title'], url, description=playlist['description'])          
def getBookmark(name, imdb='0'):
    import hashlib
    dev.log('getBookmark(%s)' % name)
    offset = '0'
    #log('getBookmark 1')
    idFile = hashlib.md5()
    #log('getBookmark 2')
    for i in name: idFile.update(str(i))
    #log('getBookmark 3')
    for i in imdb: idFile.update(str(i))
    #log('getBookmark 4')
    idFile = str(idFile.hexdigest())
    #log('getBookmark: idFile calculated: %s' % idFile)
    xbmcvfs.mkdir(vars.dataPath) #Create the directory if it does not yet exist
    dbcon = database.connect(vars.databaseFile)
    dbcur = dbcon.cursor()
    dbcur.execute("SELECT * FROM bookmark WHERE idFile = '%s'" % idFile)
    match = dbcur.fetchone()
    offset = str(match[1])
    dbcon.commit()
    return offset  
def browse(api_url = 'default', params = False, type=''):
    if api_url == 'default':
        if type == '' or type == 'tv':
            api_url = 'http://youtubelibrary.nl/api/v1/playlists/tv'+build_url()+'&limit=20'
        if type == 'musicvideo':
            api_url = 'http://youtubelibrary.nl/api/v1/playlists/musicvideos'+build_url()+'&limit=20'
        if type == 'movies':
            api_url = 'http://youtubelibrary.nl/api/v1/playlists/movies'+build_url()+'&limit=20'
    
    #Check if we should add params
    if isinstance(params,dict):
        for key, val in params.iteritems():
            api_url += '&'+key+'='+val
    
    
    dev.log('Browse the API with url: '+api_url)
    data = json.load(urllib2.urlopen(api_url))
    
    if 'data' not in data:
        url = dev.build_url({'mode': 'ApiIndex'})
        dev.adddir('Something went wrong', url, description='There was an error connecting to the Ytlibrary API.')
        return False;


    for playlist in data['data']:
        #videos.append(search_result)
        url = dev.build_url({'mode': 'ApiAddPlaylist', 'id': playlist['id'], 'type': type})
        dev.adddir(playlist['title'], url, playlist['thumb'], fanart=playlist['fanart'], description=playlist['description'])
        
    if 'paginator' in data:
        if 'prev_page' in data['paginator']:
            if data['paginator']['prev_page'] is not None:
                url = dev.build_url({'mode': 'ApiBrowse', 'api_url': data['paginator']['prev_page'], 'type': type})
                dev.adddir('<< Page '+str(data['paginator']['current_page']-1), url, description='Go to the previous page')       
    
    if 'paginator' in data:
        if 'next_page' in data['paginator']:
            if data['paginator']['next_page'] is not None:
                url = dev.build_url({'mode': 'ApiBrowse', 'api_url': data['paginator']['next_page'], 'type': type})
                dev.adddir('>> Page '+str(data['paginator']['current_page']+1), url, description='Go to the next page to see more pre-configured playlists.')          
def playYoutubeVid(id, meta=None, poster=None):
    dev.log('poster: '+poster)
    #Poster URL that hickups the addon: image://C%3a%5cKodi%5cportable_data%5cuserdata%5caddon_data%5cplugin.video.youtubelibrary%5cStreams%5cTV%5cSleuteltje%20-%20Bios%20Intros%5cfolder.jpg/
    #poster = None
    if meta is None:
        #Create an empty meta, so we can fill it with the information grabbed from youtube
        meta = {}
    if poster is None:
        poster = 'Default.png'
    elif poster.startswith('image://'):
        poster = poster[8:-1]
        poster = urllib.unquote(urllib.unquote(poster))
        dev.log('poster cleaned: '+poster)
    
    
    #YDStreamExtractor.disableDASHVideo(True) #Kodi (XBMC) only plays the video for DASH streams, so you don't want these normally. Of course these are the only 1080p streams on YouTube
    
    try:
        #url = id #a youtube ID will work as well and of course you could pass the url of another site
        vid = YDStreamExtractor.getVideoInfo(id,quality=1) #quality is 0=SD, 1=720p, 2=1080p and is a maximum
        stream_url = vid.streamURL() #This is what Kodi (XBMC) will play
    except:
        dev.log('Failed to get a valid stream_url!')
        return False #Failed to grab a video title
    
    if 'title' not in meta:
        meta['title'] = vid.title #Store the youtube title in the meta  
    
    
    #xbmc.Player().play(v.getbest().url) #Play this video
    liz = xbmcgui.ListItem(meta['title'], iconImage=poster, thumbnailImage=poster)
    liz.setInfo( type="Video", infoLabels=meta )
    liz.setPath(stream_url)
    return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
def playYoutubeVid(id, meta=None, poster=None):
    dev.log('poster: '+poster)
    #Poster URL that hickups the addon: image://C%3a%5cKodi%5cportable_data%5cuserdata%5caddon_data%5cplugin.video.youtubelibrary%5cStreams%5cTV%5cSleuteltje%20-%20Bios%20Intros%5cfolder.jpg/
    #poster = None
    if meta is None:
        #Create an empty meta, so we can fill it with the information grabbed from youtube
        meta = {}
    if poster is None:
        poster = 'Default.png'
    elif poster.startswith('image://'):
        poster = poster[8:-1]
        poster = urllib.unquote(urllib.unquote(poster))
        dev.log('poster cleaned: '+poster)
    
    
	#YDStreamExtractor.disableDASHVideo(True) #Kodi (XBMC) only plays the video for DASH streams, so you don't want these normally. Of course these are the only 1080p streams on YouTube
	
	try:
		#url = id #a youtube ID will work as well and of course you could pass the url of another site
		vid = YDStreamExtractor.getVideoInfo(id,quality=1) #quality is 0=SD, 1=720p, 2=1080p and is a maximum
		stream_url = vid.streamURL() #This is what Kodi (XBMC) will play
	except:
		dev.log('Failed to get a valid stream_url!')
		return False #Failed to grab a video title
	
	if 'title' not in meta:
		meta['title'] = vid.title #Store the youtube title in the meta  
	
	
	#xbmc.Player().play(v.getbest().url) #Play this video
	liz = xbmcgui.ListItem(meta['title'], iconImage=poster, thumbnailImage=poster)
	liz.setInfo( type="Video", infoLabels=meta )
	liz.setPath(stream_url)
	return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
Example #58
0
def deleteBookmark(name, imdb='0'):
    dev.log('deleteBookmark(%s)' % name)
    import hashlib
    try:
        idFile = hashlib.md5()
        for i in name:
            idFile.update(str(i))
        for i in imdb:
            idFile.update(str(i))
        idFile = str(idFile.hexdigest())
        control.makeFile(control.vars.dataPath)
        dbcon = database.connect(os.path.join(vars.dataPath, 'settings.db'))
        dbcur = dbcon.cursor()
        dbcur.execute("CREATE TABLE IF NOT EXISTS bookmark ("
                      "idFile TEXT, "
                      "timeInSeconds TEXT, "
                      "UNIQUE(idFile)"
                      ");")
        dbcur.execute("DELETE FROM bookmark WHERE idFile = '%s'" % idFile)
        dbcon.commit()
    except:
        pass
def get_duration_vids(vid_ids, extra_info=False):
    dev.log('Grabbing duration of youtube videos')

    #Create a seperated string of vid_ids to give to the API
    idlist = ''
    for id in vid_ids:
        idlist += id + ','
    idlist = idlist[:-1]
    dev.log(
        'GET duration vids: https://www.googleapis.com/youtube/v3/videos?part=snippet%2C+contentDetails&maxResults=50&id='
        + idlist + '&key=' + vars.API_KEY)

    youtube = build_youtube()

    search_response = youtube.videos().list(part="contentDetails,statistics",
                                            maxResults=50,
                                            id=idlist).execute()

    #Get the duration of each video in the response
    durations = {}
    extra = {}
    for vid in search_response.get("items", []):
        dur = vid['contentDetails']['duration']
        dur = dur[2:]  #Strip PT from the duration
        #dev.log('Duration of video: '+dur)

        seconds = hms_to_sec(dur)

        #dev.log('Which makes the video %s seconds long' % seconds)
        vidid = vid['id']
        durations[vidid] = seconds
        if extra_info is not False:
            extra[vidid] = vid['statistics']
        #except Exception as e:
        #dev.log("Couldnt extract time: %s" % e)
        #pass
    if extra_info is not False:
        return durations, extra
    return durations
Example #60
0
def getBookmark(name, imdb='0'):
    import hashlib
    dev.log('getBookmark(%s)' % name)
    offset = '0'
    #log('getBookmark 1')
    idFile = hashlib.md5()
    #log('getBookmark 2')
    for i in name:
        idFile.update(str(i))
    #log('getBookmark 3')
    for i in imdb:
        idFile.update(str(i))
    #log('getBookmark 4')
    idFile = str(idFile.hexdigest())
    #log('getBookmark: idFile calculated: %s' % idFile)
    xbmcvfs.mkdir(
        vars.dataPath)  #Create the directory if it does not yet exist
    dbcon = database.connect(vars.databaseFile)
    dbcur = dbcon.cursor()
    dbcur.execute("SELECT * FROM bookmark WHERE idFile = '%s'" % idFile)
    match = dbcur.fetchone()
    offset = str(match[1])
    dbcon.commit()
    return offset