def notifycount(count): log(L(ARTWORK_UPDATED_MESSAGE).format(count), xbmc.LOGINFO) if count: xbmcgui.Dialog().notification(L(ARTWORK_UPDATED_MESSAGE).format(count), L(FINAL_MESSAGE), '-', 7500) else: xbmcgui.Dialog().notification(L(NO_ARTWORK_UPDATED_MESSAGE), L(SOMETHING_MISSING) + ' ' + L(FINAL_MESSAGE), '-', 8000)
def get_movie_path_list(stackedpath): """Returns a list of filenames that can be used to find a movie's supporting files. The list includes both possible filenames for stacks, and the VIDEO_TS/BDMV parent directory. If neither applies, returns a list of one item, the original path. Check for the supporting files from each of these results.""" result = [] if not stackedpath.startswith('stack://'): result = [stackedpath] else: firstpath, path2 = stackedpath[8:].split(' , ')[0:2] path, filename = split(firstpath) if filename: filename2 = basename(path2) for regex in moviestacking: offset = 0 while True: match = regex.match(filename, offset) match2 = regex.match(filename2, offset) if match != None and match2 != None and match.group(1).lower() == match2.group(1).lower(): if match.group(2).lower() == match2.group(2).lower(): offset = match.start(3) continue result = [firstpath, path + '/' + filename[:offset] + match.group(1).rstrip() + match.group(4)] break else: # folder stacking pass # I can't even get Kodi to add stacked VIDEO_TS rips period if not result: log("Couldn't get an unstacked path from \"{0}\"".format(stackedpath), xbmc.LOGINFO) result = [firstpath] if basename(dirname(result[0])) in ('VIDEO_TS', 'BDMV'): result.append(dirname(dirname(result[0])) + '/' + basename(result[0])) return result
def process_medialist(self, medialist, alwaysnotify=False, stop_on_error=False): self.init_run(len(medialist) > 0) processed = {'tvshow': {}, 'movie': [], 'episode': []} artcount = 0 currentitem = 0 if medialist: gatherer = Gatherer(self.monitor, self.only_filesystem) for mediaitem in medialist: if not mediainfo.is_known_mediatype(mediaitem): continue log('Processing {0}'.format(mediaitem['label']), xbmc.LOGINFO) if self.visible: self.progress.update(currentitem * 100 // len(medialist), message=mediaitem['label']) currentitem += 1 self.add_additional_iteminfo(mediaitem) cleaned = mediaitem.get_artwork_updates(cleaner.clean_artwork(mediaitem), mediaitem['art']) if cleaned: add_art_to_library(mediaitem['mediatype'], mediaitem.get('seasons'), mediaitem['dbid'], cleaned) mediaitem['art'].update(cleaned) mediaitem['art'] = dict(item for item in mediaitem['art'].iteritems() if item[1]) forcedart, availableart, services_hit, error = gatherer.getartwork(mediaitem) if error: header = L(PROVIDER_ERROR_MESSAGE).format(error['providername']) xbmcgui.Dialog().notification(header, error['message'], xbmcgui.NOTIFICATION_WARNING) log('{0}\n{1}'.format(header, error['message'])) if stop_on_error: break else: add_processeditem(processed, mediaitem) for arttype, imagelist in availableart.iteritems(): self.sort_images(arttype, imagelist, mediaitem['file']) existingart = dict(mediaitem['art']) # Remove existing local artwork if it is no longer available localart = [(arttype, image['url']) for arttype, image in forcedart.iteritems() \ if not image['url'].startswith('http')] selectedart = dict((arttype, None) for arttype, url in existingart.iteritems() \ if not url.startswith('http') and (arttype, url) not in localart) selectedart.update((key, image['url']) for key, image in forcedart.iteritems()) selectedart = mediainfo.renumber_all_artwork(selectedart) existingart.update(selectedart) selectedart.update(self.get_top_missing_art(mediaitem['mediatype'], existingart, availableart, mediaitem.get('seasons'))) selectedart = mediainfo.get_artwork_updates(mediaitem['art'], selectedart) if selectedart: add_art_to_library(mediaitem['mediatype'], mediaitem.get('seasons'), mediaitem['dbid'], selectedart) artcount += len(selectedart) if not services_hit: if self.monitor.abortRequested(): break elif self.monitor.waitForAbort(THROTTLE_TIME): break self.finish_run() if alwaysnotify or artcount: notifycount(artcount) return processed
def _get_episodeid(self, episode): if 'unknown' in episode['uniqueid']: return episode['uniqueid']['unknown'] else: idsource, result = episode['uniqueid'].iteritems()[0] if episode['uniqueid'] else '', '' if result: # I don't know what this might be, I'm not even sure Kodi can do anything else at the moment, but just in case log("Didn't find 'unknown' uniqueid for episode, just picked the first, from '%s'." % idsource, xbmc.LOGINFO) else: log("Didn't find a uniqueid for episode '%s', can't look it up. I expect the ID from TheTVDB, which generally comes from the scraper." % episode['label'], xbmc.LOGNOTICE) return result
def onNotification(self, sender, method, data): if method.startswith("Other."): if sender == "script.artwork.beef": message = 'Received notification "{0}"'.format(method) if data != "null": message += " - data:\n" + data log(message, xbmc.LOGINFO) else: return if method == "Other.CancelCurrent": if self.status == STATUS_PROCESSING: self.abort = True elif self.signal: self.set_signal(None) self.processor.close_progress() elif method == "Other.ProcessNewItems": self.processor.create_progress() if addon.get_setting("lastalldate") == "0": self.set_signal("allitems") else: self.set_signal("unprocesseditems") elif method == "Other.ProcessAllItems": self.processor.create_progress() self.set_signal("allitems") elif method == "Other.ProcessAfterSettings": self.processaftersettings = True elif method == "Player.OnStop": if self.serviceenabled: data = json.loads(data) if self.watchitem(data): self.stoppeditems.add((data["item"]["type"], data["item"]["id"])) elif method == "VideoLibrary.OnScanStarted": if self.serviceenabled and self.status == STATUS_PROCESSING: self.abort = True elif method == "VideoLibrary.OnScanFinished": if self.serviceenabled: self.set_signal("something") elif method == "VideoLibrary.OnUpdate": if not self.serviceenabled: return data = json.loads(data) if not self.watchitem(data): return if (data["item"]["type"], data["item"]["id"]) in self.stoppeditems: self.stoppeditems.remove((data["item"]["type"], data["item"]["id"])) return if not self.toomany_recentitems: self.recentitems[data["item"]["type"]].append(data["item"]["id"]) if not self.scanning: self.set_signal("something")
def load(self): self.clear() if xbmcvfs.exists(self.filename): with closing(xbmcvfs.File(self.filename)) as jsonfile: try: processed = json.load(jsonfile) except ValueError: log("Had trouble loading ProcessedItems, starting fresh.", xbmc.LOGWARNING, tag="json") return if processed.get("version") == self.version: tvshows = processed.get("tvshow") if isinstance(tvshows, dict): self.tvshow = dict((int(tvshowid), seasons) for tvshowid, seasons in tvshows.iteritems()) movies = processed.get("movie") if isinstance(movies, list): self.movie = movies episodes = processed.get("episode") if isinstance(episodes, list): self.episode = episodes
def runon_allmedia(heading, countmessage, function): progress = xbmcgui.DialogProgressBG() progress.create(heading) monitor = xbmc.Monitor() steps_to_run = ((quickjson.get_movies, L(M.LISTING_ALL).format(L(M.MOVIES))), (quickjson.get_tvshows, L(M.LISTING_ALL).format(L(M.SERIES))), (quickjson.get_seasons, L(M.LISTING_ALL).format(L(M.SEASONS))), (quickjson.get_episodes, L(M.LISTING_ALL).format(L(M.EPISODES)))) stepsize = 100 // len(steps_to_run) def update_art_for_items(items, start): changedcount = 0 for i, item in enumerate(items): progress.update(start + i * stepsize // len(items)) mediainfo.prepare_mediaitem(item) processed = function(item) processed = mediainfo.get_artwork_updates(item['art'], processed) if processed: mediainfo.update_art_in_library(item['mediatype'], item['dbid'], processed) changedcount += len(processed) if monitor.abortRequested(): break return changedcount fixcount = 0 for i, (listfunc, message) in enumerate(steps_to_run): start = i * stepsize progress.update(start, message=message) fixcount += update_art_for_items(listfunc(), start) if monitor.abortRequested(): break progress.close() countmessage = countmessage.format(fixcount) log(countmessage, xbmc.LOGINFO) xbmcgui.Dialog().notification('Artwork Beef', countmessage)
def log(self, message, level=xbmc.LOGDEBUG): log(message, level, tag='%s.%s' % (self.name.sort, self.mediatype))
series = quickjson.get_tvshow_details(episode["tvshowid"], tvshow_properties) if series["imdbnumber"] in autoaddepisodes: addepisodesfrom.add(episode["tvshowid"]) newitems.append(episode) else: ignoreepisodesfrom.add(episode["tvshowid"]) if self.abortRequested(): return self.reset_recent() processed = self.processor.process_medialist(newitems) self.processed.extend(processed) self.processed.save() def onSettingsChanged(self): self.serviceenabled = addon.get_setting("enableservice") self.only_filesystem = addon.get_setting("only_filesystem") mediatypes.update_settings() self.processor.update_settings() if self.processaftersettings: self.processor.create_progress() xbmc.sleep(200) self.processaftersettings = False self.set_signal("unprocesseditems") if __name__ == "__main__": log("Service started", xbmc.LOGINFO) ArtworkService().run() log("Service stopped", xbmc.LOGINFO)
def process_item(self, mediatype, dbid, mode): if self.processor_busy: return if mode == MODE_GUI: xbmc.executebuiltin('ActivateWindow(busydialog)') if mediatype == mediatypes.TVSHOW: mediaitem = quickjson.get_tvshow_details(dbid, tvshow_properties) elif mediatype == mediatypes.MOVIE: mediaitem = quickjson.get_movie_details(dbid, movie_properties) elif mediatype == mediatypes.EPISODE: mediaitem = quickjson.get_episode_details(dbid, episode_properties) else: xbmc.executebuiltin('Dialog.Close(busydialog)') xbmcgui.Dialog().notification("Artwork Beef", L(NOT_SUPPORTED_MESSAGE).format(mediatype), '-', 6500) return if mode == MODE_GUI: self.init_run() self.add_additional_iteminfo(mediaitem) gatherer = Gatherer(self.monitor, self.only_filesystem) forcedart, availableart, _, error = gatherer.getartwork(mediaitem, False) if error: header = L(PROVIDER_ERROR_MESSAGE).format(error['providername']) xbmcgui.Dialog().notification(header, error['message'], xbmcgui.NOTIFICATION_WARNING) log('{0}\n{1}'.format(header, error['message'])) for arttype, imagelist in availableart.iteritems(): self.sort_images(arttype, imagelist, mediaitem['file']) xbmc.executebuiltin('Dialog.Close(busydialog)') if availableart: if 'seasons' in mediaitem and 'fanart' in availableart: for season in mediaitem['seasons'].keys(): unseasoned_backdrops = [dict(art) for art in availableart['fanart'] if not art.get('hasseason')] key = 'season.{0}.fanart'.format(season) if key in availableart: availableart[key].extend(unseasoned_backdrops) else: availableart[key] = unseasoned_backdrops tag_forcedandexisting_art(availableart, forcedart, mediaitem['art']) selectedarttype, selectedart = prompt_for_artwork(mediaitem['mediatype'], mediaitem['label'], availableart, self.monitor) if selectedarttype: if selectedarttype.startswith('season.'): gentype = selectedarttype.rsplit('.', 1)[1] multiselect = mediatypes.artinfo[mediatypes.SEASON].get(gentype, {}).get('multiselect', False) else: multiselect = mediatypes.artinfo[mediaitem['mediatype']][selectedarttype]['multiselect'] if multiselect: existingurls = [url for exacttype, url in mediaitem['art'].iteritems() \ if mediainfo.arttype_matches_base(exacttype, selectedarttype)] urls_toset = [url for url in existingurls if url not in selectedart[1]] urls_toset.extend([url for url in selectedart[0] if url not in urls_toset]) selectedart = dict(mediainfo.iter_renumbered_artlist(selectedart, selectedarttype, mediaitem['art'].keys())) else: selectedart = {selectedarttype: selectedart} selectedart = mediainfo.get_artwork_updates(mediaitem['art'], selectedart) if selectedart: add_art_to_library(mediaitem['mediatype'], mediaitem.get('seasons'), mediaitem['dbid'], selectedart) notifycount(len(selectedart)) else: xbmcgui.Dialog().notification(L(NOT_AVAILABLE_MESSAGE), L(SOMETHING_MISSING) + ' ' + L(FINAL_MESSAGE), '-', 8000) self.finish_run() else: medialist = [mediaitem] autoaddepisodes = addon.get_setting('autoaddepisodes_list') if addon.get_setting('episode.fanart') else () if mediatype == mediatypes.TVSHOW and mediaitem['imdbnumber'] in autoaddepisodes: medialist.extend(quickjson.get_episodes(dbid, properties=episode_properties)) self.process_medialist(medialist, True)