From 309f444b0b1df7a87d7281e6327ab626cdcb502d Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 29 Dec 2023 00:31:58 +0100 Subject: [PATCH 1/7] Initial version of rewatch support --- README.md | 6 ++-- .../resource.language.en_US/strings.po | 4 +++ resources/lib/syncEpisodes.py | 12 ++++--- resources/lib/utilities.py | 31 +++++++++++++++++-- resources/settings.xml | 5 +++ 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7c97d796..6d94a07b 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ Automatically scrobble all TV episodes and movies you are watching to Trakt.tv! - Automatically scrobble what you're watching - [Mobile apps](http://trakt.tv/downloads) for iPhone, iPad, Android, and Windows Phone -- Share what you're watching (in real time) and rating to facebook and twitter +- Share what you're watching (in real time) and rating to Facebook and Twitter - Personalized calendar so you never miss a TV show -- Follow your friends and people you're interesed in +- Follow your friends and people you're interested in - Use watchlists so you don't forget what to watch - Track your media collections and impress your friends - Create custom lists around any topics you choose @@ -51,7 +51,7 @@ Remote streaming content will scrobble assuming the metadata is correctly set in ### Installation -If your not a developer, you should only install this from the official Kodi repo via Kodi itself. If you are a dev, here is how you install the dev version: +If you're not a developer, you should only install this from the official Kodi repo via Kodi itself. If you are a dev, here is how you install the dev version: 1. Download the zip ([download it here](../../zipball/main)) 2. Install script.trakt by zip. Go to _Settings_ > _Add-ons_ > _Install from zip file_ > Choose the just downloaded zip diff --git a/resources/language/resource.language.en_US/strings.po b/resources/language/resource.language.en_US/strings.po index c238553d..40121f1b 100644 --- a/resources/language/resource.language.en_US/strings.po +++ b/resources/language/resource.language.en_US/strings.po @@ -777,3 +777,7 @@ msgstr "" #~ msgctxt "#32161" #~ msgid "Enter the PIN provided in the box below." #~ msgstr "Enter the PIN provided in the box below." + +msgctxt "#32192" +msgid "Rewatch resets watch status" +msgstr "Rewatch resets watch status" \ No newline at end of file diff --git a/resources/lib/syncEpisodes.py b/resources/lib/syncEpisodes.py index 70fbc848..36eae041 100644 --- a/resources/lib/syncEpisodes.py +++ b/resources/lib/syncEpisodes.py @@ -208,9 +208,9 @@ def __traktLoadShows(self): int(y), line2=kodiUtilities.getString(32102) % (i, x)) # will keep the data in python structures - just like the KODI response - show = show.to_dict() - - showsWatched['shows'].append(show) + show_dict = show.to_dict() + show_dict['reset_at'] = show.reset_at if hasattr(show, 'reset_at') else None + showsWatched['shows'].append(show_dict) i = 0 x = float(len(traktShowsRated)) @@ -424,9 +424,11 @@ def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, if kodiUtilities.getSettingAsBool('kodi_episode_playcount') and not self.sync.IsCanceled(): updateKodiTraktShows = copy.deepcopy(traktShows) updateKodiKodiShows = copy.deepcopy(kodiShows) + utilities.updateTraktLastWatchedBasedOnResetAt(updateKodiTraktShows) kodiShowsUpdate = utilities.compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, kodiUtilities.getSettingAsBool( - "scrobble_fallback"), watched=True, restrict=True, collected=kodiShowsCollected) + "scrobble_fallback"), watched=True, restrict=True, collected=kodiShowsCollected, + reset=kodiUtilities.getSettingAsBool('kodi_episode_reset')) if len(kodiShowsUpdate['shows']) == 0: self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString( @@ -446,7 +448,7 @@ def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, for season in show['seasons']: for episode in season['episodes']: episodes.append({'episodeid': episode['ids']['episodeid'], 'playcount': episode['plays'], - "lastplayed": utilities.convertUtcToDateTime(episode['last_watched_at'])}) + "lastplayed": utilities.convertUtcToDateTime(episode['last_watched_at']).strftime("%Y-%m-%d %H:%M:%S") if episode['last_watched_at'] else None}) # split episode list into chunks of 50 chunksize = 50 diff --git a/resources/lib/utilities.py b/resources/lib/utilities.py index e322ba33..8ab03a3c 100644 --- a/resources/lib/utilities.py +++ b/resources/lib/utilities.py @@ -203,7 +203,6 @@ def convertDateTimeToUTC(toConvert): def convertUtcToDateTime(toConvert): if toConvert: - dateFormat = "%Y-%m-%d %H:%M:%S" try: naive = dateutil.parser.parse(toConvert) utc = naive.replace(tzinfo=tzutc()) @@ -212,7 +211,7 @@ def convertUtcToDateTime(toConvert): logger.debug( 'convertUtcToDateTime() ValueError: movie/show was collected/watched outside of the unix timespan. Fallback to datetime now') local = datetime.now() - return local.strftime(dateFormat) + return local else: return toConvert @@ -391,7 +390,7 @@ def compareShows(shows_col1, shows_col2, matchByTitleAndYear, rating=False, rest # always return shows_col1 if you have enrich it, but don't return shows_col2 -def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, restrict=False, collected=False, playback=False, rating=False): +def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, restrict=False, collected=False, playback=False, rating=False, reset=False): shows = [] # logger.debug("epi shows_col1 %s" % shows_col1) # logger.debug("epi shows_col2 %s" % shows_col2) @@ -462,6 +461,21 @@ def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, eps[ep]['ids'] = { 'episodeid': collectedSeasons[season][ep]['ids']['episodeid']} season_diff[season] = eps + if reset: + t = list( + set(collectedSeasons[season]).difference(set(diff))) + if len(t) > 0: + eps = {} + for ep in t: + eps[ep] = a[ep] + if 'episodeid' in collectedSeasons[season][ep]['ids']: + if 'ids' in eps: + eps[ep]['ids']['episodeid'] = collectedSeasons[season][ep]['ids'][ + 'episodeid'] + else: + eps[ep]['ids'] = { + 'episodeid': collectedSeasons[season][ep]['ids']['episodeid']} + season_diff[season] = eps else: eps = {} for ep in diff: @@ -571,3 +585,14 @@ def _fuzzyMatch(string1, string2, match_percent=55.0): s = difflib.SequenceMatcher(None, string1, string2) s.find_longest_match(0, len(string1), 0, len(string2)) return (difflib.SequenceMatcher(None, string1, string2).ratio() * 100) >= match_percent + + +def updateTraktLastWatchedBasedOnResetAt(traktShows): + for show in traktShows['shows']: + if show['reset_at']: + for season in show['seasons']: + for episode in season['episodes']: + last_watched = convertUtcToDateTime(episode['last_watched_at']) + if last_watched and last_watched < show['reset_at']: + episode['last_watched_at'] = None + episode['plays'] = 0 \ No newline at end of file diff --git a/resources/settings.xml b/resources/settings.xml index 60c10045..379b437a 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -585,6 +585,11 @@ false 1 + + + false + 1 + From be33a6a2af1b8e3397f0b311be0214beec4f8b01 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 29 Dec 2023 14:18:06 +0100 Subject: [PATCH 2/7] Fixes related to timestamps --- .../resource.language.en_US/strings.po | 8 +- resources/lib/kodiUtilities.py | 20 ++-- resources/lib/syncEpisodes.py | 11 +- resources/lib/syncMovies.py | 2 +- resources/lib/utilities.py | 110 +++++++++--------- resources/settings.xml | 16 ++- 6 files changed, 99 insertions(+), 68 deletions(-) diff --git a/resources/language/resource.language.en_US/strings.po b/resources/language/resource.language.en_US/strings.po index 40121f1b..23a9ea7b 100644 --- a/resources/language/resource.language.en_US/strings.po +++ b/resources/language/resource.language.en_US/strings.po @@ -779,5 +779,9 @@ msgstr "" #~ msgstr "Enter the PIN provided in the box below." msgctxt "#32192" -msgid "Rewatch resets watch status" -msgstr "Rewatch resets watch status" \ No newline at end of file +msgid "Remove watched status from Kodi when rewatching" +msgstr "Remove watched status from Kodi when rewatching" + +msgctxt "#32193" +msgid "\tInclude specials" +msgstr "\tInclude specials" \ No newline at end of file diff --git a/resources/lib/kodiUtilities.py b/resources/lib/kodiUtilities.py index 52bebc5f..0fca61c9 100644 --- a/resources/lib/kodiUtilities.py +++ b/resources/lib/kodiUtilities.py @@ -165,11 +165,13 @@ def kodiRpcToTraktMediaObject(type, data, mode='collected'): data['ids'] = utilities.guessBestTraktId(id, type)[0] if 'lastplayed' in data: - episode['watched_at'] = utilities.convertDateTimeToUTC( - data['lastplayed']) + episode['last_watched_at'] = utilities.to_iso8601_datetime( + utilities.from_datetime(data['lastplayed']) + ) if 'dateadded' in data: - episode['collected_at'] = utilities.convertDateTimeToUTC( - data['dateadded']) + episode['collected_at'] = utilities.to_iso8601_datetime( + utilities.from_datetime(data['dateadded']) + ) if 'runtime' in data: episode['runtime'] = data['runtime'] episode['rating'] = data['userrating'] if 'userrating' in data and data['userrating'] > 0 else 0 @@ -184,11 +186,13 @@ def kodiRpcToTraktMediaObject(type, data, mode='collected'): if checkExclusion(data.pop('file')): return if 'lastplayed' in data: - data['watched_at'] = utilities.convertDateTimeToUTC( - data.pop('lastplayed')) + data['last_watched_at'] = utilities.to_iso8601_datetime( + utilities.from_datetime(data.pop('lastplayed')) + ) if 'dateadded' in data: - data['collected_at'] = utilities.convertDateTimeToUTC( - data.pop('dateadded')) + data['collected_at'] = utilities.to_iso8601_datetime( + utilities.from_datetime(data.pop('dateadded')) + ) if data['playcount'] is None: data['plays'] = 0 else: diff --git a/resources/lib/syncEpisodes.py b/resources/lib/syncEpisodes.py index 36eae041..02f88dce 100644 --- a/resources/lib/syncEpisodes.py +++ b/resources/lib/syncEpisodes.py @@ -209,7 +209,9 @@ def __traktLoadShows(self): # will keep the data in python structures - just like the KODI response show_dict = show.to_dict() - show_dict['reset_at'] = show.reset_at if hasattr(show, 'reset_at') else None + # reset_at is not included when calling `.to_dict()` + # but needed for watched shows to know whether to reset the watched state + show_dict['reset_at'] = utilities.to_iso8601_datetime(show.reset_at) if hasattr(show, 'reset_at') else None showsWatched['shows'].append(show_dict) i = 0 @@ -424,7 +426,10 @@ def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, if kodiUtilities.getSettingAsBool('kodi_episode_playcount') and not self.sync.IsCanceled(): updateKodiTraktShows = copy.deepcopy(traktShows) updateKodiKodiShows = copy.deepcopy(kodiShows) - utilities.updateTraktLastWatchedBasedOnResetAt(updateKodiTraktShows) + + if kodiUtilities.getSettingAsBool('kodi_episode_reset'): + utilities.updateTraktLastWatchedBasedOnResetAt( + updateKodiTraktShows, updateSpecials=kodiUtilities.getSettingAsBool('kodi_episode_reset_specials')) kodiShowsUpdate = utilities.compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, kodiUtilities.getSettingAsBool( "scrobble_fallback"), watched=True, restrict=True, collected=kodiShowsCollected, @@ -448,7 +453,7 @@ def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, for season in show['seasons']: for episode in season['episodes']: episodes.append({'episodeid': episode['ids']['episodeid'], 'playcount': episode['plays'], - "lastplayed": utilities.convertUtcToDateTime(episode['last_watched_at']).strftime("%Y-%m-%d %H:%M:%S") if episode['last_watched_at'] else None}) + "lastplayed": utilities.to_datetime(utilities.from_iso8601_datetime(episode['last_watched_at']))}) # split episode list into chunks of 50 chunksize = 50 diff --git a/resources/lib/syncMovies.py b/resources/lib/syncMovies.py index 89bf500e..359e03ac 100644 --- a/resources/lib/syncMovies.py +++ b/resources/lib/syncMovies.py @@ -293,7 +293,7 @@ def __addMoviesToKodiWatched(self, traktMovies, kodiMovies, fromPercent, toPerce # split movie list into chunks of 50 chunksize = 50 chunked_movies = utilities.chunks([{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": {"movieid": kodiMoviesToUpdate[i]['movieid'], "playcount": kodiMoviesToUpdate[i] - ['plays'], "lastplayed": utilities.convertUtcToDateTime(kodiMoviesToUpdate[i]['last_watched_at'])}, "id": i} for i in range(len(kodiMoviesToUpdate))], chunksize) + ['plays'], "lastplayed": utilities.to_datetime(utilities.from_iso8601_datetime(kodiMoviesToUpdate[i]['last_watched_at']))}, "id": i} for i in range(len(kodiMoviesToUpdate))], chunksize) i = 0 x = float(len(kodiMoviesToUpdate)) for chunk in chunked_movies: diff --git a/resources/lib/utilities.py b/resources/lib/utilities.py index 8ab03a3c..591ab794 100644 --- a/resources/lib/utilities.py +++ b/resources/lib/utilities.py @@ -10,6 +10,7 @@ import dateutil.parser from datetime import datetime from dateutil.tz import tzutc, tzlocal +import arrow # make strptime call prior to doing anything, to try and prevent threading # errors @@ -181,39 +182,49 @@ def findEpisodeMatchInList(id, seasonNumber, episodeNumber, list, idType): return {} -def convertDateTimeToUTC(toConvert): - if toConvert: - dateFormat = "%Y-%m-%d %H:%M:%S" - try: - naive = datetime.strptime(toConvert, dateFormat) - except TypeError: - naive = datetime(*(time.strptime(toConvert, dateFormat)[0:6])) - - try: - local = naive.replace(tzinfo=tzlocal()) - utc = local.astimezone(tzutc()) - except ValueError: - logger.debug( - 'convertDateTimeToUTC() ValueError: movie/show was collected/watched outside of the unix timespan. Fallback to datetime utcnow') - utc = datetime.utcnow() - return str(utc) - else: - return toConvert - - -def convertUtcToDateTime(toConvert): - if toConvert: - try: - naive = dateutil.parser.parse(toConvert) - utc = naive.replace(tzinfo=tzutc()) - local = utc.astimezone(tzlocal()) - except ValueError: - logger.debug( - 'convertUtcToDateTime() ValueError: movie/show was collected/watched outside of the unix timespan. Fallback to datetime now') - local = datetime.now() - return local - else: - return toConvert +def to_datetime(value): + if not value: + return None + + return value.strftime('%Y-%m-%d %H:%M:%S') + + +def from_datetime(value): + if not value: + return None + + if arrow is None: + raise Exception('"arrow" module is not available') + + # Parse datetime + dt = arrow.get(value, 'YYYY-MM-DD HH:mm:ss') + + # Return datetime object + return dt.datetime + + +def to_iso8601_datetime(value): + if not value: + return None + + return value.strftime('%Y-%m-%dT%H:%M:%S') + '.000-00:00' + + +def from_iso8601_datetime(value): + if not value: + return None + + if arrow is None: + raise Exception('"arrow" module is not available') + + # Parse ISO8601 datetime + dt = arrow.get(value, 'YYYY-MM-DDTHH:mm:ss.SZZ') + + # Convert to UTC + dt = dt.to('UTC') + + # Return datetime object + return dt.datetime def createError(ex): @@ -411,6 +422,13 @@ def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, if season in season_col2: b = season_col2[season] diff = list(set(a).difference(set(b))) + for key in a: + # update lastplayed in KODI if they don't match trakt + if not key in b or a[key]['last_watched_at'] != b[key]['last_watched_at']: + diff.append(key) + # make unique + diff = list(set(diff)) + logger.debug("a: %s" % diff) if playback: t = list(set(a).intersection(set(b))) if len(t) > 0: @@ -461,21 +479,6 @@ def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, eps[ep]['ids'] = { 'episodeid': collectedSeasons[season][ep]['ids']['episodeid']} season_diff[season] = eps - if reset: - t = list( - set(collectedSeasons[season]).difference(set(diff))) - if len(t) > 0: - eps = {} - for ep in t: - eps[ep] = a[ep] - if 'episodeid' in collectedSeasons[season][ep]['ids']: - if 'ids' in eps: - eps[ep]['ids']['episodeid'] = collectedSeasons[season][ep]['ids'][ - 'episodeid'] - else: - eps[ep]['ids'] = { - 'episodeid': collectedSeasons[season][ep]['ids']['episodeid']} - season_diff[season] = eps else: eps = {} for ep in diff: @@ -587,12 +590,15 @@ def _fuzzyMatch(string1, string2, match_percent=55.0): return (difflib.SequenceMatcher(None, string1, string2).ratio() * 100) >= match_percent -def updateTraktLastWatchedBasedOnResetAt(traktShows): +def updateTraktLastWatchedBasedOnResetAt(traktShows, updateSpecials=False): for show in traktShows['shows']: if show['reset_at']: + reset_at = from_iso8601_datetime(show['reset_at']) for season in show['seasons']: + if not updateSpecials and season['number'] == 0: + continue for episode in season['episodes']: - last_watched = convertUtcToDateTime(episode['last_watched_at']) - if last_watched and last_watched < show['reset_at']: + last_watched = from_iso8601_datetime(episode['last_watched_at']) + if last_watched and last_watched < reset_at: episode['last_watched_at'] = None - episode['plays'] = 0 \ No newline at end of file + episode['plays'] = 0 # TODO remove? diff --git a/resources/settings.xml b/resources/settings.xml index 379b437a..76c763f5 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -580,12 +580,24 @@ true 1 - + + + false + 1 + + true + + + false 1 + + true + true + - + false 1 From c058028f8c010ae167204af8eff0ba7ccf20b5ec Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 29 Dec 2023 14:33:24 +0100 Subject: [PATCH 3/7] Cleanup --- resources/language/resource.language.en_US/strings.po | 4 ++-- resources/lib/syncEpisodes.py | 3 +-- resources/lib/utilities.py | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/resources/language/resource.language.en_US/strings.po b/resources/language/resource.language.en_US/strings.po index 23a9ea7b..19ccf4d0 100644 --- a/resources/language/resource.language.en_US/strings.po +++ b/resources/language/resource.language.en_US/strings.po @@ -783,5 +783,5 @@ msgid "Remove watched status from Kodi when rewatching" msgstr "Remove watched status from Kodi when rewatching" msgctxt "#32193" -msgid "\tInclude specials" -msgstr "\tInclude specials" \ No newline at end of file +msgid "Include specials" +msgstr "Include specials" \ No newline at end of file diff --git a/resources/lib/syncEpisodes.py b/resources/lib/syncEpisodes.py index 02f88dce..ea5d8e5e 100644 --- a/resources/lib/syncEpisodes.py +++ b/resources/lib/syncEpisodes.py @@ -432,8 +432,7 @@ def __addEpisodesToKodiWatched(self, traktShows, kodiShows, kodiShowsCollected, updateKodiTraktShows, updateSpecials=kodiUtilities.getSettingAsBool('kodi_episode_reset_specials')) kodiShowsUpdate = utilities.compareEpisodes(updateKodiTraktShows, updateKodiKodiShows, kodiUtilities.getSettingAsBool( - "scrobble_fallback"), watched=True, restrict=True, collected=kodiShowsCollected, - reset=kodiUtilities.getSettingAsBool('kodi_episode_reset')) + "scrobble_fallback"), watched=True, restrict=True, collected=kodiShowsCollected) if len(kodiShowsUpdate['shows']) == 0: self.sync.UpdateProgress(toPercent, line1=kodiUtilities.getString( diff --git a/resources/lib/utilities.py b/resources/lib/utilities.py index 591ab794..0e65874a 100644 --- a/resources/lib/utilities.py +++ b/resources/lib/utilities.py @@ -401,7 +401,7 @@ def compareShows(shows_col1, shows_col2, matchByTitleAndYear, rating=False, rest # always return shows_col1 if you have enrich it, but don't return shows_col2 -def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, restrict=False, collected=False, playback=False, rating=False, reset=False): +def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, restrict=False, collected=False, playback=False, rating=False): shows = [] # logger.debug("epi shows_col1 %s" % shows_col1) # logger.debug("epi shows_col2 %s" % shows_col2) @@ -428,7 +428,6 @@ def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, diff.append(key) # make unique diff = list(set(diff)) - logger.debug("a: %s" % diff) if playback: t = list(set(a).intersection(set(b))) if len(t) > 0: @@ -601,4 +600,4 @@ def updateTraktLastWatchedBasedOnResetAt(traktShows, updateSpecials=False): last_watched = from_iso8601_datetime(episode['last_watched_at']) if last_watched and last_watched < reset_at: episode['last_watched_at'] = None - episode['plays'] = 0 # TODO remove? + episode['plays'] = 0 From 50de3cba2a96160bc8765c2783715790d9a997ff Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Sun, 31 Dec 2023 16:34:35 +0100 Subject: [PATCH 4/7] Restrict new logic to logic for kodi --- resources/lib/utilities.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/resources/lib/utilities.py b/resources/lib/utilities.py index 0e65874a..142164d2 100644 --- a/resources/lib/utilities.py +++ b/resources/lib/utilities.py @@ -422,12 +422,14 @@ def compareEpisodes(shows_col1, shows_col2, matchByTitleAndYear, watched=False, if season in season_col2: b = season_col2[season] diff = list(set(a).difference(set(b))) - for key in a: - # update lastplayed in KODI if they don't match trakt - if not key in b or a[key]['last_watched_at'] != b[key]['last_watched_at']: - diff.append(key) - # make unique - diff = list(set(diff)) + # only for removing plays from kodi + if watched and restrict: + for key in a: + # update lastplayed in KODI if they don't match trakt + if not key in b or a[key]['plays'] != b[key]['plays']: + diff.append(key) + # make unique + diff = list(set(diff)) if playback: t = list(set(a).intersection(set(b))) if len(t) > 0: From 1269a1e843da4d52d21350246f3499b0df6518aa Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Mon, 11 Mar 2024 12:52:11 +0100 Subject: [PATCH 5/7] Formatting --- resources/lib/syncEpisodes.py | 2 +- resources/lib/utilities.py | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/lib/syncEpisodes.py b/resources/lib/syncEpisodes.py index 418769ea..f87c4bb3 100644 --- a/resources/lib/syncEpisodes.py +++ b/resources/lib/syncEpisodes.py @@ -585,7 +585,7 @@ def __addEpisodesToKodiWatched( if kodiUtilities.getSettingAsBool("kodi_episode_reset"): utilities.updateTraktLastWatchedBasedOnResetAt( updateKodiTraktShows, - updateSpecials=kodiUtilities.getSettingAsBool("kodi_episode_reset_specials") + kodiUtilities.getSettingAsBool("kodi_episode_reset_specials") ) kodiShowsUpdate = utilities.compareEpisodes( diff --git a/resources/lib/utilities.py b/resources/lib/utilities.py index 5fa45fcd..e4f3a972 100644 --- a/resources/lib/utilities.py +++ b/resources/lib/utilities.py @@ -496,7 +496,7 @@ def compareEpisodes( if watched and restrict: for key in a: # update lastplayed in KODI if they don't match trakt - if not key in b or a[key]['plays'] != b[key]['plays']: + if not key in b or a[key]["plays"] != b[key]["plays"]: diff.append(key) # make unique diff = list(set(diff)) @@ -718,15 +718,15 @@ def _fuzzyMatch(string1, string2, match_percent=55.0): ) >= match_percent -def updateTraktLastWatchedBasedOnResetAt(traktShows, updateSpecials=False): - for show in traktShows['shows']: - if show['reset_at']: - reset_at = from_iso8601_datetime(show['reset_at']) - for season in show['seasons']: - if not updateSpecials and season['number'] == 0: +def updateTraktLastWatchedBasedOnResetAt(trakt_shows, update_specials=False): + for show in trakt_shows["shows"]: + if show["reset_at"]: + reset_at = from_iso8601_datetime(show["reset_at"]) + for season in show["seasons"]: + if not update_specials and season["number"] == 0: continue - for episode in season['episodes']: - last_watched = from_iso8601_datetime(episode['last_watched_at']) + for episode in season["episodes"]: + last_watched = from_iso8601_datetime(episode["last_watched_at"]) if last_watched and last_watched < reset_at: - episode['last_watched_at'] = None - episode['plays'] = 0 + episode["last_watched_at"] = None + episode["plays"] = 0 From 695a3e2de8af429daf2f8d4628ebe4ad16738189 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Sun, 14 Jul 2024 20:22:11 +0200 Subject: [PATCH 6/7] Move translation to en_GB --- resources/language/resource.language.en_GB/strings.po | 8 ++++++++ resources/language/resource.language.en_US/strings.po | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/language/resource.language.en_GB/strings.po b/resources/language/resource.language.en_GB/strings.po index df3d6b30..8352be59 100644 --- a/resources/language/resource.language.en_GB/strings.po +++ b/resources/language/resource.language.en_GB/strings.po @@ -774,6 +774,14 @@ msgctxt "#32191" msgid "Password" msgstr "" +msgctxt "#32192" +msgid "Remove watched status from Kodi when rewatching" +msgstr "" + +msgctxt "#32193" +msgid "Include specials" +msgstr "" + msgctxt "#42191" msgid "Optional password needed to authenticate with the proxy." msgstr "" diff --git a/resources/language/resource.language.en_US/strings.po b/resources/language/resource.language.en_US/strings.po index 965ef216..6b8b8e16 100644 --- a/resources/language/resource.language.en_US/strings.po +++ b/resources/language/resource.language.en_US/strings.po @@ -777,11 +777,3 @@ msgstr "" #~ msgctxt "#32161" #~ msgid "Enter the PIN provided in the box below." #~ msgstr "Enter the PIN provided in the box below." - -msgctxt "#32192" -msgid "Remove watched status from Kodi when rewatching" -msgstr "Remove watched status from Kodi when rewatching" - -msgctxt "#32193" -msgid "Include specials" -msgstr "Include specials" \ No newline at end of file From dd8d70bab135a8e95e7d2fc59c34f247a0414e63 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 15 Aug 2024 17:56:04 +0200 Subject: [PATCH 7/7] Revert changes to watch_at timestamp --- resources/lib/kodiUtilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/kodiUtilities.py b/resources/lib/kodiUtilities.py index c85fb486..3900539f 100644 --- a/resources/lib/kodiUtilities.py +++ b/resources/lib/kodiUtilities.py @@ -185,7 +185,7 @@ def kodiRpcToTraktMediaObject(type, data, mode="collected"): data["ids"] = utilities.guessBestTraktId(id, type)[0] if "lastplayed" in data: - episode["last_watched_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data["lastplayed"])) + episode["watched_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data["lastplayed"])) if "dateadded" in data: episode["collected_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data["dateadded"])) if "runtime" in data: @@ -204,7 +204,7 @@ def kodiRpcToTraktMediaObject(type, data, mode="collected"): if checkExclusion(data.pop("file")): return if "lastplayed" in data: - data["last_watched_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data.pop("lastplayed"))) + data["watched_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data.pop("lastplayed"))) if "dateadded" in data: data["collected_at"] = utilities.to_iso8601_datetime(utilities.from_datetime(data.pop("dateadded"))) if data["playcount"] is None: