Exemplo n.º 1
0
class traktService:

	scrobbler = None
	tagger = None
	updateTagsThread = None
	watcher = None
	syncThread = None
	dispatchQueue = queue.SqliteQueue()
	_interval = 10 * 60 # how often to send watching call
	
	def __init__(self):
		threading.Thread.name = 'trakt'

	def _dispatchQueue(self, data):
		utilities.Debug("Queuing for dispatch: %s" % data)
		self.dispatchQueue.append(data)
	
	def _dispatch(self, data):
		utilities.Debug("Dispatch: %s" % data)
		action = data['action']
		if action == 'started':
			del data['action']
			self.scrobbler.playbackStarted(data)
			self.watcher = threading.Timer(self._interval, self.doWatching)
			self.watcher.name = "trakt-watching"
			self.watcher.start()
		elif action == 'ended' or action == 'stopped':
			self.scrobbler.playbackEnded()
			if self.watcher:
				if self.watcher.isAlive():
					self.watcher.cancel()
					self.watcher = None
		elif action == 'paused':
			self.scrobbler.playbackPaused()
		elif action == 'resumed':
			self.scrobbler.playbackResumed()
		elif action == 'seek' or action == 'seekchapter':
			self.scrobbler.playbackSeek()
		elif action == 'databaseUpdated':
			self.doSync()
		elif action == 'scanStarted':
			pass
		elif action == 'settingsChanged':
			utilities.Debug("Settings changed, reloading.")
			globals.traktapi.updateSettings()
			self.tagger.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():
				utilities.Debug("Performing a manual sync.")
				self.doSync(manual=True, silent=data['silent'])
			else:
				utilities.Debug("There already is a sync in progress.")
		elif action == 'updatetags':
			if self.updateTagsThread and self.updateTagsThread.isAlive():
				utilities.Debug("Currently updating tags already.")
			else:
				self.updateTagsThread = threading.Thread(target=self.tagger.updateTagsFromTrakt, name="trakt-updatetags")
				self.updateTagsThread.start()
		elif action == 'managelists':
			self.tagger.manageLists()
		elif action == 'itemlists':
			del data['action']
			self.tagger.itemLists(data)
		elif action == 'addtolist':
			del data['action']
			list = data['list']
			del data['list']
			self.tagger.manualAddToList(list, data)
		elif action == 'removefromlist':
			del data['action']
			list = data['list']
			del data['list']
			self.tagger.manualRemoveFromList(list, data)
		elif action == 'loadsettings':
			force = False
			if 'force' in data:
				force = data['force']
			globals.traktapi.getAccountSettings(force)
		else:
			utilities.Debug("Unknown dispatch action, '%s'." % action)

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

		utilities.Debug("Service thread starting.")

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

		# queue a loadsettings action
		self.dispatchQueue.append({'action': 'loadsettings'})

		# 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)

		# init tagging class
		self.tagger = Tagger(globals.traktapi)
		
		# start loop for events
		while (not xbmc.abortRequested):
			while len(self.dispatchQueue) and (not xbmc.abortRequested):
				data = self.dispatchQueue.get()
				utilities.Debug("Queued dispatch: %s" % data)
				self._dispatch(data)

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

			xbmc.sleep(500)

		# we are shutting down
		utilities.Debug("Beginning shut down.")

		# check if watcher is set and active, if so, cancel it.
		if self.watcher:
			if self.watcher.isAlive():
				self.watcher.cancel()

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

		# check update tags thread.
		if self.updateTagsThread and self.updateTagsThread.isAlive():
			self.updateTagsThread.join()

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

	def doWatching(self):
		# check if we're still playing a video
		if not xbmc.Player().isPlayingVideo():
			self.watcher = None
			return

		# call watching method
		self.scrobbler.watching()

		# start a new timer thread
		self.watcher = threading.Timer(self._interval, self.doWatching)
		self.watcher.name = "trakt-watching"
		self.watcher.start()

	def doManualRating(self, data):

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

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

		if not data['action'] in ['rate', 'unrate']:
			utilities.Debug("doManualRating(): Unknown action passed.")
			return
			
		if 'dbid' in data:
			utilities.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:
				utilities.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:
				utilities.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['tvdb_id'], 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'])
			elif action == 'unrate':
				rateMedia(media_type, summaryInfo, unrate=True)
		else:
			utilities.Debug("doManualRating(): Summary info was empty, possible problem retrieving data from trakt.tv")

	def doMarkWatched(self, data):

		media_type = data['media_type']
		simulate = utilities.getSettingAsBool('simulate_sync')
		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)
					utilities.Debug("doMarkWatched(): '%s' is not watched on trakt, marking it as watched." % s)
					movie = {}
					movie['imdb_id'] = data['id']
					movie['title'] = summaryInfo['title']
					movie['year'] = summaryInfo['year']
					movie['plays'] = 1
					movie['last_played'] = int(time())
					params = {'movies': [movie]}
					utilities.Debug("doMarkWatched(): %s" % str(params))
					
					if not simulate:
						result = globals.traktapi.updateSeenMovie(params)
						if result:
							if markedNotification:
								utilities.notification(utilities.getString(1550), s)
						else:
							utilities.notification(utilities.getString(1551), s)
					else:
						if markedNotification:
							utilities.notification(utilities.getString(1550), 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)
					utilities.Debug("doMarkWathced(): '%s' is not watched on trakt, marking it as watched." % s)
					params = {}
					params['imdb_id'] = summaryInfo['show']['imdb_id']
					params['tvdb_id'] = summaryInfo['show']['tvdb_id']
					params['title'] = summaryInfo['show']['title']
					params['year'] = summaryInfo['show']['year']
					params['episodes'] = [{'season': data['season'], 'episode': data['episode']}]
					utilities.Debug("doMarkWatched(): %s" % str(params))
					
					if not simulate:
						result = globals.traktapi.updateSeenEpisode(params)
						if result:
							if markedNotification:
								utilities.notification(utilities.getString(1550), s)
						else:
							utilities.notification(utilities.getString(1551), s)
					else:
						if markedNotification:
							utilities.notification(utilities.getString(1550), 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 = {}
				params['imdb_id'] = showInfo['imdb_id']
				params['tvdb_id'] = showInfo['tvdb_id']
				params['title'] = showInfo['title']
				params['year'] = showInfo['year']
				params['episodes'] = []
				for ep in summaryInfo:
					if ep['episode'] in data['episodes']:
						if not ep['watched']:
							params['episodes'].append({'season': ep['season'], 'episode': ep['episode']})

				utilities.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:
					utilities.Debug("doMarkWatched(): %s" % str(params))
					if not simulate:
						result = globals.traktapi.updateSeenEpisode(params)
						if result:
							if markedNotification:
								utilities.notification(utilities.getString(1550), utilities.getString(1552) % (len(params['episodes']), s))
						else:
							utilities.notification(utilities.getString(1551), utilities.getString(1552) % (len(params['episodes']), s))
					else:
						if markedNotification:
							utilities.notification(utilities.getString(1550), utilities.getString(1552) % (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 = {}
				params['imdb_id'] = summaryInfo['imdb_id']
				params['tvdb_id'] = summaryInfo['tvdb_id']
				params['title'] = summaryInfo['title']
				params['year'] = summaryInfo['year']
				params['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']})
				utilities.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:
					utilities.Debug("doMarkWatched(): %s" % str(params))
					if not simulate:
						result = globals.traktapi.updateSeenEpisode(params)
						if result:
							if markedNotification:
								utilities.notification(utilities.getString(1550), utilities.getString(1552) % (len(params['episodes']), s))
						else:
							utilities.notification(utilities.getString(1551), utilities.getString(1552) % (len(params['episodes']), s))
					else:
						if markedNotification:
							utilities.notification(utilities.getString(1550), utilities.getString(1552) % (len(params['episodes']), s))

	def doSync(self, manual=False, silent=False):
		self.syncThread = syncThread(manual, silent)
		self.syncThread.start()
Exemplo n.º 2
0
class traktService:

	scrobbler = None
	watcher = None
	syncThread = None
	dispatchQueue = Queue.Queue()
	_interval = 10 * 60 # how often to send watching call
	
	def __init__(self):
		threading.Thread.name = 'trakt'

	def _dispatchQueue(self, data):
		utilities.Debug("Queuing for dispatch: %s" % data)
		self.dispatchQueue.put(data)
	
	def _dispatch(self, data):
		utilities.Debug("Dispatch: %s" % data)
		action = data['action']
		if action == 'started':
			del data['action']
			self.scrobbler.playbackStarted(data)
			self.watcher = threading.Timer(self._interval, self.doWatching)
			self.watcher.name = "trakt-watching"
			self.watcher.start()
		elif action == 'ended' or action == 'stopped':
			self.scrobbler.playbackEnded()
			if self.watcher:
				if self.watcher.isAlive():
					self.watcher.cancel()
					self.watcher = None
		elif action == 'paused':
			self.scrobbler.playbackPaused()
		elif action == 'resumed':
			self.scrobbler.playbackResumed()
		elif action == 'seek' or action == 'seekchapter':
			self.scrobbler.playbackSeek()
		elif action == 'databaseUpdated':
			self.doSync()
		elif action == 'scanStarted':
			pass
		elif action == 'settingsChanged':
			utilities.Debug("Settings changed, reloading.")
			globals.traktapi.updateSettings()
		else:
			utilities.Debug("Unknown dispatch action, '%s'." % action)

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

		utilities.Debug("Service thread starting.")

		# clear any left over properties
		utilities.clearProperty('traktManualSync')
		utilities.clearProperty('traktManualRateData')
		utilities.clearProperty('traktManualRate')
		
		# 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 not self.dispatchQueue.empty() and (not xbmc.abortRequested):
				data = self.dispatchQueue.get()
				utilities.Debug("Queued dispatch: %s" % data)
				self._dispatch(data)

			# check if we were tasked to do a manual sync
			if utilities.getPropertyAsBool('traktManualSync'):
				if not self.syncThread.isAlive():
					utilities.Debug("Performing a manual sync.")
					self.doSync(manual=True)
				else:
					utilities.Debug("There already is a sync in progress.")

				utilities.clearProperty('traktManualSync')

			# check if we were tasked to do a manual rating
			if utilities.getPropertyAsBool('traktManualRate'):
				self.doManualRating()
				utilities.clearProperty('traktManualRateData')
				utilities.clearProperty('traktManualRate')
			
			if xbmc.Player().isPlayingVideo():
				self.scrobbler.update()

			xbmc.sleep(500)

		# we are shutting down
		utilities.Debug("Beginning shut down.")

		# check if watcher is set and active, if so, cancel it.
		if self.watcher:
			if self.watcher.isAlive():
				self.watcher.cancel()

		# 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 doWatching(self):
		# check if we're still playing a video
		if not xbmc.Player().isPlayingVideo():
			self.watcher = None
			return

		# call watching method
		self.scrobbler.watching()

		# start a new timer thread
		self.watcher = threading.Timer(self._interval, self.doWatching)
		self.watcher.name = "trakt-watching"
		self.watcher.start()

	def doManualRating(self):
		data = json.loads(utilities.getProperty('traktManualRateData'))

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

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

		if not data['action'] in ['rate', 'unrate']:
			utilities.Debug("doManualRating(): Unknown action passed.")
			return
			
		if 'dbid' in data:
			utilities.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:
				utilities.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:
				utilities.Debug("Getting data for manual %s of non-library '%s' with ID of '%s'" % (action, media_type, data['remoteid']))

		if utilities.isEpisode(media_type):
			result = {}
			if 'dbid' in data:
				result = utilities.getEpisodeDetailsFromXbmc(data['dbid'], ['showtitle', 'season', 'episode', 'tvshowid'])
				if not result:
					utilities.Debug("doManualRating(): No data was returned from XBMC, aborting manual %s." % action)
					return
			else:
				result['tvdb_id'] = data['remoteid']
				result['season'] = data['season']
				result['episode'] = data['episode']

			summaryInfo = globals.traktapi.getEpisodeSummary(result['tvdb_id'], result['season'], result['episode'])
		elif utilities.isShow(media_type):
			result = {}
			if 'dbid' in data:
				result = utilities.getShowDetailsFromXBMC(data['dbid'], ['imdbnumber'])
				if not result:
					utilities.Debug("doManualRating(): No data was returned from XBMC, aborting manual %s." % action)
					return
			else:
				result['imdbnumber'] = data['remoteid']

			summaryInfo = globals.traktapi.getShowSummary(result['imdbnumber'])
		elif utilities.isMovie(media_type):
			result = {}
			if 'dbid' in data:
				result = utilities.getMovieDetailsFromXbmc(data['dbid'], ['imdbnumber', 'title', 'year'])
				if not result:
					utilities.Debug("doManualRating(): No data was returned from XBMC, aborting manual %s." % action)
					return
			else:
				result['imdbnumber'] = data['remoteid']

			summaryInfo = globals.traktapi.getMovieSummary(result['imdbnumber'])
		
		if not summaryInfo is None:
			if action == 'rate':
				if not 'rating' in data:
					rateMedia(media_type, summaryInfo)
				else:
					rateMedia(media_type, summaryInfo, rating=data['rating'])
			elif action == 'unrate':
				rateMedia(media_type, summaryInfo, unrate=True)
		else:
			utilities.Debug("doManualRating(): Summary info was empty, possible problem retrieving data from trakt.tv")

	def doSync(self, manual=False):
		self.syncThread = syncThread(manual)
		self.syncThread.start()
Exemplo n.º 3
0
class traktService:
    scrobbler = None
    updateTagsThread = None
    syncThread = None
    dispatchQueue = sqlitequeue.SqliteQueue()

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

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

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

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

        logger.debug("Service thread starting.")

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

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

        # init traktapi class
        globals.traktapi = traktAPI()

        # init sync thread
        self.syncThread = syncThread()

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

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

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

            xbmc.sleep(500)

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

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

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

    def doManualRating(self, data):

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

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

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

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

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

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

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

    def doMarkWatched(self, data):

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

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

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

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

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

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

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

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

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

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

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

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

    def doSync(self, manual=False, silent=False, library="all"):
        self.syncThread = syncThread(manual, silent, library)
        self.syncThread.start()
Exemplo n.º 4
0
class traktService:

    scrobbler = None
    tagger = None
    updateTagsThread = None
    watcher = None
    syncThread = None
    dispatchQueue = queue.SqliteQueue()
    _interval = 10 * 60  # how often to send watching call

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

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

    def _dispatch(self, data):
        utilities.Debug("Dispatch: %s" % data)
        action = data['action']
        if action == 'started':
            del data['action']
            self.scrobbler.playbackStarted(data)
            self.watcher = threading.Timer(self._interval, self.doWatching)
            self.watcher.name = "trakt-watching"
            self.watcher.start()
        elif action == 'ended' or action == 'stopped':
            self.scrobbler.playbackEnded()
            if self.watcher:
                if self.watcher.isAlive():
                    self.watcher.cancel()
                    self.watcher = None
        elif action == 'paused':
            self.scrobbler.playbackPaused()
        elif action == 'resumed':
            self.scrobbler.playbackResumed()
        elif action == 'seek' or action == 'seekchapter':
            self.scrobbler.playbackSeek()
        elif action == 'databaseUpdated':
            self.doSync()
        elif action == 'scanStarted':
            pass
        elif action == 'settingsChanged':
            utilities.Debug("Settings changed, reloading.")
            globals.traktapi.updateSettings()
            self.tagger.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():
                utilities.Debug("Performing a manual sync.")
                self.doSync(manual=True)
            else:
                utilities.Debug("There already is a sync in progress.")
        elif action == 'updatetags':
            if self.updateTagsThread and self.updateTagsThread.isAlive():
                utilities.Debug("Currently updating tags already.")
            else:
                self.updateTagsThread = threading.Thread(
                    target=self.tagger.updateTagsFromTrakt,
                    name="trakt-updatetags")
                self.updateTagsThread.start()
        elif action == 'managelists':
            self.tagger.manageLists()
        elif action == 'itemlists':
            del data['action']
            self.tagger.itemLists(data)
        elif action == 'addtolist':
            del data['action']
            list = data['list']
            del data['list']
            self.tagger.manualAddToList(list, data)
        elif action == 'removefromlist':
            del data['action']
            list = data['list']
            del data['list']
            self.tagger.manualRemoveFromList(list, data)
        else:
            utilities.Debug("Unknown dispatch action, '%s'." % action)

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

        utilities.Debug("Service thread starting.")

        # 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)

        # init tagging class
        self.tagger = Tagger(globals.traktapi)

        # purge queue
        self.dispatchQueue.purge()

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

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

            xbmc.sleep(500)

        # we are shutting down
        utilities.Debug("Beginning shut down.")

        # check if watcher is set and active, if so, cancel it.
        if self.watcher:
            if self.watcher.isAlive():
                self.watcher.cancel()

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

        # check update tags thread.
        if self.updateTagsThread and self.updateTagsThread.isAlive():
            self.updateTagsThread.join()

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

    def doWatching(self):
        # check if we're still playing a video
        if not xbmc.Player().isPlayingVideo():
            self.watcher = None
            return

        # call watching method
        self.scrobbler.watching()

        # start a new timer thread
        self.watcher = threading.Timer(self._interval, self.doWatching)
        self.watcher.name = "trakt-watching"
        self.watcher.start()

    def doManualRating(self, data):

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

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

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

        if 'dbid' in data:
            utilities.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:
                utilities.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:
                utilities.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['tvdb_id'], 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'])
            elif action == 'unrate':
                rateMedia(media_type, summaryInfo, unrate=True)
        else:
            utilities.Debug(
                "doManualRating(): Summary info was empty, possible problem retrieving data from trakt.tv"
            )

    def doMarkWatched(self, data):

        media_type = data['media_type']
        simulate = utilities.getSettingAsBool('simulate_sync')
        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)
                    utilities.Debug(
                        "doMarkWatched(): '%s' is not watched on trakt, marking it as watched."
                        % s)
                    movie = {}
                    movie['imdb_id'] = data['id']
                    movie['title'] = summaryInfo['title']
                    movie['year'] = summaryInfo['year']
                    movie['plays'] = 1
                    movie['last_played'] = int(time())
                    params = {'movies': [movie]}
                    utilities.Debug("doMarkWatched(): %s" % str(params))

                    if not simulate:
                        result = globals.traktapi.updateSeenMovie(params)
                        if result:
                            if markedNotification:
                                utilities.notification(
                                    utilities.getString(1550), s)
                        else:
                            utilities.notification(utilities.getString(1551),
                                                   s)
                    else:
                        if markedNotification:
                            utilities.notification(utilities.getString(1550),
                                                   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)
                    utilities.Debug(
                        "doMarkWathced(): '%s' is not watched on trakt, marking it as watched."
                        % s)
                    params = {}
                    params['imdb_id'] = summaryInfo['show']['imdb_id']
                    params['tvdb_id'] = summaryInfo['show']['tvdb_id']
                    params['title'] = summaryInfo['show']['title']
                    params['year'] = summaryInfo['show']['year']
                    params['episodes'] = [{
                        'season': data['season'],
                        'episode': data['episode']
                    }]
                    utilities.Debug("doMarkWatched(): %s" % str(params))

                    if not simulate:
                        result = globals.traktapi.updateSeenEpisode(params)
                        if result:
                            if markedNotification:
                                utilities.notification(
                                    utilities.getString(1550), s)
                        else:
                            utilities.notification(utilities.getString(1551),
                                                   s)
                    else:
                        if markedNotification:
                            utilities.notification(utilities.getString(1550),
                                                   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 = {}
                params['imdb_id'] = showInfo['imdb_id']
                params['tvdb_id'] = showInfo['tvdb_id']
                params['title'] = showInfo['title']
                params['year'] = showInfo['year']
                params['episodes'] = []
                for ep in summaryInfo:
                    if ep['episode'] in data['episodes']:
                        if not ep['watched']:
                            params['episodes'].append({
                                'season': ep['season'],
                                'episode': ep['episode']
                            })

                utilities.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:
                    utilities.Debug("doMarkWatched(): %s" % str(params))
                    if not simulate:
                        result = globals.traktapi.updateSeenEpisode(params)
                        if result:
                            if markedNotification:
                                utilities.notification(
                                    utilities.getString(1550),
                                    utilities.getString(1552) %
                                    (len(params['episodes']), s))
                        else:
                            utilities.notification(
                                utilities.getString(1551),
                                utilities.getString(1552) %
                                (len(params['episodes']), s))
                    else:
                        if markedNotification:
                            utilities.notification(
                                utilities.getString(1550),
                                utilities.getString(1552) %
                                (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 = {}
                params['imdb_id'] = summaryInfo['imdb_id']
                params['tvdb_id'] = summaryInfo['tvdb_id']
                params['title'] = summaryInfo['title']
                params['year'] = summaryInfo['year']
                params['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']
                                    })
                utilities.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:
                    utilities.Debug("doMarkWatched(): %s" % str(params))
                    if not simulate:
                        result = globals.traktapi.updateSeenEpisode(params)
                        if result:
                            if markedNotification:
                                utilities.notification(
                                    utilities.getString(1550),
                                    utilities.getString(1552) %
                                    (len(params['episodes']), s))
                        else:
                            utilities.notification(
                                utilities.getString(1551),
                                utilities.getString(1552) %
                                (len(params['episodes']), s))
                    else:
                        if markedNotification:
                            utilities.notification(
                                utilities.getString(1550),
                                utilities.getString(1552) %
                                (len(params['episodes']), s))

    def doSync(self, manual=False):
        self.syncThread = syncThread(manual)
        self.syncThread.start()
Exemplo n.º 5
0
class traktService:

	scrobbler = None
	watcher = None
	syncThread = None
	dispatchQueue = Queue.Queue()
	_interval = 10 * 60 # how often to send watching call
	
	def __init__(self):
		threading.Thread.name = 'trakt'

	def _dispatchQueue(self, data):
		utilities.Debug("Queuing for dispatch: %s" % data)
		self.dispatchQueue.put(data)
	
	def _dispatch(self, data):
		utilities.Debug("Dispatch: %s" % data)
		action = data['action']
		if action == 'started':
			del data['action']
			self.scrobbler.playbackStarted(data)
			self.watcher = threading.Timer(self._interval, self.doWatching)
			self.watcher.name = "trakt-watching"
			self.watcher.start()
		elif action == 'ended' or action == 'stopped':
			self.scrobbler.playbackEnded()
			if self.watcher:
				if self.watcher.isAlive():
					self.watcher.cancel()
					self.watcher = None
		elif action == 'paused':
			self.scrobbler.playbackPaused()
		elif action == 'resumed':
			self.scrobbler.playbackResumed()
		elif action == 'seek' or action == 'seekchapter':
			self.scrobbler.playbackSeek()
		elif action == 'databaseUpdated':
			self.doSync()
		elif action == 'scanStarted':
			pass
		elif action == 'settingsChanged':
			utilities.Debug("Settings changed, reloading.")
			globals.traktapi.updateSettings()
		else:
			utilities.Debug("Unknown dispatch action, '%s'." % action)

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

		utilities.Debug("Service thread starting.")
		
		# 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 not self.dispatchQueue.empty() and (not xbmc.abortRequested):
				data = self.dispatchQueue.get()
				utilities.Debug("Queued dispatch: %s" % data)
				self._dispatch(data)

			# check if we were tasked to do a manual sync
			if utilities.getPropertyAsBool('traktManualSync'):
				if not self.syncThread.isAlive():
					utilities.Debug("Performing a manual sync.")
					self.doSync(manual=True)
				else:
					utilities.Debug("There already is a sync in progress.")

				utilities.clearProperty('traktManualSync')

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

			xbmc.sleep(500)

		# we are shutting down
		utilities.Debug("Beginning shut down.")

		# check if watcher is set and active, if so, cancel it.
		if self.watcher:
			if self.watcher.isAlive():
				self.watcher.cancel()

		# 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 doWatching(self):
		# check if we're still playing a video
		if not xbmc.Player().isPlayingVideo():
			self.watcher = None
			return

		# call watching method
		self.scrobbler.watching()

		# start a new timer thread
		self.watcher = threading.Timer(self._interval, self.doWatching)
		self.watcher.name = "trakt-watching"
		self.watcher.start()

	def doSync(self, manual=False):
		self.syncThread = syncThread(manual)
		self.syncThread.start()