def identify_unmatched(mediatype):
    busy = pykodi.get_busydialog()
    busy.create()
    processed = ProcessedItems()
    ulist = quickjson.get_item_list(mediatype)
    if mediatype == mediatypes.MUSICVIDEO:
        for item in ulist:
            item['label'] = info.build_music_label(item)
    unmatched = [
        item for item in ulist
        if not processed.get_data(item[mediatype +
                                       'id'], mediatype, item['label'])
    ]
    busy.close()
    if unmatched:
        selected = xbmcgui.Dialog().select(L(
            M.UNMATCHED_ITEMS), [item['label'] for item in unmatched])
        if selected < 0:
            return  # Cancelled
        mediaitem = info.MediaItem(unmatched[selected])
        info.add_additional_iteminfo(mediaitem, processed, search)
        processor = ArtworkProcessor()
        if processor.manual_id(mediaitem):
            processor.process_item(mediatype, mediaitem.dbid, 'auto')
    else:
        xbmcgui.Dialog().notification("Artwork Beef", L(M.NO_UNMATCHED_ITEMS),
                                      xbmcgui.NOTIFICATION_INFO)
Beispiel #2
0
 def doget(self, url, **kwargs):
     try:
         return self.getter(url, **kwargs)
     except GetterError as ex:
         message = L(CANT_CONTACT_PROVIDER) if ex.connection_error else L(
             HTTP_ERROR).format(ex.message)
         raise ProviderError(message, ex.cause)
Beispiel #3
0
 def onInit(self):
     # This is called every time the window is shown
     if not self.selected:
         self.getControl(
             1).setLabel("Artwork Beef: " +
                         L(CHOOSE_TYPE_HEADER).format(self.medialabel))
         self.getControl(3).setVisible(False)
         self.getControl(5).setVisible(self.show_refresh)
         self.getControl(5).setLabel(L(REFRESH_ITEM))
         self.guilist = self.getControl(6)
         for arttype in self.arttypes:
             listitem = xbmcgui.ListItem(arttype['label'])
             summary = L(AVAILABLE_COUNT).format(arttype['count'])
             listitem.setLabel2(summary)
             # DEPRECATED: Above Krypton and higher (only), below Jarvis and lower (only)
             listitem.setProperty('Addon.Summary', summary)
             listitem.setPath(arttype['arttype'])
             if arttype.get('url'):
                 listitem.setIconImage(arttype['url'])
                 # DEPRECATED: Above is deprecated in Jarvis, but still works through Krypton (at least)
                 # listitem.setArt({'icon': arttype.get('url')})
             self.guilist.addItem(listitem)
     else:
         self.selected = None
     self.setFocus(self.guilist)
def make_local():
    fileman = FileManager()

    def downloadforitem(mediaitem):
        try:
            fileman.downloadfor(mediaitem)
            newart = dict((k, v)
                          for k, v in mediaitem.downloadedart.iteritems()
                          if not v or not v.startswith('http'))
            for arttype in newart:
                # remove old URL from texture cache
                if mediaitem.art.get(arttype, '').startswith('http'):
                    quickjson.remove_texture_byurl(mediaitem.art[arttype])
            return newart
        except FileError as ex:
            mediaitem.error = ex.message
            log(ex.message, xbmc.LOGERROR)
            xbmcgui.Dialog().notification("Artwork Beef", ex.message,
                                          xbmcgui.NOTIFICATION_ERROR)
            return {}

    downloaded = runon_medialist(downloadforitem, L(M.MAKE_LOCAL), fg=True)
    xbmcgui.Dialog().ok(
        "Artwork Beef",
        L(M.DOWNLOAD_COUNT).format(downloaded) +
        ' - {0:0.2f}MB'.format(fileman.size / 1000000.00))
def show_artwork_log():
    if pykodi.get_kodi_version() < 16:
        xbmcgui.Dialog().notification("Artwork Beef",
                                      L(M.VERSION_REQUIRED).format("Kodi 16"),
                                      xbmcgui.NOTIFICATION_INFO)
        return
    xbmcgui.Dialog().textviewer("Artwork Beef: " + L(M.REPORT_TITLE),
                                reporting.get_latest_report())
Beispiel #6
0
    def onInit(self):
        self.getControl(1).setLabel(
            "Artwork Beef: " +
            L(CHOOSE_ART_HEADER).format(self.arttype, self.medialabel))
        self.getControl(3).setVisible(False)
        self.getControl(5).setVisible(self.multi)
        self.getControl(5).setLabel('$LOCALIZE[186]')
        self.guilist = self.getControl(6)

        for image in self.artlist:
            provider = image['provider'].display
            if isinstance(provider, int):
                provider = L(provider)
            secondprovider = image.get('second provider')
            if secondprovider:
                if isinstance(secondprovider, int):
                    secondprovider = L(secondprovider)
                provider = '{0}, {1}'.format(provider, secondprovider)
            title = image.get('title')
            if not title and 'subtype' in image:
                title = image['subtype'].display
            language = xbmc.convertLanguage(
                image['language'],
                xbmc.ENGLISH_NAME) if image.get('language') else None
            if not title:
                title = language
            if title and len(title) < 20 and not secondprovider:
                label = '{0} from {1}'.format(title, provider)
                summary = language if language and language != title else ''
            else:
                label = provider
                if language and language != title:
                    title = language + ' ' + title
                summary = title if title else ''
            rating = image.get('rating')
            size = image.get('size')
            if (rating or size) and summary:
                summary += '\n'
            if size:
                summary += image['size'].display
            if rating and size:
                summary += '   '
            if rating:
                summary += image['rating'].display
            listitem = xbmcgui.ListItem(label)
            listitem.setLabel2(summary)
            # DEPRECATED: Above Krypton and higher (only), below Jarvis and lower (only)
            listitem.setProperty('Addon.Summary', summary)
            listitem.setIconImage(image['preview'])
            # DEPRECATED: Above is deprecated in Jarvis, but still works through Krypton (at least)
            # listitem.setArt({'icon': image['preview']})
            listitem.setPath(image['url'])
            if image.get('existing'):
                listitem.select(True)
            self.guilist.addItem(listitem)
        self.setFocus(self.guilist)
def save_arttypes(arttype_map):
    root = read_xml()
    if root is None:
        xbmcgui.Dialog().notification("Artwork Beef", L(MALFORMED),
                                      xbmcgui.NOTIFICATION_WARNING)
        return False

    set_arttypes(root, arttype_map)

    if save_backup():
        save_xml(root)
        xbmcgui.Dialog().ok("Artwork Beef", L(RESTART_KODI))
 def doget(self, url, **kwargs):
     try:
         result = self.getter(url, **kwargs)
         if not result and url.startswith('http://'):
             # Try https, the browser "that totally shows this image" probably is, even if no redirect
             result, err = self.doget('https://' + url[7:])
             if err or not result:
                 result = None
         return result, None
     except GetterError as ex:
         message = L(CANT_CONTACT_PROVIDER) if ex.connection_error \
             else L(HTTP_ERROR).format(ex.message) + '\n' + url
         return None, message
def cache_artwork(librarytype='videos'):
    fileman = FileManager(False, True)
    if not fileman.imagecachebase:
        xbmcgui.Dialog().notification("Artwork Beef",
                                      L(M.REMOTE_CONTROL_REQUIRED),
                                      xbmcgui.NOTIFICATION_WARNING)
        return
    heading = L(M.CACHE_VIDEO_ARTWORK if librarytype ==
                'videos' else M.CACHE_MUSIC_ARTWORK)
    cached = runon_medialist(lambda mi: fileman.cachefor(mi.art, True),
                             heading,
                             librarytype,
                             fg=True)
    xbmcgui.Dialog().ok("Artwork Beef", L(M.CACHED_COUNT).format(cached))
def save_backup():
    if xbmcvfs.exists(FILENAME):
        xbmcvfs.copy(FILENAME, FILENAME_BAK)
        result = xbmcvfs.exists(FILENAME_BAK)
        if result:
            xbmcgui.Dialog().notification("Artwork Beef", L(BACKUP_SUCCESSFUL))
        else:
            xbmcgui.Dialog().notification("Artwork Beef",
                                          L(BACKUP_UNSUCCESSFUL),
                                          xbmc.LOGWARNING)
        return result
    log("advancedsettings.xml doesn't exist, can't save backup",
        xbmc.LOGNOTICE)
    return True
def report_item(mediaitem, forcedreport=False, manual=False, downloaded_size=0):
    if debug or not forcedreport and not settings.report_peritem:
        return
    with _get_file() as reportfile:
        itemtitle = "{0} '{1}'".format(mediaitem.mediatype, mediaitem.label) if mediaitem.mediatype != mediatypes.EPISODE \
            else "{0} '{1}' of '{2}'".format(mediaitem.mediatype, mediaitem.label, mediaitem.showtitle)
        message = "== {0}: ".format(get_datetime()) if forcedreport else ""
        message += L(PROCESSING_MANUALLY if manual else PROCESSING)
        write(reportfile, message.format(itemtitle))
        message = L(NO_IDS_MESSAGE) if mediaitem.missingid \
            else L(MISSING_LABEL).format(', '.join(mediaitem.missingart)) if mediaitem.missingart \
            else L(NO_MISSING_ARTWORK)
        write(reportfile, message)

        if mediaitem.downloadedart:
            message = L(DOWNLOAD_COUNT).format(len(mediaitem.downloadedart))
            if downloaded_size:
                message += ' - {0:0.2f}MB'.format(downloaded_size / 1000000.00)
            write(reportfile, message)
        if mediaitem.updatedart:
            write(reportfile, L(UPDATED_LABEL).format(', '.join(mediaitem.updatedart)))
        elif manual or mediaitem.missingart:
            write(reportfile, L(NO_UPDATES))

        if mediaitem.error:
            write(reportfile, L(ERROR_MESSAGE).format(pykodi.scrub_message(mediaitem.error)))
        if forcedreport:
            finish_chunk(reportfile)
    if forcedreport and _should_rotate():
        _rotate_file()
def report_start(medialist):
    if debug:
        return
    with _get_file() as reportfile:
        write(reportfile, "== {0}: ".format(get_datetime()) + L(PROCESSING_AUTOMATICALLY))
        if not medialist:
            write(reportfile, L(NO_ITEMS))
            write(reportfile, '')
            return
        mediatypecount = {}
        for item in medialist:
            mediatypecount[item.mediatype] = mediatypecount.get(item.mediatype, 0) + 1

        write(reportfile, L(ITEM_COUNT).format(len(medialist)) + " - " +
            ', '.join('{0}: {1}'.format(mt, mediatypecount[mt]) for mt in mediatypecount))
Beispiel #13
0
 def doget(self, url, **kwargs):
     try:
         result = self.getter(url, **kwargs)
         if not result and url.startswith('http://'):
             # Try https, the browser "that totally shows this image" probably is, even if no redirect
             result, err = self.doget('https://' + url[7:])
             if err or not result:
                 result = None
         return result, None
     except GetterError as ex:
         if ex.response is not None and ex.response.status_code == 403:
             # TVDB returns Forbidden for certain images. Don't show an error message, replace it
             return None, None
         message = L(CANT_CONTACT_PROVIDER) if ex.connection_error \
             else L(HTTP_ERROR).format(ex.message) + '\n' + url
         return None, message
    def onInit(self):
        self.getControl(1).setLabel(L(ACTION_SELECTSERIES))
        self.getControl(3).setVisible(False)
        self.getControl(5).setVisible(True)
        self.getControl(5).setLabel('$LOCALIZE[186]')
        self.guilist = self.getControl(6)
        self.guilist.setVisible(True)

        for series in self.serieslist:
            listitem = xbmcgui.ListItem(series['label'])
            summary = str(series['year']) + ' - ' + series['plot']
            listitem.setLabel2(summary)
            # DEPRECATED: Above Krypton and higher (only), below Jarvis and lower (only)
            listitem.setProperty('Addon.Summary', summary)
            listitem.setProperty('imdbnumber', series['imdbnumber'])
            art = series['art']
            if 'poster' in series['art']:
                art['thumb'] = series['art']['poster']
            listitem.setArt(art)
            if series['imdbnumber'] in self.originalselected:
                listitem.select(True)
                self.selected.append(series['imdbnumber'])
            self.guilist.addItem(listitem)
        self.originalselected = list(self.selected)
        self.setFocus(self.guilist)
def restore_backup():
    if xbmcvfs.exists(FILENAME_BAK):
        xbmcvfs.copy(FILENAME_BAK, FILENAME)
        xbmcvfs.delete(FILENAME_BAK)
        result = xbmcvfs.exists(FILENAME)
        if result:
            xbmcgui.Dialog().notification("Artwork Beef",
                                          L(RESTORE_SUCCESSFUL))
        else:
            xbmcgui.Dialog().notification("Artwork Beef",
                                          L(RESTORE_UNSUCCESSFUL),
                                          xbmc.LOGWARNING)
        return result
    log("advancedsettings.xml.beef.bak doesn't exist, can't restore backup",
        xbmc.LOGWARNING)
    return False
Beispiel #16
0
def save_arttypes_to_asxml():
    can_continue = xbmcgui.Dialog().ok("Artwork Beef", L(M.INTRO_TEXT))
    if not can_continue:
        return
    include_multiple = xbmcgui.Dialog().yesno("Artwork Beef",
                                              L(M.INCLUDE_MULTIPLES))
    art_toset = {}
    for mediatype in mediatypes.artinfo:
        if include_multiple:
            art_toset[mediatype] = list(
                mediatypes.iter_every_arttype(mediatype))
        else:
            art_toset[mediatype] = [
                a for a in mediatypes.iter_every_arttype(mediatype)
                if not a[-1].isdigit()
            ]

    advancedsettings.save_arttypes(art_toset)
Beispiel #17
0
def set_autoaddepisodes():
    busy = pykodi.get_busydialog()
    busy.create()
    serieslist = [
        series for series in quickjson.get_tvshows(True)
        if series.get('imdbnumber')
    ]
    busy.close()
    selected = SeriesSelector('DialogSelect.xml',
                              settings.addon_path,
                              serieslist=serieslist,
                              selected=settings.autoadd_episodes).prompt()
    if selected != settings.autoadd_episodes:
        settings.autoadd_episodes = selected
        if xbmcgui.Dialog().yesno(L(M.ADD_MISSING_HEADER),
                                  L(M.ADD_MISSING_MESSAGE)):
            pykodi.execute_builtin(
                'NotifyAll(script.artwork.beef:control, ProcessAfterSettings)')
def report_startup():
    if not xbmcvfs.exists(settings.datapath):
        xbmcvfs.mkdir(settings.datapath)
    with _get_file() as reportfile:
        reportfile.seek(0, os.SEEK_SET)
        newline = "= " + L(RUNNING_VERSION).format(settings.useragent)
        line_exists = any(newline in line for line in reportfile)
        if not line_exists:
            reportfile.seek(0, os.SEEK_END)
            write(reportfile, newline)
            finish_chunk(reportfile)
Beispiel #19
0
def remove_art():
    # TODO: seasons and episodes and whatever like "add missing artwork" does
    listitem = sys.listitem
    mediatype = get_mediatype(listitem)
    dbid = get_dbid(listitem)

    if not (dbid or mediatype):
        return

    if not xbmcgui.Dialog().yesno("Artwork Beef: " + L(32427), L(750)):
        return
    remove_localfiles = xbmcgui.Dialog().yesno("Artwork Beef", L(32062))
    mediaitem = info.MediaItem(quickjson.get_item_details(dbid, mediatype))
    mediaitem.selectedart = cleaner.remove_specific_arttype(mediaitem, '* all')
    if remove_localfiles:
        FileManager().remove_deselected_files(mediaitem, True)
    info.update_art_in_library(mediatype, dbid, mediaitem.selectedart)
    info.remove_local_from_texturecache(mediaitem.art.values(), True)
    xbmcgui.Dialog().notification("Artwork Beef",
                                  L(32027).format(len(mediaitem.selectedart)))
Beispiel #20
0
def recyclefile(filename):
    firstdir = utils.parent_dir(filename)
    directory = TEMP_DIR
    pathsep = utils.get_pathsep(directory)
    if firstdir in ('extrafanart', 'extrathumbs'):
        directory += utils.parent_dir(os.path.dirname(filename)) + pathsep
    directory += firstdir
    if not xbmcvfs.exists(directory):
        xbmcvfs.mkdirs(directory)
    recycled_filename = directory + pathsep + os.path.basename(filename)
    if not xbmcvfs.copy(filename, recycled_filename):
        raise FileError(L(CANT_WRITE_TO_FILE).format(recycled_filename))
Beispiel #21
0
def add_missing_for():
    options = [(L(M.FOR_NEW_VIDEOS), 'ProcessNewVideos'),
               (L(M.FOR_OLD_VIDEOS), 'ProcessNewAndOldVideos'),
               (L(M.FOR_ALL_VIDEOS), 'ProcessAllVideos')]
    if get_kodi_version() >= 18:
        options.extend(((L(M.FOR_NEW_AUDIO), 'ProcessNewMusic'),
                        (L(M.FOR_OLD_AUDIO), 'ProcessNewAndOldMusic'),
                        (L(M.FOR_ALL_AUDIO), 'ProcessAllMusic')))

    selected = xbmcgui.Dialog().select(L(M.ADD_MISSING_FOR),
                                       [option[0] for option in options])
    if selected >= 0 and selected < len(options):
        pykodi.execute_builtin(
            'NotifyAll(script.artwork.beef:control, {0})'.format(
                options[selected][1]))
Beispiel #22
0
 def _build_imagecachebase(self):
     result = pykodi.execute_jsonrpc({
         "jsonrpc": "2.0",
         "id": 1,
         "method": "Settings.GetSettings",
         "params": {
             "filter": {
                 "category": "control",
                 "section": "services"
             }
         }
     })
     port = 80
     username = ''
     password = ''
     secure = False
     server_enabled = True
     if result.get('result', {}).get('settings'):
         for setting in result['result']['settings']:
             if setting[
                     'id'] == 'services.webserver' and not setting['value']:
                 server_enabled = False
                 break
             if setting['id'] == 'services.webserverusername':
                 username = setting['value']
             elif setting['id'] == 'services.webserverport':
                 port = setting['value']
             elif setting['id'] == 'services.webserverpassword':
                 password = setting['value']
             elif setting['id'] == 'services.webserverssl' and setting[
                     'value']:
                 secure = True
         username = '******'.format(
             username, password) if username and password else ''
     else:
         server_enabled = False
     if server_enabled:
         protocol = 'https' if secure else 'http'
         self.imagecachebase = '{0}://{1}localhost:{2}/image/'.format(
             protocol, username, port)
     else:
         self.imagecachebase = None
         log(L(REMOTE_CONTROL_REQUIRED), xbmc.LOGWARNING)
Beispiel #23
0
 def get_external_artwork(self,
                          mediatype,
                          seasons,
                          uniqueids,
                          missing=None):
     images = {}
     error = None
     for provider in providers.external.get(mediatype, ()):
         errcount = self.providererrors.get(provider.name, 0)
         if errcount == MAX_ERRORS:
             continue
         try:
             providerimages = provider.get_images(uniqueids, missing)
             self.providererrors[provider.name] = 0
         except Exception as ex:
             # gross. need to split "getting" and "parsing" then catch and wrap exceptions
             # on the latter, then leave most of this code back for "ProviderError" only
             errcount += 1
             self.providererrors[provider.name] = errcount
             if errcount != 1 and errcount != MAX_ERRORS:
                 continue
             error = {'providername': provider.name.display}
             if errcount == 1:  # notify on first error
                 error['message'] = getattr(ex, 'message', repr(ex))
             elif errcount == MAX_ERRORS:  # and on last error when we're no longer going to try this provider
                 error['message'] = L(TOO_MANY_ERRORS)
             if not isinstance(ex, ProviderError):
                 log("Error parsing provider response", xbmc.LOGWARNING)
                 log(traceback.format_exc(), xbmc.LOGWARNING)
             continue
         for arttype, artlist in providerimages.iteritems():
             if arttype.startswith('season.'):
                 season = arttype.rsplit('.', 2)[1]
                 if int(season) not in seasons:
                     # Don't add artwork for seasons we don't have
                     continue
             if arttype not in images:
                 images[arttype] = []
             images[arttype].extend(artlist)
         if self.monitor.abortRequested():
             break
     return images, error
Beispiel #24
0
 def manual_id(self, mediaitem):
     label = ENTER_COLLECTION_NAME if mediaitem.mediatype == mediatypes.MOVIESET else ENTER_ARTIST_TRACK_NAMES
     result = xbmcgui.Dialog().input(L(label), mediaitem.label)
     if not result:
         return False  # Cancelled
     options = search[mediaitem.mediatype].search(result,
                                                  mediaitem.mediatype)
     selected = xbmcgui.Dialog().select(
         mediaitem.label, [option['label'] for option in options])
     if selected < 0:
         return False  # Cancelled
     uq = options[selected]['uniqueids']
     toset = uq.get('tmdb')
     if not toset and 'mbtrack' in uq and 'mbgroup' in uq and 'mbartist' in uq:
         toset = '{0}/{1}/{2}'.format(uq['mbtrack'], uq['mbgroup'],
                                      uq['mbartist'])
     if toset:
         self.processed.set_data(mediaitem.dbid, mediaitem.mediatype,
                                 mediaitem.label, toset)
     return bool(toset)
Beispiel #25
0
def tag_forcedandexisting_art(availableart, forcedart, existingart):
    typeinsert = {}
    for exacttype, artlist in sorted(
            forcedart.iteritems(),
            key=lambda arttype: natural_sort(arttype[0])):
        arttype = info.get_basetype(exacttype)
        if arttype not in availableart:
            availableart[arttype] = artlist
        else:
            for image in artlist:
                match = next((available for available in availableart[arttype]
                              if available['url'] == image['url']), None)
                if match:
                    if 'title' in image and 'title' not in match:
                        match['title'] = image['title']
                    match['second provider'] = image['provider'].display
                else:
                    typeinsert[arttype] = typeinsert[
                        arttype] + 1 if arttype in typeinsert else 0
                    availableart[arttype].insert(typeinsert[arttype], image)

    typeinsert = {}
    for exacttype, existingurl in existingart.iteritems():
        arttype = info.get_basetype(exacttype)
        if arttype in availableart:
            match = next((available for available in availableart[arttype]
                          if available['url'] == existingurl), None)
            if match:
                match['preview'] = existingurl
                match['existing'] = True
            else:
                typeinsert[arttype] = typeinsert[
                    arttype] + 1 if arttype in typeinsert else 0
                image = {
                    'url': existingurl,
                    'preview': existingurl,
                    'title': exacttype,
                    'existing': True,
                    'provider': SortedDisplay('current', L(CURRENT_ART))
                }
                availableart[arttype].insert(typeinsert[arttype], image)
def report_end(medialist, abortedcount, downloaded_size):
    if debug:
        return
    if len(medialist) <= 1:
        if _should_rotate():
            _rotate_file()
        return
    with _get_file() as reportfile:
        write(reportfile, get_datetime() + ": " + L(PROCESSING_ABORTED if abortedcount else PROCESSING_FINISHED))
        if abortedcount:
            write(reportfile, L(PROCESSED_COUNT).format(abortedcount))
        arttypecount = {}
        total = 0
        downloaded = 0
        errorcount = 0
        for item in medialist:
            for arttype in item.updatedart:
                arttype = get_basetype(arttype)
                arttypecount[arttype] = arttypecount.get(arttype, 0) + 1
                total += 1
            if item.error:
                errorcount += 1
            downloaded += len(item.downloadedart)

        if downloaded:
            # TODO: include # of existing items downloaded, or the # of items added and downloaded
            write(reportfile, L(DOWNLOAD_COUNT).format(downloaded)
                + ' - {0:0.2f}MB'.format(downloaded_size / 1000000.00))
        if not total:
            write(reportfile, L(NO_UPDATES))
        else:
            write(reportfile, L(UPDATE_COUNT).format(total) + " - " +
                ', '.join('{0}: {1}'.format(at, arttypecount[at]) for at in arttypecount))
        if errorcount:
            write(reportfile, L(ERRORS_MESSAGE))
        finish_chunk(reportfile)
    if _should_rotate():
        _rotate_file()
def add_additional_iteminfo(mediaitem, processed, search=None):
    '''Get more data from the Kodi library, processed items, and look up web service IDs.'''
    if search and mediaitem.mediatype in search:
        search = search[mediaitem.mediatype]
    if mediaitem.mediatype == mediatypes.TVSHOW:
        # TODO: Split seasons out to separate items
        if not mediaitem.seasons:
            mediaitem.seasons, seasonart = _get_seasons_artwork(
                quickjson.get_seasons(mediaitem.dbid))
            mediaitem.art.update(seasonart)
        if search and settings.default_tvidsource == 'tmdb' and 'tvdb' not in mediaitem.uniqueids:
            # TODO: Set to the Kodi library if found
            resultids = search.get_more_uniqueids(mediaitem.uniqueids,
                                                  mediaitem.mediatype)
            if 'tvdb' in resultids:
                mediaitem.uniqueids['tvdb'] = resultids['tvdb']
    elif mediaitem.mediatype == mediatypes.SEASON:
        tvshow = quickjson.get_item_details(mediaitem.tvshowid,
                                            mediatypes.TVSHOW)
        mediaitem.file = tvshow['file']
    elif mediaitem.mediatype == mediatypes.EPISODE:
        if settings.default_tvidsource == 'tmdb':
            # TheMovieDB scraper sets episode IDs that can't be used in the API, but seriesID/season/episode works
            uniqueids = quickjson.get_item_details(
                mediaitem.tvshowid, mediatypes.TVSHOW)['uniqueid']
            uniqueid = uniqueids.get('tmdb', uniqueids.get('unknown'))
            if uniqueid:
                mediaitem.uniqueids['tmdbse'] = '{0}/{1}/{2}'.format(
                    uniqueid, mediaitem.season, mediaitem.episode)
    elif mediaitem.mediatype == mediatypes.MOVIESET:
        if not mediaitem.uniqueids.get('tmdb'):
            uniqueid = processed.get_data(mediaitem.dbid, mediaitem.mediatype,
                                          mediaitem.label)
            if search and not uniqueid and not mediatypes.only_filesystem(
                    mediaitem.mediatype):
                searchresults = search.search(mediaitem.label,
                                              mediaitem.mediatype)
                if searchresults:
                    for result in searchresults:
                        if result['label'] == mediaitem.label:
                            uniqueid = result['uniqueids']['tmdb']
                            break
                    uniqueid = searchresults[0]['uniqueids']['tmdb']
                if uniqueid:
                    processed.set_data(mediaitem.dbid, mediatypes.MOVIESET,
                                       mediaitem.label, uniqueid)
                else:
                    processed.set_data(mediaitem.dbid, mediatypes.MOVIESET,
                                       mediaitem.label, None)
                    mediaitem.error = L(CANT_FIND_MOVIESET)
                    log(
                        "Could not find set '{0}' on TheMovieDB".format(
                            mediaitem.label), xbmc.LOGNOTICE)

            mediaitem.uniqueids['tmdb'] = uniqueid
        if not processed.exists(mediaitem.dbid, mediaitem.mediatype,
                                mediaitem.label):
            _remove_set_movieposters(mediaitem)
        if settings.setartwork_fromparent and not mediaitem.file:
            _identify_parent_movieset(mediaitem)
    elif mediaitem.mediatype == mediatypes.MUSICVIDEO:
        if not mediaitem.uniqueids.get('mbtrack') or not mediaitem.uniqueids.get('mbgroup') \
                or not mediaitem.uniqueids.get('mbartist'):
            newdata = processed.get_data(mediaitem.dbid, mediaitem.mediatype,
                                         mediaitem.label)
            if newdata:
                mb_t, mb_al, mb_ar = newdata.split('/')
                mediaitem.uniqueids = {
                    'mbtrack': mb_t,
                    'mbgroup': mb_al,
                    'mbartist': mb_ar
                }
            elif search and not mediatypes.only_filesystem(
                    mediaitem.mediatype):
                results = search.search(mediaitem.label, mediatypes.MUSICVIDEO)
                uq = results and results[0].get('uniqueids')
                if uq and uq.get('mbtrack') and uq.get('mbgroup') and uq.get(
                        'mbartist'):
                    mediaitem.uniqueids = uq
                    processed.set_data(
                        mediaitem.dbid, mediatypes.MUSICVIDEO, mediaitem.label,
                        uq['mbtrack'] + '/' + uq['mbgroup'] + '/' +
                        uq['mbartist'])
                else:
                    processed.set_data(mediaitem.dbid, mediatypes.MUSICVIDEO,
                                       mediaitem.label, None)
                    mediaitem.error = L(CANT_FIND_MUSICVIDEO)
                    log(
                        "Could not find music video '{0}' on TheAudioDB".
                        format(mediaitem.label), xbmc.LOGNOTICE)
    elif mediaitem.mediatype == mediatypes.ALBUM:
        folders = _identify_album_folders(mediaitem)
        if folders:
            mediaitem.file, mediaitem.discfolders = folders
Beispiel #28
0
 def downloadfor(self, mediaitem, allartwork=True):
     if self.fileerror_count >= FILEERROR_LIMIT:
         return False, ''
     if not info.can_saveartwork(mediaitem):
         return False, ''
     to_download = get_downloadable_art(mediaitem, allartwork)
     if not to_download:
         return False, ''
     services_hit = False
     error = ''
     localfiles = get_local_art(mediaitem, allartwork)
     for arttype, url in to_download.items():
         hostname = urlparse.urlparse(url).netloc
         if self.provider_errors.get(hostname, 0) >= PROVIDERERROR_LIMIT:
             continue
         full_basefilepath = info.build_artwork_basepath(mediaitem, arttype)
         if not full_basefilepath:
             continue
         if self.debug:
             mediaitem.downloadedart[arttype] = full_basefilepath + '.ext'
             continue
         result, err = self.doget(url)
         if err:
             error = err
             self.provider_errors[hostname] = self.provider_errors.get(
                 hostname, 0) + 1
             continue
         if not result:
             # 404 URL dead, wipe it so we can add another one later
             mediaitem.downloadedart[arttype] = None
             continue
         self.size += int(result.headers.get('content-length', 0))
         services_hit = True
         ext = get_file_extension(result.headers.get('content-type'), url)
         if not ext:
             log("Can't determine extension for '{0}'\nfor image type '{1}'"
                 .format(url, arttype))
             continue
         full_basefilepath += '.' + ext
         if xbmcvfs.exists(full_basefilepath):
             if extrafanart_name_used(full_basefilepath, localfiles):
                 # REVIEW: can this happen in any other circumstance?
                 full_basefilepath = get_next_filename(
                     full_basefilepath, localfiles)
                 localfiles.append(full_basefilepath)
             if xbmcvfs.exists(
                     full_basefilepath) and settings.recycle_removed:
                 recyclefile(full_basefilepath)
         else:
             folder = os.path.dirname(full_basefilepath)
             if not xbmcvfs.exists(folder):
                 xbmcvfs.mkdirs(folder)
         # For now this just downloads the whole thing in memory, then saves it to file.
         #  Maybe chunking it will be better when GIFs are handled
         file_ = xbmcvfs.File(full_basefilepath, 'wb')
         with closing(file_):
             if not file_.write(result.content):
                 self.fileerror_count += 1
                 raise FileError(
                     L(CANT_WRITE_TO_FILE).format(full_basefilepath))
             self.fileerror_count = 0
         mediaitem.downloadedart[arttype] = full_basefilepath
         log("downloaded '{0}'\nto image file '{1}'".format(
             url, full_basefilepath))
     return services_hit, error
Beispiel #29
0
def main():
    settings.update_settings()
    mediatypes.update_settings()
    command = get_command()
    if command.get('dbid') and command.get('mediatype'):
        processor = ArtworkProcessor()
        processor.process_item(command['mediatype'], int(command['dbid']),
                               command.get('mode', 'auto'))
    elif 'command' in command:
        if command['command'] == 'set_autoaddepisodes':
            set_autoaddepisodes()
        elif command['command'] == 'show_artwork_log':
            show_artwork_log()
        elif command['command'] == 'set_download_artwork' and command.get(
                'mediatype'):
            set_download_artwork(command['mediatype'])
    else:
        processor = ArtworkProcessor()
        if processor.processor_busy:
            options = [
                (L(M.STOP),
                 'NotifyAll(script.artwork.beef:control, CancelCurrent)')
            ]
        else:
            options = [
                (L(M.ADD_MISSING_FOR), add_missing_for),
                (L(M.NEW_LOCAL_FILES),
                 'NotifyAll(script.artwork.beef:control, ProcessLocalVideos)'),
                (L(M.IDENTIFY_UNMATCHED_SETS),
                 lambda: identify_unmatched(mediatypes.MOVIESET)),
                (L(M.IDENTIFY_UNMATCHED_MVIDS),
                 lambda: identify_unmatched(mediatypes.MUSICVIDEO)),
                (L(M.REMOVE_SPECIFIC_TYPES), remove_specific_arttypes),
                (L(M.MAKE_LOCAL), make_local),
                (L(M.CACHE_VIDEO_ARTWORK), cache_artwork)
            ]
            if get_kodi_version() >= 18:
                options.append(
                    (L(M.CACHE_MUSIC_ARTWORK), lambda: cache_artwork('music')))
                options.append(
                    (L(M.SAVE_ARTTYPES_TO_ASXML), save_arttypes_to_asxml))
                if advancedsettings.has_backup():
                    options.append((L(M.RESTORE_ASXML_BACKUP),
                                    advancedsettings.restore_backup))
        selected = xbmcgui.Dialog().select('Artwork Beef',
                                           [option[0] for option in options])
        if selected >= 0 and selected < len(options):
            action = options[selected][1]
            if isinstance(action, basestring):
                pykodi.execute_builtin(action)
            else:
                action()
Beispiel #30
0
def runon_medialist(function,
                    heading,
                    medialist='videos',
                    typelabel=None,
                    fg=False):
    progress = xbmcgui.DialogProgress() if fg else xbmcgui.DialogProgressBG()
    progress.create(heading)
    monitor = xbmc.Monitor()

    if medialist == 'videos':
        steps_to_run = [
            (lambda: quickjson.get_item_list(mediatypes.MOVIE), L(M.MOVIES)),
            (info.get_cached_tvshows, L(M.SERIES)),
            (quickjson.get_seasons, L(M.SEASONS)),
            (lambda: quickjson.get_item_list(mediatypes.MOVIESET),
             L(M.MOVIESETS)), (quickjson.get_episodes, L(M.EPISODES)),
            (lambda: quickjson.get_item_list(mediatypes.MUSICVIDEO),
             L(M.MUSICVIDEOS))
        ]
    elif medialist == 'music' and get_kodi_version() >= 18:
        steps_to_run = [
            (lambda: quickjson.get_item_list(mediatypes.ARTIST), L(M.ARTISTS)),
            (lambda: quickjson.get_item_list(mediatypes.ALBUM), L(M.ALBUMS)),
            (lambda: quickjson.get_item_list(mediatypes.SONG), L(M.SONGS))
        ]
    else:
        steps_to_run = ((lambda: medialist, typelabel), )
    stepsize = 100 // len(steps_to_run)

    def update_art_for_items(items, start):
        changedcount = 0
        for i, item in enumerate(items):
            if fg:
                progress.update(start + i * stepsize // len(items),
                                item['label'])
            else:
                progress.update(start + i * stepsize // len(items))
            item = info.MediaItem(item)
            if item.mediatype == mediatypes.SEASON:
                item.file = info.get_cached_tvshow(item.tvshowid)['file']
            updates = function(item)
            if isinstance(updates, int):
                changedcount += updates
            else:
                processed = utils.get_simpledict_updates(item.art, updates)
                if processed:
                    info.update_art_in_library(item.mediatype, item.dbid,
                                               processed)
                    changedcount += len(processed)
            if monitor.abortRequested() or fg and progress.iscanceled():
                break
        return changedcount

    fixcount = 0
    for i, (list_fn, listtype) in enumerate(steps_to_run):
        start = i * stepsize
        if fg:
            progress.update(start, line1=L(M.LISTING_ALL).format(listtype))
        else:
            progress.update(start, message=L(M.LISTING_ALL).format(listtype))
        fixcount += update_art_for_items(list_fn(), start)
        if monitor.abortRequested() or fg and progress.iscanceled():
            break

    info.clear_cache()
    progress.close()
    return fixcount