def getInfoLabelDetails(result): type = result['item']['type'] data = {'action': 'started'} # check type of item if 'id' not in result['item'] or type == 'channel': # do a deeper check to see if we have enough data to perform scrobbles logger.debug( "getInfoLabelDetails - Started playing a non-library file, checking available data." ) season = int(xbmc.getInfoLabel('VideoPlayer.Season') or '-1') episode = int(xbmc.getInfoLabel('VideoPlayer.Episode') or '-1') showtitle = (xbmc.getInfoLabel('VideoPlayer.TVShowTitle') or xbmc.getInfoLabel('VideoPlayer.Title')) title = xbmc.getInfoLabel('VideoPlayer.EpisodeName') year = (xbmc.getInfoLabel('VideoPlayer.Year') or utilities.regex_year(showtitle)[1]) video_ids = xbmcgui.Window(10000).getProperty('script.trakt.ids') if video_ids: data['video_ids'] = json.loads(video_ids) logger.debug( "getInfoLabelDetails info - ids: %s, showtitle: %s, Year: %s, Season: %s, Episode: %s" % (video_ids, showtitle, year, season, episode)) if season >= 0 and episode > 0 and (showtitle or video_ids): # we have season, episode and either a show title or video_ids, can scrobble this as an episode type = 'episode' data['type'] = 'episode' data['season'] = season data['episode'] = episode data['showtitle'] = showtitle data['title'] = (title or showtitle) if year.isdigit(): data['year'] = int(year) logger.debug( "getInfoLabelDetails - Playing a non-library 'episode' - %s - S%02dE%02d - %s." % (data['showtitle'], data['season'], data['episode'], data['title'])) elif (year or video_ids) and season < 0 and not title: # we have a year or video_id and no season/showtitle info, enough for a movie type = 'movie' data['type'] = 'movie' if year.isdigit(): data['year'] = int(year) data['title'] = utilities.regex_year(showtitle)[0] logger.debug( "getInfoLabelDetails - Playing a non-library 'movie' - %s (%s)." % (data['title'], data.get('year', 'NaN'))) elif (showtitle or title): title, season, episode = utilities.regex_tvshow(title) if season < 0 and episode < 0: title, season, episode = utilities.regex_tvshow(showtitle) data['type'] = 'episode' data['season'] = season data['episode'] = episode data['title'] = data['showtitle'] = (title or showtitle) logger.debug( "getInfoLabelDetails - Title: %s, showtitle: %s, season: %d, episode: %d" % (title, showtitle, season, episode)) else: logger.debug( "getInfoLabelDetails - Non-library file, not enough data for scrobbling, skipping." ) return {}, {} return type, data
def test_regex_year_year_1(): assert utilities.regex_year('ShowTitle (2014)')[1] == '2014'
def test_regex_year_year_2(): assert utilities.regex_year('ShowTitle')[1] == ''
def test_regex_year_year_2(): assert utilities.regex_year('ShowTitle')[1] == ''
def test_regex_year_title_1(): assert utilities.regex_year('ShowTitle (2014)')[0] == 'ShowTitle'
def test_regex_year_year_1(): assert utilities.regex_year('ShowTitle (2014)')[1] == '2014'
def test_regex_year_title_1(): assert utilities.regex_year('ShowTitle (2014)')[0] == 'ShowTitle'
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.playlistIndex = xbmc.PlayList( xbmc.PLAYLIST_VIDEO).getposition() self.isMultiPartEpisode = False if utilities.isMovie(self.curVideo['type']): if 'id' in self.curVideo: self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject( 'movie', kodiUtilities.getMovieDetailsFromKodi( self.curVideo['id'], [ 'uniqueid', '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' ]) 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 'show_ids' in episodeDetailsKodi: self.traktShowSummary['ids'] = episodeDetailsKodi[ 'show_ids'] 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)
def transitionCheck(self, isSeek=False): if not xbmc.Player().isPlayingVideo(): return if self.isPlaying: t = xbmc.Player().getTime() l = xbmc.PlayList(xbmc.PLAYLIST_VIDEO).getposition() if self.isPVR: if self.stopScrobbler: self.stopScrobbler = False self.lastMPCheck = time.time( ) + 600 #10min transition sleep self.__scrobble('stop') return self.watchedTime = (utilities._to_sec( xbmc.getInfoLabel('PVR.EpgEventElapsedTime(hh:mm:ss)'))) self.videoDuration = int( utilities._to_sec( xbmc.getInfoLabel('PVR.EpgEventDuration(hh:mm:ss)'))) elif self.playlistIndex == l: self.watchedTime = t else: logger.debug( "Current playlist item changed! Not updating time! (%d -> %d)" % (self.playlistIndex, l)) # do transition check every minute if (time.time() > (self.lastMPCheck + 60)) or isSeek: self.lastMPCheck = time.time() watchedPercent = self.__calculateWatchedPercent() if 'id' in self.curVideo and self.isMultiPartEpisode: epIndex = self._currentEpisode( watchedPercent, self.curVideo['multi_episode_count']) if self.curMPEpisode != epIndex: response = self.__scrobble('stop') if response is not None: logger.debug("Scrobble response: %s" % str(response)) self.videosToRate.append(self.curVideoInfo) # update current information self.curMPEpisode = epIndex self.curVideoInfo = kodiUtilities.kodiRpcToTraktMediaObject( 'episode', kodiUtilities.getEpisodeDetailsFromKodi( self.curVideo['multi_episode_data'][ self.curMPEpisode], [ 'showtitle', 'season', 'episode', 'tvshowid', 'uniqueid', 'file', 'playcount' ])) logger.debug( "Multi episode transition - call start for next episode" ) response = self.__scrobble('start') self.__preFetchUserRatings(response) elif self.isPVR: activePlayers = kodiUtilities.kodiJsonRequest({ "jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1 }) logger.debug("Scrobble - activePlayers: %s" % activePlayers) playerId = int(activePlayers[0]['playerid']) logger.debug( "Scrobble - Doing Player.GetItem kodiJsonRequest") result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'Player.GetItem', 'params': { 'playerid': playerId }, 'id': 1 }) if result: logger.debug("Scrobble - %s" % result) type, curVideo = kodiUtilities.getInfoLabelDetails( result) if curVideo != self.curVideo: response = self.__scrobble('stop') if response is not None: logger.debug("Scrobble response: %s" % str(response)) logger.debug("Scrobble PVR transition") # update current information self.curVideo = curVideo if utilities.isMovie(self.curVideo['type']): if 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = { 'title': self.curVideo['title'], 'year': self.curVideo['year'] } else: logger.debug( "Scrobble Couldn't set curVideoInfo for movie type" ) logger.debug( "Scrobble Movie type, curVideoInfo: %s" % self.curVideoInfo) elif utilities.isEpisode( self.curVideo['type']): if '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( "Scrobble Couldn't set curVideoInfo/traktShowSummary for episode type" ) logger.debug( "Scrobble Episode type, curVideoInfo: %s" % self.curVideoInfo) logger.debug( "Scrobble Episode type, traktShowSummary: %s" % self.traktShowSummary) response = self.__scrobble('start') elif isSeek: self.__scrobble('start')
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)