def update(self, forceCheck=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: Debug( "[Scrobbler] 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 forceCheck: self.lastMPCheck = time.time() watchedPercent = (self.watchedTime / self.videoDuration) * 100 epIndex = self._currentEpisode( watchedPercent, self.curVideo['multi_episode_count']) if self.curMPEpisode != epIndex: # current episode in multi-part episode has changed Debug( "[Scrobbler] Attempting to scrobble episode part %d of %d." % (self.curMPEpisode + 1, self.curVideo['multi_episode_count'])) # recalculate watchedPercent and duration for multi-part, and scrobble adjustedDuration = int( self.videoDuration / self.curVideo['multi_episode_count']) watchedPercent = ( (self.watchedTime - (adjustedDuration * self.curMPEpisode)) / adjustedDuration) * 100 response = self.traktapi.scrobbleEpisode( self.traktShowSummary, self.traktSummaryInfo, watchedPercent) if response != None: Debug("[Scrobbler] Scrobble response: %s" % str(response)) # update current information self.curMPEpisode = epIndex self.curVideoInfo = utilities.getEpisodeDetailsFromKodi( self.curVideo['multi_episode_data'] [self.curMPEpisode], [ 'showtitle', 'season', 'episode', 'tvshowid', 'uniqueid' ])
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 = utilities.kodiRpcToTraktMediaObject( 'episode', utilities.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 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 = utilities.kodiRpcToTraktMediaObject( "episode", utilities.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 update(self, forceCheck = 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 forceCheck: self.lastMPCheck = time.time() watchedPercent = self.__calculateWatchedPercent() epIndex = self._currentEpisode(watchedPercent, self.curVideo['multi_episode_count']) if self.curMPEpisode != epIndex: # current episode in multi-part episode has changed logger.debug("Attempting to stop scrobble episode part %d of %d." % (self.curMPEpisode + 1, self.curVideo['multi_episode_count'])) # recalculate watchedPercent and duration for multi-part, and scrobble adjustedDuration = int(self.videoDuration / self.curVideo['multi_episode_count']) watchedPercent = ((self.watchedTime - (adjustedDuration * self.curMPEpisode)) / adjustedDuration) * 100 response = self.traktapi.scrobbleEpisode(self.traktShowSummary, self.curVideoInfo, watchedPercent, 'stop') if response is not None: logger.debug("Scrobble response: %s" % str(response)) # update current information self.curMPEpisode = epIndex self.curVideoInfo = utilities.kodiRpcToTraktMediaObject('episode', utilities.getEpisodeDetailsFromKodi(self.curVideo['multi_episode_data'][self.curMPEpisode], ['showtitle', 'season', 'episode', 'tvshowid', 'uniqueid', 'file', 'playcount'])) if not forceCheck: logger.debug("Attempting to start scrobble episode part %d of %d." % (self.curMPEpisode + 1, self.curVideo['multi_episode_count'])) response = self.traktapi.scrobbleEpisode(self.traktShowSummary, self.curVideoInfo, 0, 'start') if response is not None: logger.debug("Scrobble response: %s" % str(response))
def playbackStarted(self, data): logger.debug("playbackStarted(data: %s)" % data) if not data: return self.curVideo = data self.curVideoInfo = None self.videosToRate = [] if ( not utilities.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 = utilities.kodiRpcToTraktMediaObject( "movie", utilities.getMovieDetailsFromKodi( self.curVideo["id"], ["imdbnumber", "title", "year", "file", "lastplayed", "playcount"] ), ) elif "video_ids" in self.curVideo: self.curVideoInfo = {"ids": self.curVideo["video_ids"]} elif "title" in self.curVideo and "year" in self.curVideo: self.curVideoInfo = {"title": self.curVideo["title"], "year": self.curVideo["year"]} elif utilities.isEpisode(self.curVideo["type"]): if "id" in self.curVideo: episodeDetailsKodi = utilities.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 = utilities.kodiRpcToTraktMediaObject("episode", episodeDetailsKodi) if not self.curVideoInfo: # getEpisodeDetailsFromKodi was empty logger.debug( "Episode details from Kodi was empty, ID (%d) seems invalid, aborting further scrobbling of this episode." % self.curVideo["id"] ) self.curVideo = None self.isPlaying = False self.watchedTime = 0 return elif "video_ids" in self.curVideo and "season" in self.curVideo and "episode" in self.curVideo: self.curVideoInfo = {"season": self.curVideo["season"], "number": self.curVideo["episode"]} self.traktShowSummary = {"ids": self.curVideo["video_ids"]} elif "title" in self.curVideo and "season" in self.curVideo and "episode" in self.curVideo: self.curVideoInfo = { "title": self.curVideo["title"], "season": self.curVideo["season"], "number": self.curVideo["episode"], } title, year = utilities.regex_year(self.curVideo["showtitle"]) if not year: self.traktShowSummary = {"title": self.curVideo["showtitle"]} else: self.traktShowSummary = {"title": title, "year": year} if "year" in self.curVideo: self.traktShowSummary["year"] = self.curVideo["year"] if "multi_episode_count" in self.curVideo and self.curVideo["multi_episode_count"] > 1: self.isMultiPartEpisode = True self.isPlaying = True self.isPaused = False result = {} if utilities.getSettingAsBool("scrobble_movie") or utilities.getSettingAsBool("scrobble_episode"): result = self.__scrobble("start") elif ( utilities.getSettingAsBool("rate_movie") and utilities.isMovie(self.curVideo["type"]) and "ids" in self.curVideoInfo ): result = {"movie": self.traktapi.getMovieSummary(utilities.best_id(self.curVideoInfo["ids"])).to_dict()} elif ( utilities.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"] self.__preFetchUserRatings(result)
def playbackStarted(self, data): logger.debug("playbackStarted(data: %s)" % data) if not data: return self.curVideo = data self.curVideoInfo = None self.videosToRate = [] if not utilities.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 = utilities.kodiRpcToTraktMediaObject('movie', utilities.getMovieDetailsFromKodi(self.curVideo['id'], ['imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount'])) elif 'video_ids' in self.curVideo: self.curVideoInfo = {'ids': self.curVideo['video_ids']} elif 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'year': self.curVideo['year']} elif utilities.isEpisode(self.curVideo['type']): if 'id' in self.curVideo: episodeDetailsKodi = utilities.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 = utilities.kodiRpcToTraktMediaObject('episode', episodeDetailsKodi) if not self.curVideoInfo: # getEpisodeDetailsFromKodi was empty logger.debug("Episode details from Kodi was empty, ID (%d) seems invalid, aborting further scrobbling of this episode." % self.curVideo['id']) self.curVideo = None self.isPlaying = False self.watchedTime = 0 return elif 'video_ids' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = {'season': self.curVideo['season'], 'number': self.curVideo['episode']} self.traktShowSummary = {'ids': self.curVideo['video_ids']} elif 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'season': self.curVideo['season'], 'number': self.curVideo['episode']} title, year = utilities.regex_year(self.curVideo['showtitle']) if not year: self.traktShowSummary = {'title': self.curVideo['showtitle']} else: self.traktShowSummary = {'title': title, 'year': year} if 'year' in self.curVideo: self.traktShowSummary['year'] = self.curVideo['year'] if 'multi_episode_count' in self.curVideo and self.curVideo['multi_episode_count'] > 1: self.isMultiPartEpisode = True self.isPlaying = True self.isPaused = False result = {} if utilities.getSettingAsBool('scrobble_movie') or utilities.getSettingAsBool('scrobble_episode'): result = self.__scrobble('start') elif utilities.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()} if 'id' in self.curVideo: result['movie']['movieid'] = self.curVideo['id'] elif utilities.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: result['episode']['episodeid'] = self.curVideo['id'] self.__preFetchUserRatings(result)
def Main(): args = __getArguments() data = {} if args["action"] == "pin_info": xbmc.executebuiltin("Dialog.Close(all, true)") pinInfo = xbmcgui.WindowXMLDialog("PinInfoWindow.xml", __addon__.getAddonInfo("path")) pinInfo.doModal() del pinInfo if args["action"] == "contextmenu": buttons = [] media_type = __getMediaType() if media_type in ["movie", "show", "season", "episode"]: buttons.append("rate") if media_type in ["movie", "show", "season", "episode"]: buttons.append("togglewatched") 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 = __getMediaType() if not utils.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 utils.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 utils.isMovie(media_type): result = utils.getMovieDetailsFromKodi(data["dbid"], ["imdbnumber", "title", "year"]) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args["action"]) return data["imdbnumber"] = result["imdbnumber"] elif utils.isShow(media_type) or utils.isSeason(media_type): result = utils.getShowDetailsFromKodi(data["dbid"], ["imdbnumber", "tag"]) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args["action"]) return data["imdbnumber"] = result["imdbnumber"] data["tag"] = result["tag"] elif utils.isEpisode(media_type): result = utils.getEpisodeDetailsFromKodi( data["dbid"], ["showtitle", "season", "episode", "tvshowid", "uniqueid", "file", "playcount"] ) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args["action"]) return data["imdbnumber"] = result["episodeid"] data["season"] = result["season"] data["episode"] = result["episode"] else: data["imdbnumber"] = 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 = __getMediaType() if media_type in ["movie", "show", "season", "episode"]: data = {"media_type": media_type} if utils.isMovie(media_type): dbid = int(xbmc.getInfoLabel("ListItem.DBID")) result = utils.getMovieDetailsFromKodi(dbid, ["imdbnumber", "title", "year", "playcount"]) if result: if result["playcount"] == 0: data["id"] = result["imdbnumber"] else: logger.debug("Movie alread marked as watched in Kodi.") else: logger.debug("Error getting movie details from Kodi.") return elif utils.isEpisode(media_type): dbid = int(xbmc.getInfoLabel("ListItem.DBID")) result = utils.getEpisodeDetailsFromKodi( dbid, ["showtitle", "season", "episode", "tvshowid", "playcount"] ) if result: if result["playcount"] == 0: data["id"] = result["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 utils.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel("ListItem.TVShowTitle") result = utils.kodiJsonRequest( { "jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties": ["title", "imdbnumber", "year"]}, "id": 0, } ) if result and "tvshows" in result: for show in result["tvshows"]: if show["title"] == showTitle: showID = show["tvshowid"] data["id"] = show["imdbnumber"] 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 = utils.kodiJsonRequest( { "jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": { "tvshowid": showID, "season": season, "properties": ["season", "episode", "playcount"], }, "id": 0, } ) if result and "episodes" in result: episodes = [] for episode in result["episodes"]: if episode["playcount"] == 0: episodes.append(episode["episode"]) if len(episodes) == 0: 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 utils.isShow(media_type): dbid = int(xbmc.getInfoLabel("ListItem.DBID")) result = utils.getShowDetailsFromKodi(dbid, ["year", "imdbnumber"]) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result["label"] data["id"] = result["imdbnumber"] result = utils.kodiJsonRequest( { "jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": dbid, "properties": ["season", "episode", "playcount", "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)") 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 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 = utilities.kodiRpcToTraktMediaObject('movie', utilities.getMovieDetailsFromKodi(self.curVideo['id'], ['imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount'])) elif 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'year': self.curVideo['year']} elif utilities.isEpisode(self.curVideo['type']): if 'id' in self.curVideo: episodeDetailsKodi = utilities.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 = utilities.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 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'season': self.curVideo['season'], 'number': self.curVideo['episode']} title, year = utilities.regex_year(self.curVideo['showtitle']) if not year: self.traktShowSummary = {'title': self.curVideo['showtitle']} else: self.traktShowSummary = {'title': title, 'year': year} if 'year' in self.curVideo: self.traktShowSummary['year'] = self.curVideo['year'] if 'multi_episode_count' in self.curVideo: self.isMultiPartEpisode = True self.isPlaying = True self.isPaused = False result = self.__scrobble('start') if result: if utilities.isMovie(self.curVideo['type']) and utilities.getSettingAsBool('rate_movie'): # pre-get sumamry information, for faster rating dialog. logger.debug("Movie rating is enabled, pre-fetching summary information.") if result['movie']['ids']['imdb']: self.curVideoInfo['user'] = {'ratings': self.traktapi.getMovieRatingForUser(result['movie']['ids']['imdb'])} self.curVideoInfo['ids'] = result['movie']['ids'] else: logger.debug("'%s (%d)' has no valid id, can't get rating." % (self.curVideoInfo['title'], self.curVideoInfo['year'])) elif utilities.isEpisode(self.curVideo['type']) and utilities.getSettingAsBool('rate_episode'): # pre-get sumamry information, for faster rating dialog. logger.debug("Episode rating is enabled, pre-fetching summary information.") if result['show']['ids']['tvdb']: self.curVideoInfo['user'] = {'ratings' : self.traktapi.getEpisodeRatingForUser(result['show']['ids']['tvdb'], self.curVideoInfo['season'], self.curVideoInfo['number'])} self.curVideoInfo['ids'] = result['episode']['ids'] else: logger.debug("'%s - S%02dE%02d' has no valid id, can't get rating." % (self.curVideoInfo['showtitle'], self.curVideoInfo['season'], self.curVideoInfo['episode']))
def playbackStarted(self, data): logger.debug("playbackStarted(data: %s)" % data) if not data: return self.curVideo = data self.curVideoInfo = None self.videosToRate = [] if not utilities.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 = utilities.kodiRpcToTraktMediaObject('movie', utilities.getMovieDetailsFromKodi(self.curVideo['id'], ['imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount'])) elif 'video_ids' in self.curVideo: self.curVideoInfo = {'ids': self.curVideo['video_ids'], 'title': self.curVideo['title'], 'year': self.curVideo['year']} elif 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'year': self.curVideo['year']} elif utilities.isEpisode(self.curVideo['type']): if 'id' in self.curVideo: episodeDetailsKodi = utilities.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 = utilities.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 = {'title': self.curVideo['title'], 'season': self.curVideo['season'], 'number': self.curVideo['episode']} self.traktShowSummary = {'ids': self.curVideo['video_ids']} elif 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = {'title': self.curVideo['title'], 'season': self.curVideo['season'], 'number': self.curVideo['episode']} title, year = utilities.regex_year(self.curVideo['showtitle']) if not year: self.traktShowSummary = {'title': self.curVideo['showtitle']} else: self.traktShowSummary = {'title': title, 'year': year} if 'year' in self.curVideo: self.traktShowSummary['year'] = self.curVideo['year'] if 'multi_episode_count' in self.curVideo and self.curVideo['multi_episode_count'] > 1: self.isMultiPartEpisode = True self.isPlaying = True self.isPaused = False result = {} if utilities.getSettingAsBool('scrobble_movie') or utilities.getSettingAsBool('scrobble_episode'): result = self.__scrobble('start') elif utilities.getSettingAsBool('rate_movie') and utilities.isMovie(self.curVideo['type']) and 'ids' in self.curVideoInfo: result = {'movie': self.traktapi.getMovieSummary(utilities.best_id(self.curVideoInfo['ids'])).to_dict()} elif utilities.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()} self.__preFetchUserRatings(result)
def Main(): args = __getArguments() data = {} if args['action'] == 'pin_info': xbmc.executebuiltin( 'Dialog.Close(all, true)' ) #FIXME stupid hack we need to do as the AddonInfo dialog won't go away xbmc.executebuiltin('Dialog.Close(all, true)') gui_utils.get_pin() if args['action'] == 'contextmenu': buttons = [] media_type = utils.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 = utils.getMediaType() if not utils.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 utils.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 utils.isMovie(media_type): result = utils.getMovieDetailsFromKodi( data['dbid'], ['imdbnumber', 'title', 'year']) if not result: logger.debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return elif utils.isShow(media_type): tvshow_id = data['dbid'] elif utils.isSeason(media_type): result = utils.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 utils.isEpisode(media_type): result = utils.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 utils.isShow(media_type) or utils.isSeason( media_type) or utils.isEpisode(media_type): result = utils.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 = utils.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utils.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getMovieDetailsFromKodi( dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] else: logger.debug("Movie alread marked as watched in Kodi.") else: logger.debug("Error getting movie details from Kodi.") return elif utils.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getEpisodeDetailsFromKodi( dbid, [ 'showtitle', 'season', 'episode', 'tvshowid', 'playcount' ]) if result: if result['playcount'] == 0: data['id'] = result['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 utils.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': { 'properties': ['title', 'imdbnumber', 'year'] }, 'id': 0 }) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] 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 = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) if len(episodes) == 0: 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 utils.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', '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 = utils.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utils.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getMovieDetailsFromKodi( dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: data['id'] = result['imdbnumber'] else: logger.debug("Error getting movie details from Kodi.") return elif utils.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getEpisodeDetailsFromKodi( dbid, [ 'showtitle', 'season', 'episode', 'tvshowid', 'playcount' ]) if result: 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 utils.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': { 'properties': ['title', 'imdbnumber', 'year'] }, 'id': 0 }) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] 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 = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) data['season'] = season data['episodes'] = episodes else: logger.debug( "Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utils.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', '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 Main(): args = __getArguments() data = {} if args['action'] == 'pin_info': xbmc.executebuiltin('Dialog.Close(all, true)') gui_utils.get_pin() if args['action'] == 'contextmenu': buttons = [] media_type = utils.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: buttons.append("rate") if media_type in ['movie', 'show', 'season', 'episode']: buttons.append("togglewatched") 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 = utils.getMediaType() if not utils.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 utils.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 utils.isMovie(media_type): result = utils.getMovieDetailsFromKodi(data['dbid'], ['imdbnumber', 'title', 'year']) if not result: logger.debug("No data was returned from Kodi, aborting manual %s." % args['action']) return elif utils.isShow(media_type): tvshow_id = data['dbid'] elif utils.isSeason(media_type): result = utils.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 utils.isEpisode(media_type): result = utils.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 utils.isShow(media_type) or utils.isSeason(media_type) or utils.isEpisode(media_type): result = utils.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 = utils.getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utils.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getMovieDetailsFromKodi(dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] else: logger.debug("Movie alread marked as watched in Kodi.") else: logger.debug("Error getting movie details from Kodi.") return elif utils.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getEpisodeDetailsFromKodi(dbid, ['showtitle', 'season', 'episode', 'tvshowid', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['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 utils.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = utils.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': {'properties': ['title', 'imdbnumber', 'year']}, 'id': 0}) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] 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 = utils.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount']}, 'id': 0}) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) if len(episodes) == 0: 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 utils.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber']) if not result: logger.debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = utils.kodiJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': {'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount', '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)") q = sqlitequeue.SqliteQueue() if 'action' in data: logger.debug("Queuing for dispatch: %s" % data) q.append(data)
def playbackStarted(self, data): Debug("[Scrobbler] playbackStarted(data: %s)" % data) if not data: return self.curVideo = data self.curVideoInfo = None if 'type' in self.curVideo: Debug("[Scrobbler] Watching: %s" % self.curVideo['type']) if not xbmc.Player().isPlayingVideo(): Debug("[Scrobbler] 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: Debug("[Scrobbler] 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): Debug( "[Scrobbler] Warning: Cant find playlist length, assuming that this item is by itself" ) self.playlistLength = 1 self.traktSummaryInfo = None self.isMultiPartEpisode = False if utilities.isMovie(self.curVideo['type']): if 'id' in self.curVideo: self.curVideoInfo = utilities.kodiRpcToTraktMediaObject( 'movie', utilities.getMovieDetailsFromKodi( self.curVideo['id'], [ 'imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount' ])) Debug("Trakt ticket: %s" % self.curVideo) if utilities.getSettingAsBool('rate_movie'): # pre-get sumamry information, for faster rating dialog. Debug( "[Scrobbler] Movie rating is enabled, pre-fetching summary information." ) if self.curVideoInfo['ids']['imdb']: self.traktSummaryInfo = self.traktapi.getMovieSummary( self.curVideoInfo['ids']['imdb']) elif self.curVideoInfo['ids']['tmdb']: self.traktSummaryInfo = self.traktapi.getMovieSummary( self.curVideoInfo['ids']['tmdb']) else: self.curVideoInfo['ids']['imdb'] = None Debug( "[Scrobbler] Can not get summary information for '%s (%d)' as is has no valid id, will retry during a watching call." % (self.curVideoInfo['title'], self.curVideoInfo['year'])) elif 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = {'ids': {}} self.curVideoInfo['ids']['imdb'] = None self.curVideoInfo['title'] = self.curVideo['title'] self.curVideoInfo['year'] = self.curVideo['year'] elif utilities.isEpisode(self.curVideo['type']): if 'id' in self.curVideo: episodeDetailsKodi = utilities.getEpisodeDetailsFromKodi( self.curVideo['id'], [ 'showtitle', 'season', 'episode', 'tvshowid', 'uniqueid', 'file', 'playcount' ]) tvdb = episodeDetailsKodi['imdbnumber'] self.curVideoInfo = utilities.kodiRpcToTraktMediaObject( 'episode', episodeDetailsKodi) if not self.curVideoInfo: # getEpisodeDetailsFromKodi was empty Debug( "[Scrobbler] 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 if utilities.getSettingAsBool('rate_episode'): # pre-get sumamry information, for faster rating dialog. Debug( "[Scrobbler] Episode rating is enabled, pre-fetching summary information." ) if tvdb: lookupShow = self.traktapi.getIdLookup( 'tvdb', tvdb) self.traktShowSummary = self.traktapi.getShowSummary( lookupShow['ids']['slug']) self.traktSummaryInfo = self.traktapi.getEpisodeSummary( lookupShow['ids'], self.curVideoInfo['season'], self.curVideoInfo['number']) else: Debug( "[Scrobbler] Can not get summary information for '%s - S%02dE%02d' as it has no valid id, will retry during a watching call." % (self.curVideoInfo['showtitle'], self.curVideoInfo['season'], self.curVideoInfo['episode'])) else: self.traktShowSummary = { 'title': episodeDetailsKodi['showtitle'] } self.traktShowSummary['ids'] = {'tvdb': tvdb} elif 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = {'tvdb_id': None} self.curVideoInfo['title'] = self.curVideo['title'] self.curVideoInfo['season'] = self.curVideo['season'] self.curVideoInfo['number'] = self.curVideo['episode'] self.traktShowSummary = { 'title': self.curVideo['showtitle'] } if 'year' in self.curVideo: self.traktShowSummary['year'] = self.curVideo['year'] if 'multi_episode_count' in self.curVideo: self.isMultiPartEpisode = True self.markedAsWatched = [] episode_count = self.curVideo['multi_episode_count'] for i in range(episode_count): self.markedAsWatched.append(False) self.isPlaying = True self.isPaused = False self.__scrobble('start')
def Main(): args = __getArguments() data = {} if args['action'] == 'sync': data = {'action': 'manualSync', 'silent': False} if 'silent' in args: data['silent'] = (args['silent'].lower() == 'true') data['library'] = "all" if 'library' in args and args['library'] in ['episodes', 'movies']: data['library'] = args['library'] elif args['action'] in ['rate', 'unrate']: data = {'action': args['action']} media_type = None if 'media_type' in args and 'dbid' in args: media_type = args['media_type'] try: data['dbid'] = int(args['dbid']) except ValueError: utils.Debug( "Manual %s triggered for library item, but DBID is invalid." % args['action']) return elif 'media_type' in args and 'remoteid' in args: media_type = args['media_type'] data['remoteid'] = args['remoteid'] if 'season' in args: if not 'episode' in args: utils.Debug( "Manual %s triggered for non-library episode, but missing episode number." % args['action']) return try: data['season'] = int(args['season']) data['episode'] = int(args['episode']) except ValueError: utils.Debug( "Error parsing season or episode for manual %s" % args['action']) return else: media_type = __getMediaType() if not utils.isValidMediaType(media_type): utils.Debug("Error, not in video library.") return data['dbid'] = int(xbmc.getInfoLabel('ListItem.DBID')) if media_type is None: utils.Debug( "Manual %s triggered on an unsupported content container." % args['action']) elif utils.isValidMediaType(media_type): data['media_type'] = media_type if 'dbid' in data: utils.Debug("Manual %s of library '%s' with an ID of '%s'." % (args['action'], media_type, data['dbid'])) if utils.isMovie(media_type): result = utils.getMovieDetailsFromKodi( data['dbid'], ['imdbnumber', 'title', 'year']) if not result: utils.Debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return data['imdbnumber'] = result['imdbnumber'] elif utils.isShow(media_type): result = utils.getShowDetailsFromKodi( data['dbid'], ['imdbnumber', 'tag']) if not result: utils.Debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return data['imdbnumber'] = result['imdbnumber'] data['tag'] = result['tag'] elif utils.isEpisode(media_type): result = utils.getEpisodeDetailsFromKodi( data['dbid'], ['showtitle', 'season', 'episode', 'imdbnumber']) if not result: utils.Debug( "No data was returned from Kodi, aborting manual %s." % args['action']) return data['imdbnumber'] = result['imdbnumber'] data['season'] = result['season'] data['episode'] = result['episode'] else: if 'season' in data: utils.Debug( "Manual %s of non-library '%s' S%02dE%02d, with an ID of '%s'." % (args['action'], media_type, data['season'], data['episode'], data['remoteid'])) data['imdbnumber'] = data['remoteid'] else: utils.Debug( "Manual %s of non-library '%s' with an ID of '%s'." % (args['action'], media_type, data['remoteid'])) data['imdbnumber'] = data['remoteid'] if args['action'] == 'rate' and 'rating' in args: if args['rating'] in [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' ]: data['rating'] = int(args['rating']) data = {'action': 'manualRating', 'ratingData': data} else: utils.Debug("Manual %s of '%s' is unsupported." % (args['action'], media_type)) elif args['action'] == 'togglewatched': media_type = __getMediaType() if media_type in ['movie', 'show', 'season', 'episode']: data = {'media_type': media_type} if utils.isMovie(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getMovieDetailsFromKodi( dbid, ['imdbnumber', 'title', 'year', 'playcount']) if result: if result['playcount'] == 0: data['id'] = result['imdbnumber'] else: utils.Debug("Movie alread marked as watched in Kodi.") else: utils.Debug("Error getting movie details from Kodi.") return elif utils.isEpisode(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getEpisodeDetailsFromKodi( dbid, [ 'showtitle', 'season', 'episode', 'tvshowid', 'playcount' ]) if result: if result['playcount'] == 0: data['id'] = result['tvdb_id'] data['season'] = result['season'] data['episode'] = result['episode'] else: utils.Debug( "Episode already marked as watched in Kodi.") else: utils.Debug("Error getting episode details from Kodi.") return elif utils.isSeason(media_type): showID = None showTitle = xbmc.getInfoLabel('ListItem.TVShowTitle') result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': { 'properties': ['title', 'imdbnumber', 'year'] }, 'id': 0 }) if result and 'tvshows' in result: for show in result['tvshows']: if show['title'] == showTitle: showID = show['tvshowid'] data['id'] = show['imdbnumber'] break else: utils.Debug("Error getting TV shows from Kodi.") return season = xbmc.getInfoLabel('ListItem.Season') if season == "": season = 0 else: season = int(season) result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': showID, 'season': season, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: episodes = [] for episode in result['episodes']: if episode['playcount'] == 0: episodes.append(episode['episode']) if len(episodes) == 0: utils.Debug( "'%s - Season %d' is already marked as watched." % (showTitle, season)) return data['season'] = season data['episodes'] = episodes else: utils.Debug( "Error getting episodes from '%s' for Season %d" % (showTitle, season)) return elif utils.isShow(media_type): dbid = int(xbmc.getInfoLabel('ListItem.DBID')) result = utils.getShowDetailsFromKodi(dbid, ['year', 'imdbnumber']) if not result: utils.Debug("Error getting show details from Kodi.") return showTitle = result['label'] data['id'] = result['imdbnumber'] result = utils.kodiJsonRequest({ 'jsonrpc': '2.0', 'method': 'VideoLibrary.GetEpisodes', 'params': { 'tvshowid': dbid, 'properties': ['season', 'episode', 'playcount'] }, 'id': 0 }) if result and 'episodes' in result: i = 0 s = {} for e in result['episodes']: season = str(e['season']) if not season in s: s[season] = [] if e['playcount'] == 0: s[season].append(e['episode']) i += 1 if i == 0: utils.Debug("'%s' is already marked as watched." % showTitle) return data['seasons'] = dict( (k, v) for k, v in s.iteritems() if v) else: utils.Debug( "Error getting episode details for '%s' from Kodi." % showTitle) return if len(data) > 1: utils.Debug( "Marking '%s' with the following data '%s' as watched on trakt.tv" % (media_type, str(data))) data['action'] = 'markWatched' # execute toggle watched action xbmc.executebuiltin("Action(ToggleWatched)") q = sqliteQueue.SqliteQueue() if 'action' in data: utils.Debug("Queuing for dispatch: %s" % data) q.append(data)
def playbackStarted(self, data): logger.debug("playbackStarted(data: %s)" % data) if not data: return self.curVideo = data self.curVideoInfo = None 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 = utilities.kodiRpcToTraktMediaObject( 'movie', utilities.getMovieDetailsFromKodi( self.curVideo['id'], [ 'imdbnumber', 'title', 'year', 'file', 'lastplayed', 'playcount' ])) elif 'title' in self.curVideo and 'year' in self.curVideo: self.curVideoInfo = { 'title': self.curVideo['title'], 'year': self.curVideo['year'] } elif utilities.isEpisode(self.curVideo['type']): if 'id' in self.curVideo: episodeDetailsKodi = utilities.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 = utilities.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 'title' in self.curVideo and 'season' in self.curVideo and 'episode' in self.curVideo: self.curVideoInfo = { 'title': self.curVideo['title'], 'season': self.curVideo['season'], 'number': self.curVideo['episode'] } title, year = utilities.regex_year( self.curVideo['showtitle']) if not year: self.traktShowSummary = { 'title': self.curVideo['showtitle'] } else: self.traktShowSummary = {'title': title, 'year': year} if 'year' in self.curVideo: self.traktShowSummary['year'] = self.curVideo['year'] if 'multi_episode_count' in self.curVideo: self.isMultiPartEpisode = True self.isPlaying = True self.isPaused = False result = self.__scrobble('start') if result: if utilities.isMovie( self.curVideo['type']) and utilities.getSettingAsBool( 'rate_movie'): # pre-get sumamry information, for faster rating dialog. logger.debug( "Movie rating is enabled, pre-fetching summary information." ) if result['movie']['ids']['imdb']: self.curVideoInfo['user'] = { 'ratings': self.traktapi.getMovieRatingForUser( result['movie']['ids']['imdb']) } self.curVideoInfo['ids'] = result['movie']['ids'] else: logger.debug( "'%s (%d)' has no valid id, can't get rating." % (self.curVideoInfo['title'], self.curVideoInfo['year'])) elif utilities.isEpisode( self.curVideo['type']) and utilities.getSettingAsBool( 'rate_episode'): # pre-get sumamry information, for faster rating dialog. logger.debug( "Episode rating is enabled, pre-fetching summary information." ) if result['show']['ids']['tvdb']: self.curVideoInfo['user'] = { 'ratings': self.traktapi.getEpisodeRatingForUser( result['show']['ids']['tvdb'], self.curVideoInfo['season'], self.curVideoInfo['number']) } self.curVideoInfo['ids'] = result['episode']['ids'] else: logger.debug( "'%s - S%02dE%02d' has no valid id, can't get rating." % (self.curVideoInfo['showtitle'], self.curVideoInfo['season'], self.curVideoInfo['episode']))