Example #1
0
def Main():
    args = __getArguments()
    data = {}

    if args['action'] == 'auth_info':
        data['action'] = 'auth_info'

    if args['action'] == 'contextmenu':
        buttons = []
        media_type = kodiUtilities.getMediaType()

        if media_type in ['movie', 'show', 'season', 'episode']:
            buttons.append("rate")
            buttons.append("togglewatched")
            buttons.append("addtowatchlist")

        buttons.append("sync")

        contextMenu = traktContextMenu(media_type=media_type, buttons=buttons)
        contextMenu.doModal()
        _action = contextMenu.action
        del contextMenu

        if _action is None:
            return

        logger.debug("'%s' selected from trakt.tv action menu" % _action)
        args['action'] = _action

    if args['action'] == 'sync':
        data = {'action': 'manualSync', 'silent': False}
        if 'silent' in args:
            data['silent'] = (args['silent'].lower() == 'true')
        data['library'] = "all"
        if 'library' in args and args['library'] in ['episodes', 'movies']:
            data['library'] = args['library']

    elif args['action'] in ['rate', 'unrate']:
        data = {'action': args['action']}
        media_type = None
        if 'media_type' in args and 'dbid' in args:
            media_type = args['media_type']
            try:
                data['dbid'] = int(args['dbid'])
            except ValueError:
                logger.debug(
                    "Manual %s triggered for library item, but DBID is invalid."
                    % args['action'])
                return
        elif 'media_type' in args and 'remoteid' in args:
            media_type = args['media_type']
            data['remoteid'] = args['remoteid']
            try:
                data['season'] = int(args['season'])
                data['episode'] = int(args['episode'])
            except ValueError:
                logger.debug("Error parsing season or episode for manual %s" %
                             args['action'])
                return
            except KeyError:
                pass
        else:
            media_type = kodiUtilities.getMediaType()
            if not utilities.isValidMediaType(media_type):
                logger.debug("Error, not in video library.")
                return
            data['dbid'] = int(xbmc.getInfoLabel('ListItem.DBID'))

        if media_type is None:
            logger.debug(
                "Manual %s triggered on an unsupported content container." %
                args['action'])
        elif utilities.isValidMediaType(media_type):
            data['media_type'] = media_type
            if 'dbid' in data:
                logger.debug("Manual %s of library '%s' with an ID of '%s'." %
                             (args['action'], media_type, data['dbid']))
                if utilities.isMovie(media_type):
                    result = kodiUtilities.getMovieDetailsFromKodi(
                        data['dbid'], ['imdbnumber', 'title', 'year'])
                    if not result:
                        logger.debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return

                elif utilities.isShow(media_type):
                    tvshow_id = data['dbid']

                elif utilities.isSeason(media_type):
                    result = kodiUtilities.getSeasonDetailsFromKodi(
                        data['dbid'], ['tvshowid', 'season'])
                    if not result:
                        logger.debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return
                    tvshow_id = result['tvshowid']
                    data['season'] = result['season']

                elif utilities.isEpisode(media_type):
                    result = kodiUtilities.getEpisodeDetailsFromKodi(
                        data['dbid'], ['season', 'episode', 'tvshowid'])
                    if not result:
                        logger.debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return
                    tvshow_id = result['tvshowid']
                    data['season'] = result['season']
                    data['episode'] = result['episode']

                if utilities.isShow(media_type) or utilities.isSeason(
                        media_type) or utilities.isEpisode(media_type):
                    result = kodiUtilities.getShowDetailsFromKodi(
                        tvshow_id, ['imdbnumber'])
                    if not result:
                        logger.debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return

                data['video_id'] = result['imdbnumber']
            else:
                data['video_id'] = data['remoteid']
                if 'season' in data and 'episode' in data:
                    logger.debug(
                        "Manual %s of non-library '%s' S%02dE%02d, with an ID of '%s'."
                        % (args['action'], media_type, data['season'],
                           data['episode'], data['remoteid']))
                elif 'season' in data:
                    logger.debug(
                        "Manual %s of non-library '%s' S%02d, with an ID of '%s'."
                        % (args['action'], media_type, data['season'],
                           data['remoteid']))
                else:
                    logger.debug(
                        "Manual %s of non-library '%s' with an ID of '%s'." %
                        (args['action'], media_type, data['remoteid']))

            if args['action'] == 'rate' and 'rating' in args:
                if args['rating'] in [
                        '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'
                ]:
                    data['rating'] = int(args['rating'])

            data = {'action': 'manualRating', 'ratingData': data}

        else:
            logger.debug("Manual %s of '%s' is unsupported." %
                         (args['action'], media_type))

    elif args['action'] == 'togglewatched':
        media_type = kodiUtilities.getMediaType()
        if media_type in ['movie', 'show', 'season', 'episode']:
            data = {'media_type': media_type}
            if utilities.isMovie(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getMovieDetailsFromKodi(
                    dbid, ['imdbnumber', 'title', 'year', 'playcount'])
                if result:
                    if result['playcount'] == 0:
                        data['id'] = result['imdbnumber']
                    else:
                        logger.debug("Movie alread marked as watched in Kodi.")
                else:
                    logger.debug("Error getting movie details from Kodi.")
                    return

            elif utilities.isEpisode(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getEpisodeDetailsFromKodi(
                    dbid, [
                        'showtitle', 'season', 'episode', 'tvshowid',
                        'playcount'
                    ])
                if result:
                    if result['playcount'] == 0:
                        data['id'] = result['imdbnumber']
                        data['season'] = result['season']
                        data['number'] = result['episode']
                        data['title'] = result['showtitle']
                    else:
                        logger.debug(
                            "Episode already marked as watched in Kodi.")
                else:
                    logger.debug("Error getting episode details from Kodi.")
                    return

            elif utilities.isSeason(media_type):
                showID = None
                showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle')
                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetTVShows',
                    'params': {
                        'properties': ['title', 'imdbnumber', 'year']
                    },
                    'id': 0
                })
                if result and 'tvshows' in result:
                    for show in result['tvshows']:
                        if show['title'] == showTitle:
                            showID = show['tvshowid']
                            data['id'] = show['imdbnumber']
                            data['title'] = show['title']
                            break
                else:
                    logger.debug("Error getting TV shows from Kodi.")
                    return

                season = xbmc.getInfoLabel('ListItem.Season')
                if season == "":
                    season = 0
                else:
                    season = int(season)

                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetEpisodes',
                    'params': {
                        'tvshowid': showID,
                        'season': season,
                        'properties': ['season', 'episode', 'playcount']
                    },
                    'id': 0
                })
                if result and 'episodes' in result:
                    episodes = []
                    for episode in result['episodes']:
                        if episode['playcount'] == 0:
                            episodes.append(episode['episode'])

                    if len(episodes) == 0:
                        logger.debug(
                            "'%s - Season %d' is already marked as watched." %
                            (showTitle, season))
                        return

                    data['season'] = season
                    data['episodes'] = episodes
                else:
                    logger.debug(
                        "Error getting episodes from '%s' for Season %d" %
                        (showTitle, season))
                    return

            elif utilities.isShow(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getShowDetailsFromKodi(
                    dbid, ['year', 'imdbnumber'])
                if not result:
                    logger.debug("Error getting show details from Kodi.")
                    return
                showTitle = result['label']
                data['id'] = result['imdbnumber']
                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetEpisodes',
                    'params': {
                        'tvshowid':
                        dbid,
                        'properties':
                        ['season', 'episode', 'playcount', 'showtitle']
                    },
                    'id': 0
                })
                if result and 'episodes' in result:
                    i = 0
                    s = {}
                    for e in result['episodes']:
                        data['title'] = e['showtitle']
                        season = str(e['season'])
                        if not season in s:
                            s[season] = []
                        if e['playcount'] == 0:
                            s[season].append(e['episode'])
                            i += 1

                    if i == 0:
                        logger.debug("'%s' is already marked as watched." %
                                     showTitle)
                        return

                    data['seasons'] = dict(
                        (k, v) for k, v in s.iteritems() if v)
                else:
                    logger.debug(
                        "Error getting episode details for '%s' from Kodi." %
                        showTitle)
                    return

            if len(data) > 1:
                logger.debug(
                    "Marking '%s' with the following data '%s' as watched on Trakt.tv"
                    % (media_type, str(data)))
                data['action'] = 'markWatched'

        # execute toggle watched action
        xbmc.executebuiltin("Action(ToggleWatched)")

    elif args['action'] == 'addtowatchlist':
        media_type = kodiUtilities.getMediaType()
        if media_type in ['movie', 'show', 'season', 'episode']:
            data = {'media_type': media_type}
            if utilities.isMovie(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getMovieDetailsFromKodi(
                    dbid, ['imdbnumber', 'title', 'year', 'playcount'])
                if result:
                    data['id'] = result['imdbnumber']

                else:
                    logger.debug("Error getting movie details from Kodi.")
                    return

            elif utilities.isEpisode(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getEpisodeDetailsFromKodi(
                    dbid, [
                        'showtitle', 'season', 'episode', 'tvshowid',
                        'playcount'
                    ])
                if result:
                    data['id'] = result['imdbnumber']
                    data['season'] = result['season']
                    data['number'] = result['episode']
                    data['title'] = result['showtitle']

                else:
                    logger.debug("Error getting episode details from Kodi.")
                    return

            elif utilities.isSeason(media_type):
                showID = None
                showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle')
                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetTVShows',
                    'params': {
                        'properties': ['title', 'imdbnumber', 'year']
                    },
                    'id': 0
                })
                if result and 'tvshows' in result:
                    for show in result['tvshows']:
                        if show['title'] == showTitle:
                            showID = show['tvshowid']
                            data['id'] = show['imdbnumber']
                            data['title'] = show['title']
                            break
                else:
                    logger.debug("Error getting TV shows from Kodi.")
                    return

                season = xbmc.getInfoLabel('ListItem.Season')
                if season == "":
                    season = 0
                else:
                    season = int(season)

                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetEpisodes',
                    'params': {
                        'tvshowid': showID,
                        'season': season,
                        'properties': ['season', 'episode', 'playcount']
                    },
                    'id': 0
                })
                if result and 'episodes' in result:
                    episodes = []
                    for episode in result['episodes']:
                        if episode['playcount'] == 0:
                            episodes.append(episode['episode'])

                    data['season'] = season
                    data['episodes'] = episodes
                else:
                    logger.debug(
                        "Error getting episodes from '%s' for Season %d" %
                        (showTitle, season))
                    return

            elif utilities.isShow(media_type):
                dbid = int(xbmc.getInfoLabel('ListItem.DBID'))
                result = kodiUtilities.getShowDetailsFromKodi(
                    dbid, ['year', 'imdbnumber'])
                if not result:
                    logger.debug("Error getting show details from Kodi.")
                    return
                showTitle = result['label']
                data['id'] = result['imdbnumber']
                result = kodiUtilities.kodiJsonRequest({
                    'jsonrpc': '2.0',
                    'method': 'VideoLibrary.GetEpisodes',
                    'params': {
                        'tvshowid':
                        dbid,
                        'properties':
                        ['season', 'episode', 'playcount', 'showtitle']
                    },
                    'id': 0
                })
                if result and 'episodes' in result:
                    s = {}
                    for e in result['episodes']:
                        data['title'] = e['showtitle']
                        season = str(e['season'])
                        if not season in s:
                            s[season] = []
                        if e['playcount'] == 0:
                            s[season].append(e['episode'])

                    data['seasons'] = dict(
                        (k, v) for k, v in s.iteritems() if v)
                else:
                    logger.debug(
                        "Error getting episode details for '%s' from Kodi." %
                        showTitle)
                    return

            if len(data) > 1:
                logger.debug(
                    "Adding '%s' with the following data '%s' to users watchlist on Trakt.tv"
                    % (media_type, str(data)))
                data['action'] = 'addtowatchlist'

    q = sqlitequeue.SqliteQueue()
    if 'action' in data:
        logger.debug("Queuing for dispatch: %s" % data)
        q.append(data)
Example #2
0
class traktService:
    scrobbler = None
    updateTagsThread = None
    syncThread = None
    dispatchQueue = sqlitequeue.SqliteQueue()

    def __init__(self):
        threading.Thread.name = 'trakt'

    def _dispatchQueue(self, data):
        logger.debug("Queuing for dispatch: %s" % data)
        self.dispatchQueue.append(data)

    def _dispatch(self, data):
        try:
            logger.debug("Dispatch: %s" % data)
            action = data['action']
            if action == 'started':
                del data['action']
                self.scrobbler.playbackStarted(data)
            elif action == 'ended' or action == 'stopped':
                self.scrobbler.playbackEnded()
            elif action == 'paused':
                self.scrobbler.playbackPaused()
            elif action == 'resumed':
                self.scrobbler.playbackResumed()
            elif action == 'seek' or action == 'seekchapter':
                self.scrobbler.playbackSeek()
            elif action == 'scanFinished':
                if utilities.getSettingAsBool('sync_on_update'):
                    logger.debug("Performing sync after library update.")
                    self.doSync()
            elif action == 'databaseCleaned':
                if utilities.getSettingAsBool('sync_on_update') and (
                        utilities.getSettingAsBool('clean_trakt_movies')
                        or utilities.getSettingAsBool('clean_trakt_episodes')):
                    logger.debug("Performing sync after library clean.")
                    self.doSync()
            elif action == 'settingsChanged':
                logger.debug("Settings changed, reloading.")
                globals.traktapi.updateSettings()
            elif action == 'markWatched':
                del data['action']
                self.doMarkWatched(data)
            elif action == 'manualRating':
                ratingData = data['ratingData']
                self.doManualRating(ratingData)
            elif action == 'addtowatchlist':  # add to watchlist
                del data['action']
                self.doAddToWatchlist(data)
            elif action == 'manualSync':
                if not self.syncThread.isAlive():
                    logger.debug("Performing a manual sync.")
                    self.doSync(manual=True,
                                silent=data['silent'],
                                library=data['library'])
                else:
                    logger.debug("There already is a sync in progress.")
            elif action == 'settings':
                utilities.showSettings()
            else:
                logger.debug("Unknown dispatch action, '%s'." % action)
        except Exception as ex:
            message = utilities.createError(ex)
            logger.fatal(message)

    def run(self):
        startup_delay = utilities.getSettingAsInt('startup_delay')
        if startup_delay:
            logger.debug("Delaying startup by %d seconds." % startup_delay)
            xbmc.sleep(startup_delay * 1000)

        logger.debug("Service thread starting.")

        # purge queue before doing anything
        self.dispatchQueue.purge()

        # setup event driven classes
        self.Player = traktPlayer(action=self._dispatchQueue)
        self.Monitor = traktMonitor(action=self._dispatchQueue)

        # init traktapi class
        globals.traktapi = traktAPI()

        # init sync thread
        self.syncThread = syncThread()

        # init scrobbler class
        self.scrobbler = Scrobbler(globals.traktapi)

        # start loop for events
        while not self.Monitor.abortRequested():
            if not utilities.getSetting('authorization'):
                last_reminder = utilities.getSettingAsInt('last_reminder')
                now = int(time.time())
                if last_reminder >= 0 and last_reminder < now - (24 * 60 * 60):
                    gui_utils.get_pin()

            while len(self.dispatchQueue) and (
                    not self.Monitor.abortRequested()):
                data = self.dispatchQueue.get()
                logger.debug("Queued dispatch: %s" % data)
                self._dispatch(data)

            if xbmc.Player().isPlayingVideo():
                self.scrobbler.transitionCheck()

            if self.Monitor.waitForAbort(1):
                # Abort was requested while waiting. We should exit
                break

        # we are shutting down
        logger.debug("Beginning shut down.")

        # delete player/monitor
        del self.Player
        del self.Monitor

        # check if sync thread is running, if so, join it.
        if self.syncThread.isAlive():
            self.syncThread.join()

    def doManualRating(self, data):
        action = data['action']
        media_type = data['media_type']
        summaryInfo = None

        if not utilities.isValidMediaType(media_type):
            logger.debug(
                "doManualRating(): Invalid media type '%s' passed for manual %s."
                % (media_type, action))
            return

        if not data['action'] in ['rate', 'unrate']:
            logger.debug("doManualRating(): Unknown action passed.")
            return

        logger.debug(
            "Getting data for manual %s of %s: video_id: |%s| dbid: |%s|" %
            (action, media_type, data.get('video_id'), data.get('dbid')))

        id_type = utilities.parseIdToTraktIds(str(data['video_id']),
                                              media_type)[1]

        if not id_type:
            logger.debug("doManualRating(): Unrecognized id_type: |%s|-|%s|." %
                         (media_type, data['video_id']))
            return

        ids = globals.traktapi.getIdLookup(data['video_id'], id_type)

        if not ids:
            logger.debug("doManualRating(): No Results for: |%s|-|%s|." %
                         (media_type, data['video_id']))
            return

        trakt_id = dict(ids[0].keys)['trakt']
        if utilities.isEpisode(media_type):
            summaryInfo = globals.traktapi.getEpisodeSummary(
                trakt_id, data['season'], data['episode'])
            userInfo = globals.traktapi.getEpisodeRatingForUser(
                trakt_id, data['season'], data['episode'], 'trakt')
        elif utilities.isSeason(media_type):
            summaryInfo = globals.traktapi.getShowSummary(trakt_id)
            userInfo = globals.traktapi.getSeasonRatingForUser(
                trakt_id, data['season'], 'trakt')
        elif utilities.isShow(media_type):
            summaryInfo = globals.traktapi.getShowSummary(trakt_id)
            userInfo = globals.traktapi.getShowRatingForUser(trakt_id, 'trakt')
        elif utilities.isMovie(media_type):
            summaryInfo = globals.traktapi.getMovieSummary(trakt_id)
            userInfo = globals.traktapi.getMovieRatingForUser(
                trakt_id, 'trakt')

        if summaryInfo is not None:
            summaryInfo = summaryInfo.to_dict()
            summaryInfo['user'] = {'ratings': userInfo}
            if utilities.isEpisode(media_type):
                summaryInfo['season'] = data['season']
                summaryInfo['number'] = data['episode']
                summaryInfo['episodeid'] = data.get('dbid')
            elif utilities.isSeason(media_type):
                summaryInfo['season'] = data['season']
            elif utilities.isMovie(media_type):
                summaryInfo['movieid'] = data.get('dbid')
            elif utilities.isShow(media_type):
                summaryInfo['tvshowid'] = data.get('dbid')

            if action == 'rate':
                if not 'rating' in data:
                    rateMedia(media_type, [summaryInfo])
                else:
                    rateMedia(media_type, [summaryInfo], rating=data['rating'])
        else:
            logger.debug(
                "doManualRating(): Summary info was empty, possible problem retrieving data from Trakt.tv"
            )

    def doAddToWatchlist(self, data):
        media_type = data['media_type']

        if utilities.isMovie(media_type):
            summaryInfo = globals.traktapi.getMovieSummary(
                data['id']).to_dict()
            if summaryInfo:
                s = utilities.getFormattedItemName(media_type, summaryInfo)
                logger.debug(
                    "doAddToWatchlist(): '%s' trying to add to users watchlist."
                    % s)
                params = {'movies': [summaryInfo]}
                logger.debug("doAddToWatchlist(): %s" % str(params))

                result = globals.traktapi.addToWatchlist(params)
                if result:
                    utilities.notification(utilities.getString(32165), s)
                else:
                    utilities.notification(utilities.getString(32166), s)
        elif utilities.isEpisode(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0],
                    'seasons': [{
                        'number': data['season'],
                        'episodes': [{
                            'number': data['number']
                        }]
                    }]
                }]
            }
            logger.debug("doAddToWatchlist(): %s" % str(summaryInfo))
            s = utilities.getFormattedItemName(media_type, data)

            result = globals.traktapi.addToWatchlist(summaryInfo)
            if result:
                utilities.notification(utilities.getString(32165), s)
            else:
                utilities.notification(utilities.getString(32166), s)
        elif utilities.isSeason(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0],
                    'seasons': [{
                        'number': data['season']
                    }]
                }]
            }
            s = utilities.getFormattedItemName(media_type, data)

            logger.debug(
                "doAddToWatchlist(): '%s - Season %d' trying to add to users watchlist."
                % (data['id'], data['season']))

            result = globals.traktapi.addToWatchlist(summaryInfo)
            if result:
                utilities.notification(utilities.getString(32165), s)
            else:
                utilities.notification(utilities.getString(32166), s)
        elif utilities.isShow(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0]
                }]
            }
            s = utilities.getFormattedItemName(media_type, data)
            logger.debug("doAddToWatchlist(): %s" % str(summaryInfo))

            result = globals.traktapi.addToWatchlist(summaryInfo)
            if result:
                utilities.notification(utilities.getString(32165), s)
            else:
                utilities.notification(utilities.getString(32166), s)

    def doMarkWatched(self, data):

        media_type = data['media_type']

        if utilities.isMovie(media_type):
            summaryInfo = globals.traktapi.getMovieSummary(
                data['id']).to_dict()
            if summaryInfo:
                if not summaryInfo['watched']:
                    s = utilities.getFormattedItemName(media_type, summaryInfo)
                    logger.debug(
                        "doMarkWatched(): '%s' is not watched on Trakt, marking it as watched."
                        % s)
                    params = {'movies': [summaryInfo]}
                    logger.debug("doMarkWatched(): %s" % str(params))

                    result = globals.traktapi.addToHistory(params)
                    if result:
                        utilities.notification(utilities.getString(32113), s)
                    else:
                        utilities.notification(utilities.getString(32114), s)
        elif utilities.isEpisode(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0],
                    'seasons': [{
                        'number': data['season'],
                        'episodes': [{
                            'number': data['number']
                        }]
                    }]
                }]
            }
            logger.debug("doMarkWatched(): %s" % str(summaryInfo))
            s = utilities.getFormattedItemName(media_type, data)

            result = globals.traktapi.addToHistory(summaryInfo)
            if result:
                utilities.notification(utilities.getString(32113), s)
            else:
                utilities.notification(utilities.getString(32114), s)
        elif utilities.isSeason(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0],
                    'seasons': [{
                        'number': data['season'],
                        'episodes': []
                    }]
                }]
            }
            s = utilities.getFormattedItemName(media_type, data)
            for ep in data['episodes']:
                summaryInfo['shows'][0]['seasons'][0]['episodes'].append(
                    {'number': ep})

            logger.debug(
                "doMarkWatched(): '%s - Season %d' has %d episode(s) that are going to be marked as watched."
                % (data['id'], data['season'],
                   len(summaryInfo['shows'][0]['seasons'][0]['episodes'])))

            if len(summaryInfo['shows'][0]['seasons'][0]['episodes']) > 0:
                logger.debug("doMarkWatched(): %s" % str(summaryInfo))

                result = globals.traktapi.addToHistory(summaryInfo)
                if result:
                    utilities.notification(
                        utilities.getString(32113),
                        utilities.getString(32115) %
                        (result['added']['episodes'], s))
                else:
                    utilities.notification(utilities.getString(32114), s)
        elif utilities.isShow(media_type):
            summaryInfo = {
                'shows': [{
                    'ids':
                    utilities.parseIdToTraktIds(data['id'], media_type)[0],
                    'seasons': []
                }]
            }
            if summaryInfo:
                s = utilities.getFormattedItemName(media_type, data)
                logger.debug('data: %s' % data)
                for season in data['seasons']:
                    episodeJson = []
                    for episode in data['seasons'][season]:
                        episodeJson.append({'number': episode})
                    summaryInfo['shows'][0]['seasons'].append({
                        'number':
                        season,
                        'episodes':
                        episodeJson
                    })

                if len(summaryInfo['shows'][0]['seasons'][0]['episodes']) > 0:
                    logger.debug("doMarkWatched(): %s" % str(summaryInfo))

                    result = globals.traktapi.addToHistory(summaryInfo)
                    if result:
                        utilities.notification(
                            utilities.getString(32113),
                            utilities.getString(32115) %
                            (result['added']['episodes'], s))
                    else:
                        utilities.notification(utilities.getString(32114), s)

    def doSync(self, manual=False, silent=False, library="all"):
        self.syncThread = syncThread(manual, silent, library)
        self.syncThread.start()
Example #3
0
class traktService:
    scrobbler = None
    updateTagsThread = None
    syncThread = None
    dispatchQueue = sqlitequeue.SqliteQueue()

    def __init__(self):
        threading.Thread.name = 'trakt'

    def _dispatchQueue(self, data):
        logger.debug("Queuing for dispatch: %s" % data)
        self.dispatchQueue.append(data)

    def _dispatch(self, data):
        try:
            logger.debug("Dispatch: %s" % data)
            action = data['action']
            if action == 'started':
                del data['action']
                self.scrobbler.playbackStarted(data)
            elif action == 'ended' or action == 'stopped':
                self.scrobbler.playbackEnded()
            elif action == 'paused':
                self.scrobbler.playbackPaused()
            elif action == 'resumed':
                self.scrobbler.playbackResumed()
            elif action == 'seek' or action == 'seekchapter':
                self.scrobbler.playbackSeek()
            elif action == 'databaseUpdated':
                if utilities.getSettingAsBool('sync_on_update'):
                    logger.debug("Performing sync after library update.")
                    self.doSync()
            elif action == 'databaseCleaned':
                if utilities.getSettingAsBool('sync_on_update') and (
                        utilities.getSettingAsBool('clean_trakt_movies')
                        or utilities.getSettingAsBool('clean_trakt_episodes')):
                    logger.debug("Performing sync after library clean.")
                    self.doSync()
            elif action == 'settingsChanged':
                logger.debug("Settings changed, reloading.")
                globals.traktapi.updateSettings()
            elif action == 'markWatched':
                del data['action']
                self.doMarkWatched(data)
            elif action == 'manualRating':
                ratingData = data['ratingData']
                self.doManualRating(ratingData)
            elif action == 'manualSync':
                if not self.syncThread.isAlive():
                    logger.debug("Performing a manual sync.")
                    self.doSync(manual=True,
                                silent=data['silent'],
                                library=data['library'])
                else:
                    logger.debug("There already is a sync in progress.")
            elif action == 'settings':
                utilities.showSettings()
            elif action == 'scanStarted':
                pass
            else:
                logger.debug("Unknown dispatch action, '%s'." % action)
        except Exception as ex:
            message = utilities.createError(ex)
            logger.fatal(message)

    def run(self):
        startup_delay = utilities.getSettingAsInt('startup_delay')
        if startup_delay:
            logger.debug("Delaying startup by %d seconds." % startup_delay)
            xbmc.sleep(startup_delay * 1000)

        logger.debug("Service thread starting.")

        # purge queue before doing anything
        self.dispatchQueue.purge()

        # setup event driven classes
        self.Player = traktPlayer(action=self._dispatchQueue)
        self.Monitor = traktMonitor(action=self._dispatchQueue)

        # init traktapi class
        globals.traktapi = traktAPI()

        # init sync thread
        self.syncThread = syncThread()

        # init scrobbler class
        self.scrobbler = Scrobbler(globals.traktapi)

        # start loop for events
        while not xbmc.abortRequested:
            while len(self.dispatchQueue) and (not xbmc.abortRequested):
                data = self.dispatchQueue.get()
                logger.debug("Queued dispatch: %s" % data)
                self._dispatch(data)

            if xbmc.Player().isPlayingVideo():
                self.scrobbler.update()

            xbmc.sleep(500)

        # we are shutting down
        logger.debug("Beginning shut down.")

        # delete player/monitor
        del self.Player
        del self.Monitor

        # check if sync thread is running, if so, join it.
        if self.syncThread.isAlive():
            self.syncThread.join()

    def doManualRating(self, data):

        action = data['action']
        media_type = data['media_type']
        summaryInfo = None

        if not utilities.isValidMediaType(media_type):
            logger.debug(
                "doManualRating(): Invalid media type '%s' passed for manual %s."
                % (media_type, action))
            return

        if not data['action'] in ['rate', 'unrate']:
            logger.debug("doManualRating(): Unknown action passed.")
            return

        if 'dbid' in data:
            logger.debug(
                "Getting data for manual %s of library '%s' with ID of '%s'" %
                (action, media_type, data['dbid']))
        elif 'remoteitd' in data:
            if 'season' in data:
                logger.debug(
                    "Getting data for manual %s of non-library '%s' S%02dE%02d, with ID of '%s'."
                    % (action, media_type, data['season'], data['episode'],
                       data['remoteid']))
            else:
                logger.debug(
                    "Getting data for manual %s of non-library '%s' with ID of '%s'"
                    % (action, media_type, data['remoteid']))

        if utilities.isEpisode(media_type):
            summaryInfo = globals.traktapi.getEpisodeSummary(
                data['trakt'], data['season'], data['episode'])
        elif utilities.isShow(media_type):
            summaryInfo = globals.traktapi.getShowSummary(data['imdbnumber'])
        elif utilities.isMovie(media_type):
            summaryInfo = globals.traktapi.getMovieSummary(data['imdbnumber'])

        if not summaryInfo is None:
            if utilities.isMovie(media_type) or utilities.isShow(media_type):
                summaryInfo['xbmc_id'] = data['dbid']

            if action == 'rate':
                if not 'rating' in data:
                    rateMedia(media_type, summaryInfo)
                else:
                    rateMedia(media_type, summaryInfo, rating=data['rating'])
        else:
            logger.debug(
                "doManualRating(): Summary info was empty, possible problem retrieving data from Trakt.tv"
            )

    def doMarkWatched(self, data):

        media_type = data['media_type']
        markedNotification = utilities.getSettingAsBool(
            'show_marked_notification')

        if utilities.isMovie(media_type):
            summaryInfo = globals.traktapi.getMovieSummary(data['id'])
            if summaryInfo:
                if not summaryInfo['watched']:
                    s = utilities.getFormattedItemName(media_type, summaryInfo)
                    logger.debug(
                        "doMarkWatched(): '%s' is not watched on Trakt, marking it as watched."
                        % s)
                    movie = {
                        'imdb_id': data['id'],
                        'title': summaryInfo['title'],
                        'year': summaryInfo['year'],
                        'plays': 1,
                        'last_played': int(time())
                    }
                    params = {'movies': [movie]}
                    logger.debug("doMarkWatched(): %s" % str(params))

                    result = globals.traktapi.updateSeenMovie(params)
                    if result:
                        if markedNotification:
                            utilities.notification(utilities.getString(32113),
                                                   s)
                    else:
                        utilities.notification(utilities.getString(32114), s)

        elif utilities.isEpisode(media_type):
            summaryInfo = globals.traktapi.getEpisodeSummary(
                data['id'], data['season'], data['episode'])
            if summaryInfo:
                if not summaryInfo['episode']['watched']:
                    s = utilities.getFormattedItemName(media_type, summaryInfo)
                    logger.debug(
                        "doMarkWathced(): '%s' is not watched on Trakt, marking it as watched."
                        % s)
                    params = {
                        'imdb_id':
                        summaryInfo['ids']['imdb_id'],
                        'tvdb_id':
                        summaryInfo['ids']['tvdb_id'],
                        'title':
                        summaryInfo['title'],
                        'year':
                        summaryInfo['year'],
                        'episodes': [{
                            'season': data['season'],
                            'episode': data['episode']
                        }]
                    }
                    logger.debug("doMarkWatched(): %s" % str(params))

                    result = globals.traktapi.updateSeenEpisode(params)
                    if result:
                        if markedNotification:
                            utilities.notification(utilities.getString(32113),
                                                   s)
                    else:
                        utilities.notification(utilities.getString(32114), s)

        elif utilities.isSeason(media_type):
            showInfo = globals.traktapi.getShowSummary(data['id'])
            if not showInfo:
                return
            summaryInfo = globals.traktapi.getSeasonInfo(
                data['id'], data['season'])
            if summaryInfo:
                showInfo['season'] = data['season']
                s = utilities.getFormattedItemName(media_type, showInfo)
                params = {
                    'imdb_id': summaryInfo['ids']['imdb'],
                    'tvdb_id': summaryInfo['ids']['tvdb'],
                    'title': showInfo['title'],
                    'year': showInfo['year'],
                    'episodes': []
                }
                for ep in summaryInfo:
                    if ep['episode'] in data['episodes']:
                        if not ep['watched']:
                            params['episodes'].append({
                                'season': ep['season'],
                                'episode': ep['episode']
                            })

                logger.debug(
                    "doMarkWatched(): '%s - Season %d' has %d episode(s) that are going to be marked as watched."
                    % (showInfo['title'], data['season'],
                       len(params['episodes'])))

                if len(params['episodes']) > 0:
                    logger.debug("doMarkWatched(): %s" % str(params))

                    result = globals.traktapi.updateSeenEpisode(params)
                    if result:
                        if markedNotification:
                            utilities.notification(
                                utilities.getString(32113),
                                utilities.getString(32115) %
                                (len(params['episodes']), s))
                    else:
                        utilities.notification(
                            utilities.getString(32114),
                            utilities.getString(32115) %
                            (len(params['episodes']), s))

        elif utilities.isShow(media_type):
            summaryInfo = globals.traktapi.getShowSummary(data['id'],
                                                          extended=True)
            if summaryInfo:
                s = utilities.getFormattedItemName(media_type, summaryInfo)
                params = {
                    'imdb_id': summaryInfo['ids']['imdb'],
                    'tvdb_id': summaryInfo['ids']['tvdb'],
                    'title': summaryInfo['title'],
                    'year': summaryInfo['year'],
                    'episodes': []
                }
                for season in summaryInfo['seasons']:
                    for ep in season['episodes']:
                        if str(season['season']) in data['seasons']:
                            if ep['episode'] in data['seasons'][str(
                                    season['season'])]:
                                if not ep['watched']:
                                    params['episodes'].append({
                                        'season':
                                        ep['season'],
                                        'episode':
                                        ep['episode']
                                    })
                logger.debug(
                    "doMarkWatched(): '%s' has %d episode(s) that are going to be marked as watched."
                    % (summaryInfo['title'], len(params['episodes'])))

                if len(params['episodes']) > 0:
                    logger.debug("doMarkWatched(): %s" % str(params))

                    result = globals.traktapi.updateSeenEpisode(params)
                    if result:
                        if markedNotification:
                            utilities.notification(
                                utilities.getString(32113),
                                utilities.getString(32115) %
                                (len(params['episodes']), s))
                    else:
                        utilities.notification(
                            utilities.getString(32114),
                            utilities.getString(32115) %
                            (len(params['episodes']), s))

    def doSync(self, manual=False, silent=False, library="all"):
        self.syncThread = syncThread(manual, silent, library)
        self.syncThread.start()