Exemple #1
0
def do_refresh_series(series_id_str, config, debug):
    try:
        thetvdb = TheTvDb(config, debug)
        database = Database(config, debug)

        try:
            series_id = int(series_id_str)
        except:
            print "Argument is not a valid series id: %s" % (series_id_str, )
            return 1

        series = database.get_series(series_id)
        if series is not None:
            new_series = thetvdb.get_series_info(series.id)
            new_series.watch = series.watch

            database.clear_series(series.id)
            database.clear_all_episodes(series.id)

            database.add_series(new_series)
            episodes = get_episodes(thetvdb, database, new_series)
        else:
            new_series = thetvdb.get_series_info(series_id)
            series = new_series

            database.add_series(new_series)
            episodes = get_episodes(thetvdb, database, new_series)

        print "Metadata for series '%s' and its episodes has been cleared from the local cache and reloaded from TheTvDb.com." % (series.title, )
        return 0
    except:
        traceback.print_exc()
        return 11
Exemple #2
0
def watch_series_guts(series_id_str, watch, config, debug):
    try:
        thetvdb = TheTvDb(config, debug)
        database = Database(config, debug)

        try:
            series_id = int(series_id_str)
        except:
            print "Argument is not a valid series id: %s" % (series_id_str, )
            return 2

        series = database.get_series(series_id)
        if series is None:
            series = thetvdb.get_series_info(series_id)
            if series is not None:
                database.add_series(series)

        if not series is None:
            database.watch_series(series, watch)
            return 0
        else:
            print "No series with id '%i' exists in the local cache.  Did you lookup the series?" % (series_id,)
            return 3
    except:
        traceback.print_exc()
        return 11
Exemple #3
0
def do_series_lookup(name, config, debug):
    try:
        thetvdb = TheTvDb(config, debug)
        database = Database(config, debug)

        results = thetvdb.lookup_series_info(name)

        for r in results:
            database.add_series(r)
            print "%i: %s" % (r.id, r.title)

        return 0 
    except:
        traceback.print_exc()
        return 11
 def __init__(self):
     """Initialization and main code run"""
     self.win = xbmcgui.Window(10000)
     self.addon = xbmcaddon.Addon(ADDON_ID)
     self.thetvdb = TheTvDb()
     self.__set_dates()
     action, action_param = self.get_params()
     self.improve_dates = self.addon.getSetting("ImproveDates") == 'true'
     log_msg("MainModule called with action: %s - parameter: %s" % (action, action_param))
     # launch module for action provided by this script
     try:
         getattr(self, action)(action_param)
     except Exception as exc:
         log_exception(__name__, exc)
     finally:
         self.close()
 def __init__(self):
     '''Initialize and load all our helpers'''
     self._studiologos_path = ""
     self.cache = SimpleCache()
     self.addon = xbmcaddon.Addon(ADDON_ID)
     self.kodidb = KodiDb()
     self.omdb = Omdb(self.cache)
     self.tmdb = Tmdb(self.cache)
     self.channellogos = ChannelLogos(self.kodidb)
     self.fanarttv = FanartTv(self.cache)
     self.imdb = Imdb(self.cache)
     self.google = GoogleImages(self.cache)
     self.studiologos = StudioLogos(self.cache)
     self.animatedart = AnimatedArt(self.cache, self.kodidb)
     self.thetvdb = TheTvDb()
     self.musicart = MusicArtwork(self)
     self.pvrart = PvrArtwork(self)
     log_msg("Initialized")
Exemple #6
0
def do_episode_lookup(episode_search_pattern, config, debug):
    try:
        thetvdb = TheTvDb(config, debug)
        database = Database(config, debug)

        split_pattern = episode_search_pattern.split(':')

        if len(split_pattern) < 1 or len(split_pattern) > 3:
            print "Search pattern must be of the form series_id[:season_number[:episode_number]]"
            return 1

        series_id = split_pattern[0]
        series = database.get_series(series_id)
        if series is None:
            print "No series with id '%i' exists in the local cache.  Did you lookup the series?" % (series_id,)
            return 2

        existing_episode_list = database.get_all_episodes(series_id)
        if len(existing_episode_list) == 0:
            all_episodes = thetvdb.get_full_episode_list(series)
            for e in all_episodes:
                database.add_episode(e, series)


        if len(split_pattern) == 1:
            print_episodes(database.get_all_episodes(series_id))
        elif len(split_pattern) == 2:
            season = int(split_pattern[1])
            print_episodes(database.get_episodes(series_id, season))
        elif len(split_pattern) == 3:
            season = int(split_pattern[1])
            episode = int(split_pattern[2])

            result = get_specific_episode(thetvdb, database, series, season, episode)
            if result is None:
                print "Could not locate an episode matching pattern: %s" % (episode_search_pattern, )
                return 3

            print_episodes([result])

        return 0 
    except:
        traceback.print_exc()
        return 11
 def __init__(self):
     '''Initialization and main code run'''
     self.win = xbmcgui.Window(10000)
     self.addon = xbmcaddon.Addon(ADDON_ID)
     self.thetvdb = TheTvDb()
     self.set_dates()
     action, action_param = self.get_params()
     self.improve_dates = self.addon.getSetting("ImproveDates") == 'true'
     log_msg("MainModule called with action: %s - parameter: %s" % (action, action_param))
     # launch module for action provided by this script
     try:
         getattr(self, action)(action_param)
     except Exception as exc:
         log_exception(__name__, exc)
     finally:
         self.close()
Exemple #8
0
 def __init__(self):
     '''Initialize and load all our helpers'''
     self._studiologos_path = ""
     self.cache = SimpleCache()
     self.addon = xbmcaddon.Addon(ADDON_ID)
     self.kodidb = KodiDb()
     self.omdb = Omdb(self.cache)
     self.tmdb = Tmdb(self.cache)
     self.channellogos = ChannelLogos(self.kodidb)
     self.fanarttv = FanartTv(self.cache)
     self.imdb = Imdb(self.cache)
     self.google = GoogleImages(self.cache)
     self.studiologos = StudioLogos(self.cache)
     self.animatedart = AnimatedArt(self.cache, self.kodidb)
     self.thetvdb = TheTvDb()
     self.musicart = MusicArtwork(self)
     self.pvrart = PvrArtwork(self)
     log_msg("Initialized")
class MainModule:
    '''mainmodule provides the script methods for the nextaired addon'''

    def __init__(self):
        '''Initialization and main code run'''
        self.win = xbmcgui.Window(10000)
        self.addon = xbmcaddon.Addon(ADDON_ID)
        self.thetvdb = TheTvDb()
        self.set_dates()
        action, action_param = self.get_params()
        self.improve_dates = self.addon.getSetting("ImproveDates") == 'true'
        log_msg("MainModule called with action: %s - parameter: %s" % (action, action_param))
        # launch module for action provided by this script
        try:
            getattr(self, action)(action_param)
        except Exception as exc:
            log_exception(__name__, exc)
        finally:
            self.close()

    def close(self):
        '''Cleanup Kodi Cpython instances on exit'''
        del self.win
        del self.addon
        del self.thetvdb
        log_msg("MainModule exited")

    @staticmethod
    def get_params():
        '''extract the action and it's parameter from the called script path'''
        action = "main"
        action_param = ""
        if len(sys.argv) > 1:
            arg = sys.argv[1]
            action = arg.split('=')[0].lower()
            action_param = arg.replace(action + "=", "").lower()
        return action, action_param

    def set_dates(self):
        '''set the date variables'''
        self.now = time()
        self.date = date.today()
        self.datestr = str(self.date)
        self.yesterday = self.date - timedelta(days=1)
        self.yesterstr = str(self.yesterday)
        self.tomorrow = self.date + timedelta(days=1)
        self.weekdays = []
        for j in range(11, 18):
            self.weekdays.append(xbmc.getLocalizedString(j))
        self.wdays = []
        for j in range(41, 48):
            self.wdays.append(xbmc.getLocalizedString(j))
        self.local_months = []
        for j in range(51, 63):
            self.local_months.append(xbmc.getLocalizedString(j))
        self.ampm = xbmc.getCondVisibility('String.Contains(System.Time,Am) | String.Contains(System.Time,Pm)') == 1

    def reset(self, action_param):
        '''reset and force update of all data'''
        if action_param == "true":
            dialog = xbmcgui.Dialog()
            heading = self.addon.getAddonInfo("name").decode("utf-8")
            if dialog.yesno(heading, self.addon.getLocalizedString(32213)):
                dialog = xbmcgui.DialogProgress()
                dialog.create(heading, self.addon.getLocalizedString(32214))
                self.update_data(True)
                dialog.close()
            del dialog

    def update_data(self, ignore_cache=False):
        '''updates all data we need in cache'''
        if self.win.getProperty("nextaired.update_data"):
            log_msg("Update data skipped, another update is in progress")
        else:
            self.win.setProperty("nextaired.update_data", "busy")
            # build details in cache for all continuing series in the kodi db
            log_msg("Updating TheTVDB info for all continuing Kodi tv shows...", xbmc.LOGNOTICE)
            self.thetvdb.ignore_cache = ignore_cache
            continuing_kodi_shows = self.thetvdb.get_kodishows_details(continuing_only=True)
            self.win.setProperty("NextAired.Total", "%s" % len(continuing_kodi_shows))
            # build nextaired episodes listing in cache
            log_msg("Retrieving next airing episodes for all continuing Kodi tv shows...", xbmc.LOGNOTICE)
            want_yesterday = self.addon.getSetting("WantYesterday") == 'true'
            self.thetvdb.get_kodi_unaired_episodes(include_last_episode=want_yesterday)
            # set the window properties for the shows that are airing today
            prev_total = self.win.getProperty("NextAired.TodayTotal")
            prev_total = int(prev_total) if prev_total else 0
            # clear previous properties
            for count in range(prev_total + 1):
                self.clear_properties("%s." % count)
            shows_airing_today = self.thetvdb.get_kodishows_airingtoday()
            all_titles = []
            for count, show_details in enumerate(shows_airing_today):
                self.set_properties(show_details, "%s." % count)
                all_titles.append(show_details["title"])
            self.win.setProperty("NextAired.TodayTotal", "%s" % len(shows_airing_today))
            self.win.setProperty("NextAired.TodayShow", "[CR]".join(all_titles))
            self.thetvdb.ignore_cache = False
            self.win.clearProperty("nextaired.update_data")
            log_msg("Update complete", xbmc.LOGNOTICE)

    def force(self, action_param):
        '''force update of data by script - calls update_data after user confirmation'''
        if action_param == "true":
            dialog = xbmcgui.DialogProgress()
            dialog.create(self.addon.getAddonInfo("name").decode("utf-8"), self.addon.getLocalizedString(32215))
            self.update_data()
            dialog.close()
            del dialog

    def update(self, action_param):
        '''perform update of data in cache - called by the background service'''
        if action_param == "true":
            self.update_data()

    def updateshow(self, showtitle):
        '''force update of single show'''
        if showtitle:
            log_msg("Update show data requested for TV Show: %s" % showtitle)
            self.win.setProperty("nextaired.update_data", "busy")
            self.thetvdb.ignore_cache = True
            self.thetvdb.get_kodishow_details(showtitle)
            self.thetvdb.ignore_cache = False
            self.win.clearProperty("nextaired.update_data")

    def tvshowtitle(self, showtitle, prefix=""):
        '''set details for single show by name'''
        log_msg("Set NextAired properties for TV Show: %s" % showtitle)
        details = self.thetvdb.get_kodishow_details(showtitle)
        if not details or not showtitle:
            self.clear_properties(prefix)
        else:
            self.set_properties(details, prefix)

    def backend(self, action_param):
        '''start monitoring listitem details to set window properties'''
        if not action_param or action_param == "false" or self.win.getProperty("NextAired.backend"):
            log_msg("Start backend aborted, required param missing or backend already running")
            return
        log_msg("Monitoring of listitems started...")
        self.win.setProperty("NextAired.backend", "running")
        try:

            # try parsing the multi-attributes
            li_range_left, li_range_right = self.get_listitem_range(action_param)
            monitor = xbmc.Monitor()
            last_showtitle = ""
            while not monitor.abortRequested() and xbmc.getCondVisibility("Window.IsActive(10025)"):
                showtitle = xbmc.getInfoLabel("ListItem.TvShowTitle").decode("utf-8")
                if showtitle != last_showtitle:
                    last_showtitle = showtitle
                    self.tvshowtitle(showtitle)
                    if li_range_left or li_range_right:
                        # set properties for the given listitem range
                        for count in range(li_range_left, li_range_right):
                            showtitle = xbmc.getInfoLabel("ListItem(%s).TvShowTitle" % count).decode("utf-8")
                            self.tvshowtitle(showtitle, "(%s)" % count)
                monitor.waitForAbort(0.5)
            # clear properties when exiting video library
            if not monitor.abortRequested():
                self.clear_properties()
                if li_range_left or li_range_right:
                    for count in range(li_range_left, li_range_right):
                        self.clear_properties("(%s)" % count)
            del monitor
        except Exception as exc:
            log_exception(__name__, exc)
        finally:
            self.win.clearProperty("NextAired.backend")
        log_msg("Monitoring of listitems ended...")

    @staticmethod
    def get_listitem_range(paramstr):
        '''get the special range params from the parameter string'''
        li_range_left = 0
        li_range_right = 0
        if paramstr != "true":
            try:
                li_range_right = int(paramstr.split(" ")[1])
                li_range_left = int(paramstr.split(" ")[0])
                li_range_right += 1
            except Exception:
                pass
        return li_range_left, li_range_right

    def set_properties(self, details, prefix=""):
        '''set the window properties for the given show'''
        self.win.setProperty("NextAired%s.Label" % prefix, details["title"])
        self.win.setProperty("NextAired%s.Thumb" % prefix, details["art"].get("thumb"))
        self.win.setProperty("NextAired%s.AirTime" % prefix, details["airdaytime"])
        self.win.setProperty("NextAired%s.Path" % prefix, details["file"])
        self.win.setProperty("NextAired%s.Library" % prefix, "videodb://tvshows/titles/%s/" % details["tvshowid"])
        self.win.setProperty("NextAired%s.Status" % prefix, details["status"])
        self.win.setProperty("NextAired%s.Network" % prefix, " / ".join(details["studio"]))
        self.win.setProperty("NextAired%s.Started" % prefix, details["firstaired"])
        self.win.setProperty("NextAired%s.Classification" % prefix, details["classification"])
        self.win.setProperty("NextAired%s.Genre" % prefix, " / ".join(details["genre"]))
        self.win.setProperty("NextAired%s.Premiered" % prefix, str(details["year"]))
        self.win.setProperty("NextAired%s.Runtime" % prefix, str(details["runtime"]))
        self.win.setProperty("NextAired%s.FanArt" % prefix, details["art"]["fanart"])
        if details.get("next_episode"):
            # set next airing episode details if exist
            self.win.setProperty("NextAired%s.NextDate" % prefix, details["next_episode"]["airdate"])
            self.win.setProperty("NextAired%s.NextDay" % prefix, details["next_episode"]["airdate.long"])
            self.win.setProperty("NextAired%s.NextTitle" % prefix, details["next_episode"]["title"])
            nextnumber = "%sx%s" % (details["next_episode"]["season"], details["next_episode"]["episode"])
            self.win.setProperty("NextAired%s.NextNumber" % prefix, nextnumber)
            self.win.setProperty("NextAired%s.NextEpisodeNumber" % prefix, str(details["next_episode"]["episode"]))
            self.win.setProperty("NextAired%s.NextSeasonNumber" % prefix, str(details["next_episode"]["season"]))
        else:
            # clear next episode properties if we don't have that data
            for prop in ["NextDate", "NextDay", "NextTitle", "NextNumber", "NextEpisodeNumber", "NextSeasonNumber"]:
                self.win.clearProperty("NextAired%s.%s" % (prefix, prop))
        if details.get("last_episode"):
            self.win.setProperty("NextAired%s.LatestDate" % prefix, details["last_episode"]["airdate"])
            self.win.setProperty("NextAired%s.LatestDay" % prefix, details["last_episode"]["airdate.long"])
            self.win.setProperty("NextAired%s.LatestTitle" % prefix, details["last_episode"]["title"])
            nextnumber = "%sx%s" % (details["last_episode"]["season"], details["last_episode"]["episode"])
            self.win.setProperty("NextAired%s.LatestNumber" % prefix, nextnumber)
            self.win.setProperty("NextAired%s.LatestEpisodeNumber" % prefix, str(details["last_episode"]["episode"]))
            self.win.setProperty("NextAired%s.LatestSeasonNumber" % prefix, str(details["last_episode"]["season"]))
        else:
            # clear last episode properties if we don't have that data
            for prop in ["LatestDate", "LatestDay", "LatestTitle",
                         "LatestNumber", "LatestEpisodeNumber", "LatestSeasonNumber"]:
                self.win.clearProperty("NextAired%s.%s" % (prefix, prop))
        self.win.setProperty("NextAired%s.Airday" % prefix, details["airday"])
        self.win.setProperty("NextAired%s.ShortTime" % prefix, details["airtime"])
        self.win.setProperty("NextAired%s.Art(poster)" % prefix, details["art"].get("poster"))
        self.win.setProperty("NextAired%s.Art(banner)" % prefix, details["art"].get("banner"))
        self.win.setProperty("NextAired%s.Art(fanart)" % prefix, details["art"].get("fanart"))
        self.win.setProperty("NextAired%s.Art(landscape)" % prefix, details["art"].get("landscape"))
        self.win.setProperty("NextAired%s.Art(clearlogo)" % prefix, details["art"].get("clearlogo"))
        self.win.setProperty("NextAired%s.Art(characterart)" % prefix, details["art"].get("characterart"))

    def clear_properties(self, prefix=""):
        '''clears the nextaired window Properties'''
        props = ["label", "thumb", "airtime", "path", "library", "status", "statusid", "network", "started",
                 "classification", "genre", "premiered", "country", "runtime", "fanart", "airstoday", "nextdate",
                 "nextday", "nexttitle", "nextnumber", "nextepisodenumber", "nextseasonnumber", "latestdate",
                 "latestday", "latesttitle", "latestnumber", "latestepisodenumber", "latestseasonnumber", "airday",
                 "shorttime", "art(poster)", "art(banner)", "art(fanart)", "art(landscape)"]
        for prop in props:
            self.win.clearProperty("NextAired%s.%s" % (prefix, prop))

    def main(self, action_param=None):
        '''show the NextAired dialog'''
        weekday = self.date.weekday()
        self.win.setProperty("NextAired.TodayText", xbmc.getLocalizedString(33006))
        self.win.setProperty("NextAired.TomorrowText", xbmc.getLocalizedString(33007))
        self.win.setProperty("NextAired.YesterdayText", self.addon.getLocalizedString(32018))
        self.win.setProperty("NextAired.TodayDate", self.str_date(self.date, 'DropYear'))
        self.win.setProperty("NextAired.TomorrowDate", self.str_date(self.tomorrow, 'DropThisYear'))
        self.win.setProperty("NextAired.YesterdayDate", self.str_date(self.yesterday, 'DropThisYear'))
        for count in range(0, 7):
            wdate = self.date
            if count != weekday:
                wdate += timedelta(days=(count - weekday + 7) % 7)
            self.win.setProperty("NextAired.%d.Date" % (count + 1), self.str_date(wdate, 'DropThisYear'))
        from next_aired_dialog import NextAiredDialog
        today_style = self.addon.getSetting("TodayStyle") == 'true'
        scan_days = int(self.addon.getSetting("ScanDays2" if today_style else "ScanDays"))
        want_yesterday = self.addon.getSetting("WantYesterday") == 'true'
        eps_list = self.get_nextaired_listing(include_last_episode=want_yesterday)
        xml = "script-NextAired-TVGuide%s.xml" % (2 if today_style else "")
        xml_path = self.addon.getAddonInfo('path').decode('utf-8')
        dialog = NextAiredDialog(
            xml,
            xml_path,
            "Default",
            listing=eps_list,
            nice_date=self.nice_date,
            scan_days=scan_days,
            today_style=today_style,
            want_yesterday=want_yesterday)
        dialog.doModal()
        del dialog

    def get_nextaired_listing(self, include_last_episode=False):
        '''get the listing of all continuing series, include last episode and unaired episodes'''
        eps_list = self.thetvdb.get_kodi_unaired_episodes(
            single_episode_per_show=False, include_last_episode=include_last_episode)
        return eps_list

    def str_date(self, d, style=None):
        '''The style setting only affects "nice" dates, not the historic format.'''
        if d is None:
            return ''
        return self.nice_date(d, style) if self.improve_dates else d.strftime(DATE_FORMAT)

    def nice_date(self, d, style=None):
        '''Specify style DropThisYear, DropYear, or Short (or omit for the full info).'''
        tt = d.timetuple()
        if style == 'Short':
            fmt = NICE_SHORT_DATE
        elif style == 'DropYear' or (style == 'DropThisYear' and tt[0] == self.date.year):
            fmt = NICE_DATE_NO_YEAR
        else:
            fmt = NICE_DATE_FORMAT
        d = fmt % {
            'year': tt[0],
            'mm': tt[1],
            'month': self.local_months[
                tt[1] - 1],
            'day': tt[2],
            'wday': self.wdays[
                tt[6]],
            'unk': '??'}
        return d
class MainModule:
    """mainmodule provides the script methods for the nextaired addon"""

    def __init__(self):
        """Initialization and main code run"""
        self.win = xbmcgui.Window(10000)
        self.addon = xbmcaddon.Addon(ADDON_ID)
        self.thetvdb = TheTvDb()
        self.__set_dates()
        action, action_param = self.get_params()
        self.improve_dates = self.addon.getSetting("ImproveDates") == 'true'
        log_msg("MainModule called with action: %s - parameter: %s" % (action, action_param))
        # launch module for action provided by this script
        try:
            getattr(self, action)(action_param)
        except Exception as exc:
            log_exception(__name__, exc)
        finally:
            self.close()

    def close(self):
        """Cleanup Kodi Cpython instances on exit"""
        del self.win
        del self.addon
        del self.thetvdb
        log_msg("MainModule exited")

    @staticmethod
    def get_params():
        """extract the action and it's parameter from the called script path"""
        action = "main"
        action_param = ""
        if len(sys.argv) > 1:
            arg = sys.argv[1]
            action = arg.split('=')[0].lower()
            action_param = arg.replace(action + "=", "").lower()
        return action, action_param

    def __set_dates(self):
        """set the date variables"""
        self.now = time()
        self.date = date.today()
        self.datestr = str(self.date)
        self.yesterday = self.date - timedelta(days=1)
        self.yesterstr = str(self.yesterday)
        self.tomorrow = self.date + timedelta(days=1)
        self.weekdays = []
        for j in range(11, 18):
            self.weekdays.append(xbmc.getLocalizedString(j))
        self.wdays = []
        for j in range(41, 48):
            self.wdays.append(xbmc.getLocalizedString(j))
        self.local_months = []
        for j in range(51, 63):
            self.local_months.append(xbmc.getLocalizedString(j))
        self.ampm = xbmc.getCondVisibility('String.Contains(System.Time,Am) | String.Contains(System.Time,Pm)') == 1

    def reset(self, action_param):
        """reset and force update of all data"""
        if action_param == "true":
            dialog = xbmcgui.Dialog()
            heading = self.addon.getAddonInfo("name").decode("utf-8")
            if dialog.yesno(heading, self.addon.getLocalizedString(32213)):
                dialog = xbmcgui.DialogProgress()
                dialog.create(heading, self.addon.getLocalizedString(32214))
                self.update_data(True)
                dialog.close()
            del dialog

    def update_data(self, ignore_cache=False):
        """updates all data we need in cache"""
        if self.win.getProperty("nextaired.update_data"):
            log_msg("Update data skipped, another update is in progress")
        else:
            self.win.setProperty("nextaired.update_data", "busy")
            # build details in cache for all continuing series in the kodi db
            log_msg("Updating TheTVDB info for all continuing Kodi tv shows...", xbmc.LOGNOTICE)
            self.thetvdb.ignore_cache = ignore_cache
            continuing_kodi_shows = self.thetvdb.get_kodishows_details(continuing_only=True)
            self.win.setProperty("NextAired.Total", "%s" % len(continuing_kodi_shows))
            # build nextaired episodes listing in cache
            log_msg("Retrieving next airing episodes for all continuing Kodi tv shows...", xbmc.LOGNOTICE)
            want_yesterday = self.addon.getSetting("WantYesterday") == 'true'
            self.thetvdb.get_kodi_unaired_episodes(include_last_episode=want_yesterday)
            # set the window properties for the shows that are airing today
            prev_total = self.win.getProperty("NextAired.TodayTotal")
            prev_total = int(prev_total) if prev_total else 0
            # clear previous properties
            for count in range(prev_total + 1):
                self.clear_properties("%s." % count)
            shows_airing_today = self.thetvdb.get_kodishows_airingtoday()
            all_titles = []
            for count, show_details in enumerate(shows_airing_today):
                self.set_properties(show_details, "%s." % count)
                all_titles.append(show_details["title"])
            self.win.setProperty("NextAired.TodayTotal", "%s" % len(shows_airing_today))
            self.win.setProperty("NextAired.TodayShow", "[CR]".join(all_titles))
            self.thetvdb.ignore_cache = False
            self.win.clearProperty("nextaired.update_data")
            log_msg("Update complete", xbmc.LOGNOTICE)

    def force(self, action_param):
        """force update of data by script - calls update_data after user confirmation"""
        if action_param == "true":
            dialog = xbmcgui.DialogProgress()
            dialog.create(self.addon.getAddonInfo("name").decode("utf-8"), self.addon.getLocalizedString(32215))
            self.update_data()
            dialog.close()
            del dialog

    def update(self, action_param):
        """perform update of data in cache - called by the background service"""
        if action_param == "true":
            self.update_data()

    def updateshow(self, showtitle):
        """force update of single show"""
        if showtitle:
            log_msg("Update show data requested for TV Show: %s" % showtitle)
            self.win.setProperty("nextaired.update_data", "busy")
            self.thetvdb.ignore_cache = True
            self.thetvdb.get_kodishow_details(showtitle)
            self.thetvdb.ignore_cache = False
            self.win.clearProperty("nextaired.update_data")

    def tvshowtitle(self, showtitle, prefix=""):
        """set details for single show by name"""
        log_msg("Set NextAired properties for TV Show: %s" % showtitle)
        details = self.thetvdb.get_kodishow_details(showtitle)
        if not details or not showtitle:
            self.clear_properties(prefix)
        else:
            self.set_properties(details, prefix)

    def backend(self, action_param):
        """start monitoring listitem details to set window properties"""
        if not action_param or action_param == "false" or self.win.getProperty("NextAired.backend"):
            log_msg("Start backend aborted, required param missing or backend already running")
            return
        log_msg("Monitoring of listitems started...")
        self.win.setProperty("NextAired.backend", "running")
        try:

            # try parsing the multi-attributes
            li_range_left, li_range_right = self.get_listitem_range(action_param)
            monitor = xbmc.Monitor()
            last_showtitle = ""
            while not monitor.abortRequested() and xbmc.getCondVisibility("Window.IsActive(10025)"):
                showtitle = xbmc.getInfoLabel("ListItem.TvShowTitle").decode("utf-8")
                if showtitle != last_showtitle:
                    last_showtitle = showtitle
                    self.tvshowtitle(showtitle)
                    if li_range_left or li_range_right:
                        # set properties for the given listitem range
                        for count in range(li_range_left, li_range_right):
                            showtitle = xbmc.getInfoLabel("ListItem(%s).TvShowTitle" % count).decode("utf-8")
                            self.tvshowtitle(showtitle, "(%s)" % count)
                monitor.waitForAbort(0.5)
            # clear properties when exiting video library
            if not monitor.abortRequested():
                self.clear_properties()
                if li_range_left or li_range_right:
                    for count in range(li_range_left, li_range_right):
                        self.clear_properties("(%s)" % count)
            del monitor
        except Exception as exc:
            log_exception(__name__, exc)
        finally:
            self.win.clearProperty("NextAired.backend")
        log_msg("Monitoring of listitems ended...")

    @staticmethod
    def get_listitem_range(paramstr):
        """get the special range params from the parameter string"""
        li_range_left = 0
        li_range_right = 0
        if paramstr != "true":
            try:
                li_range_right = int(paramstr.split(" ")[1])
                li_range_left = int(paramstr.split(" ")[0])
                li_range_right += 1
            except Exception:
                pass
        return li_range_left, li_range_right

    def set_properties(self, details, prefix=""):
        """set the window properties for the given show"""
        self.win.setProperty("NextAired%s.Label" % prefix, details["title"])
        self.win.setProperty("NextAired%s.Thumb" % prefix, details["art"].get("thumb"))
        self.win.setProperty("NextAired%s.AirTime" % prefix, details["airdaytime"])
        self.win.setProperty("NextAired%s.Path" % prefix, details["file"])
        self.win.setProperty("NextAired%s.Library" % prefix, "videodb://tvshows/titles/%s/" % details["tvshowid"])
        self.win.setProperty("NextAired%s.Status" % prefix, details["status"])
        self.win.setProperty("NextAired%s.Network" % prefix, " / ".join(details["studio"]))
        self.win.setProperty("NextAired%s.Started" % prefix, details["firstaired"])
        self.win.setProperty("NextAired%s.Classification" % prefix, details["classification"])
        self.win.setProperty("NextAired%s.Genre" % prefix, " / ".join(details["genre"]))
        self.win.setProperty("NextAired%s.Premiered" % prefix, str(details["year"]))
        self.win.setProperty("NextAired%s.Runtime" % prefix, str(details["runtime"]))
        self.win.setProperty("NextAired%s.FanArt" % prefix, details["art"]["fanart"])
        if details.get("next_episode"):
            # set next airing episode details if exist
            self.win.setProperty("NextAired%s.NextDate" % prefix, details["next_episode"]["airdate"])
            self.win.setProperty("NextAired%s.NextDay" % prefix, details["next_episode"]["airdate.long"])
            self.win.setProperty("NextAired%s.NextTitle" % prefix, details["next_episode"]["title"])
            nextnumber = "%sx%s" % (details["next_episode"]["season"], details["next_episode"]["episode"])
            self.win.setProperty("NextAired%s.NextNumber" % prefix, nextnumber)
            self.win.setProperty("NextAired%s.NextEpisodeNumber" % prefix, str(details["next_episode"]["episode"]))
            self.win.setProperty("NextAired%s.NextSeasonNumber" % prefix, str(details["next_episode"]["season"]))
        else:
            # clear next episode properties if we don't have that data
            for prop in ["NextDate", "NextDay", "NextTitle", "NextNumber", "NextEpisodeNumber", "NextSeasonNumber"]:
                self.win.clearProperty("NextAired%s.%s" % (prefix, prop))
        if details.get("last_episode"):
            self.win.setProperty("NextAired%s.LatestDate" % prefix, details["last_episode"]["airdate"])
            self.win.setProperty("NextAired%s.LatestDay" % prefix, details["last_episode"]["airdate.long"])
            self.win.setProperty("NextAired%s.LatestTitle" % prefix, details["last_episode"]["title"])
            nextnumber = "%sx%s" % (details["last_episode"]["season"], details["last_episode"]["episode"])
            self.win.setProperty("NextAired%s.LatestNumber" % prefix, nextnumber)
            self.win.setProperty("NextAired%s.LatestEpisodeNumber" % prefix, str(details["last_episode"]["episode"]))
            self.win.setProperty("NextAired%s.LatestSeasonNumber" % prefix, str(details["last_episode"]["season"]))
        else:
            # clear last episode properties if we don't have that data
            for prop in ["LatestDate", "LatestDay", "LatestTitle",
                         "LatestNumber", "LatestEpisodeNumber", "LatestSeasonNumber"]:
                self.win.clearProperty("NextAired%s.%s" % (prefix, prop))
        self.win.setProperty("NextAired%s.Airday" % prefix, details["airday"])
        self.win.setProperty("NextAired%s.ShortTime" % prefix, details["airtime"])
        self.win.setProperty("NextAired%s.Art(poster)" % prefix, details["art"].get("poster"))
        self.win.setProperty("NextAired%s.Art(banner)" % prefix, details["art"].get("banner"))
        self.win.setProperty("NextAired%s.Art(fanart)" % prefix, details["art"].get("fanart"))
        self.win.setProperty("NextAired%s.Art(landscape)" % prefix, details["art"].get("landscape"))
        self.win.setProperty("NextAired%s.Art(clearlogo)" % prefix, details["art"].get("clearlogo"))
        self.win.setProperty("NextAired%s.Art(characterart)" % prefix, details["art"].get("characterart"))

    def clear_properties(self, prefix=""):
        """clears the nextaired window Properties"""
        props = ["label", "thumb", "airtime", "path", "library", "status", "statusid", "network", "started",
                 "classification", "genre", "premiered", "country", "runtime", "fanart", "airstoday", "nextdate",
                 "nextday", "nexttitle", "nextnumber", "nextepisodenumber", "nextseasonnumber", "latestdate",
                 "latestday", "latesttitle", "latestnumber", "latestepisodenumber", "latestseasonnumber", "airday",
                 "shorttime", "art(poster)", "art(banner)", "art(fanart)", "art(landscape)"]
        for prop in props:
            self.win.clearProperty("NextAired%s.%s" % (prefix, prop))

    def main(self, action_param=None):
        """show the NextAired dialog"""
        weekday = self.date.weekday()
        self.win.setProperty("NextAired.TodayText", xbmc.getLocalizedString(33006))
        self.win.setProperty("NextAired.TomorrowText", xbmc.getLocalizedString(33007))
        self.win.setProperty("NextAired.YesterdayText", self.addon.getLocalizedString(32018))
        self.win.setProperty("NextAired.TodayDate", self.str_date(self.date, 'DropYear'))
        self.win.setProperty("NextAired.TomorrowDate", self.str_date(self.tomorrow, 'DropThisYear'))
        self.win.setProperty("NextAired.YesterdayDate", self.str_date(self.yesterday, 'DropThisYear'))
        for count in range(0, 7):
            wdate = self.date
            if count != weekday:
                wdate += timedelta(days=(count - weekday + 7) % 7)
            self.win.setProperty("NextAired.%d.Date" % (count + 1), self.str_date(wdate, 'DropThisYear'))
        from next_aired_dialog import NextAiredDialog
        today_style = self.addon.getSetting("TodayStyle") == 'true'
        scan_days = int(self.addon.getSetting("ScanDays2" if today_style else "ScanDays"))
        want_yesterday = self.addon.getSetting("WantYesterday") == 'true'
        eps_list = self.get_nextaired_listing(include_last_episode=want_yesterday)
        xml = "script-NextAired-TVGuide%s.xml" % (2 if today_style else "")
        xml_path = self.addon.getAddonInfo('path').decode('utf-8')
        dialog = NextAiredDialog(
            xml,
            xml_path,
            "Default",
            listing=eps_list,
            nice_date=self.nice_date,
            scan_days=scan_days,
            today_style=today_style,
            want_yesterday=want_yesterday)
        dialog.doModal()
        del dialog

    def get_nextaired_listing(self, include_last_episode=False):
        """get the listing of all continuing series, include last episode and unaired episodes"""
        eps_list = self.thetvdb.get_kodi_unaired_episodes(
            single_episode_per_show=False, include_last_episode=include_last_episode)
        return eps_list

    def str_date(self, d, style=None):
        """The style setting only affects "nice" dates, not the historic format."""
        if d is None:
            return ''
        return self.nice_date(d, style) if self.improve_dates else d.strftime(DATE_FORMAT)

    def nice_date(self, d, style=None):
        """Specify style DropThisYear, DropYear, or Short (or omit for the full info)."""
        tt = d.timetuple()
        if style == 'Short':
            fmt = NICE_SHORT_DATE
        elif style == 'DropYear' or (style == 'DropThisYear' and tt[0] == self.date.year):
            fmt = NICE_DATE_NO_YEAR
        else:
            fmt = NICE_DATE_FORMAT
        d = fmt % {
            'year': tt[0],
            'mm': tt[1],
            'month': self.local_months[
                tt[1] - 1],
            'day': tt[2],
            'wday': self.wdays[
                tt[6]],
            'unk': '??'}
        return d
Exemple #11
0
 def thetvdb(self):
     '''public TheTvDb object - for lazy loading'''
     if not self._thetvdb:
         from thetvdb import TheTvDb
         self._thetvdb = TheTvDb()
     return self._thetvdb
from thetvdb import TheTvDb
from koding import dolog

api_key = '12E8AAC46571E4C1'
tvdb = TheTvDb()

Series_info = []
Seasons = []
Season_number = []
Season_Episodes = []
Season_Episode = []
Episode_ID = []


def get_series_info(ID):
    series_info = tvdb.get_series(ID)
    Series_info.append(series_info)


'''
tvdb.get_series == {'rating': 7, 'art': {'posters': [u'http://thetvdb.com/banners/posters/79412-1.jpg', u'http://thetvdb.com/banners/posters/79412-2.jpg', u'http://thetvdb.com/banners/posters/79412-3.jpg'], 'banner': u'http://thetvdb.com/banners/graphical/79412-g.jpg', 'poster': u'http://thetvdb.com/banners/posters/79412-1.jpg'}, 'airdaytime.short': u'Fri ', 'airdaytime.label': u'Friday  - Network: Tokyo MX', 'plot': u'Ten years after the Holy War in Hong Kong, Mochizuki Jirou, aka the Silver Blade, and the lone hero who fought and defeated the Kowloon Children despite the loss of his lover, returns to Japan with his young brother, Mochizuki Kotaro. The two quickly discover that the Kowloon Children who survived the Holy War are seeking to infiltrate the \u201cSpecial Zone\u201d\u2014a thriving city protected by an invisible barrier that will not allow Kowloon Children entrance\u2014unless they\u2019re invited. Red Bloods refer to the humans; Black Bloods are the vampires, and the Mochizuki Brothers are Old Blood\u2014the last descendants of an elite clan of vampires. When Kotaro is abducted by one of the Kowloon Children, Jirou has no choice but to fight once more.', 'votes': 12, 'network': u'Tokyo MX', 'airdaytime': u'Friday  (Tokyo MX)', 'airtime': '', 'airday': u'Friday', 'status': u'Ended', 'rating.tvdb': 7, 'tvdb_id': 79412, 'imdbnumber': u'tt0878230', 'studio': [u'Tokyo MX'], 'genre': [u'Action', u'Animation', u'Comedy', u'Fantasy'], 'airdaytime.label.short': u'Fri  - Network: Tokyo MX', 'votes.tvdb': 12, 'airday.short': u'Fri', 'title': u'Black Blood Brothers', 'firstaired': u'2006-09-08', 'runtime': 1500}
'''


def get_seasons(ID):
    series_seasons = tvdb.get_series_episodes(ID)
    for results in series_seasons:
        season = results['airedSeason']
        if season not in Seasons:
            Seasons.append(season)
            Season_number.append({'season_number': season})
Exemple #13
0
debug(sys.argv)
debug("----")
try:
    params = parameters_string_to_dict(sys.argv[2])
    mode = urllib.unquote_plus(params.get('mode', ''))
    series = urllib.unquote_plus(params.get('series', ''))
    season = urllib.unquote_plus(params.get('season', ''))
    debug("Parameter Holen geklappt")
except:
    debug("Parameter Holen nicht geklappt")
    mode = ""
debug("Mode ist : " + mode)
if mode == "":
    title = gettitle()
    lastplayd_title, lastepisode_name, fehlen = get_episodedata(title)
    tvdb = TheTvDb("de-DE")
    wert = tvdb.search_series(title.decode("utf-8"))
    count = 0
    gefunden = 0
    wertnr = 0
    x = 0
    for serie in wert:
        serienname = serie["seriesName"]
        nummer = similar(title, serienname)
        if nummer >= wertnr:
            wertnr = nummer
            gefunden = count
            x = 1
        count += 1
    debug("1. +++suche++" + title)
    debug(wert)
class MetadataUtils(object):
    '''
        Provides all kind of mediainfo for kodi media, returned as dict with details
    '''
    close_called = False

    def __init__(self):
        '''Initialize and load all our helpers'''
        self._studiologos_path = ""
        self.cache = SimpleCache()
        self.addon = xbmcaddon.Addon(ADDON_ID)
        self.kodidb = KodiDb()
        self.omdb = Omdb(self.cache)
        self.tmdb = Tmdb(self.cache)
        self.channellogos = ChannelLogos(self.kodidb)
        self.fanarttv = FanartTv(self.cache)
        self.imdb = Imdb(self.cache)
        self.google = GoogleImages(self.cache)
        self.studiologos = StudioLogos(self.cache)
        self.animatedart = AnimatedArt(self.cache, self.kodidb)
        self.thetvdb = TheTvDb()
        self.musicart = MusicArtwork(self)
        self.pvrart = PvrArtwork(self)
        log_msg("Initialized")

    def close(self):
        '''Cleanup instances'''
        self.close_called = True
        self.cache.close()
        self.addon = None
        del self.addon
        del self.kodidb
        del self.omdb
        del self.tmdb
        del self.channellogos
        del self.fanarttv
        del self.imdb
        del self.google
        del self.studiologos
        del self.animatedart
        del self.thetvdb
        del self.musicart
        del self.pvrart
        log_msg("Exited")

    def __del__(self):
        '''make sure close is called'''
        if not self.close_called:
            self.close()

    @use_cache(14)
    def get_extrafanart(self, file_path):
        '''helper to retrieve the extrafanart path for a kodi media item'''
        from helpers.extrafanart import get_extrafanart
        return get_extrafanart(file_path)

    def get_music_artwork(self,
                          artist,
                          album="",
                          track="",
                          disc="",
                          ignore_cache=False,
                          flush_cache=False):
        '''method to get music artwork for the goven artist/album/song'''
        return self.musicart.get_music_artwork(artist,
                                               album,
                                               track,
                                               disc,
                                               ignore_cache=ignore_cache,
                                               flush_cache=flush_cache)

    def music_artwork_options(self, artist, album="", track="", disc=""):
        '''options for music metadata for specific item'''
        return self.musicart.music_artwork_options(artist, album, track, disc)

    @use_cache(14)
    def get_extended_artwork(self,
                             imdb_id="",
                             tvdb_id="",
                             tmdb_id="",
                             media_type=""):
        '''get extended artwork for the given imdbid or tvdbid'''
        from urllib import quote_plus
        result = {"art": {}}
        if "movie" in media_type and tmdb_id:
            result["art"] = self.fanarttv.movie(tmdb_id)
        elif "movie" in media_type and imdb_id:
            result["art"] = self.fanarttv.movie(imdb_id)
        elif media_type in ["tvshow", "tvshows", "seasons", "episodes"]:
            if not tvdb_id:
                if imdb_id and not imdb_id.startswith("tt"):
                    tvdb_id = imdb_id
                elif imdb_id:
                    tvdb_id = self.thetvdb.get_series_by_imdb_id(imdb_id).get(
                        "tvdb_id")
            if tvdb_id:
                result["art"] = self.fanarttv.tvshow(tvdb_id)
        # add additional art with special path
        for arttype in ["fanarts", "posters", "clearlogos", "banners"]:
            if result["art"].get(arttype):
                result["art"][arttype] = "plugin://script.skin.helper.service/"\
                    "?action=extrafanart&fanarts=%s" % quote_plus(repr(result["art"][arttype]))
        return result

    @use_cache(14)
    def get_tmdb_details(self,
                         imdb_id="",
                         tvdb_id="",
                         title="",
                         year="",
                         media_type="",
                         preftype="",
                         manual_select=False,
                         ignore_cache=False):
        '''returns details from tmdb'''
        result = {}
        if imdb_id:
            result = self.tmdb.get_videodetails_by_externalid(
                imdb_id, "imdb_id")
        elif tvdb_id:
            result = self.tmdb.get_videodetails_by_externalid(
                tvdb_id, "tvdb_id")
        elif title and media_type in ["movies", "setmovies", "movie"]:
            result = self.tmdb.search_movie(title,
                                            year,
                                            manual_select=manual_select)
        elif title and media_type in ["tvshows", "tvshow"]:
            result = self.tmdb.search_tvshow(title,
                                             year,
                                             manual_select=manual_select)
        elif title:
            result = self.tmdb.search_video(title,
                                            year,
                                            preftype=preftype,
                                            manual_select=manual_select)
        if result.get("status"):
            result["status"] = self.translate_string(result["status"])
        if result.get("runtime"):
            result["runtime"] = result["runtime"] / 60
            result.update(self.get_duration(result["runtime"]))
        return result

    def get_moviesetdetails(self, title, set_id):
        '''get a nicely formatted dict of the movieset details which we can for example set as window props'''
        # get details from tmdb
        from helpers.moviesetdetails import get_moviesetdetails
        return get_moviesetdetails(self, title, set_id)

    @use_cache(14)
    def get_streamdetails(self, db_id, media_type, ignore_cache=False):
        '''get a nicely formatted dict of the streamdetails '''
        from helpers.streamdetails import get_streamdetails
        return get_streamdetails(self.kodidb, db_id, media_type)

    def get_pvr_artwork(self,
                        title,
                        channel="",
                        genre="",
                        manual_select=False,
                        ignore_cache=False):
        '''get artwork and mediadetails for PVR entries'''
        import requests, urllib, random
        print title.encode('utf8')
        r = requests.get(
            'http://192.168.0.2:8081/api/teleguide/get_arts?title=' +
            urllib.quote_plus(title.encode('utf8')))
        j = r.json()
        if j['arts']:
            data = {
                'art': {
                    'fanarts': j['arts'],
                    'fanart': random.choice(j['arts']),
                    'thumb': random.choice(j['arts'])
                },
                'cachestr':
                "pvr_artwork.%s.%s" % (title.lower(), channel.lower()),
                'pvrtitle': title,
                'pvrchannel': channel,
                'pvrgenre': genre,
                'genre': [genre],
                'thumbnail': random.choice(j['arts'])
            }
        else:
            data = self.pvrart.get_pvr_artwork(title,
                                               channel,
                                               genre,
                                               manual_select=manual_select,
                                               ignore_cache=ignore_cache)
        log_msg(data)
        return data

    def pvr_artwork_options(self, title, channel="", genre=""):
        '''options for pvr metadata for specific item'''
        return self.pvrart.pvr_artwork_options(title, channel, genre)

    @use_cache(14)
    def get_channellogo(self, channelname):
        '''get channellogo for the given channel name'''
        return self.channellogos.get_channellogo(channelname)

    def get_studio_logo(self, studio):
        '''get studio logo for the given studio'''
        # dont use cache at this level because of changing logospath
        return self.studiologos.get_studio_logo(studio, self.studiologos_path)

    @property
    def studiologos_path(self):
        '''path to use to lookup studio logos, must be set by the calling addon'''
        return self._studiologos_path

    @studiologos_path.setter
    def studiologos_path(self, value):
        '''path to use to lookup studio logos, must be set by the calling addon'''
        self._studiologos_path = value

    def get_animated_artwork(self,
                             imdb_id,
                             manual_select=False,
                             ignore_cache=False):
        '''get animated artwork, perform extra check if local version still exists'''
        artwork = self.animatedart.get_animated_artwork(
            imdb_id, manual_select, ignore_cache=ignore_cache)
        if not (manual_select or ignore_cache):
            refresh_needed = False
            if artwork.get("animatedposter") and not xbmcvfs.exists(
                    artwork["animatedposter"]):
                refresh_needed = True
            if artwork.get("animatedfanart") and not xbmcvfs.exists(
                    artwork["animatedfanart"]):
                refresh_needed = True
            if refresh_needed:
                artwork = self.animatedart.get_animated_artwork(
                    imdb_id, manual_select, ignore_cache=True)
        return {"art": artwork}

    @use_cache(14)
    def get_omdb_info(self, imdb_id="", title="", year="", content_type=""):
        '''Get (kodi compatible formatted) metadata from OMDB, including Rotten tomatoes details'''
        title = title.split(" (")[0]  # strip year appended to title
        result = {}
        if imdb_id:
            result = self.omdb.get_details_by_imdbid(imdb_id)
        elif title and content_type in [
                "seasons", "season", "episodes", "episode", "tvshows", "tvshow"
        ]:
            result = self.omdb.get_details_by_title(title, "", "tvshows")
        elif title and year:
            result = self.omdb.get_details_by_title(title, year, content_type)
        if result.get("status"):
            result["status"] = self.translate_string(result["status"])
        if result.get("runtime"):
            result["runtime"] = result["runtime"] / 60
            result.update(self.get_duration(result["runtime"]))
        return result

    @use_cache(7)
    def get_top250_rating(self, imdb_id):
        '''get the position in the IMDB top250 for the given IMDB ID'''
        return self.imdb.get_top250_rating(imdb_id)

    @use_cache(14)
    def get_duration(self, duration):
        '''helper to get a formatted duration'''
        if isinstance(duration, (str, unicode)) and ":" in duration:
            dur_lst = duration.split(":")
            return {
                "Duration": "%s:%s" % (dur_lst[0], dur_lst[1]),
                "Duration.Hours": dur_lst[0],
                "Duration.Minutes": dur_lst[1],
                "Runtime": str((int(dur_lst[0]) * 60) + int(dur_lst[1])),
            }
        else:
            return _get_duration(duration)

    @use_cache(2)
    def get_tvdb_details(self, imdbid="", tvdbid=""):
        '''get metadata from tvdb by providing a tvdbid or tmdbid'''
        result = {}
        self.thetvdb.days_ahead = 365
        if not tvdbid and imdbid and not imdbid.startswith("tt"):
            # assume imdbid is actually a tvdbid...
            tvdbid = imdbid
        if tvdbid:
            result = self.thetvdb.get_series(tvdbid)
        elif imdbid:
            result = self.thetvdb.get_series_by_imdb_id(imdbid)
        if result:
            if result["status"] == "Continuing":
                # include next episode info
                result["nextepisode"] = self.thetvdb.get_nextaired_episode(
                    result["tvdb_id"])
            # include last episode info
            result["lastepisode"] = self.thetvdb.get_last_episode_for_series(
                result["tvdb_id"])
            result["status"] = self.translate_string(result["status"])
            if result.get("runtime"):
                result["runtime"] = result["runtime"] / 60
                result.update(_get_duration(result["runtime"]))
        return result

    @use_cache(14)
    def get_imdbtvdb_id(self,
                        title,
                        content_type,
                        year="",
                        imdbid="",
                        tvshowtitle=""):
        '''try to figure out the imdbnumber and/or tvdbid'''
        tvdbid = ""
        if content_type in ["seasons", "episodes"] or tvshowtitle:
            title = tvshowtitle
            content_type = "tvshows"
        if imdbid and not imdbid.startswith("tt"):
            if content_type in ["tvshows", "seasons", "episodes"]:
                tvdbid = imdbid
                imdbid = ""
        if not imdbid and year:
            imdbid = self.get_omdb_info("", title, year,
                                        content_type).get("imdbnumber", "")
        if not imdbid:
            # repeat without year
            imdbid = self.get_omdb_info("", title, "",
                                        content_type).get("imdbnumber", "")
        # return results
        return (imdbid, tvdbid)

    def translate_string(self, _str):
        '''translate the received english string from the various sources like tvdb, tmbd etc'''
        translation = _str
        _str = _str.lower()
        if "continuing" in _str:
            translation = self.addon.getLocalizedString(32037)
        elif "ended" in _str:
            translation = self.addon.getLocalizedString(32038)
        elif "released" in _str:
            translation = self.addon.getLocalizedString(32040)
        return translation
Exemple #15
0
class MetadataUtils(object):
    '''
        Provides all kind of mediainfo for kodi media, returned as dict with details
    '''
    close_called = False

    def __init__(self):
        '''Initialize and load all our helpers'''
        self._studiologos_path = ""
        self.cache = SimpleCache()
        self.addon = xbmcaddon.Addon(ADDON_ID)
        self.kodidb = KodiDb()
        self.omdb = Omdb(self.cache)
        self.tmdb = Tmdb(self.cache)
        self.channellogos = ChannelLogos(self.kodidb)
        self.fanarttv = FanartTv(self.cache)
        self.imdb = Imdb(self.cache)
        self.google = GoogleImages(self.cache)
        self.studiologos = StudioLogos(self.cache)
        self.animatedart = AnimatedArt(self.cache, self.kodidb)
        self.thetvdb = TheTvDb()
        self.musicart = MusicArtwork(self)
        self.pvrart = PvrArtwork(self)
        log_msg("Initialized")

    def close(self):
        '''Cleanup instances'''
        self.close_called = True
        self.cache.close()
        self.addon = None
        del self.addon
        del self.kodidb
        del self.omdb
        del self.tmdb
        del self.channellogos
        del self.fanarttv
        del self.imdb
        del self.google
        del self.studiologos
        del self.animatedart
        del self.thetvdb
        del self.musicart
        del self.pvrart
        log_msg("Exited")

    def __del__(self):
        '''make sure close is called'''
        if not self.close_called:
            self.close()

    @use_cache(14)
    def get_extrafanart(self, file_path):
        '''helper to retrieve the extrafanart path for a kodi media item'''
        from helpers.extrafanart import get_extrafanart
        return get_extrafanart(file_path)

    def get_music_artwork(self, artist, album="", track="", disc="", ignore_cache=False, flush_cache=False):
        '''method to get music artwork for the goven artist/album/song'''
        return self.musicart.get_music_artwork(
            artist, album, track, disc, ignore_cache=ignore_cache, flush_cache=flush_cache)

    def music_artwork_options(self, artist, album="", track="", disc=""):
        '''options for music metadata for specific item'''
        return self.musicart.music_artwork_options(artist, album, track, disc)

    @use_cache(7)
    def get_extended_artwork(self, imdb_id="", tvdb_id="", tmdb_id="", media_type=""):
        '''get extended artwork for the given imdbid or tvdbid'''
        result = None
        if "movie" in media_type and tmdb_id:
            result = self.fanarttv.movie(tmdb_id)
        elif "movie" in media_type and imdb_id:
            result = self.fanarttv.movie(imdb_id)
        elif media_type in ["tvshow", "tvshows", "seasons", "episodes"]:
            if not tvdb_id:
                if imdb_id and not imdb_id.startswith("tt"):
                    tvdb_id = imdb_id
                elif imdb_id:
                    tvdb_id = self.thetvdb.get_series_by_imdb_id(imdb_id).get("tvdb_id")
            if tvdb_id:
                result = self.fanarttv.tvshow(tvdb_id)
        # add additional art with special path
        if result:
            result = {"art": result}
            for arttype in ["fanarts", "posters", "clearlogos", "banners"]:
                if result["art"].get(arttype):
                    result["art"][arttype] = "plugin://script.skin.helper.service/"\
                        "?action=extrafanart&fanarts=%s" % quote_plus(repr(result["art"][arttype]))
        return result

    def get_tmdb_details(self, imdb_id="", tvdb_id="", title="", year="", media_type="",
                         preftype="", manual_select=False, ignore_cache=False):
        '''returns details from tmdb'''
        result = {}
        if imdb_id:
            result = self.tmdb.get_videodetails_by_externalid(
                imdb_id, "imdb_id")
        elif tvdb_id:
            result = self.tmdb.get_videodetails_by_externalid(
                tvdb_id, "tvdb_id")
        elif title and media_type in ["movies", "setmovies", "movie"]:
            result = self.tmdb.search_movie(
                title, year, manual_select=manual_select)
        elif title and media_type in ["tvshows", "tvshow"]:
            result = self.tmdb.search_tvshow(
                title, year, manual_select=manual_select)
        elif title:
            result = self.tmdb.search_video(
                title, year, preftype=preftype, manual_select=manual_select)
        if result and result.get("status"):
            result["status"] = self.translate_string(result["status"])
        if result and result.get("runtime"):
            result["runtime"] = result["runtime"] / 60
            result.update(self.get_duration(result["runtime"]))
        return result

    def get_moviesetdetails(self, title, set_id):
        '''get a nicely formatted dict of the movieset details which we can for example set as window props'''
        # get details from tmdb
        from helpers.moviesetdetails import get_moviesetdetails
        return get_moviesetdetails(self, title, set_id)

    @use_cache(14)
    def get_streamdetails(self, db_id, media_type, ignore_cache=False):
        '''get a nicely formatted dict of the streamdetails '''
        from helpers.streamdetails import get_streamdetails
        return get_streamdetails(self.kodidb, db_id, media_type)

    def get_pvr_artwork(self, title, channel="", genre="", manual_select=False, ignore_cache=False):
        '''get artwork and mediadetails for PVR entries'''
        return self.pvrart.get_pvr_artwork(
            title, channel, genre, manual_select=manual_select, ignore_cache=ignore_cache)

    def pvr_artwork_options(self, title, channel="", genre=""):
        '''options for pvr metadata for specific item'''
        return self.pvrart.pvr_artwork_options(title, channel, genre)

    def get_channellogo(self, channelname):
        '''get channellogo for the given channel name'''
        return self.channellogos.get_channellogo(channelname)

    def get_studio_logo(self, studio):
        '''get studio logo for the given studio'''
        # dont use cache at this level because of changing logospath
        return self.studiologos.get_studio_logo(studio, self.studiologos_path)

    @property
    def studiologos_path(self):
        '''path to use to lookup studio logos, must be set by the calling addon'''
        return self._studiologos_path

    @studiologos_path.setter
    def studiologos_path(self, value):
        '''path to use to lookup studio logos, must be set by the calling addon'''
        self._studiologos_path = value

    def get_animated_artwork(self, imdb_id, manual_select=False, ignore_cache=False):
        '''get animated artwork, perform extra check if local version still exists'''
        artwork = self.animatedart.get_animated_artwork(
            imdb_id, manual_select=manual_select, ignore_cache=ignore_cache)
        if not (manual_select or ignore_cache):
            refresh_needed = False
            if artwork.get("animatedposter") and not xbmcvfs.exists(
                    artwork["animatedposter"]):
                refresh_needed = True
            if artwork.get("animatedfanart") and not xbmcvfs.exists(
                    artwork["animatedfanart"]):
                refresh_needed = True

        return {"art": artwork}

    def get_omdb_info(self, imdb_id="", title="", year="", content_type=""):
        '''Get (kodi compatible formatted) metadata from OMDB, including Rotten tomatoes details'''
        title = title.split(" (")[0]  # strip year appended to title
        result = {}
        if imdb_id:
            result = self.omdb.get_details_by_imdbid(imdb_id)
        elif title and content_type in ["seasons", "season", "episodes", "episode", "tvshows", "tvshow"]:
            result = self.omdb.get_details_by_title(title, "", "tvshows")
        elif title and year:
            result = self.omdb.get_details_by_title(title, year, content_type)
        if result and result.get("status"):
            result["status"] = self.translate_string(result["status"])
        if result and result.get("runtime"):
            result["runtime"] = result["runtime"] / 60
            result.update(self.get_duration(result["runtime"]))
        return result

    def get_top250_rating(self, imdb_id):
        '''get the position in the IMDB top250 for the given IMDB ID'''
        return self.imdb.get_top250_rating(imdb_id)

    @use_cache(14)
    def get_duration(self, duration):
        '''helper to get a formatted duration'''
        if isinstance(duration, (str, unicode)) and ":" in duration:
            dur_lst = duration.split(":")
            return {
                "Duration": "%s:%s" % (dur_lst[0], dur_lst[1]),
                "Duration.Hours": dur_lst[0],
                "Duration.Minutes": dur_lst[1],
                "Runtime": str((int(dur_lst[0]) * 60) + int(dur_lst[1])),
            }
        else:
            return _get_duration(duration)

    @use_cache(2)
    def get_tvdb_details(self, imdbid="", tvdbid=""):
        '''get metadata from tvdb by providing a tvdbid or tmdbid'''
        result = {}
        self.thetvdb.days_ahead = 365
        if not tvdbid and imdbid and not imdbid.startswith("tt"):
            # assume imdbid is actually a tvdbid...
            tvdbid = imdbid
        if tvdbid:
            result = self.thetvdb.get_series(tvdbid)
        elif imdbid:
            result = self.thetvdb.get_series_by_imdb_id(imdbid)
        if result:
            if result["status"] == "Continuing":
                # include next episode info
                result["nextepisode"] = self.thetvdb.get_nextaired_episode(result["tvdb_id"])
            # include last episode info
            result["lastepisode"] = self.thetvdb.get_last_episode_for_series(result["tvdb_id"])
            result["status"] = self.translate_string(result["status"])
            if result.get("runtime"):
                result["runtime"] = result["runtime"] / 60
                result.update(_get_duration(result["runtime"]))
        return result

    @use_cache(90)
    def get_imdbtvdb_id(self, title, content_type, year="", imdbid="", tvshowtitle=""):
        '''try to figure out the imdbnumber and/or tvdbid'''
        tvdbid = ""
        if content_type in ["seasons", "episodes"] or tvshowtitle:
            title = tvshowtitle
            content_type = "tvshows"
        if imdbid and not imdbid.startswith("tt"):
            if content_type in ["tvshows", "seasons", "episodes"]:
                tvdbid = imdbid
                imdbid = ""
        if not imdbid and year:
            imdbid = self.get_omdb_info(
                "", title, year, content_type).get("imdbnumber", "")
        if not imdbid:
            # repeat without year
            imdbid = self.get_omdb_info("", title, "", content_type).get("imdbnumber", "")
        # return results
        return (imdbid, tvdbid)

    def translate_string(self, _str):
        '''translate the received english string from the various sources like tvdb, tmbd etc'''
        translation = _str
        _str = _str.lower()
        if "continuing" in _str:
            translation = self.addon.getLocalizedString(32037)
        elif "ended" in _str:
            translation = self.addon.getLocalizedString(32038)
        elif "released" in _str:
            translation = self.addon.getLocalizedString(32040)
        return translation