Example #1
0
    def __scrobble(self, status):
        if not self.curVideoInfo:
            return

        logger.debug("scrobble()")
        scrobbleMovieOption = kodiUtilities.getSettingAsBool('scrobble_movie')
        scrobbleEpisodeOption = kodiUtilities.getSettingAsBool('scrobble_episode')

        watchedPercent = self.__calculateWatchedPercent()

        if utilities.isMovie(self.curVideo['type']) and scrobbleMovieOption:
            response = self.traktapi.scrobbleMovie(self.curVideoInfo, watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble movie: %s | %s | %s" % (self.curVideoInfo, watchedPercent, status))

        elif utilities.isEpisode(self.curVideo['type']) and scrobbleEpisodeOption:
            if self.isMultiPartEpisode:
                logger.debug("Multi-part episode, scrobbling part %d of %d." % (self.curMPEpisode + 1, self.curVideo['multi_episode_count']))
                adjustedDuration = int(self.videoDuration / self.curVideo['multi_episode_count'])
                watchedPercent = ((self.watchedTime - (adjustedDuration * self.curMPEpisode)) / adjustedDuration) * 100

            response = self.traktapi.scrobbleEpisode(self.traktShowSummary, self.curVideoInfo, watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble episode: %s | %s | %s | %s" % (self.traktShowSummary,
                                                                                self.curVideoInfo, watchedPercent,
                                                                                status))
Example #2
0
 def __preFetchUserRatings(self, result):
     if result:
         if utilities.isMovie(
                 self.curVideo['type']) and kodiUtilities.getSettingAsBool(
                     'rate_movie'):
             # pre-get summary information, for faster rating dialog.
             logger.debug(
                 "Movie rating is enabled, pre-fetching summary information."
             )
             self.curVideoInfo = result['movie']
             self.curVideoInfo['user'] = {
                 'ratings':
                 self.traktapi.getMovieRatingForUser(
                     result['movie']['ids']['trakt'], 'trakt')
             }
         elif utilities.isEpisode(
                 self.curVideo['type']) and kodiUtilities.getSettingAsBool(
                     'rate_episode'):
             # pre-get summary information, for faster rating dialog.
             logger.debug(
                 "Episode rating is enabled, pre-fetching summary information."
             )
             self.curVideoInfo = result['episode']
             self.curVideoInfo['user'] = {
                 'ratings':
                 self.traktapi.getEpisodeRatingForUser(
                     result['show']['ids']['trakt'],
                     self.curVideoInfo['season'],
                     self.curVideoInfo['number'], 'trakt')
             }
         logger.debug('Pre-Fetch result: %s; Info: %s' %
                      (result, self.curVideoInfo))
Example #3
0
    def __scrobble(self, status):
        if not self.curVideoInfo:
            return

        logger.debug("scrobble()")
        scrobbleMovieOption = kodiUtilities.getSettingAsBool('scrobble_movie')
        scrobbleEpisodeOption = kodiUtilities.getSettingAsBool('scrobble_episode')

        watchedPercent = self.__calculateWatchedPercent()

        if utilities.isMovie(self.curVideo['type']) and scrobbleMovieOption:
            response = self.traktapi.scrobbleMovie(self.curVideoInfo, watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble movie: %s | %s | %s" % (self.curVideoInfo, watchedPercent, status))

        elif utilities.isEpisode(self.curVideo['type']) and scrobbleEpisodeOption:
            if self.isMultiPartEpisode:
                logger.debug("Multi-part episode, scrobbling part %d of %d." % (self.curMPEpisode + 1, self.curVideo['multi_episode_count']))
                adjustedDuration = int(self.videoDuration / self.curVideo['multi_episode_count'])
                watchedPercent = ((self.watchedTime - (adjustedDuration * self.curMPEpisode)) / adjustedDuration) * 100

            logger.debug("scrobble sending show object: %s" % str(self.traktShowSummary))
            logger.debug("scrobble sending episode object: %s" % str(self.curVideoInfo))
            response = self.traktapi.scrobbleEpisode(self.traktShowSummary, self.curVideoInfo, watchedPercent, status)
            
            if (kodiUtilities.getSettingAsBool('scrobble_secondary_title')):
                logger.debug('[traktPlayer] Setting is enabled to try secondary show title, if necessary.')
                # If there is an empty response, the reason might be that the title we have isn't the actual show title,
                # but rather an alternative title. To handle this case, call the Trakt search function.
                if response is None:
                    logger.debug("Searching for show title: %s" % self.traktShowSummary['title'])
                    # This text query API is basically the same as searching on the website. Works with alternative 
                    # titles, unlike the scrobble function.
                    newResp = self.traktapi.getTextQuery(self.traktShowSummary['title'], "show", None)
                    if not newResp:
                        logger.debug("Empty Response from getTextQuery, giving up")
                    else:
                        logger.debug("Got Response from getTextQuery: %s" % str(newResp))
                        # We got something back. Have to assume the first show found is the right one; if there's more than
                        # one, there's no way to know which to use. Pull the primary title from the response (and the year,
                        # just because it's there).
                        showObj = {'title': newResp[0].title, 'year': newResp[0].year}
                        logger.debug("scrobble sending getTextQuery first show object: %s" % str(showObj))
                        # Now we can attempt the scrobble again, using the primary title this time.
                        response = self.traktapi.scrobbleEpisode(showObj, self.curVideoInfo, watchedPercent, status)
                    
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble episode: %s | %s | %s | %s" % (self.traktShowSummary,
                                                                                self.curVideoInfo, watchedPercent,
                                                                                status))
Example #4
0
 def __init__(self, show_progress=False, run_silent=False, library="all", api=None):
     self.traktapi = api
     self.show_progress = show_progress
     self.run_silent = run_silent
     self.library = library
     if self.show_progress and self.run_silent:
         logger.debug("Sync is being run silently.")
     self.sync_on_update = getSettingAsBool('sync_on_update')
     self.notify = getSettingAsBool('show_sync_notifications')
     self.notify_during_playback = not (xbmc.Player().isPlayingVideo() and getSettingAsBool("hide_notifications_playback"))
Example #5
0
 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 kodiUtilities.getSettingAsBool('sync_on_update'):
                 logger.debug("Performing sync after library update.")
                 self.doSync()
         elif action == 'databaseCleaned':
             if kodiUtilities.getSettingAsBool('sync_on_update') and (
                     kodiUtilities.getSettingAsBool('clean_trakt_movies') or
                     kodiUtilities.getSettingAsBool('clean_trakt_episodes')
             ):
                 logger.debug("Performing sync after library clean.")
                 self.doSync()
         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':
             kodiUtilities.showSettings()
         elif action == 'auth_info':
             xbmc.executebuiltin('Dialog.Close(all, true)')
             # init traktapi class
             globals.traktapi = traktAPI(True)
         else:
             logger.debug("Unknown dispatch action, '%s'." % action)
     except Exception as ex:
         message = utilities.createError(ex)
         logger.fatal(message)
Example #6
0
 def __preFetchUserRatings(self, result):
     if result:
         if utilities.isMovie(self.curVideo['type']) and kodiUtilities.getSettingAsBool('rate_movie'):
             # pre-get summary information, for faster rating dialog.
             logger.debug("Movie rating is enabled, pre-fetching summary information.")
             self.curVideoInfo = result['movie']
             self.curVideoInfo['user'] = {'ratings': self.traktapi.getMovieRatingForUser(result['movie']['ids']['trakt'], 'trakt')}
         elif utilities.isEpisode(self.curVideo['type']) and kodiUtilities.getSettingAsBool('rate_episode'):
             # pre-get summary information, for faster rating dialog.
             logger.debug("Episode rating is enabled, pre-fetching summary information.")
             self.curVideoInfo = result['episode']
             self.curVideoInfo['user'] = {'ratings': self.traktapi.getEpisodeRatingForUser(result['show']['ids']['trakt'],
                                                                                           self.curVideoInfo['season'], self.curVideoInfo['number'], 'trakt')}
         logger.debug('Pre-Fetch result: %s; Info: %s' % (result, self.curVideoInfo))
Example #7
0
 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 kodiUtilities.getSettingAsBool('sync_on_update'):
                 logger.debug("Performing sync after library update.")
                 self.doSync()
         elif action == 'databaseCleaned':
             if kodiUtilities.getSettingAsBool('sync_on_update') and (kodiUtilities.getSettingAsBool('clean_trakt_movies') or kodiUtilities.getSettingAsBool('clean_trakt_episodes')):
                 logger.debug("Performing sync after library clean.")
                 self.doSync()
         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':
             kodiUtilities.showSettings()
         elif action == 'auth_info':
             xbmc.executebuiltin('Dialog.Close(all, true)')
             # init traktapi class
             globals.traktapi = traktAPI(True)
         else:
             logger.debug("Unknown dispatch action, '%s'." % action)
     except Exception as ex:
         message = utilities.createError(ex)
         logger.fatal(message)
Example #8
0
    def __deleteEpisodesFromTraktCollection(self, traktShows, kodiShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('clean_trakt_episodes') and not self.sync.IsCanceled():
            removeTraktShows = copy.deepcopy(traktShows)
            removeKodiShows = copy.deepcopy(kodiShows)

            traktShowsRemove = self.__compareEpisodes(removeTraktShows, removeKodiShows)
            utilities.sanitizeShows(traktShowsRemove)

            if len(traktShowsRemove['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString(32077), line2=kodiUtilities.getString(32110))
                logger.debug('[Episodes Sync] Trakt.tv episode collection is clean, no episodes to remove.')
                return

            logger.debug("[Episodes Sync] %i show(s) will have episodes removed from Trakt.tv collection." % len(traktShowsRemove['shows']))
            for show in traktShowsRemove['shows']:
                logger.debug("[Episodes Sync] Episodes removed: %s" % self.__getShowAsString(show, short=True))

            self.sync.UpdateProgress(fromPercent, line1=kodiUtilities.getString(32077), line2=kodiUtilities.getString(32111) % self.__countEpisodes(traktShowsRemove))

            logger.debug("[traktRemoveEpisodes] Shows to remove %s" % traktShowsRemove)
            try:
                self.sync.traktapi.removeFromCollection(traktShowsRemove)
            except Exception as ex:
                message = utilities.createError(ex)
                logging.fatal(message)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32112) % self.__countEpisodes(traktShowsRemove))
Example #9
0
    def __addMovieProgressToKodi(self, traktMovies, kodiMovies, fromPercent, toPercent):

        if kodiUtilities.getSettingAsBool('trakt_movie_playback') and traktMovies and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            kodiMoviesToUpdate = utilities.compareMovies(updateKodiTraktMovies['movies'], updateKodiKodiMovies, restrict=True, playback=True)
            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32125))
                logger.debug("[Movies Sync] Kodi movie playbacks are up to date.")
                return

            logger.debug("[Movies Sync] %i movie(s) playbacks will be updated in Kodi" % len(kodiMoviesToUpdate))

            self.sync.UpdateProgress(fromPercent, line1='', line2=kodiUtilities.getString(32126) % len(kodiMoviesToUpdate))
            # need to calculate the progress in int from progress in percent from Trakt
            # split movie list into chunks of 50
            chunksize = 50
            chunked_movies = utilities.chunks([{"jsonrpc": "2.0", "id": i, "method": "VideoLibrary.SetMovieDetails", "params": {"movieid": kodiMoviesToUpdate[i]['movieid'], "resume": {"position": kodiMoviesToUpdate[i]['runtime'] / 100.0 * kodiMoviesToUpdate[i]['progress'], "total": kodiMoviesToUpdate[i]['runtime']}}} for i in range(len(kodiMoviesToUpdate))], chunksize)
            i = 0
            x = float(len(kodiMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32127) % ((i) * chunksize if (i) * chunksize < x else x, x))
                kodiUtilities.kodiJsonRequest(chunk)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32128) % len(kodiMoviesToUpdate))
Example #10
0
    def __scrobbleNotification(self, info):
        if not self.curVideoInfo:
            return

        if kodiUtilities.getSettingAsBool("scrobble_notification"):
            s = utilities.getFormattedItemName(self.curVideo['type'], info[self.curVideo['type']])
            kodiUtilities.notification(kodiUtilities.getString(32015), s)
Example #11
0
    def __addMoviesToKodiWatched(self, traktMovies, kodiMovies, fromPercent, toPercent):

        if kodiUtilities.getSettingAsBool('kodi_movie_playcount') and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            kodiMoviesToUpdate = utilities.compareMovies(updateKodiTraktMovies, updateKodiKodiMovies, watched=True, restrict=True)

            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32088))
                logger.debug("[Movies Sync] Kodi movie playcount is up to date.")
                return

            titles = ", ".join(["%s" % (m['title']) for m in kodiMoviesToUpdate])
            logger.debug("[Movies Sync] %i movie(s) playcount will be updated in Kodi" % len(kodiMoviesToUpdate))
            logger.debug("[Movies Sync] Movies to add: %s" % titles)

            self.sync.UpdateProgress(fromPercent, line2=kodiUtilities.getString(32065) % len(kodiMoviesToUpdate))

            # split movie list into chunks of 50
            chunksize = 50
            chunked_movies = utilities.chunks([{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": {"movieid": kodiMoviesToUpdate[i]['movieid'], "playcount": kodiMoviesToUpdate[i]['plays'], "lastplayed": utilities.convertUtcToDateTime(kodiMoviesToUpdate[i]['last_watched_at'])}, "id": i} for i in range(len(kodiMoviesToUpdate))], chunksize)
            i = 0
            x = float(len(kodiMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32089) % ((i) * chunksize if (i) * chunksize < x else x, x))

                kodiUtilities.kodiJsonRequest(chunk)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32090) % len(kodiMoviesToUpdate))
Example #12
0
    def __traktLoadShowsPlaybackProgress(self, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_episode_playback') and not self.sync.IsCanceled():
            self.sync.UpdateProgress(fromPercent, line1=kodiUtilities.getString(1485), line2=kodiUtilities.getString(32119))

            logger.debug('[Playback Sync] Getting playback progress from Trakt.tv')
            try:
                traktProgressShows = self.sync.traktapi.getEpisodePlaybackProgress()
            except Exception as ex:
                logger.debug("[Playback Sync] Invalid Trakt.tv progress list, possible error getting data from Trakt, aborting Trakt.tv playback update. Error: %s" % ex)
                return False

            i = 0
            x = float(len(traktProgressShows))
            showsProgress = {'shows': []}
            for show in traktProgressShows:
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32120) % (i, x))

                # will keep the data in python structures - just like the KODI response
                show = show.to_dict()

                showsProgress['shows'].append(show)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32121))

            return showsProgress
Example #13
0
    def __traktLoadMoviesPlaybackProgress(self, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_movie_playback') and not self.sync.IsCanceled():
            self.sync.UpdateProgress(fromPercent, line2=kodiUtilities.getString(32122))

            logger.debug('[Movies Sync] Getting playback progress from Trakt.tv')
            try:
                traktProgressMovies = self.sync.traktapi.getMoviePlaybackProgress()
            except Exception:
                logger.debug("[Movies Sync] Invalid Trakt.tv playback progress list, possible error getting data from Trakt, aborting Trakt.tv playback update.")
                return False

            i = 0
            x = float(len(traktProgressMovies))
            moviesProgress = {'movies': []}
            for movie in traktProgressMovies:
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32123) % (i, x))

                # will keep the data in python structures - just like the KODI response
                movie = movie.to_dict()

                moviesProgress['movies'].append(movie)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32124))

            return moviesProgress
Example #14
0
    def __deleteMoviesFromTraktCollection(self, traktMovies, kodiMovies, fromPercent, toPercent):

        if kodiUtilities.getSettingAsBool('clean_trakt_movies') and not self.sync.IsCanceled():
            removeTraktMovies = copy.deepcopy(traktMovies)
            removeKodiMovies = copy.deepcopy(kodiMovies)

            logger.debug("[Movies Sync] Starting to remove.")
            traktMoviesToRemove = utilities.compareMovies(removeTraktMovies, removeKodiMovies)
            utilities.sanitizeMovies(traktMoviesToRemove)
            logger.debug("[Movies Sync] Compared movies, found %s to remove." % len(traktMoviesToRemove))

            if len(traktMoviesToRemove) == 0:
                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32091))
                logger.debug("[Movies Sync] Trakt.tv movie collection is clean, no movies to remove.")
                return

            titles = ", ".join(["%s" % (m['title']) for m in traktMoviesToRemove])
            logger.debug("[Movies Sync] %i movie(s) will be removed from Trakt.tv collection." % len(traktMoviesToRemove))
            logger.debug("[Movies Sync] Movies removed: %s" % titles)

            self.sync.UpdateProgress(fromPercent, line2=kodiUtilities.getString(32076) % len(traktMoviesToRemove))

            moviesToRemove = {'movies': traktMoviesToRemove}
            try:
                self.sync.traktapi.removeFromCollection(moviesToRemove)
            except Exception as ex:
                message = utilities.createError(ex)
                logging.fatal(message)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32092) % len(traktMoviesToRemove))
Example #15
0
    def __addMoviesToTraktCollection(self, kodiMovies, traktMovies, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('add_movies_to_trakt') and not self.sync.IsCanceled():
            addTraktMovies = copy.deepcopy(traktMovies)
            addKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToAdd = utilities.compareMovies(addKodiMovies, addTraktMovies)
            utilities.sanitizeMovies(traktMoviesToAdd)
            logger.debug("[Movies Sync] Compared movies, found %s to add." % len(traktMoviesToAdd))

            if len(traktMoviesToAdd) == 0:
                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32084))
                logger.debug("[Movies Sync] Trakt.tv movie collection is up to date.")
                return

            titles = ", ".join(["%s" % (m['title']) for m in traktMoviesToAdd])
            logger.debug("[Movies Sync] %i movie(s) will be added to Trakt.tv collection." % len(traktMoviesToAdd))
            logger.debug("[Movies Sync] Movies to add : %s" % titles)

            self.sync.UpdateProgress(fromPercent, line2=kodiUtilities.getString(32063) % len(traktMoviesToAdd))

            moviesToAdd = {'movies': traktMoviesToAdd}
            # logger.debug("Movies to add: %s" % moviesToAdd)
            try:
                self.sync.traktapi.addToCollection(moviesToAdd)
            except Exception as ex:
                message = utilities.createError(ex)
                logging.fatal(message)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32085) % len(traktMoviesToAdd))
Example #16
0
    def __addMoviesToTraktWatched(self, kodiMovies, traktMovies, fromPercent,
                                  toPercent):
        if kodiUtilities.getSettingAsBool(
                'trakt_movie_playcount') and not self.sync.IsCanceled():
            updateTraktTraktMovies = copy.deepcopy(traktMovies)
            updateTraktKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToUpdate = utilities.compareMovies(
                updateTraktKodiMovies, updateTraktTraktMovies, watched=True)
            utilities.sanitizeMovies(traktMoviesToUpdate)

            if len(traktMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line2=kodiUtilities.getString(32086))
                logger.debug(
                    "[Movies Sync] Trakt.tv movie playcount is up to date")
                return

            titles = ", ".join(
                ["%s" % (m['title']) for m in traktMoviesToUpdate])
            logger.debug(
                "[Movies Sync] %i movie(s) playcount will be updated on Trakt.tv"
                % len(traktMoviesToUpdate))
            logger.debug("[Movies Sync] Movies updated: %s" % titles)

            self.sync.UpdateProgress(fromPercent,
                                     line2=kodiUtilities.getString(32064) %
                                     len(traktMoviesToUpdate))
            # Send request to update playcounts on Trakt.tv
            chunksize = 200
            chunked_movies = utilities.chunks(
                [movie for movie in traktMoviesToUpdate], chunksize)
            errorcount = 0
            i = 0
            x = float(len(traktMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent - fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y),
                                         line2=kodiUtilities.getString(32093) %
                                         ((i) * chunksize if
                                          (i) * chunksize < x else x, x))

                params = {'movies': chunk}
                # logger.debug("moviechunk: %s" % params)
                try:
                    self.sync.traktapi.addToHistory(params)
                except Exception as ex:
                    message = utilities.createError(ex)
                    logging.fatal(message)
                    errorcount += 1

            logger.debug("[Movies Sync] Movies updated: %d error(s)" %
                         errorcount)
            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32087) %
                                     len(traktMoviesToUpdate))
Example #17
0
    def __scrobbleNotification(self, info):
        if not self.curVideoInfo:
            return

        if kodiUtilities.getSettingAsBool("scrobble_notification"):
            s = utilities.getFormattedItemName(self.curVideo['type'],
                                               info[self.curVideo['type']])
            kodiUtilities.notification(kodiUtilities.getString(32015), s)
Example #18
0
def ratingCheck(media_type, summary_info, watched_time, total_time, playlist_length):
    """Check if a video should be rated and if so launches the rating dialog"""
    logger.debug("Rating Check called for '%s'" % media_type)
    if not kodiUtilities.getSettingAsBool("rate_%s" % media_type):
        logger.debug("'%s' is configured to not be rated." % media_type)
        return
    if summary_info is None:
        logger.debug("Summary information is empty, aborting.")
        return
    watched = (watched_time / total_time) * 100
    if watched >= kodiUtilities.getSettingAsFloat("rate_min_view_time"):
        if (playlist_length <= 1) or kodiUtilities.getSettingAsBool("rate_each_playlist_item"):
            rateMedia(media_type, summary_info)
        else:
            logger.debug("Rate each playlist item is disabled.")
    else:
        logger.debug("'%s' does not meet minimum view time for rating (watched: %0.2f%%, minimum: %0.2f%%)" % (media_type, watched, kodiUtilities.getSettingAsFloat("rate_min_view_time")))
Example #19
0
    def __scrobble(self, status):
        if not self.curVideoInfo:
            return

        logger.debug("scrobble()")
        scrobbleMovieOption = kodiUtilities.getSettingAsBool('scrobble_movie')
        scrobbleEpisodeOption = kodiUtilities.getSettingAsBool(
            'scrobble_episode')

        watchedPercent = self.__calculateWatchedPercent()

        if utilities.isMovie(self.curVideo['type']) and scrobbleMovieOption:
            response = self.traktapi.scrobbleMovie(self.curVideoInfo,
                                                   watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble movie: %s | %s | %s" %
                             (self.curVideoInfo, watchedPercent, status))

        elif utilities.isEpisode(
                self.curVideo['type']) and scrobbleEpisodeOption:
            if self.isMultiPartEpisode:
                logger.debug("Multi-part episode, scrobbling part %d of %d." %
                             (self.curMPEpisode + 1,
                              self.curVideo['multi_episode_count']))
                adjustedDuration = int(self.videoDuration /
                                       self.curVideo['multi_episode_count'])
                watchedPercent = ((self.watchedTime -
                                   (adjustedDuration * self.curMPEpisode)) /
                                  adjustedDuration) * 100

            response = self.traktapi.scrobbleEpisode(self.traktShowSummary,
                                                     self.curVideoInfo,
                                                     watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble episode: %s | %s | %s | %s" %
                             (self.traktShowSummary, self.curVideoInfo,
                              watchedPercent, status))
Example #20
0
def ratingCheck(media_type, summary_info, watched_time, total_time,
                playlist_length):
    """Check if a video should be rated and if so launches the rating dialog"""
    logger.debug("Rating Check called for '%s'" % media_type)
    if not kodiUtilities.getSettingAsBool("rate_%s" % media_type):
        logger.debug("'%s' is configured to not be rated." % media_type)
        return
    if summary_info is None:
        logger.debug("Summary information is empty, aborting.")
        return
    watched = (watched_time / total_time) * 100
    if watched >= kodiUtilities.getSettingAsFloat("rate_min_view_time"):
        if (playlist_length <= 1
            ) or kodiUtilities.getSettingAsBool("rate_each_playlist_item"):
            rateMedia(media_type, summary_info)
        else:
            logger.debug("Rate each playlist item is disabled.")
    else:
        logger.debug(
            "'%s' does not meet minimum view time for rating (watched: %0.2f%%, minimum: %0.2f%%)"
            % (media_type, watched,
               kodiUtilities.getSettingAsFloat("rate_min_view_time")))
Example #21
0
 def emit(self, record):
     levels = {
         logging.CRITICAL: xbmc.LOGFATAL,
         logging.ERROR: xbmc.LOGERROR,
         logging.WARNING: xbmc.LOGWARNING,
         logging.INFO: xbmc.LOGINFO,
         logging.DEBUG: xbmc.LOGDEBUG,
         logging.NOTSET: xbmc.LOGNONE,
     }
     if getSettingAsBool('debug'):
         try:
             xbmc.log(self.format(record), levels[record.levelno])
         except UnicodeEncodeError:
             xbmc.log(self.format(record).encode('utf-8', 'ignore'), levels[record.levelno])
Example #22
0
    def __syncEpisodeRatings(self, traktShows, kodiShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_sync_ratings') and traktShows and not self.sync.IsCanceled():
            updateKodiTraktShows = copy.deepcopy(traktShows)
            updateKodiKodiShows = copy.deepcopy(kodiShows)

            traktShowsToUpdate = self.__compareEpisodes(updateKodiKodiShows, updateKodiTraktShows, rating=True)
            if len(traktShowsToUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32181))
                logger.debug("[Episodes Sync] Trakt episode ratings are up to date.")
            else:
                logger.debug("[Episodes Sync] %i show(s) will have episode ratings added on Trakt" % len(traktShowsToUpdate['shows']))

                self.sync.UpdateProgress(fromPercent, line1='', line2=kodiUtilities.getString(32182) % len(traktShowsToUpdate['shows']))
                self.sync.traktapi.addRating(traktShowsToUpdate)


            kodiShowsUpdate = self.__compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, restrict=True, rating=True)
            if len(kodiShowsUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32173))
                logger.debug("[Episodes Sync] Kodi episode ratings are up to date.")
            else:
                logger.debug("[Episodes Sync] %i show(s) will have episode ratings added in Kodi" % len(kodiShowsUpdate['shows']))
                for s in ["%s" % self.__getShowAsString(s, short=True) for s in kodiShowsUpdate['shows']]:
                    logger.debug("[Episodes Sync] Episodes updated: %s" % s)

                episodes = []
                for show in kodiShowsUpdate['shows']:
                    for season in show['seasons']:
                        for episode in season['episodes']:
                            episodes.append({'episodeid': episode['ids']['episodeid'], 'rating': episode['rating']})

                # split episode list into chunks of 50
                chunksize = 50
                chunked_episodes = utilities.chunks([{"jsonrpc": "2.0", "id": i, "method": "VideoLibrary.SetEpisodeDetails",
                                        "params": {"episodeid": episodes[i]['episodeid'],
                                                   "userrating": episodes[i]['rating']}} for i in range(len(episodes))],
                                        chunksize)
                i = 0
                x = float(len(episodes))
                for chunk in chunked_episodes:
                    if self.sync.IsCanceled():
                        return
                    i += 1
                    y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                    self.sync.UpdateProgress(int(y), line1='', line2=kodiUtilities.getString(32174) % ((i) * chunksize if (i) * chunksize < x else x, x))

                    kodiUtilities.kodiJsonRequest(chunk)

                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32175) % len(episodes))
Example #23
0
 def emit(self, record):
     levels = {
         logging.CRITICAL: xbmc.LOGFATAL,
         logging.ERROR: xbmc.LOGERROR,
         logging.WARNING: xbmc.LOGWARNING,
         logging.INFO: xbmc.LOGINFO,
         logging.DEBUG: xbmc.LOGDEBUG,
         logging.NOTSET: xbmc.LOGNONE,
     }
     if getSettingAsBool('debug'):
         try:
             xbmc.log(self.format(record), levels[record.levelno])
         except UnicodeEncodeError:
             xbmc.log(
                 self.format(record).encode('utf-8', 'ignore'),
                 levels[record.levelno])
Example #24
0
    def __syncShowsRatings(self, traktShows, kodiShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_sync_ratings') and traktShows and not self.sync.IsCanceled():
            updateKodiTraktShows = copy.deepcopy(traktShows)
            updateKodiKodiShows = copy.deepcopy(kodiShows)

            traktShowsToUpdate = self.__compareShows(updateKodiKodiShows, updateKodiTraktShows, rating=True)
            if len(traktShowsToUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32181))
                logger.debug("[Episodes Sync] Trakt show ratings are up to date.")
            else:
                logger.debug("[Episodes Sync] %i show(s) will have show ratings added on Trakt" % len(traktShowsToUpdate['shows']))

                self.sync.UpdateProgress(fromPercent, line1='', line2=kodiUtilities.getString(32182) % len(traktShowsToUpdate['shows']))

                self.sync.traktapi.addRating(traktShowsToUpdate)

            # needs to be restricted, because we can't add a rating to an episode which is not in our Kodi collection
            kodiShowsUpdate = self.__compareShows(updateKodiTraktShows, updateKodiKodiShows, rating=True, restrict = True)

            if len(kodiShowsUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32176))
                logger.debug("[Episodes Sync] Kodi show ratings are up to date.")
            else:
                logger.debug("[Episodes Sync] %i show(s) will have show ratings added in Kodi" % len(kodiShowsUpdate['shows']))

                shows = []
                for show in kodiShowsUpdate['shows']:
                    shows.append({'tvshowid': show['tvshowid'], 'rating': show['rating']})

                # split episode list into chunks of 50
                chunksize = 50
                chunked_episodes = utilities.chunks([{"jsonrpc": "2.0", "id": i, "method": "VideoLibrary.SetTVShowDetails",
                                        "params": {"tvshowid": shows[i]['tvshowid'],
                                                   "userrating": shows[i]['rating']}} for i in range(len(shows))],
                                        chunksize)
                i = 0
                x = float(len(shows))
                for chunk in chunked_episodes:
                    if self.sync.IsCanceled():
                        return
                    i += 1
                    y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                    self.sync.UpdateProgress(int(y), line1='', line2=kodiUtilities.getString(32177) % ((i) * chunksize if (i) * chunksize < x else x, x))

                    kodiUtilities.kodiJsonRequest(chunk)

                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32178) % len(shows))
Example #25
0
    def __syncMovieRatings(self, traktMovies, kodiMovies, fromPercent, toPercent):

        if kodiUtilities.getSettingAsBool('trakt_sync_ratings') and traktMovies and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToUpdate = utilities.compareMovies(updateKodiKodiMovies, updateKodiTraktMovies, rating=True)
            if len(traktMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32179))
                logger.debug("[Movies Sync] Trakt movie ratings are up to date.")
            else:
                logger.debug("[Movies Sync] %i movie(s) ratings will be updated on Trakt" % len(traktMoviesToUpdate))

                self.sync.UpdateProgress(fromPercent, line1='', line2=kodiUtilities.getString(32180) % len(traktMoviesToUpdate))

                moviesRatings = {'movies': traktMoviesToUpdate}

                self.sync.traktapi.addRating(moviesRatings)


            kodiMoviesToUpdate = utilities.compareMovies(updateKodiTraktMovies, updateKodiKodiMovies, restrict=True, rating=True)
            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent, line1='', line2=kodiUtilities.getString(32169))
                logger.debug("[Movies Sync] Kodi movie ratings are up to date.")
            else:
                logger.debug("[Movies Sync] %i movie(s) ratings will be updated in Kodi" % len(kodiMoviesToUpdate))

                self.sync.UpdateProgress(fromPercent, line1='', line2=kodiUtilities.getString(32170) % len(kodiMoviesToUpdate))
                # split movie list into chunks of 50
                chunksize = 50
                chunked_movies = utilities.chunks([{"jsonrpc": "2.0", "id": i, "method": "VideoLibrary.SetMovieDetails",
                                                    "params": {"movieid": kodiMoviesToUpdate[i]['movieid'],
                                                               "userrating": kodiMoviesToUpdate[i]['rating']}} for i in range(len(kodiMoviesToUpdate))],
                                                  chunksize)
                i = 0
                x = float(len(kodiMoviesToUpdate))
                for chunk in chunked_movies:
                    if self.sync.IsCanceled():
                        return
                    i += 1
                    y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                    self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32171) % ((i) * chunksize if (i) * chunksize < x else x, x))
                    kodiUtilities.kodiJsonRequest(chunk)

                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32172) % len(kodiMoviesToUpdate))
Example #26
0
    def __deleteMoviesFromTraktCollection(self, traktMovies, kodiMovies,
                                          fromPercent, toPercent):

        if kodiUtilities.getSettingAsBool(
                'clean_trakt_movies') and not self.sync.IsCanceled():
            removeTraktMovies = copy.deepcopy(traktMovies)
            removeKodiMovies = copy.deepcopy(kodiMovies)

            logger.debug("[Movies Sync] Starting to remove.")
            traktMoviesToRemove = utilities.compareMovies(
                removeTraktMovies, removeKodiMovies)
            utilities.sanitizeMovies(traktMoviesToRemove)
            logger.debug("[Movies Sync] Compared movies, found %s to remove." %
                         len(traktMoviesToRemove))

            if len(traktMoviesToRemove) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line2=kodiUtilities.getString(32091))
                logger.debug(
                    "[Movies Sync] Trakt.tv movie collection is clean, no movies to remove."
                )
                return

            titles = ", ".join(
                ["%s" % (m['title']) for m in traktMoviesToRemove])
            logger.debug(
                "[Movies Sync] %i movie(s) will be removed from Trakt.tv collection."
                % len(traktMoviesToRemove))
            logger.debug("[Movies Sync] Movies removed: %s" % titles)

            self.sync.UpdateProgress(fromPercent,
                                     line2=kodiUtilities.getString(32076) %
                                     len(traktMoviesToRemove))

            moviesToRemove = {'movies': traktMoviesToRemove}
            try:
                self.sync.traktapi.removeFromCollection(moviesToRemove)
            except Exception as ex:
                message = utilities.createError(ex)
                logging.fatal(message)

            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32092) %
                                     len(traktMoviesToRemove))
Example #27
0
    def __addEpisodesToTraktCollection(self, kodiShows, traktShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('add_episodes_to_trakt') and not self.sync.IsCanceled():
            addTraktShows = copy.deepcopy(traktShows)
            addKodiShows = copy.deepcopy(kodiShows)

            tmpTraktShowsAdd = self.__compareEpisodes(addKodiShows, addTraktShows)
            traktShowsAdd = copy.deepcopy(tmpTraktShowsAdd)
            utilities.sanitizeShows(traktShowsAdd)
            # logger.debug("traktShowsAdd %s" % traktShowsAdd)

            if len(traktShowsAdd['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString(32068), line2=kodiUtilities.getString(32104))
                logger.debug("[Episodes Sync] Trakt.tv episode collection is up to date.")
                return
            logger.debug("[Episodes Sync] %i show(s) have episodes (%d) to be added to your Trakt.tv collection." % (len(traktShowsAdd['shows']), self.__countEpisodes(traktShowsAdd)))
            for show in traktShowsAdd['shows']:
                logger.debug("[Episodes Sync] Episodes added: %s" % self.__getShowAsString(show, short=True))

            self.sync.UpdateProgress(fromPercent, line1=kodiUtilities.getString(32068), line2=kodiUtilities.getString(32067) % (len(traktShowsAdd['shows'])))

            # split episode list into chunks of 50
            chunksize = 1
            chunked_episodes = utilities.chunks(traktShowsAdd['shows'], chunksize)
            errorcount = 0
            i = 0
            x = float(len(traktShowsAdd['shows']))
            for chunk in chunked_episodes:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32069) % ((i) * chunksize if (i) * chunksize < x else x, x))

                request = {'shows': chunk}
                logger.debug("[traktAddEpisodes] Shows to add %s" % request)
                try:
                    self.sync.traktapi.addToCollection(request)
                except Exception as ex:
                    message = utilities.createError(ex)
                    logging.fatal(message)
                    errorcount += 1

            logger.debug("[traktAddEpisodes] Finished with %d error(s)" % errorcount)
            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32105) % self.__countEpisodes(traktShowsAdd))
Example #28
0
    def __addMoviesToTraktWatched(self, kodiMovies, traktMovies, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_movie_playcount') and not self.sync.IsCanceled():
            updateTraktTraktMovies = copy.deepcopy(traktMovies)
            updateTraktKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToUpdate = utilities.compareMovies(updateTraktKodiMovies, updateTraktTraktMovies, watched=True)
            utilities.sanitizeMovies(traktMoviesToUpdate)

            if len(traktMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32086))
                logger.debug("[Movies Sync] Trakt.tv movie playcount is up to date")
                return

            titles = ", ".join(["%s" % (m['title']) for m in traktMoviesToUpdate])
            logger.debug("[Movies Sync] %i movie(s) playcount will be updated on Trakt.tv" % len(traktMoviesToUpdate))
            logger.debug("[Movies Sync] Movies updated: %s" % titles)

            self.sync.UpdateProgress(fromPercent, line2=kodiUtilities.getString(32064) % len(traktMoviesToUpdate))
            # Send request to update playcounts on Trakt.tv
            chunksize = 200
            chunked_movies = utilities.chunks([movie for movie in traktMoviesToUpdate], chunksize)
            errorcount = 0
            i = 0
            x = float(len(traktMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32093) % ((i) * chunksize if (i) * chunksize < x else x, x))

                params = {'movies': chunk}
                # logger.debug("moviechunk: %s" % params)
                try:
                    self.sync.traktapi.addToHistory(params)
                except Exception as ex:
                    message = utilities.createError(ex)
                    logging.fatal(message)
                    errorcount += 1

            logger.debug("[Movies Sync] Movies updated: %d error(s)" % errorcount)
            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32087) % len(traktMoviesToUpdate))
Example #29
0
    def __addEpisodesToTraktWatched(self, kodiShows, traktShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_episode_playcount') and not self.sync.IsCanceled():
            updateTraktTraktShows = copy.deepcopy(traktShows)
            updateTraktKodiShows = copy.deepcopy(kodiShows)

            traktShowsUpdate = self.__compareEpisodes(updateTraktKodiShows, updateTraktTraktShows, watched=True)
            utilities.sanitizeShows(traktShowsUpdate)
            # logger.debug("traktShowsUpdate %s" % traktShowsUpdate)

            if len(traktShowsUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString(32071), line2=kodiUtilities.getString(32106))
                logger.debug("[Episodes Sync] Trakt.tv episode playcounts are up to date.")
                return

            logger.debug("[Episodes Sync] %i show(s) are missing playcounts on Trakt.tv" % len(traktShowsUpdate['shows']))
            for show in traktShowsUpdate['shows']:
                logger.debug("[Episodes Sync] Episodes updated: %s" % self.__getShowAsString(show, short=True))

            self.sync.UpdateProgress(fromPercent, line1=kodiUtilities.getString(32071), line2=kodiUtilities.getString(32070) % (len(traktShowsUpdate['shows'])))
            errorcount = 0
            i = 0
            x = float(len(traktShowsUpdate['shows']))
            for show in traktShowsUpdate['shows']:
                if self.sync.IsCanceled():
                    return
                epCount = self.__countEpisodes([show])
                title = show['title'].encode('utf-8', 'ignore')
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=title, line3=kodiUtilities.getString(32073) % epCount)

                s = {'shows': [show]}
                logger.debug("[traktUpdateEpisodes] Shows to update %s" % s)
                try:
                    self.sync.traktapi.addToHistory(s)
                except Exception as ex:
                    message = utilities.createError(ex)
                    logging.fatal(message)
                    errorcount += 1

            logger.debug("[traktUpdateEpisodes] Finished with %d error(s)" % errorcount)
            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32072) % (len(traktShowsUpdate['shows'])), line3=" ")
Example #30
0
    def __addMoviesToTraktCollection(self, kodiMovies, traktMovies,
                                     fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool(
                'add_movies_to_trakt') and not self.sync.IsCanceled():
            addTraktMovies = copy.deepcopy(traktMovies)
            addKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToAdd = utilities.compareMovies(addKodiMovies,
                                                       addTraktMovies)
            utilities.sanitizeMovies(traktMoviesToAdd)
            logger.debug("[Movies Sync] Compared movies, found %s to add." %
                         len(traktMoviesToAdd))

            if len(traktMoviesToAdd) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line2=kodiUtilities.getString(32084))
                logger.debug(
                    "[Movies Sync] Trakt.tv movie collection is up to date.")
                return

            titles = ", ".join(["%s" % (m['title']) for m in traktMoviesToAdd])
            logger.debug(
                "[Movies Sync] %i movie(s) will be added to Trakt.tv collection."
                % len(traktMoviesToAdd))
            logger.debug("[Movies Sync] Movies to add : %s" % titles)

            self.sync.UpdateProgress(fromPercent,
                                     line2=kodiUtilities.getString(32063) %
                                     len(traktMoviesToAdd))

            moviesToAdd = {'movies': traktMoviesToAdd}
            # logger.debug("Movies to add: %s" % moviesToAdd)
            try:
                self.sync.traktapi.addToCollection(moviesToAdd)
            except Exception as ex:
                message = utilities.createError(ex)
                logging.fatal(message)

            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32085) %
                                     len(traktMoviesToAdd))
Example #31
0
    def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('kodi_episode_playcount') and not self.sync.IsCanceled():
            updateKodiTraktShows = copy.deepcopy(traktShows)
            updateKodiKodiShows = copy.deepcopy(kodiShows)

            kodiShowsUpdate = self.__compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, watched=True, restrict=True, collected=kodiShowsCollected)

            if len(kodiShowsUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString(32074), line2=kodiUtilities.getString(32107))
                logger.debug("[Episodes Sync] Kodi episode playcounts are up to date.")
                return

            logger.debug("[Episodes Sync] %i show(s) shows are missing playcounts on Kodi" % len(kodiShowsUpdate['shows']))
            for s in ["%s" % self.__getShowAsString(s, short=True) for s in kodiShowsUpdate['shows']]:
                logger.debug("[Episodes Sync] Episodes updated: %s" % s)

            # logger.debug("kodiShowsUpdate: %s" % kodiShowsUpdate)
            episodes = []
            for show in kodiShowsUpdate['shows']:
                for season in show['seasons']:
                    for episode in season['episodes']:
                        episodes.append({'episodeid': episode['ids']['episodeid'], 'playcount': episode['plays'], "lastplayed": utilities.convertUtcToDateTime(episode['last_watched_at'])})

            # split episode list into chunks of 50
            chunksize = 50
            chunked_episodes = utilities.chunks([{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": episodes[i], "id": i} for i in range(len(episodes))], chunksize)
            i = 0
            x = float(len(episodes))
            for chunk in chunked_episodes:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32108) % ((i) * chunksize if (i) * chunksize < x else x, x))

                logger.debug("[Episodes Sync] chunk %s" % str(chunk))
                result = kodiUtilities.kodiJsonRequest(chunk)
                logger.debug("[Episodes Sync] result %s" % str(result))

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32109) % len(episodes))
Example #32
0
    def __addEpisodeProgressToKodi(self, traktShows, kodiShows, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool('trakt_episode_playback') and traktShows and not self.sync.IsCanceled():
            updateKodiTraktShows = copy.deepcopy(traktShows)
            updateKodiKodiShows = copy.deepcopy(kodiShows)
            kodiShowsUpdate = self.__compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, restrict=True, playback=True)

            if len(kodiShowsUpdate['shows']) == 0:
                self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString(1441), line2=kodiUtilities.getString(32129))
                logger.debug("[Episodes Sync] Kodi episode playbacks are up to date.")
                return

            logger.debug("[Episodes Sync] %i show(s) shows are missing playbacks on Kodi" % len(kodiShowsUpdate['shows']))
            for s in ["%s" % self.__getShowAsString(s, short=True) for s in kodiShowsUpdate['shows']]:
                logger.debug("[Episodes Sync] Episodes updated: %s" % s)

            episodes = []
            for show in kodiShowsUpdate['shows']:
                for season in show['seasons']:
                    for episode in season['episodes']:
                        episodes.append({'episodeid': episode['ids']['episodeid'], 'progress': episode['progress'], 'runtime': episode['runtime']})

            # need to calculate the progress in int from progress in percent from Trakt
            # split episode list into chunks of 50
            chunksize = 50
            chunked_episodes = utilities.chunks([{"jsonrpc": "2.0", "id": i, "method": "VideoLibrary.SetEpisodeDetails", "params": {"episodeid":episodes[i]['episodeid'], "resume": {"position": episodes[i]['runtime'] / 100.0 * episodes[i]['progress'], "total": episodes[i]['runtime']}}} for i in range(len(episodes))], chunksize)
            i = 0
            x = float(len(episodes))
            for chunk in chunked_episodes:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent-fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y), line2=kodiUtilities.getString(32130) % ((i) * chunksize if (i) * chunksize < x else x, x))

                kodiUtilities.kodiJsonRequest(chunk)

            self.sync.UpdateProgress(toPercent, line2=kodiUtilities.getString(32131) % len(episodes))
Example #33
0
    def __traktLoadMoviesPlaybackProgress(self, fromPercent, toPercent):
        if kodiUtilities.getSettingAsBool(
                'trakt_movie_playback') and not self.sync.IsCanceled():
            self.sync.UpdateProgress(fromPercent,
                                     line2=kodiUtilities.getString(32122))

            logger.debug(
                '[Movies Sync] Getting playback progress from Trakt.tv')
            try:
                traktProgressMovies = self.sync.traktapi.getMoviePlaybackProgress(
                )
            except Exception:
                logger.debug(
                    "[Movies Sync] Invalid Trakt.tv playback progress list, possible error getting data from Trakt, aborting Trakt.tv playback update."
                )
                return False

            i = 0
            x = float(len(traktProgressMovies))
            moviesProgress = {'movies': []}
            for movie in traktProgressMovies:
                i += 1
                y = ((i / x) * (toPercent - fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y),
                                         line2=kodiUtilities.getString(32123) %
                                         (i, x))

                # will keep the data in python structures - just like the KODI response
                movie = movie.to_dict()

                moviesProgress['movies'].append(movie)

            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32124))

            return moviesProgress
Example #34
0
    def playbackStarted(self, data):
        logger.debug("playbackStarted(data: %s)" % data)
        if not data:
            return
        self.curVideo = data
        self.curVideoInfo = None
        self.videosToRate = []

        if not kodiUtilities.getSettingAsBool('scrobble_fallback') and 'id' not in self.curVideo and 'video_ids' not in self.curVideo:
            logger.debug('Aborting scrobble to avoid fallback: %s' % (self.curVideo))
            return
             
        if 'type' in self.curVideo:
            logger.debug("Watching: %s" % self.curVideo['type'])
            if not xbmc.Player().isPlayingVideo():
                logger.debug("Suddenly stopped watching item")
                return
            xbmc.sleep(1000)  # Wait for possible silent seek (caused by resuming)
            try:
                self.watchedTime = xbmc.Player().getTime()
                self.videoDuration = xbmc.Player().getTotalTime()
            except Exception as e:
                logger.debug("Suddenly stopped watching item: %s" % e.message)
                self.curVideo = None
                return

            if self.videoDuration == 0:
                if utilities.isMovie(self.curVideo['type']):
                    self.videoDuration = 90
                elif utilities.isEpisode(self.curVideo['type']):
                    self.videoDuration = 30
                else:
                    self.videoDuration = 1

            self.playlistLength = len(xbmc.PlayList(xbmc.PLAYLIST_VIDEO))
            self.playlistIndex = xbmc.PlayList(xbmc.PLAYLIST_VIDEO).getposition()
            if self.playlistLength == 0:
                logger.debug("Warning: Cant find playlist length, assuming that this item is by itself")
                self.playlistLength = 1

            self.isMultiPartEpisode = False
            if utilities.isMovie(self.curVideo['type']):
                if 'id' in self.curVideo:
                    self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject('movie', kodiUtilities.getMovieDetailsFromKodi(self.curVideo['id'], ['imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount']))
                elif 'video_ids' in self.curVideo:
                    self.curVideoInfo = {'ids': self.curVideo['video_ids']}
                elif 'title' in self.curVideo and 'year' in self.curVideo:
                    self.curVideoInfo = {'title': self.curVideo['title'], 'year': self.curVideo['year']}

            elif utilities.isEpisode(self.curVideo['type']):
                if 'id' in self.curVideo:
                    episodeDetailsKodi = kodiUtilities.getEpisodeDetailsFromKodi(self.curVideo['id'], ['showtitle', 'season', 'episode', 'tvshowid', 'uniqueid', 'file', 'playcount'])
                    tvdb = episodeDetailsKodi['imdbnumber']
                    title, year = utilities.regex_year(episodeDetailsKodi['showtitle'])
                    if not year:
                        self.traktShowSummary = {'title': episodeDetailsKodi['showtitle'], 'year': episodeDetailsKodi['year']}
                    else:
                        self.traktShowSummary = {'title': title, 'year': year}
                    if tvdb:
                        self.traktShowSummary['ids'] = {'tvdb': tvdb}
                    self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject('episode', episodeDetailsKodi)
                    if not self.curVideoInfo:  # getEpisodeDetailsFromKodi was empty
                        logger.debug("Episode details from Kodi was empty, ID (%d) seems invalid, aborting further scrobbling of this episode." % self.curVideo['id'])
                        self.curVideo = None
                        self.isPlaying = False
                        self.watchedTime = 0
                        return
                elif 'video_ids' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo:
                    self.curVideoInfo = {'season': self.curVideo['season'], 'number': self.curVideo['episode']}
                    self.traktShowSummary = {'ids': self.curVideo['video_ids']}
                elif 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo:
                    self.curVideoInfo = {'title': self.curVideo['title'], 'season': self.curVideo['season'],
                                         'number': self.curVideo['episode']}

                    title, year = utilities.regex_year(self.curVideo['showtitle'])
                    if not year:
                        self.traktShowSummary = {'title': self.curVideo['showtitle']}
                    else:
                        self.traktShowSummary = {'title': title, 'year': year}

                    if 'year' in self.curVideo:
                        self.traktShowSummary['year'] = self.curVideo['year']

                if 'multi_episode_count' in self.curVideo and self.curVideo['multi_episode_count'] > 1:
                    self.isMultiPartEpisode = True

            self.isPlaying = True
            self.isPaused = False

            result = {}
            if kodiUtilities.getSettingAsBool('scrobble_movie') or kodiUtilities.getSettingAsBool('scrobble_episode'):
                result = self.__scrobble('start')
            elif kodiUtilities.getSettingAsBool('rate_movie') and utilities.isMovie(self.curVideo['type']) and 'ids' in self.curVideoInfo:
                best_id = utilities.best_id(self.curVideoInfo['ids'])
                result = {'movie': self.traktapi.getMovieSummary(best_id).to_dict()}
            elif kodiUtilities.getSettingAsBool('rate_episode') and utilities.isEpisode(self.curVideo['type']) and 'ids' in self.traktShowSummary:
                best_id = utilities.best_id(self.traktShowSummary['ids'])
                result = {'show': self.traktapi.getShowSummary(best_id).to_dict(),
                          'episode': self.traktapi.getEpisodeSummary(best_id, self.curVideoInfo['season'],
                                                                     self.curVideoInfo['number']).to_dict()}
                result['episode']['season'] = self.curVideoInfo['season']

            if 'id' in self.curVideo:
                if utilities.isMovie(self.curVideo['type']):
                    result['movie']['movieid'] = self.curVideo['id']
                elif utilities.isEpisode(self.curVideo['type']):
                    result['episode']['episodeid'] = self.curVideo['id']
                
            self.__preFetchUserRatings(result)
Example #35
0
 def __syncPlaybackCheck(self, media_type):
     if media_type == 'movies':
         return getSettingAsBool('trakt_movie_playback')
     else:
         return getSettingAsBool('trakt_episode_playback')
Example #36
0
 def __syncCollectionCheck(self, media_type):
     if media_type == 'movies':
         return getSettingAsBool('add_movies_to_trakt') or getSettingAsBool('clean_trakt_movies')
     else:
         return getSettingAsBool('add_episodes_to_trakt') or getSettingAsBool('clean_trakt_episodes')
Example #37
0
 def __syncRatingsCheck(self):
     return getSettingAsBool('trakt_sync_ratings')
Example #38
0
    def playbackStarted(self, data):
        logger.debug("playbackStarted(data: %s)" % data)
        if not data:
            return
        self.curVideo = data
        self.curVideoInfo = None
        self.videosToRate = []

        if not kodiUtilities.getSettingAsBool(
                'scrobble_fallback'
        ) and 'id' not in self.curVideo and 'video_ids' not in self.curVideo:
            logger.debug('Aborting scrobble to avoid fallback: %s' %
                         (self.curVideo))
            return

        if 'type' in self.curVideo:
            logger.debug("Watching: %s" % self.curVideo['type'])
            if not xbmc.Player().isPlayingVideo():
                logger.debug("Suddenly stopped watching item")
                return
            xbmc.sleep(
                1000)  # Wait for possible silent seek (caused by resuming)
            try:
                self.watchedTime = xbmc.Player().getTime()
                self.videoDuration = xbmc.Player().getTotalTime()
            except Exception as e:
                logger.debug("Suddenly stopped watching item: %s" % e.message)
                self.curVideo = None
                return

            if self.videoDuration == 0:
                if utilities.isMovie(self.curVideo['type']):
                    self.videoDuration = 90
                elif utilities.isEpisode(self.curVideo['type']):
                    self.videoDuration = 30
                else:
                    self.videoDuration = 1

            self.playlistLength = len(xbmc.PlayList(xbmc.PLAYLIST_VIDEO))
            self.playlistIndex = xbmc.PlayList(
                xbmc.PLAYLIST_VIDEO).getposition()
            if self.playlistLength == 0:
                logger.debug(
                    "Warning: Cant find playlist length, assuming that this item is by itself"
                )
                self.playlistLength = 1

            self.isMultiPartEpisode = False
            if utilities.isMovie(self.curVideo['type']):
                if 'id' in self.curVideo:
                    self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject(
                        'movie',
                        kodiUtilities.getMovieDetailsFromKodi(
                            self.curVideo['id'], [
                                'imdbnumber', 'title', 'year', 'file',
                                'lastplayed', 'playcount'
                            ]))
                elif 'video_ids' in self.curVideo:
                    self.curVideoInfo = {'ids': self.curVideo['video_ids']}
                elif 'title' in self.curVideo and 'year' in self.curVideo:
                    self.curVideoInfo = {
                        'title': self.curVideo['title'],
                        'year': self.curVideo['year']
                    }
                else:
                    logger.debug("Couldn't set curVideoInfo for movie type")
                logger.debug("Movie type, curVideoInfo: %s" %
                             self.curVideoInfo)

            elif utilities.isEpisode(self.curVideo['type']):
                if 'id' in self.curVideo:
                    episodeDetailsKodi = kodiUtilities.getEpisodeDetailsFromKodi(
                        self.curVideo['id'], [
                            'showtitle', 'season', 'episode', 'tvshowid',
                            'uniqueid', 'file', 'playcount'
                        ])
                    tvdb = episodeDetailsKodi['imdbnumber']
                    title, year = utilities.regex_year(
                        episodeDetailsKodi['showtitle'])
                    if not year:
                        self.traktShowSummary = {
                            'title': episodeDetailsKodi['showtitle'],
                            'year': episodeDetailsKodi['year']
                        }
                    else:
                        self.traktShowSummary = {'title': title, 'year': year}
                    if tvdb:
                        self.traktShowSummary['ids'] = {'tvdb': tvdb}
                    self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject(
                        'episode', episodeDetailsKodi)
                    if not self.curVideoInfo:  # getEpisodeDetailsFromKodi was empty
                        logger.debug(
                            "Episode details from Kodi was empty, ID (%d) seems invalid, aborting further scrobbling of this episode."
                            % self.curVideo['id'])
                        self.curVideo = None
                        self.isPlaying = False
                        self.watchedTime = 0
                        return
                elif 'video_ids' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo:
                    self.curVideoInfo = {
                        'season': self.curVideo['season'],
                        'number': self.curVideo['episode']
                    }
                    self.traktShowSummary = {'ids': self.curVideo['video_ids']}
                elif 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo:
                    self.curVideoInfo = {
                        'title': self.curVideo['title'],
                        'season': self.curVideo['season'],
                        'number': self.curVideo['episode']
                    }

                    title, year = utilities.regex_year(
                        self.curVideo['showtitle'])
                    if not year:
                        self.traktShowSummary = {
                            'title': self.curVideo['showtitle']
                        }
                    else:
                        self.traktShowSummary = {'title': title, 'year': year}

                    if 'year' in self.curVideo:
                        self.traktShowSummary['year'] = self.curVideo['year']
                else:
                    logger.debug(
                        "Couldn't set curVideoInfo/traktShowSummary for episode type"
                    )

                if 'multi_episode_count' in self.curVideo and self.curVideo[
                        'multi_episode_count'] > 1:
                    self.isMultiPartEpisode = True

                logger.debug("Episode type, curVideoInfo: %s" %
                             self.curVideoInfo)
                logger.debug("Episode type, traktShowSummary: %s" %
                             self.traktShowSummary)

            self.isPlaying = True
            self.isPaused = False

            result = {}
            if kodiUtilities.getSettingAsBool(
                    'scrobble_movie') or kodiUtilities.getSettingAsBool(
                        'scrobble_episode'):
                result = self.__scrobble('start')
            elif kodiUtilities.getSettingAsBool(
                    'rate_movie') and utilities.isMovie(
                        self.curVideo['type']) and 'ids' in self.curVideoInfo:
                best_id = utilities.best_id(self.curVideoInfo['ids'])
                result = {
                    'movie': self.traktapi.getMovieSummary(best_id).to_dict()
                }
            elif kodiUtilities.getSettingAsBool(
                    'rate_episode') and utilities.isEpisode(
                        self.curVideo['type']
                    ) and 'ids' in self.traktShowSummary:
                best_id = utilities.best_id(self.traktShowSummary['ids'])
                result = {
                    'show':
                    self.traktapi.getShowSummary(best_id).to_dict(),
                    'episode':
                    self.traktapi.getEpisodeSummary(
                        best_id, self.curVideoInfo['season'],
                        self.curVideoInfo['number']).to_dict()
                }
                result['episode']['season'] = self.curVideoInfo['season']

            if 'id' in self.curVideo:
                if utilities.isMovie(self.curVideo['type']):
                    result['movie']['movieid'] = self.curVideo['id']
                elif utilities.isEpisode(self.curVideo['type']):
                    result['episode']['episodeid'] = self.curVideo['id']

            self.__preFetchUserRatings(result)
Example #39
0
def rateMedia(media_type, itemsToRate, unrate=False, rating=None):
    """Launches the rating dialog"""
    for summary_info in itemsToRate:
        if not utilities.isValidMediaType(media_type):
            logger.debug("Not a valid media type")
            return
        elif 'user' not in summary_info:
            logger.debug("No user data")
            return

        s = utilities.getFormattedItemName(media_type, summary_info)

        logger.debug("Summary Info %s" % summary_info)

        if unrate:
            rating = None

            if summary_info['user']['ratings']['rating'] > 0:
                rating = 0

            if not rating is None:
                logger.debug("'%s' is being unrated." % s)
                __rateOnTrakt(rating, media_type, summary_info, unrate=True)
            else:
                logger.debug("'%s' has not been rated, so not unrating." % s)

            return

        rerate = kodiUtilities.getSettingAsBool('rate_rerate')
        if rating is not None:
            if summary_info['user']['ratings']['rating'] == 0:
                logger.debug("Rating for '%s' is being set to '%d' manually." %
                             (s, rating))
                __rateOnTrakt(rating, media_type, summary_info)
            else:
                if rerate:
                    if not summary_info['user']['ratings']['rating'] == rating:
                        logger.debug(
                            "Rating for '%s' is being set to '%d' manually." %
                            (s, rating))
                        __rateOnTrakt(rating, media_type, summary_info)
                    else:
                        kodiUtilities.notification(
                            kodiUtilities.getString(32043), s)
                        logger.debug("'%s' already has a rating of '%d'." %
                                     (s, rating))
                else:
                    kodiUtilities.notification(kodiUtilities.getString(32041),
                                               s)
                    logger.debug("'%s' is already rated." % s)
            return

        if summary_info['user']['ratings'] and summary_info['user']['ratings'][
                'rating']:
            if not rerate:
                logger.debug("'%s' has already been rated." % s)
                kodiUtilities.notification(kodiUtilities.getString(32041), s)
                return
            else:
                logger.debug("'%s' is being re-rated." % s)

        xbmc.executebuiltin('Dialog.Close(all, true)')

        gui = RatingDialog("script-trakt-RatingDialog.xml",
                           __addon__.getAddonInfo('path'),
                           media_type=media_type,
                           media=summary_info,
                           rerate=rerate)

        gui.doModal()
        if gui.rating:
            rating = gui.rating
            if rerate:
                rating = gui.rating

                if summary_info['user']['ratings'] and summary_info['user'][
                        'ratings']['rating'] > 0 and rating == summary_info[
                            'user']['ratings']['rating']:
                    rating = 0

            if rating == 0 or rating == "unrate":
                __rateOnTrakt(rating, gui.media_type, gui.media, unrate=True)
            else:
                __rateOnTrakt(rating, gui.media_type, gui.media)
        else:
            logger.debug("Rating dialog was closed with no rating.")

        del gui
        #Reset rating and unrate for multi part episodes
        unrate = False
        rating = None
Example #40
0
    def __syncMovieRatings(self, traktMovies, kodiMovies, fromPercent,
                           toPercent):

        if kodiUtilities.getSettingAsBool(
                'trakt_sync_ratings'
        ) and traktMovies and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            traktMoviesToUpdate = utilities.compareMovies(
                updateKodiKodiMovies, updateKodiTraktMovies, rating=True)
            if len(traktMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line1='',
                                         line2=kodiUtilities.getString(32179))
                logger.debug(
                    "[Movies Sync] Trakt movie ratings are up to date.")
            else:
                logger.debug(
                    "[Movies Sync] %i movie(s) ratings will be updated on Trakt"
                    % len(traktMoviesToUpdate))

                self.sync.UpdateProgress(fromPercent,
                                         line1='',
                                         line2=kodiUtilities.getString(32180) %
                                         len(traktMoviesToUpdate))

                moviesRatings = {'movies': traktMoviesToUpdate}

                self.sync.traktapi.addRating(moviesRatings)

            kodiMoviesToUpdate = utilities.compareMovies(updateKodiTraktMovies,
                                                         updateKodiKodiMovies,
                                                         restrict=True,
                                                         rating=True)
            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line1='',
                                         line2=kodiUtilities.getString(32169))
                logger.debug(
                    "[Movies Sync] Kodi movie ratings are up to date.")
            else:
                logger.debug(
                    "[Movies Sync] %i movie(s) ratings will be updated in Kodi"
                    % len(kodiMoviesToUpdate))

                self.sync.UpdateProgress(fromPercent,
                                         line1='',
                                         line2=kodiUtilities.getString(32170) %
                                         len(kodiMoviesToUpdate))
                # split movie list into chunks of 50
                chunksize = 50
                chunked_movies = utilities.chunks([{
                    "jsonrpc": "2.0",
                    "id": i,
                    "method": "VideoLibrary.SetMovieDetails",
                    "params": {
                        "movieid": kodiMoviesToUpdate[i]['movieid'],
                        "userrating": kodiMoviesToUpdate[i]['rating']
                    }
                } for i in range(len(kodiMoviesToUpdate))], chunksize)
                i = 0
                x = float(len(kodiMoviesToUpdate))
                for chunk in chunked_movies:
                    if self.sync.IsCanceled():
                        return
                    i += 1
                    y = ((i / x) * (toPercent - fromPercent)) + fromPercent
                    self.sync.UpdateProgress(
                        int(y),
                        line2=kodiUtilities.getString(32171) %
                        ((i) * chunksize if (i) * chunksize < x else x, x))
                    kodiUtilities.kodiJsonRequest(chunk)

                self.sync.UpdateProgress(toPercent,
                                         line2=kodiUtilities.getString(32172) %
                                         len(kodiMoviesToUpdate))
Example #41
0
    def __addMovieProgressToKodi(self, traktMovies, kodiMovies, fromPercent,
                                 toPercent):

        if kodiUtilities.getSettingAsBool(
                'trakt_movie_playback'
        ) and traktMovies and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            kodiMoviesToUpdate = utilities.compareMovies(
                updateKodiTraktMovies['movies'],
                updateKodiKodiMovies,
                restrict=True,
                playback=True)
            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line1='',
                                         line2=kodiUtilities.getString(32125))
                logger.debug(
                    "[Movies Sync] Kodi movie playbacks are up to date.")
                return

            logger.debug(
                "[Movies Sync] %i movie(s) playbacks will be updated in Kodi" %
                len(kodiMoviesToUpdate))

            self.sync.UpdateProgress(fromPercent,
                                     line1='',
                                     line2=kodiUtilities.getString(32126) %
                                     len(kodiMoviesToUpdate))
            # need to calculate the progress in int from progress in percent from Trakt
            # split movie list into chunks of 50
            chunksize = 50
            chunked_movies = utilities.chunks([{
                "jsonrpc": "2.0",
                "id": i,
                "method": "VideoLibrary.SetMovieDetails",
                "params": {
                    "movieid": kodiMoviesToUpdate[i]['movieid'],
                    "resume": {
                        "position":
                        kodiMoviesToUpdate[i]['runtime'] / 100.0 *
                        kodiMoviesToUpdate[i]['progress'],
                        "total":
                        kodiMoviesToUpdate[i]['runtime']
                    }
                }
            } for i in range(len(kodiMoviesToUpdate))], chunksize)
            i = 0
            x = float(len(kodiMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent - fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y),
                                         line2=kodiUtilities.getString(32127) %
                                         ((i) * chunksize if
                                          (i) * chunksize < x else x, x))
                kodiUtilities.kodiJsonRequest(chunk)

            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32128) %
                                     len(kodiMoviesToUpdate))
Example #42
0
    def __addMoviesToKodiWatched(self, traktMovies, kodiMovies, fromPercent,
                                 toPercent):

        if kodiUtilities.getSettingAsBool(
                'kodi_movie_playcount') and not self.sync.IsCanceled():
            updateKodiTraktMovies = copy.deepcopy(traktMovies)
            updateKodiKodiMovies = copy.deepcopy(kodiMovies)

            kodiMoviesToUpdate = utilities.compareMovies(updateKodiTraktMovies,
                                                         updateKodiKodiMovies,
                                                         watched=True,
                                                         restrict=True)

            if len(kodiMoviesToUpdate) == 0:
                self.sync.UpdateProgress(toPercent,
                                         line2=kodiUtilities.getString(32088))
                logger.debug(
                    "[Movies Sync] Kodi movie playcount is up to date.")
                return

            titles = ", ".join(
                ["%s" % (m['title']) for m in kodiMoviesToUpdate])
            logger.debug(
                "[Movies Sync] %i movie(s) playcount will be updated in Kodi" %
                len(kodiMoviesToUpdate))
            logger.debug("[Movies Sync] Movies to add: %s" % titles)

            self.sync.UpdateProgress(fromPercent,
                                     line2=kodiUtilities.getString(32065) %
                                     len(kodiMoviesToUpdate))

            # split movie list into chunks of 50
            chunksize = 50
            chunked_movies = utilities.chunks([{
                "jsonrpc": "2.0",
                "method": "VideoLibrary.SetMovieDetails",
                "params": {
                    "movieid":
                    kodiMoviesToUpdate[i]['movieid'],
                    "playcount":
                    kodiMoviesToUpdate[i]['plays'],
                    "lastplayed":
                    utilities.convertUtcToDateTime(
                        kodiMoviesToUpdate[i]['last_watched_at'])
                },
                "id": i
            } for i in range(len(kodiMoviesToUpdate))], chunksize)
            i = 0
            x = float(len(kodiMoviesToUpdate))
            for chunk in chunked_movies:
                if self.sync.IsCanceled():
                    return
                i += 1
                y = ((i / x) * (toPercent - fromPercent)) + fromPercent
                self.sync.UpdateProgress(int(y),
                                         line2=kodiUtilities.getString(32089) %
                                         ((i) * chunksize if
                                          (i) * chunksize < x else x, x))

                kodiUtilities.kodiJsonRequest(chunk)

            self.sync.UpdateProgress(toPercent,
                                     line2=kodiUtilities.getString(32090) %
                                     len(kodiMoviesToUpdate))
Example #43
0
 def __syncWatchedCheck(self, media_type):
     if media_type == 'movies':
         return getSettingAsBool('trakt_movie_playcount') or getSettingAsBool('kodi_movie_playcount')
     else:
         return getSettingAsBool('trakt_episode_playcount') or getSettingAsBool('kodi_episode_playcount')
Example #44
0
    def __scrobble(self, status):
        if not self.curVideoInfo:
            return

        logger.debug("scrobble()")
        scrobbleMovieOption = kodiUtilities.getSettingAsBool('scrobble_movie')
        scrobbleEpisodeOption = kodiUtilities.getSettingAsBool(
            'scrobble_episode')

        watchedPercent = self.__calculateWatchedPercent()

        if utilities.isMovie(self.curVideo['type']) and scrobbleMovieOption:
            response = self.traktapi.scrobbleMovie(self.curVideoInfo,
                                                   watchedPercent, status)
            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble movie: %s | %s | %s" %
                             (self.curVideoInfo, watchedPercent, status))

        elif utilities.isEpisode(
                self.curVideo['type']) and scrobbleEpisodeOption:
            if self.isMultiPartEpisode:
                logger.debug("Multi-part episode, scrobbling part %d of %d." %
                             (self.curMPEpisode + 1,
                              self.curVideo['multi_episode_count']))
                adjustedDuration = int(self.videoDuration /
                                       self.curVideo['multi_episode_count'])
                watchedPercent = ((self.watchedTime -
                                   (adjustedDuration * self.curMPEpisode)) /
                                  adjustedDuration) * 100

            logger.debug("scrobble sending show object: %s" %
                         str(self.traktShowSummary))
            logger.debug("scrobble sending episode object: %s" %
                         str(self.curVideoInfo))
            response = self.traktapi.scrobbleEpisode(self.traktShowSummary,
                                                     self.curVideoInfo,
                                                     watchedPercent, status)

            if (kodiUtilities.getSettingAsBool('scrobble_secondary_title')):
                logger.debug(
                    '[traktPlayer] Setting is enabled to try secondary show title, if necessary.'
                )
                # If there is an empty response, the reason might be that the title we have isn't the actual show title,
                # but rather an alternative title. To handle this case, call the Trakt search function.
                if response is None:
                    logger.debug("Searching for show title: %s" %
                                 self.traktShowSummary['title'])
                    # This text query API is basically the same as searching on the website. Works with alternative
                    # titles, unlike the scrobble function.
                    newResp = self.traktapi.getTextQuery(
                        self.traktShowSummary['title'], "show", None)
                    if not newResp:
                        logger.debug(
                            "Empty Response from getTextQuery, giving up")
                    else:
                        logger.debug("Got Response from getTextQuery: %s" %
                                     str(newResp))
                        # We got something back. Have to assume the first show found is the right one; if there's more than
                        # one, there's no way to know which to use. Pull the primary title from the response (and the year,
                        # just because it's there).
                        showObj = {
                            'title': newResp[0].title,
                            'year': newResp[0].year
                        }
                        logger.debug(
                            "scrobble sending getTextQuery first show object: %s"
                            % str(showObj))
                        # Now we can attempt the scrobble again, using the primary title this time.
                        response = self.traktapi.scrobbleEpisode(
                            showObj, self.curVideoInfo, watchedPercent, status)

            if response is not None:
                self.__scrobbleNotification(response)
                logger.debug("Scrobble response: %s" % str(response))
                return response
            else:
                logger.debug("Failed to scrobble episode: %s | %s | %s | %s" %
                             (self.traktShowSummary, self.curVideoInfo,
                              watchedPercent, status))
Example #45
0
    def onPlayBackStarted(self):
        xbmc.sleep(1000)
        self.type = None
        self.id = None

        # take the user start scrobble offset into account
        scrobbleStartOffset = kodiUtilities.getSettingAsInt(
            'scrobble_start_offset') * 60
        if scrobbleStartOffset > 0:
            waitFor = 10
            waitedFor = 0
            # check each 10 seconds if we can abort or proceed
            while not xbmc.abortRequested and scrobbleStartOffset > waitedFor:
                waitedFor += waitFor
                time.sleep(waitFor)
                if not self.isPlayingVideo():
                    logger.debug(
                        '[traktPlayer] Playback stopped before reaching the scrobble offset'
                    )
                    return

        # only do anything if we're playing a video
        if self.isPlayingVideo():
            # get item data from json rpc
            logger.debug(
                "[traktPlayer] onPlayBackStarted() - Doing Player.GetItem kodiJsonRequest"
            )
            result = kodiUtilities.kodiJsonRequest({
                'jsonrpc': '2.0',
                'method': 'Player.GetItem',
                'params': {
                    'playerid': 1
                },
                'id': 1
            })
            if result:
                logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result)
                # check for exclusion
                _filename = None
                try:
                    _filename = self.getPlayingFile()
                except:
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped."
                    )
                    return

                if kodiUtilities.checkExclusion(_filename):
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring."
                        % _filename)
                    return

                self.type = result['item']['type']

                data = {'action': 'started'}

                if (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr')):
                    logger.debug(
                        '[traktPlayer] Setting is enabled to try scrobbling mythtv pvr recording, if necessary.'
                    )

                # check type of item
                if 'id' not in result['item']:
                    # do a deeper check to see if we have enough data to perform scrobbles
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data."
                    )

                    season = xbmc.getInfoLabel('VideoPlayer.Season')
                    episode = xbmc.getInfoLabel('VideoPlayer.Episode')
                    showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle')
                    year = xbmc.getInfoLabel('VideoPlayer.Year')
                    video_ids = xbmcgui.Window(10000).getProperty(
                        'script.trakt.ids')
                    if video_ids:
                        data['video_ids'] = json.loads(video_ids)

                    logger.debug(
                        "[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s"
                        % (video_ids, showtitle, year, season, episode))

                    if season and episode and (showtitle or video_ids):
                        # we have season, episode and either a show title or video_ids, can scrobble this as an episode
                        self.type = 'episode'
                        data['type'] = 'episode'
                        data['season'] = int(season)
                        data['episode'] = int(episode)
                        data['showtitle'] = showtitle
                        data['title'] = xbmc.getInfoLabel('VideoPlayer.Title')
                        if year.isdigit():
                            data['year'] = int(year)
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s."
                            % (data['showtitle'], data['season'],
                               data['episode'], data['title']))
                    elif (year or video_ids) and not season and not showtitle:
                        # we have a year or video_id and no season/showtitle info, enough for a movie
                        self.type = 'movie'
                        data['type'] = 'movie'
                        if year.isdigit():
                            data['year'] = int(year)
                        data['title'] = xbmc.getInfoLabel('VideoPlayer.Title')
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)."
                            % (data['title'], data.get('year', 'NaN')))
                    elif showtitle:
                        title, season, episode = utilities.regex_tvshow(
                            showtitle)
                        data['type'] = 'episode'
                        data['season'] = season
                        data['episode'] = episode
                        data['title'] = data['showtitle'] = title
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d"
                            % (title, showtitle, season, episode))
                    else:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping."
                        )
                        return

                elif self.type == 'episode' or self.type == 'movie':
                    # get library id
                    self.id = result['item']['id']
                    data['id'] = self.id
                    data['type'] = self.type

                    if self.type == 'episode':
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Doing multi-part episode check."
                        )
                        result = kodiUtilities.kodiJsonRequest({
                            'jsonrpc': '2.0',
                            'method': 'VideoLibrary.GetEpisodeDetails',
                            'params': {
                                'episodeid':
                                self.id,
                                'properties':
                                ['tvshowid', 'season', 'episode', 'file']
                            },
                            'id': 1
                        })
                        if result:
                            logger.debug(
                                "[traktPlayer] onPlayBackStarted() - %s" %
                                result)
                            tvshowid = int(
                                result['episodedetails']['tvshowid'])
                            season = int(result['episodedetails']['season'])
                            currentfile = result['episodedetails']['file']

                            result = kodiUtilities.kodiJsonRequest({
                                'jsonrpc': '2.0',
                                'method': 'VideoLibrary.GetEpisodes',
                                'params': {
                                    'tvshowid': tvshowid,
                                    'season': season,
                                    'properties': ['episode', 'file'],
                                    'sort': {
                                        'method': 'episode'
                                    }
                                },
                                'id': 1
                            })
                            if result:
                                logger.debug(
                                    "[traktPlayer] onPlayBackStarted() - %s" %
                                    result)
                                # make sure episodes array exists in results
                                if 'episodes' in result:
                                    multi = []
                                    for i in range(result['limits']['start'],
                                                   result['limits']['total']):
                                        if currentfile == result['episodes'][
                                                i]['file']:
                                            multi.append(result['episodes'][i]
                                                         ['episodeid'])
                                    if len(multi) > 1:
                                        data['multi_episode_data'] = multi
                                        data['multi_episode_count'] = len(
                                            multi)
                                        logger.debug(
                                            "[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode."
                                        )
                                    else:
                                        logger.debug(
                                            "[traktPlayer] onPlayBackStarted() - This is a single episode."
                                        )
                elif (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr')
                      and self.type == 'unknown' and result['item']['label']):
                    # If we have label/id but no show type, then this might be a PVR recording.

                    # DEBUG INFO: This code is useful when trying to figure out what info is available. Many of the fields
                    # that you'd expect (TVShowTitle, episode, season, etc) are always blank. In Kodi v15, we got the show
                    # and episode name in the VideoPlayer label. In v16, that's gone, but the Player.Filename infolabel
                    # is populated with several interesting things. If these things change in future versions, uncommenting
                    # this code will hopefully provide some useful info in the debug log.
                    #logger.debug("[traktPlayer] onPlayBackStarted() - TEMP Checking all videoplayer infolabels.")
                    #for il in ['VideoPlayer.Time','VideoPlayer.TimeRemaining','VideoPlayer.TimeSpeed','VideoPlayer.Duration','VideoPlayer.Title','VideoPlayer.TVShowTitle','VideoPlayer.Season','VideoPlayer.Episode','VideoPlayer.Genre','VideoPlayer.Director','VideoPlayer.Country','VideoPlayer.Year','VideoPlayer.Rating','VideoPlayer.UserRating','VideoPlayer.Votes','VideoPlayer.RatingAndVotes','VideoPlayer.mpaa','VideoPlayer.IMDBNumber','VideoPlayer.EpisodeName','VideoPlayer.PlaylistPosition','VideoPlayer.PlaylistLength','VideoPlayer.Cast','VideoPlayer.CastAndRole','VideoPlayer.Album','VideoPlayer.Artist','VideoPlayer.Studio','VideoPlayer.Writer','VideoPlayer.Tagline','VideoPlayer.PlotOutline','VideoPlayer.Plot','VideoPlayer.LastPlayed','VideoPlayer.PlayCount','VideoPlayer.VideoCodec','VideoPlayer.VideoResolution','VideoPlayer.VideoAspect','VideoPlayer.AudioCodec','VideoPlayer.AudioChannels','VideoPlayer.AudioLanguage','VideoPlayer.SubtitlesLanguage','VideoPlayer.StereoscopicMode','VideoPlayer.EndTime','VideoPlayer.NextTitle','VideoPlayer.NextGenre','VideoPlayer.NextPlot','VideoPlayer.NextPlotOutline','VideoPlayer.NextStartTime','VideoPlayer.NextEndTime','VideoPlayer.NextDuration','VideoPlayer.ChannelName','VideoPlayer.ChannelNumber','VideoPlayer.SubChannelNumber','VideoPlayer.ChannelNumberLabel','VideoPlayer.ChannelGroup','VideoPlayer.ParentalRating','Player.FinishTime','Player.FinishTime(format)','Player.Chapter','Player.ChapterCount','Player.Time','Player.Time(format)','Player.TimeRemaining','Player.TimeRemaining(format)','Player.Duration','Player.Duration(format)','Player.SeekTime','Player.SeekOffset','Player.SeekOffset(format)','Player.SeekStepSize','Player.ProgressCache','Player.Folderpath','Player.Filenameandpath','Player.StartTime','Player.StartTime(format)','Player.Title','Player.Filename']:
                    #    logger.debug("[traktPlayer] TEMP %s : %s" % (il, xbmc.getInfoLabel(il)))
                    #for k,v in result.iteritems():
                    #    logger.debug("[traktPlayer] onPlayBackStarted() - result - %s : %s" % (k,v))
                    #for k,v in result['item'].iteritems():
                    #    logger.debug("[traktPlayer] onPlayBackStarted() - result.item - %s : %s" % (k,v))

                    # As of Kodi v16 with the MythTV PVR addon, the only way I could find to get the TV show and episode
                    # info is from the Player.Filename infolabel. It shows up like this:
                    # ShowName [sXXeYY ](year) EpisodeName, channel, PVRFileName
                    # The season and episode info may or may not be present. For example:
                    # Elementary s04e10 (2016) Alma Matters, TV (WWMT-HD), 20160129_030000.pvr
                    # DC's Legends of Tomorrow (2016) Pilot, Part 2, TV (CW W MI), 20160129_010000.pvr
                    foundLabel = xbmc.getInfoLabel('Player.Filename')
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Found unknown video type with label: %s. Might be a PVR episode, searching Trakt for it."
                        % foundLabel)
                    splitLabel = foundLabel.rsplit(", ", 2)
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Post-split of label: %s "
                        % splitLabel)
                    if len(splitLabel) != 3:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Label doesn't have the ShowName sXXeYY (year) EpisodeName, channel, PVRFileName format that was expected. Giving up."
                        )
                        return
                    foundShowAndEpInfo = splitLabel[0]
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - show plus episode info: %s"
                        % foundShowAndEpInfo)
                    splitShowAndEpInfo = re.split(
                        ' (s\d\de\d\d)? ?\((\d\d\d\d)\) ', foundShowAndEpInfo,
                        1)
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Post-split of show plus episode info: %s "
                        % splitShowAndEpInfo)
                    if len(splitShowAndEpInfo) != 4:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Show plus episode info doesn't have the ShowName sXXeYY (year) EpisodeName format that was expected. Giving up."
                        )
                        return
                    foundShowName = splitShowAndEpInfo[0]
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - using show name: %s"
                        % foundShowName)
                    foundEpisodeName = splitShowAndEpInfo[3]
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - using episode name: %s"
                        % foundEpisodeName)
                    foundEpisodeYear = splitShowAndEpInfo[2]
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - using episode year: %s"
                        % foundEpisodeYear)
                    epYear = None
                    try:
                        epYear = int(foundEpisodeYear)
                    except ValueError:
                        epYear = None
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - verified episode year: %d"
                        % epYear)
                    # All right, now we have the show name, episode name, and (maybe) episode year. All good, but useless for
                    # scrobbling since Trakt only understands IDs, not names.
                    data['video_ids'] = None
                    data['season'] = None
                    data['episode'] = None
                    data['episodeTitle'] = None
                    # First thing to try, a text query to the Trakt DB looking for this episode. Note
                    # that we can't search for show and episode together, because the Trakt function gets confused and returns nothing.
                    newResp = globals.traktapi.getTextQuery(
                        foundEpisodeName, "episode", epYear)
                    if not newResp:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Empty Response from getTextQuery, giving up"
                        )
                    else:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Got Response from getTextQuery: %s"
                            % str(newResp))
                        # We got something back. See if one of the returned values is for the show we're looking for. Often it's
                        # not, but since there's no way to tell the search which show we want, this is all we can do.
                        rightResp = None
                        for thisResp in newResp:
                            compareShowName = thisResp.show.title
                            logger.debug(
                                "[traktPlayer] onPlayBackStarted() - comparing show name: %s"
                                % compareShowName)
                            if thisResp.show.title == foundShowName:
                                logger.debug(
                                    "[traktPlayer] onPlayBackStarted() - found the right show, using this response"
                                )
                                rightResp = thisResp
                                break
                        if rightResp is None:
                            logger.debug(
                                "[traktPlayer] onPlayBackStarted() - Failed to find matching episode/show via text search."
                            )
                        else:
                            # OK, now we have a episode object to work with.
                            self.type = 'episode'
                            data['type'] = 'episode'
                            # You'd think we could just use the episode key that Trakt just returned to us, but the scrobbler
                            # function (see scrobber.py) only understands the show key plus season/episode values.
                            showKeys = {}
                            for eachKey in rightResp.show.keys:
                                showKeys[eachKey[0]] = eachKey[1]
                            data['video_ids'] = showKeys
                            # For some reason, the Trakt search call returns the season and episode as an array in the pk field.
                            # You'd think individual episode and season fields would be better, but whatever.
                            data['season'] = rightResp.pk[0]
                            data['episode'] = rightResp.pk[1]
                    # At this point if we haven't found the episode data yet, the episode-title-text-search method
                    # didn't work.
                    if (not data['season']):
                        # This text query API is basically the same as searching on the website. Works with alternative
                        # titles, unlike the scrobble function. Though we can't use the episode year since that would only
                        # match the show if we're dealing with season 1.
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Searching for show title via getTextQuery: %s"
                            % foundShowName)
                        newResp = globals.traktapi.getTextQuery(
                            foundShowName, "show", None)
                        if not newResp:
                            logger.debug(
                                "[traktPlayer] onPlayBackStarted() - Empty Show Response from getTextQuery, falling back on episode text query"
                            )
                        else:
                            logger.debug(
                                "[traktPlayer] onPlayBackStarted() - Got Show Response from getTextQuery: %s"
                                % str(newResp))
                            # We got something back. Have to assume the first show found is the right one; if there's more than
                            # one, there's no way to know which to use. Pull the ids from the show data, and store 'em for scrobbling.
                            showKeys = {}
                            for eachKey in newResp[0].keys:
                                showKeys[eachKey[0]] = eachKey[1]
                            data['video_ids'] = showKeys
                            # Now to find the episode. There's no search function to look for an episode within a show, but
                            # we can get all the episodes and look for the title.
                            while (not data['season']):
                                logger.debug(
                                    "[traktPlayer] onPlayBackStarted() - Querying for all seasons/episodes of this show"
                                )
                                epQueryResp = globals.traktapi.getShowWithAllEpisodesList(
                                    data['video_ids']['trakt'])
                                if not epQueryResp:
                                    # Nothing returned. Giving up.
                                    logger.debug(
                                        "[traktPlayer] onPlayBackStarted() - No response received"
                                    )
                                    break
                                else:
                                    # Got the list back. Go through each season.
                                    logger.debug(
                                        "[traktPlayer] onPlayBackStarted() - Got response with seasons: %s"
                                        % str(epQueryResp))
                                    for eachSeason in epQueryResp:
                                        # For each season, check each episode.
                                        logger.debug(
                                            "[traktPlayer] onPlayBackStarted() - Processing season: %s"
                                            % str(eachSeason))
                                        for eachEpisodeNumber in eachSeason.episodes:
                                            thisEpTitle = None
                                            # Get the title. The try block is here in case the title doesn't exist for some entries.
                                            try:
                                                thisEpTitle = eachSeason.episodes[
                                                    eachEpisodeNumber].title
                                            except:
                                                thisEpTitle = None
                                            logger.debug(
                                                "[traktPlayer] onPlayBackStarted() - Checking episode number %d with title %s"
                                                % (eachEpisodeNumber,
                                                   thisEpTitle))
                                            if (foundEpisodeName == thisEpTitle
                                                ):
                                                # Found it! Save the data. The scrobbler wants season and episode number. Which for some
                                                # reason is stored as a pair in the first item in the keys array.
                                                data[
                                                    'season'] = eachSeason.episodes[
                                                        eachEpisodeNumber].keys[
                                                            0][0]
                                                data[
                                                    'episode'] = eachSeason.episodes[
                                                        eachEpisodeNumber].keys[
                                                            0][1]
                                                # Title too, just for the heck of it. Though it's not actually used.
                                                data[
                                                    'episodeTitle'] = thisEpTitle
                                                break
                                        # If we already found our data, no need to go through the rest of the seasons.
                                        if (data['season']):
                                            break
                    # Now we've done all we can.
                    if (data['season']):
                        # OK, that's everything. Data should be all set for scrobbling.
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' : show trakt key %s, season: %d, episode: %d"
                            % (data['video_ids'], data['season'],
                               data['episode']))
                    else:
                        # Still no data? Too bad, have to give up.
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - Did our best, but couldn't get info for this show and episode. Skipping."
                        )
                        return
                else:
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping."
                        % self.type)
                    return

                pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
                plSize = len(pl)
                if plSize > 1:
                    pos = pl.getposition()
                    if not self.plIndex is None:
                        logger.debug(
                            "[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event."
                        )
                        self.onPlayBackEnded()
                    self.plIndex = pos
                    logger.debug(
                        "[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d"
                        % (plSize, (pos + 1)))

                self._playing = True

                # send dispatch
                self.action(data)
Example #46
0
    def onPlayBackStarted(self):
        xbmc.sleep(1000)
        self.type = None
        self.id = None

        # take the user start scrobble offset into account
        scrobbleStartOffset = kodiUtilities.getSettingAsInt('scrobble_start_offset')*60
        if scrobbleStartOffset > 0:
            waitFor = 10
            waitedFor = 0
            # check each 10 seconds if we can abort or proceed
            while not xbmc.abortRequested and scrobbleStartOffset > waitedFor:
                waitedFor += waitFor
                time.sleep(waitFor)
                if not self.isPlayingVideo():
                    logger.debug('[traktPlayer] Playback stopped before reaching the scrobble offset')
                    return

        # only do anything if we're playing a video
        if self.isPlayingVideo():
            # get item data from json rpc
            logger.debug("[traktPlayer] onPlayBackStarted() - Doing Player.GetItem kodiJsonRequest")
            result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': {'playerid': 1}, 'id': 1})
            if result:
                logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result)
                # check for exclusion
                _filename = None
                try:
                    _filename = self.getPlayingFile()
                except:
                    logger.debug("[traktPlayer] onPlayBackStarted() - Exception trying to get playing filename, player suddenly stopped.")
                    return

                if kodiUtilities.checkExclusion(_filename):
                    logger.debug("[traktPlayer] onPlayBackStarted() - '%s' is in exclusion settings, ignoring." % _filename)
                    return

                self.type = result['item']['type']

                data = {'action': 'started'}

                if (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr')):
                    logger.debug('[traktPlayer] Setting is enabled to try scrobbling mythtv pvr recording, if necessary.')

                # check type of item
                if 'id' not in result['item']:
                    # do a deeper check to see if we have enough data to perform scrobbles
                    logger.debug("[traktPlayer] onPlayBackStarted() - Started playing a non-library file, checking available data.")

                    season = xbmc.getInfoLabel('VideoPlayer.Season')
                    episode = xbmc.getInfoLabel('VideoPlayer.Episode')
                    showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle')
                    year = xbmc.getInfoLabel('VideoPlayer.Year')
                    video_ids = xbmcgui.Window(10000).getProperty('script.trakt.ids')
                    if video_ids:
                        data['video_ids'] = json.loads(video_ids)

                    logger.debug("[traktPlayer] info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode))

                    if season and episode and (showtitle or video_ids):
                        # we have season, episode and either a show title or video_ids, can scrobble this as an episode
                        self.type = 'episode'
                        data['type'] = 'episode'
                        data['season'] = int(season)
                        data['episode'] = int(episode)
                        data['showtitle'] = showtitle
                        data['title'] = xbmc.getInfoLabel('VideoPlayer.Title')
                        if year.isdigit():
                            data['year'] = int(year)
                        logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title']))
                    elif (year or video_ids) and not season and not showtitle:
                        # we have a year or video_id and no season/showtitle info, enough for a movie
                        self.type = 'movie'
                        data['type'] = 'movie'
                        if year.isdigit():
                            data['year'] = int(year)
                        data['title'] = xbmc.getInfoLabel('VideoPlayer.Title')
                        logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN')))
                    elif showtitle:
                        title, season, episode = utilities.regex_tvshow(showtitle)
                        data['type'] = 'episode'
                        data['season'] = season
                        data['episode'] = episode
                        data['title'] = data['showtitle'] = title
                        logger.debug("[traktPlayer] onPlayBackStarted() - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode))
                    else:
                        logger.debug("[traktPlayer] onPlayBackStarted() - Non-library file, not enough data for scrobbling, skipping.")
                        return

                elif self.type == 'episode' or self.type == 'movie':
                    # get library id
                    self.id = result['item']['id']
                    data['id'] = self.id
                    data['type'] = self.type

                    if self.type == 'episode':
                        logger.debug("[traktPlayer] onPlayBackStarted() - Doing multi-part episode check.")
                        result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodeDetails', 'params': {'episodeid': self.id, 'properties': ['tvshowid', 'season', 'episode', 'file']}, 'id': 1})
                        if result:
                            logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result)
                            tvshowid = int(result['episodedetails']['tvshowid'])
                            season = int(result['episodedetails']['season'])
                            currentfile = result['episodedetails']['file']

                            result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': tvshowid, 'season': season, 'properties': ['episode', 'file'], 'sort': {'method': 'episode'}}, 'id': 1})
                            if result:
                                logger.debug("[traktPlayer] onPlayBackStarted() - %s" % result)
                                # make sure episodes array exists in results
                                if 'episodes' in result:
                                    multi = []
                                    for i in range(result['limits']['start'], result['limits']['total']):
                                        if currentfile == result['episodes'][i]['file']:
                                            multi.append(result['episodes'][i]['episodeid'])
                                    if len(multi) > 1:
                                        data['multi_episode_data'] = multi
                                        data['multi_episode_count'] = len(multi)
                                        logger.debug("[traktPlayer] onPlayBackStarted() - This episode is part of a multi-part episode.")
                                    else:
                                        logger.debug("[traktPlayer] onPlayBackStarted() - This is a single episode.")
                elif (kodiUtilities.getSettingAsBool('scrobble_mythtv_pvr') and self.type == 'unknown' and result['item']['label']):
                    # If we have label/id but no show type, then this might be a PVR recording.

                    # DEBUG INFO: This code is useful when trying to figure out what info is available. Many of the fields
                    # that you'd expect (TVShowTitle, episode, season, etc) are always blank. In Kodi v15, we got the show
                    # and episode name in the VideoPlayer label. In v16, that's gone, but the Player.Filename infolabel
                    # is populated with several interesting things. If these things change in future versions, uncommenting
                    # this code will hopefully provide some useful info in the debug log.
                    #logger.debug("[traktPlayer] onPlayBackStarted() - TEMP Checking all videoplayer infolabels.")
                    #for il in ['VideoPlayer.Time','VideoPlayer.TimeRemaining','VideoPlayer.TimeSpeed','VideoPlayer.Duration','VideoPlayer.Title','VideoPlayer.TVShowTitle','VideoPlayer.Season','VideoPlayer.Episode','VideoPlayer.Genre','VideoPlayer.Director','VideoPlayer.Country','VideoPlayer.Year','VideoPlayer.Rating','VideoPlayer.UserRating','VideoPlayer.Votes','VideoPlayer.RatingAndVotes','VideoPlayer.mpaa','VideoPlayer.IMDBNumber','VideoPlayer.EpisodeName','VideoPlayer.PlaylistPosition','VideoPlayer.PlaylistLength','VideoPlayer.Cast','VideoPlayer.CastAndRole','VideoPlayer.Album','VideoPlayer.Artist','VideoPlayer.Studio','VideoPlayer.Writer','VideoPlayer.Tagline','VideoPlayer.PlotOutline','VideoPlayer.Plot','VideoPlayer.LastPlayed','VideoPlayer.PlayCount','VideoPlayer.VideoCodec','VideoPlayer.VideoResolution','VideoPlayer.VideoAspect','VideoPlayer.AudioCodec','VideoPlayer.AudioChannels','VideoPlayer.AudioLanguage','VideoPlayer.SubtitlesLanguage','VideoPlayer.StereoscopicMode','VideoPlayer.EndTime','VideoPlayer.NextTitle','VideoPlayer.NextGenre','VideoPlayer.NextPlot','VideoPlayer.NextPlotOutline','VideoPlayer.NextStartTime','VideoPlayer.NextEndTime','VideoPlayer.NextDuration','VideoPlayer.ChannelName','VideoPlayer.ChannelNumber','VideoPlayer.SubChannelNumber','VideoPlayer.ChannelNumberLabel','VideoPlayer.ChannelGroup','VideoPlayer.ParentalRating','Player.FinishTime','Player.FinishTime(format)','Player.Chapter','Player.ChapterCount','Player.Time','Player.Time(format)','Player.TimeRemaining','Player.TimeRemaining(format)','Player.Duration','Player.Duration(format)','Player.SeekTime','Player.SeekOffset','Player.SeekOffset(format)','Player.SeekStepSize','Player.ProgressCache','Player.Folderpath','Player.Filenameandpath','Player.StartTime','Player.StartTime(format)','Player.Title','Player.Filename']:
                    #    logger.debug("[traktPlayer] TEMP %s : %s" % (il, xbmc.getInfoLabel(il)))
                    #for k,v in result.iteritems():
                    #    logger.debug("[traktPlayer] onPlayBackStarted() - result - %s : %s" % (k,v))
                    #for k,v in result['item'].iteritems():
                    #    logger.debug("[traktPlayer] onPlayBackStarted() - result.item - %s : %s" % (k,v))

                    # As of Kodi v16 with the MythTV PVR addon, the only way I could find to get the TV show and episode
                    # info is from the Player.Filename infolabel. It shows up like this:
                    # ShowName [sXXeYY ](year) EpisodeName, channel, PVRFileName
                    # The season and episode info may or may not be present. For example:
                    # Elementary s04e10 (2016) Alma Matters, TV (WWMT-HD), 20160129_030000.pvr
                    # DC's Legends of Tomorrow (2016) Pilot, Part 2, TV (CW W MI), 20160129_010000.pvr
                    foundLabel = xbmc.getInfoLabel('Player.Filename')
                    logger.debug("[traktPlayer] onPlayBackStarted() - Found unknown video type with label: %s. Might be a PVR episode, searching Trakt for it." % foundLabel)
                    splitLabel = foundLabel.rsplit(", ", 2)
                    logger.debug("[traktPlayer] onPlayBackStarted() - Post-split of label: %s " % splitLabel)
                    if len(splitLabel) != 3:
                        logger.debug("[traktPlayer] onPlayBackStarted() - Label doesn't have the ShowName sXXeYY (year) EpisodeName, channel, PVRFileName format that was expected. Giving up.")
                        return
                    foundShowAndEpInfo = splitLabel[0]
                    logger.debug("[traktPlayer] onPlayBackStarted() - show plus episode info: %s" % foundShowAndEpInfo)
                    splitShowAndEpInfo = re.split(' (s\d\de\d\d)? ?\((\d\d\d\d)\) ',foundShowAndEpInfo, 1)
                    logger.debug("[traktPlayer] onPlayBackStarted() - Post-split of show plus episode info: %s " % splitShowAndEpInfo)
                    if len(splitShowAndEpInfo) != 4:
                        logger.debug("[traktPlayer] onPlayBackStarted() - Show plus episode info doesn't have the ShowName sXXeYY (year) EpisodeName format that was expected. Giving up.")
                        return
                    foundShowName = splitShowAndEpInfo[0]
                    logger.debug("[traktPlayer] onPlayBackStarted() - using show name: %s" % foundShowName)
                    foundEpisodeName = splitShowAndEpInfo[3]
                    logger.debug("[traktPlayer] onPlayBackStarted() - using episode name: %s" % foundEpisodeName)
                    foundEpisodeYear = splitShowAndEpInfo[2]
                    logger.debug("[traktPlayer] onPlayBackStarted() - using episode year: %s" % foundEpisodeYear)
                    epYear = None
                    try:
                        epYear = int(foundEpisodeYear)
                    except ValueError:
                        epYear = None
                    logger.debug("[traktPlayer] onPlayBackStarted() - verified episode year: %d" % epYear)
                    # All right, now we have the show name, episode name, and (maybe) episode year. All good, but useless for
                    # scrobbling since Trakt only understands IDs, not names.
                    data['video_ids'] = None
                    data['season'] = None
                    data['episode'] = None
                    data['episodeTitle'] = None
                    # First thing to try, a text query to the Trakt DB looking for this episode. Note
                    # that we can't search for show and episode together, because the Trakt function gets confused and returns nothing.
                    newResp = globals.traktapi.getTextQuery(foundEpisodeName, "episode", epYear)
                    if not newResp:
                        logger.debug("[traktPlayer] onPlayBackStarted() - Empty Response from getTextQuery, giving up")
                    else:
                        logger.debug("[traktPlayer] onPlayBackStarted() - Got Response from getTextQuery: %s" % str(newResp))
                        # We got something back. See if one of the returned values is for the show we're looking for. Often it's
                        # not, but since there's no way to tell the search which show we want, this is all we can do.
                        rightResp = None
                        for thisResp in newResp:
                            compareShowName = thisResp.show.title
                            logger.debug("[traktPlayer] onPlayBackStarted() - comparing show name: %s" % compareShowName)
                            if thisResp.show.title == foundShowName:
                                logger.debug("[traktPlayer] onPlayBackStarted() - found the right show, using this response")
                                rightResp = thisResp
                                break
                        if rightResp is None:
                            logger.debug("[traktPlayer] onPlayBackStarted() - Failed to find matching episode/show via text search.")
                        else:
                            # OK, now we have a episode object to work with.
                            self.type = 'episode'
                            data['type'] = 'episode'
                            # You'd think we could just use the episode key that Trakt just returned to us, but the scrobbler
                            # function (see scrobber.py) only understands the show key plus season/episode values.
                            showKeys = { }
                            for eachKey in rightResp.show.keys:
                                showKeys[eachKey[0]] = eachKey[1]
                            data['video_ids'] = showKeys
                            # For some reason, the Trakt search call returns the season and episode as an array in the pk field.
                            # You'd think individual episode and season fields would be better, but whatever.
                            data['season'] = rightResp.pk[0];
                            data['episode'] = rightResp.pk[1];
                    # At this point if we haven't found the episode data yet, the episode-title-text-search method
                    # didn't work.
                    if (not data['season']):
                        # This text query API is basically the same as searching on the website. Works with alternative
                        # titles, unlike the scrobble function. Though we can't use the episode year since that would only
                        # match the show if we're dealing with season 1.
                        logger.debug("[traktPlayer] onPlayBackStarted() - Searching for show title via getTextQuery: %s" % foundShowName)
                        newResp = globals.traktapi.getTextQuery(foundShowName, "show", None)
                        if not newResp:
                            logger.debug("[traktPlayer] onPlayBackStarted() - Empty Show Response from getTextQuery, falling back on episode text query")
                        else:
                            logger.debug("[traktPlayer] onPlayBackStarted() - Got Show Response from getTextQuery: %s" % str(newResp))
                            # We got something back. Have to assume the first show found is the right one; if there's more than
                            # one, there's no way to know which to use. Pull the ids from the show data, and store 'em for scrobbling.
                            showKeys = { }
                            for eachKey in newResp[0].keys:
                                showKeys[eachKey[0]] = eachKey[1]
                            data['video_ids'] = showKeys
                            # Now to find the episode. There's no search function to look for an episode within a show, but
                            # we can get all the episodes and look for the title.
                            while (not data['season']):
                                logger.debug("[traktPlayer] onPlayBackStarted() - Querying for all seasons/episodes of this show")
                                epQueryResp = globals.traktapi.getShowWithAllEpisodesList(data['video_ids']['trakt'])
                                if not epQueryResp:
                                    # Nothing returned. Giving up.
                                    logger.debug("[traktPlayer] onPlayBackStarted() - No response received")
                                    break;
                                else:
                                    # Got the list back. Go through each season.
                                    logger.debug("[traktPlayer] onPlayBackStarted() - Got response with seasons: %s" % str(epQueryResp))
                                    for eachSeason in epQueryResp:
                                        # For each season, check each episode.
                                        logger.debug("[traktPlayer] onPlayBackStarted() - Processing season: %s" % str(eachSeason))
                                        for eachEpisodeNumber in eachSeason.episodes:
                                            thisEpTitle = None
                                            # Get the title. The try block is here in case the title doesn't exist for some entries.
                                            try:
                                                thisEpTitle = eachSeason.episodes[eachEpisodeNumber].title
                                            except:
                                                thisEpTitle = None
                                            logger.debug("[traktPlayer] onPlayBackStarted() - Checking episode number %d with title %s" % (eachEpisodeNumber, thisEpTitle))
                                            if (foundEpisodeName == thisEpTitle):
                                                # Found it! Save the data. The scrobbler wants season and episode number. Which for some
                                                # reason is stored as a pair in the first item in the keys array.
                                                data['season'] = eachSeason.episodes[eachEpisodeNumber].keys[0][0]
                                                data['episode'] = eachSeason.episodes[eachEpisodeNumber].keys[0][1]
                                                # Title too, just for the heck of it. Though it's not actually used.
                                                data['episodeTitle'] = thisEpTitle
                                                break
                                        # If we already found our data, no need to go through the rest of the seasons.
                                        if (data['season']):
                                            break;
                    # Now we've done all we can.
                    if (data['season']):
                        # OK, that's everything. Data should be all set for scrobbling.
                        logger.debug("[traktPlayer] onPlayBackStarted() - Playing a non-library 'episode' : show trakt key %s, season: %d, episode: %d" % (data['video_ids'], data['season'], data['episode']))
                    else:
                        # Still no data? Too bad, have to give up.
                        logger.debug("[traktPlayer] onPlayBackStarted() - Did our best, but couldn't get info for this show and episode. Skipping.")
                        return;
                else:
                    logger.debug("[traktPlayer] onPlayBackStarted() - Video type '%s' unrecognized, skipping." % self.type)
                    return

                pl = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
                plSize = len(pl)
                if plSize > 1:
                    pos = pl.getposition()
                    if not self.plIndex is None:
                        logger.debug("[traktPlayer] onPlayBackStarted() - User manually skipped to next (or previous) video, forcing playback ended event.")
                        self.onPlayBackEnded()
                    self.plIndex = pos
                    logger.debug("[traktPlayer] onPlayBackStarted() - Playlist contains %d item(s), and is currently on item %d" % (plSize, (pos + 1)))

                self._playing = True

                # send dispatch
                self.action(data)
Example #47
0
def rateMedia(media_type, itemsToRate, unrate=False, rating=None):
    """Launches the rating dialog"""
    for summary_info in itemsToRate:
        if not utilities.isValidMediaType(media_type):
            logger.debug("Not a valid media type")
            return
        elif 'user' not in summary_info:
            logger.debug("No user data")
            return

        s = utilities.getFormattedItemName(media_type, summary_info)

        logger.debug("Summary Info %s" % summary_info)

        if unrate:
            rating = None

            if summary_info['user']['ratings']['rating'] > 0:
                rating = 0

            if not rating is None:
                logger.debug("'%s' is being unrated." % s)
                __rateOnTrakt(rating, media_type, summary_info, unrate=True)
            else:
                logger.debug("'%s' has not been rated, so not unrating." % s)

            return

        rerate = kodiUtilities.getSettingAsBool('rate_rerate')
        if rating is not None:
            if summary_info['user']['ratings']['rating'] == 0:
                logger.debug("Rating for '%s' is being set to '%d' manually." % (s, rating))
                __rateOnTrakt(rating, media_type, summary_info)
            else:
                if rerate:
                    if not summary_info['user']['ratings']['rating'] == rating:
                        logger.debug("Rating for '%s' is being set to '%d' manually." % (s, rating))
                        __rateOnTrakt(rating, media_type, summary_info)
                    else:
                        kodiUtilities.notification(kodiUtilities.getString(32043), s)
                        logger.debug("'%s' already has a rating of '%d'." % (s, rating))
                else:
                    kodiUtilities.notification(kodiUtilities.getString(32041), s)
                    logger.debug("'%s' is already rated." % s)
            return

        if summary_info['user']['ratings'] and summary_info['user']['ratings']['rating']:
            if not rerate:
                logger.debug("'%s' has already been rated." % s)
                kodiUtilities.notification(kodiUtilities.getString(32041), s)
                return
            else:
                logger.debug("'%s' is being re-rated." % s)

        xbmc.executebuiltin('Dialog.Close(all, true)')

        gui = RatingDialog(
            "script-trakt-RatingDialog.xml",
            __addon__.getAddonInfo('path'),
            media_type=media_type,
            media=summary_info,
            rerate=rerate
        )

        gui.doModal()
        if gui.rating:
            rating = gui.rating
            if rerate:
                rating = gui.rating

                if summary_info['user']['ratings'] and summary_info['user']['ratings']['rating'] > 0 and rating == summary_info['user']['ratings']['rating']:
                    rating = 0

            if rating == 0 or rating == "unrate":
                __rateOnTrakt(rating, gui.media_type, gui.media, unrate=True)
            else:
                __rateOnTrakt(rating, gui.media_type, gui.media)
        else:
            logger.debug("Rating dialog was closed with no rating.")

        del gui
        #Reset rating and unrate for multi part episodes
        unrate=False
        rating=None