예제 #1
0
def Main():

    args = __getArguments()
    data = {}

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

    elif args['action'] in ['rate', 'unrate']:
        data = {'action': args['action']}
        media_type = None
        if 'media_type' in args and 'dbid' in args:
            media_type = args['media_type']
            try:
                data['dbid'] = int(args['dbid'])
            except ValueError:
                utils.Debug(
                    "Manual %s triggered for library item, but DBID is invalid."
                    % args['action'])
                return
        elif 'media_type' in args and 'remoteid' in args:
            media_type = args['media_type']
            data['remoteid'] = args['remoteid']
            if 'season' in args:
                if not 'episode' in args:
                    utils.Debug(
                        "Manual %s triggered for non-library episode, but missing episode number."
                        % args['action'])
                    return
                try:
                    data['season'] = int(args['season'])
                    data['episode'] = int(args['episode'])
                except ValueError:
                    utils.Debug(
                        "Error parsing season or episode for manual %s" %
                        args['action'])
                    return
        else:
            media_type = __getMediaType()
            if not utils.isValidMediaType(media_type):
                utils.Debug("Error, not in video library.")
                return
            data['dbid'] = int(xbmc.getInfoLabel('ListItem.DBID'))

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

                elif utils.isShow(media_type):
                    result = utils.getShowDetailsFromKodi(
                        data['dbid'], ['imdbnumber', 'tag'])
                    if not result:
                        utils.Debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return
                    data['imdbnumber'] = result['imdbnumber']
                    data['tag'] = result['tag']

                elif utils.isEpisode(media_type):
                    result = utils.getEpisodeDetailsFromKodi(
                        data['dbid'],
                        ['showtitle', 'season', 'episode', 'imdbnumber'])
                    if not result:
                        utils.Debug(
                            "No data was returned from Kodi, aborting manual %s."
                            % args['action'])
                        return
                    data['imdbnumber'] = result['imdbnumber']
                    data['season'] = result['season']
                    data['episode'] = result['episode']

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    q = sqliteQueue.SqliteQueue()
    if 'action' in data:
        utils.Debug("Queuing for dispatch: %s" % data)
        q.append(data)
예제 #2
0
class traktService:
	scrobbler = None
	updateTagsThread = None
	syncThread = None
	dispatchQueue = sqliteQueue.SqliteQueue()
	
	def __init__(self):
		threading.Thread.name = 'trakt'

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


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

		logger.debug("Service thread starting.")

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

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

		# init traktapi class
		globals.traktapi = traktAPI()

		# init sync thread
		self.syncThread = syncThread()

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

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

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

			xbmc.sleep(500)

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

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

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

	def doManualRating(self, data):

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

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

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

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

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

	def doMarkWatched(self, data):

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

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

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

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

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

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

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


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

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

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


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