Taxel / PlexTraktSync

A python script that syncs the movies, shows and ratings between trakt and Plex (without needing a PlexPass or Trakt VIP subscription)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error running sync command: 'str' object cannot be interpreted as an integer

usma0118 opened this issue · comments

Confirmation

  • I have read the README.md on the project homepage
  • I have checked if identical issue already exists
  • I have tried downgrading to find version that can be used as a workaround

The problem

Error when running container.

I have copied config and able to run sync in python venv without any issues.

Originally posted by @usma0118 in #1969

Steps to reproduce the behavior

Trying to run plex trakt sync in docker (kubernetes).
After deployment, i am getting TypeError: 'str' object cannot be interpreted as an integer

Error trace / logs

User
WARNING  plextraktsync without command is deprecated. Executing "plextraktsync sync"
INFO     PlexTraktSync [0.30.10]
INFO     Connecting with url: http://plex.media.svc.cluster.local:32400, timeout 30 seconds
ERROR    ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
INFO     Connecting with url: https://192-100-1-202.*************************.plex.direct:32400, timeout 30 seconds
INFO     Sync Movie sections: ['Movies', ***', '***']
INFO     Sync Show sections: ['*****', '*****', 'Cartoon', 'Documentary shows', 'TV Shows']
INFO     Enable sync plugin 'AddCollectionPlugin': False
INFO     Enable sync plugin 'ClearCollectedPlugin': False
INFO     Enable sync plugin 'LikedListsPlugin': False
INFO     Enable sync plugin 'SyncRatingsPlugin': True
INFO     Enable sync plugin 'SyncWatchedPlugin': True
INFO     Enable sync plugin 'TraktListsPlugin': False
INFO     Enable sync plugin 'WatchListPlugin': False
INFO     Enable sync plugin 'WatchProgressPlugin': False
Processing Movies   0% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1/791  [ 0:00:00 < -:--:-- , ? it/s ]
ERROR    'str' object cannot be interpreted as an integer
         ╭───────────────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────────────╮
         │ /app/plextraktsync/cli.py:26 in wrap                                                                                                │
         │                                                                                                                                     │
         │    23 │   │   │   cmd = getattr(module, name)                                                                                       │
         │    24 │   │   │                                                                                                                     │
         │    25 │   │   │   try:                                                                                                              │
         │ ❱  26 │   │   │   │   cmd(*args, **kwargs)                                                                                          │
         │    27 │   │   │   except EOFError as e:                                                                                             │
         │    28 │   │   │   │   raise ClickException(f"Program requested terminal, No terminal is                                             │
         │       connected: {e}")                                                                                                              │
         │    29 │   │   │   except ClickException as e:                                                                                       │
         │                                                                                                                                     │
         │ /app/plextraktsync/commands/sync.py:76 in sync                                                                                      │
         │                                                                                                                                     │
         │   73 │   │   │   w.print_plan(print=logger.info)                                                                                    │
         │   74 │   │   if dry_run:                                                                                                            │
         │   75 │   │   │   logger.info("Enabled dry-run mode: not making actual changes")                                                     │
         │ ❱ 76 │   │   run_async(runner, walker=w, dry_run=config.dry_run)                                                                    │
         │   77                                                                                                                                │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/decorator.py:232 in fun                                                                     │
         │                                                                                                                                     │
         │   229 │   │   def fun(*args, **kw):                                                                                                 │
         │   230 │   │   │   if not kwsyntax:                                                                                                  │
         │   231 │   │   │   │   args, kw = fix(args, kw, sig)                                                                                 │
         │ ❱ 232 │   │   │   return caller(func, *(extras + args), **kw)                                                                       │
         │   233 │   fun.__name__ = func.__name__                                                                                              │
         │   234 │   fun.__doc__ = func.__doc__                                                                                                │
         │   235 │   fun.__wrapped__ = func                                                                                                    │
         │                                                                                                                                     │
         │ /app/plextraktsync/decorators/coro.py:13 in coro                                                                                    │
         │                                                                                                                                     │
         │   10 │                                                                                                                              │
         │   11 │   https://github.com/pallets/click/issues/85#issuecomment-503464628                                                          │
         │   12 │   """                                                                                                                        │
         │ ❱ 13 │   return asyncio.run(f(*args, **kwargs))                                                                                     │
         │   14                                                                                                                                │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/asyncio/runners.py:194 in run                                                                             │
         │                                                                                                                                     │
         │   191 │   │   │   "asyncio.run() cannot be called from a running event loop")                                                       │
         │   192 │                                                                                                                             │
         │   193 │   with Runner(debug=debug, loop_factory=loop_factory) as runner:                                                            │
         │ ❱ 194 │   │   return runner.run(main)                                                                                               │
         │   195                                                                                                                               │
         │   196                                                                                                                               │
         │   197 def _cancel_all_tasks(loop):                                                                                                  │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/asyncio/runners.py:118 in run                                                                             │
         │                                                                                                                                     │
         │   115 │   │                                                                                                                         │
         │   116 │   │   self._interrupt_count = 0                                                                                             │
         │   117 │   │   try:                                                                                                                  │
         │ ❱ 118 │   │   │   return self._loop.run_until_complete(task)                                                                        │
         │   119 │   │   except exceptions.CancelledError:                                                                                     │
         │   120 │   │   │   if self._interrupt_count > 0:                                                                                     │
         │   121 │   │   │   │   uncancel = getattr(task, "uncancel", None)                                                                    │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/asyncio/base_events.py:687 in run_until_complete                                                          │
         │                                                                                                                                     │
         │    684 │   │   if not future.done():                                                                                                │
         │    685 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')                                                │
         │    686 │   │                                                                                                                        │
         │ ❱  687 │   │   return future.result()                                                                                               │
         │    688 │                                                                                                                            │
         │    689 │   def stop(self):                                                                                                          │
         │    690 │   │   """Stop running the event loop.                                                                                      │
         │                                                                                                                                     │
         │ /app/plextraktsync/commands/sync.py:13 in run_async                                                                                 │
         │                                                                                                                                     │
         │   10                                                                                                                                │
         │   11 @coro                                                                                                                          │
         │   12 async def run_async(runner, **kwargs):                                                                                         │
         │ ❱ 13 │   await runner.sync(**kwargs)                                                                                                │
         │   14                                                                                                                                │
         │   15                                                                                                                                │
         │   16 def sync(                                                                                                                      │
         │                                                                                                                                     │
         │ /app/plextraktsync/sync/Sync.py:46 in sync                                                                                          │
         │                                                                                                                                     │
         │   43 │   │   pm.hook.init(sync=self, pm=pm, is_partial=is_partial, dry_run=dry_run)                                                 │
         │   44 │   │                                                                                                                          │
         │   45 │   │   if self.config.need_library_walk:                                                                                      │
         │ ❱ 46 │   │   │   async for movie in walker.find_movies():                                                                           │
         │   47 │   │   │   │   await pm.ahook.walk_movie(movie=movie, dry_run=dry_run)                                                        │
         │   48 │   │   │                                                                                                                      │
         │   49 │   │   │   async for episode in walker.find_episodes():                                                                       │
         │                                                                                                                                     │
         │ /app/plextraktsync/plan/Walker.py:90 in find_movies                                                                                 │
         │                                                                                                                                     │
         │    87 │                                                                                                                             │
         │    88 │   async def find_movies(self) -> Generator[Media, Any, None]:                                                               │
         │    89 │   │   async for plex in self.get_plex_movies():                                                                             │
         │ ❱  90 │   │   │   movie = self.mf.resolve_any(plex)                                                                                 │
         │    91 │   │   │   if not movie:                                                                                                     │
         │    92 │   │   │   │   continue                                                                                                      │
         │    93 │   │   │   yield movie                                                                                                       │
         │                                                                                                                                     │
         │ /app/plextraktsync/media/MediaFactory.py:38 in resolve_any                                                                          │
         │                                                                                                                                     │
         │   35 │   │   │   return None                                                                                                        │
         │   36 │   │                                                                                                                          │
         │   37 │   │   for guid in guids:                                                                                                     │
         │ ❱ 38 │   │   │   m = self.resolve_guid(guid, show)                                                                                  │
         │   39 │   │   │   if m:                                                                                                              │
         │   40 │   │   │   │   self.logger.debug(f"Resolved {guid} of {guid.pm} to {m}")                                                      │
         │   41 │   │   │   │   return m                                                                                                       │
         │                                                                                                                                     │
         │ /app/plextraktsync/media/MediaFactory.py:67 in resolve_guid                                                                         │
         │                                                                                                                                     │
         │   64 │   │   │   if show:                                                                                                           │
         │   65 │   │   │   │   tm = self.trakt.find_episode_guid(guid, show.seasons)                                                          │
         │   66 │   │   │   else:                                                                                                              │
         │ ❱ 67 │   │   │   │   tm = self.trakt.find_by_guid(guid)                                                                             │
         │   68 │   │   except (TraktException, RequestException) as e:                                                                        │
         │   69 │   │   │   self.logger.warning(f"{guid.title_link}: Skipping {guid}: Trakt errors:                                            │
         │      {e}", extra={"markup": True})                                                                                                  │
         │   70 │   │   │   return None                                                                                                        │
         │                                                                                                                                     │
         │ /app/plextraktsync/trakt/TraktApi.py:253 in find_by_guid                                                                            │
         │                                                                                                                                     │
         │   250 │   │   if guid.type == "episode" and guid.is_episode:                                                                        │
         │   251 │   │   │   return self.find_by_episode_guid(guid)                                                                            │
         │   252 │   │   else:                                                                                                                 │
         │ ❱ 253 │   │   │   tm = self.search_by_id(guid.id, id_type=guid.provider, media_type=guid.type)                                      │
         │   254 │   │   │   if tm is None and guid.type == "movie":                                                                           │
         │   255 │   │   │   │   if self.search_by_id(guid.id, id_type=guid.provider, media_type="show"):                                      │
         │   256 │   │   │   │   │   self.logger.warning(f"Found match using show search:                                                      │
         │       {guid.title_link}", extra={"markup": True})                                                                                   │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/decorator.py:232 in fun                                                                     │
         │                                                                                                                                     │
         │   229 │   │   def fun(*args, **kw):                                                                                                 │
         │   230 │   │   │   if not kwsyntax:                                                                                                  │
         │   231 │   │   │   │   args, kw = fix(args, kw, sig)                                                                                 │
         │ ❱ 232 │   │   │   return caller(func, *(extras + args), **kw)                                                                       │
         │   233 │   fun.__name__ = func.__name__                                                                                              │
         │   234 │   fun.__doc__ = func.__doc__                                                                                                │
         │   235 │   fun.__wrapped__ = func                                                                                                    │
         │                                                                                                                                     │
         │ /app/plextraktsync/decorators/rate_limit.py:19 in rate_limit                                                                        │
         │                                                                                                                                     │
         │   16 │   retry = 0                                                                                                                  │
         │   17 │   while True:                                                                                                                │
         │   18 │   │   try:                                                                                                                   │
         │ ❱ 19 │   │   │   return fn(*args, **kwargs)                                                                                         │
         │   20 │   │   except RateLimitException as e:                                                                                        │
         │   21 │   │   │   if retry == retries:                                                                                               │
         │   22 │   │   │   │   logger.error(f"Trakt Error: {e}")                                                                              │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/decorator.py:232 in fun                                                                     │
         │                                                                                                                                     │
         │   229 │   │   def fun(*args, **kw):                                                                                                 │
         │   230 │   │   │   if not kwsyntax:                                                                                                  │
         │   231 │   │   │   │   args, kw = fix(args, kw, sig)                                                                                 │
         │ ❱ 232 │   │   │   return caller(func, *(extras + args), **kw)                                                                       │
         │   233 │   fun.__name__ = func.__name__                                                                                              │
         │   234 │   fun.__doc__ = func.__doc__                                                                                                │
         │   235 │   fun.__wrapped__ = func                                                                                                    │
         │                                                                                                                                     │
         │ /app/plextraktsync/decorators/retry.py:24 in retry                                                                                  │
         │                                                                                                                                     │
         │   21 │   count = 0                                                                                                                  │
         │   22 │   while True:                                                                                                                │
         │   23 │   │   try:                                                                                                                   │
         │ ❱ 24 │   │   │   return fn(*args, **kwargs)                                                                                         │
         │   25 │   │   except (                                                                                                               │
         │   26 │   │   │   BadRequest,                                                                                                        │
         │   27 │   │   │   BadResponseException,                                                                                              │
         │                                                                                                                                     │
         │ /app/plextraktsync/trakt/TraktApi.py:293 in search_by_id                                                                            │
         │                                                                                                                                     │
         │   290 │   │   │                                                                                                                     │
         │   291 │   │   │   return None                                                                                                       │
         │   292 │   │                                                                                                                         │
         │ ❱ 293 │   │   search = trakt.sync.search_by_id(                                                                                     │
         │   294 │   │   │   media_id, id_type=id_type, media_type=media_type                                                                  │
         │   295 │   │   )                                                                                                                     │
         │   296 │   │   if not search:                                                                                                        │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/trakt/core.py:573 in inner                                                                  │
         │                                                                                                                                     │
         │   570 │   │   """                                                                                                                   │
         │   571 │   │   @wraps(f)                                                                                                             │
         │   572 │   │   def inner(*args, **kwargs):                                                                                           │
         │ ❱ 573 │   │   │   self._bootstrap()                                                                                                 │
         │   574 │   │   │   resp = self._get_first(f, *args, **kwargs)                                                                        │
         │   575 │   │   │   if not isinstance(resp, tuple):                                                                                   │
         │   576 │   │   │   │   # Handle cached property responses                                                                            │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/trakt/core.py:504 in _bootstrap                                                             │
         │                                                                                                                                     │
         │   501 │   │   # Check token validity and refresh token if needed                                                                    │
         │   502 │   │   if (not OAUTH_TOKEN_VALID and OAUTH_EXPIRES_AT is not None                                                            │
         │   503 │   │   │   │   and OAUTH_REFRESH is not None):                                                                               │
         │ ❱ 504 │   │   │   _validate_token(self)                                                                                             │
         │   505 │                                                                                                                             │
         │   506 │   @staticmethod                                                                                                             │
         │   507 │   def _get_first(f, *args, **kwargs):                                                                                       │
         │                                                                                                                                     │
         │ /usr/local/lib/python3.12/site-packages/trakt/core.py:399 in _validate_token                                                        │
         │                                                                                                                                     │
         │   396 │   """Check if current OAuth token has not expired"""                                                                        │
         │   397 │   global OAUTH_TOKEN_VALID                                                                                                  │
         │   398 │   current = datetime.now(tz=timezone.utc)                                                                                   │
         │ ❱ 399 │   expires_at = datetime.fromtimestamp(OAUTH_EXPIRES_AT, tz=timezone.utc)                                                    │
         │   400 │   if expires_at - current > timedelta(days=2):                                                                              │
         │   401 │   │   OAUTH_TOKEN_VALID = True                                                                                              │
         │   402 │   else:                                                                                                                     │
         ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
         TypeError: 'str' object cannot be interpreted as an integer
Error: Error running sync command: 'str' object cannot be interpreted as an integer

Expected behavior

sync should work

Inspect of problematic items

No response

Workarounds

No response

Config file contents

---
cache:
  path: $PTS_CACHE_DIR/trakt_cache

excluded-libraries:
  - Music

config:
  dotenv_override: true

logging:
  append: false
  debug: false
  filename: plextraktsync.log

sync:
  plex_to_trakt:
    collection: false
    ratings: true
    watched_status: true
    # If plex_to_trakt watchlist=false and trakt_to_plex watchlist=true
    # the Plex watchlist will be overwritten by Trakt watchlist
    watchlist: false
  trakt_to_plex:
    liked_lists: false
    ratings: true
    watched_status: true
    watchlist: false
    watchlist_as_playlist: true
    # Setting for whether ratings from one platform should have priority.
    # Valid values are trakt, plex or none. (default: plex)
    # none - No rating priority. Existing ratings are not overwritten.
    # trakt - Trakt ratings have priority. Existing Plex ratings are overwritten.
    # plex - Plex ratings have priority. Existing Trakt ratings are overwritten.
    rating_priority: plex
watch:
  add_collection: false
  remove_collection: true
  scrobble_threshold: 90
  username_filter: true

xbmc-providers:
  movies: imdb
  shows: tvdb

Install method

docker-compose

Version

0.30.10@sha256:87845233a95ed875db07084984f2040403daf6eb411ddd52dbd60e1b0c967665

Python Version

3.7

Plex Server Version

1.4.0

Operating System and Version

Kubernetes running on Ubuntu server

Seems something wrong with your trakt api credentials: .pytrakt.json

Very likely, You can delete the file to work around the problem.

But to fix the problem you need to provide example of the file. Redact out actual token values to keep your privacy when sharing.

here goes .pytrakt
{"CLIENT_ID": "************************************", "CLIENT_SECRET": "***********************************","OAUTH_TOKEN": "*****************************************************500a6192","OAUTH_REFRESH": "19fd25fe0028e0b****************************************************f","OAUTH_EXPIRES_AT": "1724853786"}

ok, found the issue. since i was mounting .pytrakt file from externasecret (kubernetes).
it was creating expires at as string.
Now fixed.