cmathews393 / spotify-to-plex

A python script/app to sync Spotify Playlists into Plex (optionally via Lidarr)
GNU General Public License v3.0
34 stars 3 forks source link

Periodic Sync for Docker #21

Closed luckycold closed 1 week ago

luckycold commented 3 months ago

Is your feature request related to a problem? Please describe. I use a Kubernetes front end called TrueNAS Scale and it expects apps that continually run and this app thinks it's constantly failing and restarting with a "failed, backing off" error.

Describe the solution you'd like Instead of having the app end after running once, it'd be nice to have it periodically restart the sync process on a regular interval (e.g. daily, hourly, etc.) as an option.

cmathews393 commented 3 months ago

Hey lucky, this should already be the case but it looks like something is broken with the scheduler, I'll take a look this evening.

cmathews393 commented 3 months ago

@luckycold sorry, it's taking a while to figure this out. I don't really understand what's not working, I think it's not pulling in the API key on the scheduled runs for some reason.

luckycold commented 3 months ago

It's entirely possible that this is user error. I don't typically have a custom app on my interface not "just work". I would guess K8s typically figures out health checks on its own. I'll look at the logs and see if there's anything about it that might be triggering the "backing off" error. If I find anything specific to the app or if I find out that it's something I fixed on my own I'll let you know.

cmathews393 commented 3 months ago

Nah I just figured it out, based on your previous issue, I'm guessing you're also syncing to multiple users? It's switching to the secondary users, and then trying to run again when its scheduled, but its still trying to auth with that other user instead of the default user again like it does at the beginning. Should have a fixed pushed shortly

luckycold commented 3 months ago

Funny enough, I actually have my users blank. So it's not multiple users for me. The longer I look at my setup I wonder how I got it to even work partially in the first place.

luckycold commented 3 months ago

Seems I'm actually getting an error saying this:

2024-03-06T22:53:46.161862022-06:00 reading config
2024-03-06T22:53:46.161891094-06:00 config file missing!
2024-03-06T22:53:46.161899311-06:00 Current Working Directory: /usr/bin/spotiplex
2024-03-06T22:53:46.162165403-06:00 Welcome to Spotiplex! It seems this is your first run of the application, please enter your configuration variables below. Press Enter to continue...
2024-03-06T22:53:46.162249815-06:00 Traceback (most recent call last):
2024-03-06T22:53:46.162264336-06:00   File "/usr/bin/spotiplex/main.py", line 189, in <module>
2024-03-06T22:53:46.162381117-06:00     main()
2024-03-06T22:53:46.162397085-06:00   File "/usr/bin/spotiplex/main.py", line 183, in main
2024-03-06T22:53:46.162467314-06:00     spotiplex = Spotiplex()
2024-03-06T22:53:46.162480897-06:00                 ^^^^^^^^^^^
2024-03-06T22:53:46.162491056-06:00   File "/usr/bin/spotiplex/main.py", line 51, in __init__
2024-03-06T22:53:46.162566327-06:00     Spotiplex.configurator(self)
2024-03-06T22:53:46.162585156-06:00   File "/usr/bin/spotiplex/main.py", line 140, in configurator
2024-03-06T22:53:46.162602808-06:00     "lidarr_sync": input("Enter Lidarr sync option (True/False): "),
2024-03-06T22:53:46.162677978-06:00                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-06T22:53:46.162697432-06:00 EOFError: EOF when reading a line
2024-03-06T22:53:46.202556774-06:00 Enter Lidarr sync option (True/False): 
luckycold commented 3 months ago

I can tell you I didn't originally have this error a month or two ago. I only decided to report this recently and now I'm a bit more confused at what's going on.

luckycold commented 3 months ago

And if it's not clear I do have all the environment variables set (except users being blank)

cmathews393 commented 3 months ago

Oh, yep you're correct in that it's a different issue, but I recently introduced that issue. I should be able to fix that, but I'm not sure why its happening. It looks like its prompting you to go through the manual setup, as if its not in a container. I wonder if TrueNAS Scale doesn't set up containers the same way as standard docker. Let me investigate.

cmathews393 commented 3 months ago

@luckycold Would you mind pulling in the "test" tag instead of latest and seeing what happens? I think (tentatively) that its fixed! You should be able to set the interval env variable to set the seconds between runs.

cmathews393 commented 3 months ago

If you're using lidarr, its not going to work, if you're manually inputting the playlists, it should be fine. I need to go back and fix the way its processing the lists now.

luckycold commented 3 months ago

You caught me right before I was heading to bed. I went ahead and did as you asked and got a switch user error shown here:

reading config
config file missing!
Current Working Directory: /usr/bin/spotiplex
writing config
writing config
writing config
writing config
Configuration set from environment variables.
reading config
reading config
reading config
reading config
luckycold
reading config
False
Traceback (most recent call last):
  File "/usr/bin/spotiplex/main.py", line 223, in <module>
    main()
  File "/usr/bin/spotiplex/main.py", line 218, in main
    spotiplex.run()
  File "/usr/bin/spotiplex/main.py", line 133, in run
    self.process_for_user(user)
  File "/usr/bin/spotiplex/main.py", line 91, in process_for_user
    self.plex_service.plex = self.plex_service.plex.switchUser(user)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/plexapi/server.py", line 271, in switchUser
    user = user if isinstance(user, MyPlexUser) else self.myPlexAccount().user(user)
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/plexapi/myplex.py", line 669, in user
    raise NotFound(f'Unable to find user {username}')
plexapi.exceptions.NotFound: Unable to find user

So I decided to put in my Plex username to see if that would fix it and no luck same error but slightly different message:

How many lines of logs do you want to display? (Default is 500, "-1" for all):
reading config
config file missing!
Current Working Directory: /usr/bin/spotiplex
writing config
writing config
writing config
writing config
Configuration set from environment variables.
reading config
reading config
reading config
reading config
luckycold
reading config
False
Traceback (most recent call last):
  File "/usr/bin/spotiplex/main.py", line 223, in <module>
    main()
  File "/usr/bin/spotiplex/main.py", line 218, in main
    spotiplex.run()
  File "/usr/bin/spotiplex/main.py", line 133, in run
    self.process_for_user(user)
  File "/usr/bin/spotiplex/main.py", line 91, in process_for_user
    self.plex_service.plex = self.plex_service.plex.switchUser(user)
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/plexapi/server.py", line 271, in switchUser
    user = user if isinstance(user, MyPlexUser) else self.myPlexAccount().user(user)
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/plexapi/myplex.py", line 669, in user
    raise NotFound(f'Unable to find user {username}')
plexapi.exceptions.NotFound: Unable to find user luckycold

It's getting late on my end, so I'm going to continue this tomorrow. Thanks for your work though!

cmathews393 commented 3 months ago

@luckycold are you syncing from Lidarr or from a manual list? Manual lists are definitely working once I push this commit, but lidarr takes a while on my end because of the volume of playlists so I'm not 100% sure on it yet

luckycold commented 3 months ago

@cmathews393 Pretty sure I'm doing manual list. I've specified lidarr sync to false. Still the switchUser error.

luckycold commented 3 months ago

The manual list is just a link to the playlist, correct?

cmathews393 commented 3 months ago

Yeah, try repulling the image? Shouldn't be getting the user switch error anymore

luckycold commented 3 months ago

Okay, it seems that it didn't like me switching branches for that specific "custom app" I just reinstalled it and it seems to have worked. What would be a recommended interval? I tried 10 and it broke, then changed it to 600 and it seems stable now.

cmathews393 commented 3 months ago

Hmm describe broke? But I'd recommend like, 6 hours? Interval is in seconds, I think that's 21600?

cmathews393 commented 3 months ago

I've had it set to 30, and it's been running without issue for almost 24 hours. Try that and see if it loops and then I'd do longer, not sure what Spotifys API limits are,.

luckycold commented 3 months ago

When set to 10 I get this:

2024-03-08 15:39:06.305689-06:00File "/usr/bin/spotiplex/main.py", line 124, in run
2024-03-08 15:39:06.305695-06:00self.plex_service = PlexService()
2024-03-08 15:39:06.305702-06:00^^^^^^^^^^^^^
2024-03-08 15:39:06.305708-06:00File "/usr/bin/spotiplex/plex.py", line 12, in __init__
2024-03-08 15:39:06.305715-06:00self.plex = self.connect_plex()
2024-03-08 15:39:06.305721-06:00^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305728-06:00File "/usr/bin/spotiplex/plex.py", line 19, in connect_plex
2024-03-08 15:39:06.305734-06:00return PlexServer(self.server_url, self.server_token, session=session)
2024-03-08 15:39:06.305741-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305748-06:00File "/usr/local/lib/python3.12/site-packages/plexapi/server.py", line 116, in __init__
2024-03-08 15:39:06.305754-06:00data = self.query(self.key, timeout=self._timeout)
2024-03-08 15:39:06.305761-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305767-06:00File "/usr/local/lib/python3.12/site-packages/plexapi/server.py", line 759, in query
2024-03-08 15:39:06.305774-06:00response = method(url, headers=headers, timeout=timeout, **kwargs)
2024-03-08 15:39:06.305780-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305787-06:00File "/usr/local/lib/python3.12/site-packages/requests/sessions.py", line 602, in get
2024-03-08 15:39:06.305793-06:00return self.request("GET", url, **kwargs)
2024-03-08 15:39:06.305802-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305808-06:00File "/usr/local/lib/python3.12/site-packages/requests/sessions.py", line 589, in request
2024-03-08 15:39:06.305815-06:00resp = self.send(prep, **send_kwargs)
2024-03-08 15:39:06.305822-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305828-06:00File "/usr/local/lib/python3.12/site-packages/requests/sessions.py", line 703, in send
2024-03-08 15:39:06.305835-06:00r = adapter.send(request, **kwargs)
2024-03-08 15:39:06.305841-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305848-06:00File "/usr/local/lib/python3.12/site-packages/requests/adapters.py", line 486, in send
2024-03-08 15:39:06.305855-06:00resp = conn.urlopen(
2024-03-08 15:39:06.305861-06:00^^^^^^^^^^^^^
2024-03-08 15:39:06.305868-06:00File "/usr/local/lib/python3.12/site-packages/urllib3/connectionpool.py", line 790, in urlopen
2024-03-08 15:39:06.305875-06:00response = self._make_request(
2024-03-08 15:39:06.305881-06:00^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305888-06:00File "/usr/local/lib/python3.12/site-packages/urllib3/connectionpool.py", line 536, in _make_request
2024-03-08 15:39:06.305895-06:00response = conn.getresponse()
2024-03-08 15:39:06.305902-06:00^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.305909-06:00File "/usr/local/lib/python3.12/site-packages/urllib3/connection.py", line 461, in getresponse
2024-03-08 15:39:06.305915-06:00httplib_response = super().getresponse()
2024-03-08 15:39:06.309611-06:00^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.309651-06:00File "/usr/local/lib/python3.12/http/client.py", line 1423, in getresponse
2024-03-08 15:39:06.318214-06:00response.begin()
2024-03-08 15:39:06.318240-06:00File "/usr/local/lib/python3.12/http/client.py", line 350, in begin
2024-03-08 15:39:06.318248-06:00self.headers = self.msg = parse_headers(self.fp)
2024-03-08 15:39:06.318255-06:00^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318262-06:00File "/usr/local/lib/python3.12/http/client.py", line 249, in parse_headers
2024-03-08 15:39:06.318268-06:00return _parse_header_lines(headers, _class)
2024-03-08 15:39:06.318275-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318283-06:00File "/usr/local/lib/python3.12/http/client.py", line 243, in _parse_header_lines
2024-03-08 15:39:06.318290-06:00return email.parser.Parser(_class=_class).parsestr(hstring)
2024-03-08 15:39:06.318296-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318303-06:00File "/usr/local/lib/python3.12/email/parser.py", line 64, in parsestr
2024-03-08 15:39:06.318310-06:00return self.parse(StringIO(text), headersonly=headersonly)
2024-03-08 15:39:06.318316-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318322-06:00File "/usr/local/lib/python3.12/email/parser.py", line 53, in parse
2024-03-08 15:39:06.318329-06:00feedparser.feed(data)
2024-03-08 15:39:06.318335-06:00File "/usr/local/lib/python3.12/email/feedparser.py", line 174, in feed
2024-03-08 15:39:06.318342-06:00self._call_parse()
2024-03-08 15:39:06.318348-06:00File "/usr/local/lib/python3.12/email/feedparser.py", line 178, in _call_parse
2024-03-08 15:39:06.318355-06:00self._parse()
2024-03-08 15:39:06.318361-06:00File "/usr/local/lib/python3.12/email/feedparser.py", line 254, in _parsegen
2024-03-08 15:39:06.318368-06:00if self._cur.get_content_type() == 'message/delivery-status':
2024-03-08 15:39:06.318374-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318381-06:00File "/usr/local/lib/python3.12/email/message.py", line 610, in get_content_type
2024-03-08 15:39:06.318387-06:00value = self.get('content-type', missing)
2024-03-08 15:39:06.318393-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318400-06:00File "/usr/local/lib/python3.12/email/message.py", line 503, in get
2024-03-08 15:39:06.318407-06:00return self.policy.header_fetch_parse(k, v)
2024-03-08 15:39:06.318413-06:00^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-03-08 15:39:06.318420-06:00RecursionError: maximum recursion depth exceeded
cmathews393 commented 3 months ago

I got that error when I was testing stuff, but it was an issue with the loop, not with the scheduling... Hmm. I'll have to investigate