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.playlistIndex == l: self.watchedTime = t else: logger.debug( "Current playlist item changed! Not updating time! (%d -> %d)" % (self.playlistIndex, l)) if 'id' in self.curVideo and self.isMultiPartEpisode: # do transition check every minute if (time.time() > (self.lastMPCheck + 60)) or isSeek: self.lastMPCheck = time.time() watchedPercent = self.__calculateWatchedPercent() 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 isSeek: self.__scrobble('start')
def run(): args = __getArguments() data = {} if args['action'] == 'auth_info': data['action'] = 'auth_info' if args['action'] == 'contextmenu': buttons = [] media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: buttons.append("rate") buttons.append("togglewatched") buttons.append("addtowatchlist") buttons.append("sync") contextMenu = traktContextMenu(media_type=media_type, buttons=buttons) contextMenu.doModal() _action = contextMenu.action del contextMenu if _action is None: return logger.debug("'%s' selected from trakt.tv action menu" % _action) args['action'] = _action if args['action'] == 'sync': data = {'action': 'manualSync', 'silent': False} if 'silent' in args: data['silent'] = (args['silent'].lower() == 'true') data['library'] = "all" if 'library' in args and args['library'] in ['episodes', 'movies']: data['library'] = args['library'] elif args['action'] in ['rate', 'unrate']: data = {'action': args['action']} media_type = None if 'media_type' in args and 'dbid' in args: media_type = args['media_type'] try: data['dbid'] = int(args['dbid']) except ValueError: logger.debug( "Manual %s triggered for library item, but DBID is invalid." % args['action']) return elif 'media_type' in args and 'remoteid' in args: media_type = args['media_type'] data['remoteid'] = args['remoteid'] try: data['season'] = int(args['season']) data['episode'] = int(args['episode']) except ValueError: logger.debug("Error parsing season or episode for manual %s" % args['action']) return except KeyError: pass else: media_type = kodiUtilities.getMediaType() if not utilities.isValidMediaType(media_type): logger.debug("Error, not in video library.") return data['dbid'] = int(xbmc.getInfoLabel('ListItem.DBID')) if media_type is None: logger.debug( "Manual %s triggered on an unsupported content container." % args['action']) elif utilities.isValidMediaType(media_type): data['media_type'] = media_type if 'dbid' in data: logger.debug("Manual %s of library '%s' with an ID of '%s'." % (args['action'], media_type, data['dbid'])) if utilities.isMovie(media_type): result = kodiUtilities.getMovieDetailsFromKodi( data['dbid'], ['imdbnumber', 'title', 'year']) if not result: logger.debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return elif utilities.isShow(media_type): tvshow_id = data['dbid'] elif utilities.isSeason(media_type): result = kodiUtilities.getSeasonDetailsFromKodi( data['dbid'], ['tvshowid', 'season']) if not result: logger.debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return tvshow_id = result['tvshowid'] data['season'] = result['season'] elif utilities.isEpisode(media_type): result = kodiUtilities.getEpisodeDetailsFromKodi( data['dbid'], ['season', 'episode', 'tvshowid']) if not result: logger.debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return tvshow_id = result['tvshowid'] data['season'] = result['season'] data['episode'] = result['episode'] if utilities.isShow(media_type) or utilities.isSeason( media_type) or utilities.isEpisode(media_type): result = kodiUtilities.getShowDetailsFromKodi( tvshow_id, ['imdbnumber']) if not result: logger.debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return data['video_id'] = result['imdbnumber'] else: data['video_id'] = data['remoteid'] if 'season' in data and 'episode' in data: logger.debug( "Manual %s of non-library '%s' S%02dE%02d, with an ID of '%s'." % (args['action'], media_type, data['season'], data['episode'], data['remoteid'])) elif 'season' in data: logger.debug( "Manual %s of non-library '%s' S%02d, with an ID of '%s'." % (args['action'], media_type, data['season'], data['remoteid'])) else: logger.debug( "Manual %s of non-library '%s' with an ID of '%s'." % (args['action'], media_type, data['remoteid'])) if args['action'] == 'rate' and 'rating' in args: if args['rating'] in [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' ]: data['rating'] = int(args['rating']) data = {'action': 'manualRating', 'ratingData': data} else: logger.debug("Manual %s of '%s' is unsupported." % (args['action'], media_type)) elif args['action'] == 'togglewatched': media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utilities.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getMovieDetailsFromKodi( dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] else: logger.debug("Movie alread marked as watched in Kodi.") else: logger.debug("Error getting movie details from Kodi.") return elif utilities.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getEpisodeDetailsFromKodi( dbid, [ 'showtitle', 'season', 'episode', 'tvshowid', 'playcount' ]) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] data['season'] = result['season'] data['number'] = result['episode'] data['title'] = result['showtitle'] else: logger.debug( "Episode already marked as watched in Kodi.") else: logger.debug("Error getting episode details from Kodi.") return elif utilities.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': { 'properties': ['title', 'imdbnumber', 'year'] }, 'id': 0 }) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] data['title'] = show['title'] break else: logger.debug("Error getting TV shows from Kodi.") return season = xbmc.getInfoLabel('ListItem.Season') if season == "": season = 0 else: season = int(season) result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) if len(episodes) == 0: logger.debug( "'%s - Season %d' is already marked as watched." % (showTitle, season)) return data['season'] = season data['episodes'] = episodes else: logger.debug( "Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utilities.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getShowDetailsFromKodi( dbid, ['year', 'imdbnumber']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', 'showtitle'] }, 'id': 0 }) if result and 'episodes' in result: i = 0 s = {} for e in result['episodes']: data['title'] = e['showtitle'] season = str(e['season']) if not season in s: s[season] = [] if e['playcount'] == 0: s[season].append(e['episode']) i += 1 if i == 0: logger.debug("'%s' is already marked as watched." % showTitle) return data['seasons'] = dict( (k, v) for k, v in s.iteritems() if v) else: logger.debug( "Error getting episode details for '%s' from Kodi." % showTitle) return if len(data) > 1: logger.debug( "Marking '%s' with the following data '%s' as watched on Trakt.tv" % (media_type, str(data))) data['action'] = 'markWatched' # execute toggle watched action xbmc.executebuiltin("Action(ToggleWatched)") elif args['action'] == 'addtowatchlist': media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utilities.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getMovieDetailsFromKodi( dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: data['id'] = result['imdbnumber'] else: logger.debug("Error getting movie details from Kodi.") return elif utilities.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getEpisodeDetailsFromKodi( dbid, [ 'showtitle', 'season', 'episode', 'tvshowid', 'playcount' ]) if result: data['id'] = result['imdbnumber'] data['season'] = result['season'] data['number'] = result['episode'] data['title'] = result['showtitle'] else: logger.debug("Error getting episode details from Kodi.") return elif utilities.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': { 'properties': ['title', 'imdbnumber', 'year'] }, 'id': 0 }) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] data['title'] = show['title'] break else: logger.debug("Error getting TV shows from Kodi.") return season = xbmc.getInfoLabel('ListItem.Season') if season == "": season = 0 else: season = int(season) result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) data['season'] = season data['episodes'] = episodes else: logger.debug( "Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utilities.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getShowDetailsFromKodi( dbid, ['year', 'imdbnumber']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = kodiUtilities.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', 'showtitle'] }, 'id': 0 }) if result and 'episodes' in result: s = {} for e in result['episodes']: data['title'] = e['showtitle'] season = str(e['season']) if not season in s: s[season] = [] if e['playcount'] == 0: s[season].append(e['episode']) data['seasons'] = dict( (k, v) for k, v in s.iteritems() if v) else: logger.debug( "Error getting episode details for '%s' from Kodi." % showTitle) return if len(data) > 1: logger.debug( "Adding '%s' with the following data '%s' to users watchlist on Trakt.tv" % (media_type, str(data))) data['action'] = 'addtowatchlist' q = sqlitequeue.SqliteQueue() if 'action' in data: logger.debug("Queuing for dispatch: %s" % data) q.append(data)
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 __get_episode_info(self): """Provides information about episode Returns: [dict]: media information """ tvdbid = False tmdbid = False tvdbepid = False logstr = "" try: tvshow = kodiUtilities.getEpisodeDetailsFromKodi( self.media_id, [ "tvshowid", "showtitle", "season", "episode", "uniqueid", "playcount", ], ) if "uniqueid" in tvshow: if "tvdb" in tvshow["uniqueid"]: tvdbepid = tvshow["uniqueid"]["tvdb"] elif "imdb" in tvshow["uniqueid"]: tvdbepid = tvshow["uniqueid"]["imdb"] elif "tmdb" in tvshow["uniqueid"]: tmdbid = tvshow["uniqueid"]["tmdb"] elif "unknown" in tvshow["uniqueid"]: # suppose to be tvdbid !!! tvdbepid = tvshow["uniqueid"]["unknown"] if tvdbepid: if (tvdbepid).startswith("tt"): tvdbepid = False showtitle = tvshow["showtitle"] epname = str(tvshow["season"]) + "x" + str(tvshow["episode"]) logstr += f"Id: {self.media_id} Title: {tvshow['showtitle']} tvshowid: {tvshow['tvshowid']} tvdbepid: {tvdbepid}" except Exception as e: logger.error(f"getEpisodeDetailsFromKodi error for {self.media_id} : {e}") return None if tvshow["tvshowid"] != -1: try: tvdbid_query = kodiUtilities.getShowDetailsFromKodi( tvshow["tvshowid"], ["imdbnumber", "uniqueid"] ) if "uniqueid" in tvdbid_query: if "tvdb" in tvdbid_query["uniqueid"]: tvdbid = tvdbid_query["uniqueid"]["tvdb"] elif "imdb" in tvdbid_query["uniqueid"]: tvdbid = tvdbid_query["uniqueid"]["imdb"] else: tvdbid = tvdbid_query["imdbnumber"] else: tvdbid = tvdbid_query["imdbnumber"] if tvdbid: logstr += f"\ntvdbid: {tvdbid}" if tmdbid: logstr += f"\ntmdbid: {tmdbid}" except Exception: logger.info(logstr) tvdbid = False logger.error( f"could not get tvshow/episode details for {self.media_id}" ) # si imbd_id, convert to thetvdb_id if tvdbid: # logger.info('tvdbid: %s' % ( tvdbid) ) if (tvdbid).startswith("tt"): tvdbid = globals.betaseriesapi.tvdbidFromimbd(tvdbid, logstr) if not tvdbid: # if tvdbepid, convert to thetvdb_id if tvdbepid: tvdbid = globals.betaseriesapi.tvdbidFromtvdbepid( tvdbepid, showtitle, logstr ) # si aucun tvdbid, chercher avec le Titre !!! if not tvdbid: tvdbid = globals.betaseriesapi.tvdbidFromTitle(showtitle, logstr) if tvdbid: # logger.info("found tvdbid "+ str(tvdbid ) +" for " + showtitle ) logstr += f"\nBS tvdbid from title: {tvdbid}" else: logger.error( "could not fetch tvshow's thetvdb_id from title for " + showtitle ) return None follow = globals.betaseriesapi.followFromtvdbid(tvdbid, showtitle, logstr) if not tvdbepid: tvdbepid = globals.betaseriesapi.tvdbepidFromtvdbid( tvdbid, showtitle, tvshow["season"], tvshow["episode"], logstr ) if not tvdbepid: return None seen = False dl = False if tvshow["playcount"] < 1 and follow: try: seen_query = globals.betaseriesapi.tvdbInfFromtvdbepid( tvdbepid, showtitle, logstr ) seen = seen_query["user"]["seen"] dl = seen_query["user"]["downloaded"] logstr += f" dl status: {dl} seen status: {seen}" except Exception as e: logger.info(logstr) logger.warning(f"failed to get status for {showtitle} - {epname} : {e}") logger.debug(logstr) epinfo = { "int_id": int(tvdbid), "remote_id": int(tvdbepid), "playcount": int(self.playcount), "playstatus": bool(self.playstatus), "showtitle": showtitle, "title": epname, "type": "episode", "tvshow_playcount": tvshow["playcount"], "followed": bool(follow), "downloaded": bool(dl), "seen": bool(seen), } return epinfo
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)
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.playlistIndex == l: self.watchedTime = t else: logger.debug("Current playlist item changed! Not updating time! (%d -> %d)" % (self.playlistIndex, l)) if 'id' in self.curVideo and self.isMultiPartEpisode: # do transition check every minute if (time.time() > (self.lastMPCheck + 60)) or isSeek: self.lastMPCheck = time.time() watchedPercent = self.__calculateWatchedPercent() 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 isSeek: self.__scrobble('start')
def ScanBSMarkedEpisode(self): """Do self.action on recently added media in kodi based on lastdate treatment""" f = __addon__.getAddonInfo("path") + "/lastdate.tmp" try: with open(f, "r") as fic: lastdate = fic.read() except Exception: lastdate = "2001-01-01 00:00:00" newdate = lastdate new = False counter = 0 # cree table de tous les episodes result_episodes = kodiUtilities.getEpisodesFromKodi() if "episodes" in result_episodes: logger.debug( "Start scanning BS for viewed episode and compare with Kodi database" ) for media in result_episodes["episodes"]: # web_pdb.set_trace() ep_id = media["episodeid"] seen = False try: tvshow = kodiUtilities.getEpisodeDetailsFromKodi( ep_id, ["dateadded", "playcount"]) if tvshow["playcount"] > 0: seen = True except Exception as e: logger.error( f"getEpisodeDetailsFromKodi error for {ep_id} : {e}") # passe au suivant si erreur continue if tvshow["dateadded"] > lastdate: new = True if tvshow["dateadded"] > newdate: newdate = tvshow["dateadded"] # 0101 voir pour l'interet de not seen if new: # or not seen: # si pas vu, regarder sur BS si marque episode = Media(ep_id, -1, self.Play).get_media_info("episode") if episode: if seen: episode["playcount"] = 1 # follow ? # downloaded ? if not episode["followed"] or not episode["downloaded"]: self.action(episode, self.service) if episode["tvshow_playcount"] < 1 and episode["seen"]: result = kodiUtilities.setEpisodeDetailsOnKodi( ep_id, {"playcount": 1}) logger.info( f"info :{episode['showtitle']},{episode['title']}" ) if result == "OK": # logger.info(result,) logger.info( "episode marked watched or downloaded on BetaSeries.com", ) counter += 1 else: logger.error( "error: failed to mark watched or downloaded on Betaseries.com", ) if counter > 0: notification(getString(32010), getString(30021, str(counter))) else: logger.info("Scan finished, all episodes updated") with open(f, "w") as fic: fic.write(newdate)
def run(): args = __getArguments() data = {} if args['action'] == 'auth_info': data['action'] = 'auth_info' if args['action'] == 'contextmenu': buttons = [] media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: buttons.append("rate") buttons.append("togglewatched") buttons.append("addtowatchlist") buttons.append("sync") contextMenu = traktContextMenu(media_type=media_type, buttons=buttons) contextMenu.doModal() _action = contextMenu.action del contextMenu if _action is None: return logger.debug("'%s' selected from trakt.tv action menu" % _action) args['action'] = _action if args['action'] == 'sync': data = {'action': 'manualSync', 'silent': False} if 'silent' in args: data['silent'] = (args['silent'].lower() == 'true') data['library'] = "all" if 'library' in args and args['library'] in ['episodes', 'movies']: data['library'] = args['library'] elif args['action'] in ['rate', 'unrate']: data = {'action': args['action']} media_type = None if 'media_type' in args and 'dbid' in args: media_type = args['media_type'] try: data['dbid'] = int(args['dbid']) except ValueError: logger.debug("Manual %s triggered for library item, but DBID is invalid." % args['action']) return elif 'media_type' in args and 'remoteid' in args: media_type = args['media_type'] data['remoteid'] = args['remoteid'] try: data['season'] = int(args['season']) data['episode'] = int(args['episode']) except ValueError: logger.debug("Error parsing season or episode for manual %s" % args['action']) return except KeyError: pass else: media_type = kodiUtilities.getMediaType() if not utilities.isValidMediaType(media_type): logger.debug("Error, not in video library.") return data['dbid'] = int(xbmc.getInfoLabel('ListItem.DBID')) if media_type is None: logger.debug("Manual %s triggered on an unsupported content container." % args['action']) elif utilities.isValidMediaType(media_type): data['media_type'] = media_type if 'dbid' in data: logger.debug("Manual %s of library '%s' with an ID of '%s'." % (args['action'], media_type, data['dbid'])) if utilities.isMovie(media_type): result = kodiUtilities.getMovieDetailsFromKodi(data['dbid'], ['imdbnumber', 'uniqueid', 'title', 'year']) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args['action']) return elif utilities.isShow(media_type): tvshow_id = data['dbid'] elif utilities.isSeason(media_type): result = kodiUtilities.getSeasonDetailsFromKodi(data['dbid'], ['tvshowid', 'season']) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args['action']) return tvshow_id = result['tvshowid'] data['season'] = result['season'] elif utilities.isEpisode(media_type): result = kodiUtilities.getEpisodeDetailsFromKodi(data['dbid'], ['season', 'episode', 'tvshowid']) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args['action']) return tvshow_id = result['tvshowid'] data['season'] = result['season'] data['episode'] = result['episode'] if utilities.isShow(media_type) or utilities.isSeason(media_type) or utilities.isEpisode(media_type): result = kodiUtilities.getShowDetailsFromKodi(tvshow_id, ['imdbnumber', 'uniqueid']) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args['action']) return data['video_id'] = result['imdbnumber'] else: data['video_id'] = data['remoteid'] if 'season' in data and 'episode' in data: logger.debug("Manual %s of non-library '%s' S%02dE%02d, with an ID of '%s'." % (args['action'], media_type, data['season'], data['episode'], data['remoteid'])) elif 'season' in data: logger.debug("Manual %s of non-library '%s' S%02d, with an ID of '%s'." % (args['action'], media_type, data['season'], data['remoteid'])) else: logger.debug("Manual %s of non-library '%s' with an ID of '%s'." % (args['action'], media_type, data['remoteid'])) if args['action'] == 'rate' and 'rating' in args: if args['rating'] in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']: data['rating'] = int(args['rating']) data = {'action': 'manualRating', 'ratingData': data} else: logger.debug("Manual %s of '%s' is unsupported." % (args['action'], media_type)) elif args['action'] == 'togglewatched': media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utilities.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getMovieDetailsFromKodi(dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] else: logger.debug("Movie alread marked as watched in Kodi.") else: logger.debug("Error getting movie details from Kodi.") return elif utilities.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getEpisodeDetailsFromKodi(dbid, ['showtitle', 'season', 'episode', 'tvshowid', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] data['season'] = result['season'] data['number'] = result['episode'] data['title'] = result['showtitle'] else: logger.debug("Episode already marked as watched in Kodi.") else: logger.debug("Error getting episode details from Kodi.") return elif utilities.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': {'properties': ['title', 'imdbnumber', 'year']}, 'id': 0}) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] data['title'] = show['title'] break else: logger.debug("Error getting TV shows from Kodi.") return season = xbmc.getInfoLabel('ListItem.Season') if season == "": season = 0 else: season = int(season) result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount']}, 'id': 0}) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) if len(episodes) == 0: logger.debug("'%s - Season %d' is already marked as watched." % (showTitle, season)) return data['season'] = season data['episodes'] = episodes else: logger.debug("Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utilities.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber', 'uniqueid']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', 'showtitle']}, 'id': 0}) if result and 'episodes' in result: i = 0 s = {} for e in result['episodes']: data['title'] = e['showtitle'] season = str(e['season']) if not season in s: s[season] = [] if e['playcount'] == 0: s[season].append(e['episode']) i += 1 if i == 0: logger.debug("'%s' is already marked as watched." % showTitle) return data['seasons'] = dict((k, v) for k, v in list(s.items()) if v) else: logger.debug("Error getting episode details for '%s' from Kodi." % showTitle) return if len(data) > 1: logger.debug("Marking '%s' with the following data '%s' as watched on Trakt.tv" % (media_type, str(data))) data['action'] = 'markWatched' # execute toggle watched action xbmc.executebuiltin("Action(ToggleWatched)") elif args['action'] == 'addtowatchlist': media_type = kodiUtilities.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utilities.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getMovieDetailsFromKodi(dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: data['id'] = result['imdbnumber'] else: logger.debug("Error getting movie details from Kodi.") return elif utilities.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getEpisodeDetailsFromKodi(dbid, ['showtitle', 'season', 'episode', 'tvshowid', 'playcount']) if result: data['id'] = result['imdbnumber'] data['season'] = result['season'] data['number'] = result['episode'] data['title'] = result['showtitle'] else: logger.debug("Error getting episode details from Kodi.") return elif utilities.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': {'properties': ['title', 'imdbnumber', 'year']}, 'id': 0}) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] data['title'] = show['title'] break else: logger.debug("Error getting TV shows from Kodi.") return season = xbmc.getInfoLabel('ListItem.Season') if season == "": season = 0 else: season = int(season) result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount']}, 'id': 0}) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) data['season'] = season data['episodes'] = episodes else: logger.debug("Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utilities.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = kodiUtilities.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber', 'uniqueid']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = kodiUtilities.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', 'showtitle']}, 'id': 0}) if result and 'episodes' in result: s = {} for e in result['episodes']: data['title'] = e['showtitle'] season = str(e['season']) if not season in s: s[season] = [] if e['playcount'] == 0: s[season].append(e['episode']) data['seasons'] = dict((k, v) for k, v in list(s.items()) if v) else: logger.debug("Error getting episode details for '%s' from Kodi." % showTitle) return if len(data) > 1: logger.debug("Adding '%s' with the following data '%s' to users watchlist on Trakt.tv" % (media_type, str(data))) data['action'] = 'addtowatchlist' q = sqlitequeue.SqliteQueue() if 'action' in data: logger.debug("Queuing for dispatch: %s" % data) q.append(data)