|
10 | 10 | import dateutil.parser |
11 | 11 | from datetime import datetime |
12 | 12 | from dateutil.tz import tzutc, tzlocal |
| 13 | +import arrow |
13 | 14 |
|
14 | 15 | # make strptime call prior to doing anything, to try and prevent threading |
15 | 16 | # errors |
@@ -213,42 +214,49 @@ def findEpisodeMatchInList(id: str, seasonNumber: int, episodeNumber: int, list_ |
213 | 214 | return {} |
214 | 215 |
|
215 | 216 |
|
216 | | -def convertDateTimeToUTC(toConvert: Optional[str]) -> Optional[str]: |
217 | | - if toConvert: |
218 | | - dateFormat = "%Y-%m-%d %H:%M:%S" |
219 | | - try: |
220 | | - naive = datetime.strptime(toConvert, dateFormat) |
221 | | - except TypeError: |
222 | | - naive = datetime(*(time.strptime(toConvert, dateFormat)[0:6])) |
223 | | - |
224 | | - try: |
225 | | - local = naive.replace(tzinfo=tzlocal()) |
226 | | - utc = local.astimezone(tzutc()) |
227 | | - except ValueError: |
228 | | - logger.debug( |
229 | | - "convertDateTimeToUTC() ValueError: movie/show was collected/watched outside of the unix timespan. Fallback to datetime utcnow" |
230 | | - ) |
231 | | - utc = datetime.utcnow() |
232 | | - return str(utc) |
233 | | - else: |
234 | | - return toConvert |
235 | | - |
236 | | - |
237 | | -def convertUtcToDateTime(toConvert: Optional[str]) -> Optional[str]: |
238 | | - if toConvert: |
239 | | - dateFormat = "%Y-%m-%d %H:%M:%S" |
240 | | - try: |
241 | | - naive = dateutil.parser.parse(toConvert) |
242 | | - utc = naive.replace(tzinfo=tzutc()) |
243 | | - local = utc.astimezone(tzlocal()) |
244 | | - except ValueError: |
245 | | - logger.debug( |
246 | | - "convertUtcToDateTime() ValueError: movie/show was collected/watched outside of the unix timespan. Fallback to datetime now" |
247 | | - ) |
248 | | - local = datetime.now() |
249 | | - return local.strftime(dateFormat) |
250 | | - else: |
251 | | - return toConvert |
| 217 | +def toDateTime(value: Optional[datetime]) -> Optional[str]: |
| 218 | + if not value: |
| 219 | + return None |
| 220 | + |
| 221 | + return value.strftime('%Y-%m-%d %H:%M:%S') |
| 222 | + |
| 223 | + |
| 224 | +def fromDateTime(value: Optional[str]) -> Optional[datetime]: |
| 225 | + if not value: |
| 226 | + return None |
| 227 | + |
| 228 | + if arrow is None: |
| 229 | + raise Exception('"arrow" module is not available') |
| 230 | + |
| 231 | + # Parse datetime |
| 232 | + dt = arrow.get(value, 'YYYY-MM-DD HH:mm:ss') |
| 233 | + |
| 234 | + # Return datetime object |
| 235 | + return dt.datetime |
| 236 | + |
| 237 | + |
| 238 | +def toIso8601DateTime(value: Optional[datetime]) -> Optional[str]: |
| 239 | + if not value: |
| 240 | + return None |
| 241 | + |
| 242 | + return value.strftime('%Y-%m-%dT%H:%M:%S') + '.000-00:00' |
| 243 | + |
| 244 | + |
| 245 | +def fromIso8601DateTime(value: Optional[str]) -> Optional[datetime]: |
| 246 | + if not value: |
| 247 | + return None |
| 248 | + |
| 249 | + if arrow is None: |
| 250 | + raise Exception('"arrow" module is not available') |
| 251 | + |
| 252 | + # Parse ISO8601 datetime |
| 253 | + dt = arrow.get(value, 'YYYY-MM-DDTHH:mm:ss.SZZ') |
| 254 | + |
| 255 | + # Convert to UTC |
| 256 | + dt = dt.to('UTC') |
| 257 | + |
| 258 | + # Return datetime object |
| 259 | + return dt.datetime |
252 | 260 |
|
253 | 261 |
|
254 | 262 | def createError(ex: Exception) -> str: |
@@ -484,6 +492,14 @@ def compareEpisodes( |
484 | 492 | if season in season_col2: |
485 | 493 | b = season_col2[season] |
486 | 494 | diff = list(set(a).difference(set(b))) |
| 495 | + # only for removing plays from kodi |
| 496 | + if watched and restrict: |
| 497 | + for key in a: |
| 498 | + # update lastplayed in KODI if they don't match trakt |
| 499 | + if not key in b or a[key]["plays"] != b[key]["plays"]: |
| 500 | + diff.append(key) |
| 501 | + # make unique |
| 502 | + diff = list(set(diff)) |
487 | 503 | if playback: |
488 | 504 | t = list(set(a).intersection(set(b))) |
489 | 505 | if len(t) > 0: |
@@ -700,3 +716,17 @@ def _fuzzyMatch(string1: str, string2: str, match_percent: float = 55.0) -> bool |
700 | 716 | return ( |
701 | 717 | difflib.SequenceMatcher(None, string1, string2).ratio() * 100 |
702 | 718 | ) >= match_percent |
| 719 | + |
| 720 | + |
| 721 | +def updateTraktLastWatchedBasedOnResetAt(trakt_shows, update_specials=False): |
| 722 | + for show in trakt_shows["shows"]: |
| 723 | + if show["reset_at"]: |
| 724 | + reset_at = fromIso8601DateTime(show["reset_at"]) |
| 725 | + for season in show["seasons"]: |
| 726 | + if not update_specials and season["number"] == 0: |
| 727 | + continue |
| 728 | + for episode in season["episodes"]: |
| 729 | + last_watched = fromIso8601DateTime(episode["last_watched_at"]) |
| 730 | + if last_watched and last_watched < reset_at: |
| 731 | + episode["last_watched_at"] = None |
| 732 | + episode["plays"] = 0 |
0 commit comments