From 5265391ae462d1116210568b9becf5f2216ffed5 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Mon, 28 Jul 2025 16:06:57 -0700 Subject: [PATCH] good --- .spotify_cache | 2 +- core/__pycache__/plex_client.cpython-312.pyc | Bin 28845 -> 31647 bytes core/plex_client.py | 53 +++ logs/app.log | 416 ++++++++++++++++++ .../__pycache__/dashboard.cpython-312.pyc | Bin 52977 -> 71103 bytes ui/pages/dashboard.py | 390 +++++++++++++++- 6 files changed, 852 insertions(+), 9 deletions(-) diff --git a/.spotify_cache b/.spotify_cache index adb68578..4ca4ae48 100644 --- a/.spotify_cache +++ b/.spotify_cache @@ -1 +1 @@ -{"access_token": "BQDOhKfFATvb-8-rw278Xzc-T-QgPJ5_7mWFHT4yw83y2c5yvmDDQ8qdkKuiFc-Hfc8V7L6o_8w9d5Vl9TPuek9pxE-PNeNPwxsRn9CVScttd2_XEuxnR-ag53yqrMP4rSaUZnXT5pd1tqizay2aOpmdfV89BTg7-Vj3SARGgofrhBbJqO4hNZY5EqVGpWpDyzJCUeG4W7jvLC62eO8qFVpnbrqNdRKGMeZ6FfCdiVZfjrxlPv9a-LaUYeazk3aR", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753742887, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"} \ No newline at end of file +{"access_token": "BQCAxqYls1GZziWWT_RK2oephXS0gdOA6aCR_ylemRRdjvZ3ZAvgzQDiZcOvP6DdENbfoZK2d5m-a61GUp1syw9sMS6U3qjvjhGGgACvl4jytuArO-ht2crjJmeVdl_88YIrBMrlZsBnOAmOyPH8xA7X1i9hy5H5_nO32iiM1t96sm9rT9zIAe6gCQpDt36SbLafT2GZz_7dH3k6QVZRkuESnyr9xXznIsshhemd2UFnRnTGzg8ptWp7eCVAiL5d", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753746945, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"} \ No newline at end of file diff --git a/core/__pycache__/plex_client.cpython-312.pyc b/core/__pycache__/plex_client.cpython-312.pyc index ae8b0587c6227745833d5a399574ef4c30f7f17c..9f94c2e6a725fc24790bb23ab84bc4da0935bf47 100644 GIT binary patch delta 2529 zcmai#du&_P8Nly5wsRea`29$8lO|0AP11)_Z2^W7mn3aU1|)?xC^c^GapKgm!}ZOI zja`SS5~;*v)fp-kR80kfOuT|BAZVMEWI{p$fekK>tRS^gCvAUBG7ZuY`(yjgy>=I1 zgDd$v=X_6p*T3)h&Fl1~f6_G{o6RN)p0ED>)a1a)cWNFG={fwUxJWl)qq!@?AR}_Q z!5(5{`x$Q3EnARFc7RsYw4Ce&tw++eK_#YcKrKMH|tb6{EuND?r0S8+&u!eZgb*iJzg$NgCX-v->+mwHCN(O^y}qx zFH$mlk*%C)Dn$=d+bOlC;@M0o&1pu@&BJ;53 zBzN>9RSHHTQczLDaWyW5l-RVSP9kY~HXa_ABHT-g^}V!X}WahNBZ(YjsOQZ3g852v-ggag2yZh%zk?`xa`l9er6>e_k9|w|eG>zTL36Zc>cVp{JA&XTAHE9$OmEy1Vn@ zosjyOga0b=VE-;&4`1iqyL)(oHKPICzX=z?_% zT~$fjkr_FtqB0x60BI*_)wOc@EQJ6MlJw}X%#tudiyonQ4D|sle*&*!wSuN& zzd`*ZThS2A$g;N8`O&Cxf}2K-hEp4_+(#5HBD4&=mRF~U2Q5%k;mD@dMrDiw`WHwx z5TyN)Fp8=jKXk~DrrsuiU4T?`REaYi-Pha=m+CLn-=t{s?Z4yKYaNB!rd(~)Lf6&W zwh{}<6&Pkg{OlPC;;z0_`i93OXm$Y-s{24(ljc+-g`XVrI#O(kNpWxRua`+q^C^DHjGwf7fJI1RAzPZpzdkPU0-SAl z;o&A5;OBs^tUVfjf?A80{XRi9Xg*LlV@wI(r}h{no6^E*AyKWbTX+eqv&DhZQm~WEjc7)WN{`q)USr1`EF3Ip6NA zcTaYYf2FT*U?g{7B#n?bHyNrM`t9wm z{2~0@O!@So>UH<}s5PI_Z)4Y5TKpFFFBaZ!yRz@0^NjEr^r&QU_UIV><&}uxw|9!XW5KpCm22FyNx{D4v+(Z4 z?h*ydvby5`AhAidr6!xMhGnH|lY*tR3kRb&YBoq#0}+1%fk$JLyz&v*eG&`Mn|RlZ QVi`2h?KdeRl`gRS2eZlD@&Et; delta 356 zcmbRLopJ3$M!wU$yj%=G5UtUYp`5&tFOY}PV{!t|3P#zqNzM7VyR-OJgE|C zOp-u#DNLy>X>2LtEi6%zDRLs0)h9AEiF^f*X{14uwz=2%pcSzIzXuquP=7DrKP hVQFe{N%7=;Rq>4XCd*Y9@rSW9>V9GXkwvCJO#lYDV;BGc diff --git a/core/plex_client.py b/core/plex_client.py index 318924b4..56400cd2 100644 --- a/core/plex_client.py +++ b/core/plex_client.py @@ -414,6 +414,59 @@ class PlexClient: logger.error(f"Error getting library stats: {e}") return {} + def get_all_artists(self) -> List[PlexArtist]: + """Get all artists from the music library""" + if not self.ensure_connection() or not self.music_library: + logger.error("Not connected to Plex server or no music library") + return [] + + try: + artists = self.music_library.searchArtists() + logger.info(f"Found {len(artists)} artists in Plex library") + return artists + except Exception as e: + logger.error(f"Error getting all artists: {e}") + return [] + + def update_artist_genres(self, artist: PlexArtist, genres: List[str]): + """Update artist genres""" + try: + # Clear existing genres first + for genre in artist.genres: + artist.removeGenre(genre) + + # Add new genres + for genre in genres: + artist.addGenre(genre) + + logger.info(f"Updated genres for {artist.title}: {genres}") + return True + except Exception as e: + logger.error(f"Error updating genres for {artist.title}: {e}") + return False + + def update_artist_poster(self, artist: PlexArtist, image_data: bytes): + """Update artist poster image""" + try: + # Upload poster using Plex API + upload_url = f"{self.server._baseurl}/library/metadata/{artist.ratingKey}/posters" + headers = { + 'X-Plex-Token': self.server._token, + 'Content-Type': 'image/jpeg' + } + + response = requests.post(upload_url, data=image_data, headers=headers) + response.raise_for_status() + + # Refresh artist to see changes + artist.refresh() + logger.info(f"Updated poster for {artist.title}") + return True + + except Exception as e: + logger.error(f"Error updating poster for {artist.title}: {e}") + return False + def update_track_metadata(self, track_id: str, metadata: Dict[str, Any]) -> bool: if not self.ensure_connection(): return False diff --git a/logs/app.log b/logs/app.log index 928afd31..f5c28f41 100644 --- a/logs/app.log +++ b/logs/app.log @@ -213641,3 +213641,419 @@ 2025-07-28 15:30:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... 2025-07-28 15:30:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd 2025-07-28 15:30:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:32:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:32:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:32:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:32:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:32:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:32:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:32:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:33:00 - newmusic.main - INFO - change_page:278 - Changed to page: downloads +2025-07-28 15:33:02 - newmusic.soulseek_client - DEBUG - clear_all_completed_downloads:925 - Clearing all completed downloads with endpoint: transfers/downloads/all/completed +2025-07-28 15:33:02 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making DELETE request to: http://localhost:5030/api/v0/transfers/downloads/all/completed +2025-07-28 15:33:02 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:33:03 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 204 +2025-07-28 15:33:03 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: ... +2025-07-28 15:33:03 - newmusic.soulseek_client - INFO - clear_all_completed_downloads:930 - Successfully cleared all completed downloads from slskd +2025-07-28 15:33:04 - newmusic.main - INFO - change_page:278 - Changed to page: dashboard +2025-07-28 15:34:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:34:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:34:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:34:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:34:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:34:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:34:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:36:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:36:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:36:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:36:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:36:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:36:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:36:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:38:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:38:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:38:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:38:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:38:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:38:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:38:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:40:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:40:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:40:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:40:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:40:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:40:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:40:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:42:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:42:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:42:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:42:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:42:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:42:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:42:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:44:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:44:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:44:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:44:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:44:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:44:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:44:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:46:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:46:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:46:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:46:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:46:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:46:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:46:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:48:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:48:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:48:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:48:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:48:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:48:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:48:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:50:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:50:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:50:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:50:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:50:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:50:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:50:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:52:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:52:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:52:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:52:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:52:37 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:52:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:52:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:53:23 - newmusic.main - INFO - closeEvent:295 - Closing application... +2025-07-28 15:53:23 - newmusic.main - INFO - closeEvent:300 - Cleaning up Downloads page threads... +2025-07-28 15:53:23 - newmusic.main - INFO - closeEvent:305 - Stopping status monitoring thread... +2025-07-28 15:53:25 - newmusic.main - INFO - closeEvent:310 - Stopping search maintenance timer... +2025-07-28 15:53:25 - newmusic.main - INFO - closeEvent:315 - Closing Soulseek client... +2025-07-28 15:53:25 - newmusic.main - ERROR - closeEvent:319 - Error closing Soulseek client: Event loop is closed +2025-07-28 15:53:25 - newmusic.main - INFO - closeEvent:321 - Application closed successfully +2025-07-28 15:53:30 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-28 15:53:30 - newmusic.main - INFO - main:335 - Starting NewMusic application +2025-07-28 15:53:30 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:53:30 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 15:53:30 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:53:31 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:53:31 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 15:53:31 - newmusic.main - INFO - change_page:278 - Changed to page: dashboard +2025-07-28 15:53:31 - newmusic.main - INFO - setup_media_player_connections:230 - Media player connections established between sidebar and downloads page +2025-07-28 15:53:31 - newmusic.main - INFO - setup_settings_connections:235 - Settings change connections established +2025-07-28 15:53:31 - newmusic.main - INFO - setup_search_maintenance:91 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-28 15:53:31 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-28 15:53:31 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-28 15:55:05 - newmusic.main - INFO - closeEvent:295 - Closing application... +2025-07-28 15:55:05 - newmusic.main - INFO - closeEvent:300 - Cleaning up Downloads page threads... +2025-07-28 15:55:05 - newmusic.main - INFO - closeEvent:305 - Stopping status monitoring thread... +2025-07-28 15:55:07 - newmusic.main - INFO - closeEvent:310 - Stopping search maintenance timer... +2025-07-28 15:55:07 - newmusic.main - INFO - closeEvent:315 - Closing Soulseek client... +2025-07-28 15:55:07 - newmusic.main - INFO - closeEvent:321 - Application closed successfully +2025-07-28 15:55:37 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-28 15:55:37 - newmusic.main - INFO - main:335 - Starting NewMusic application +2025-07-28 15:55:37 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:55:37 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 15:55:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:55:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 15:55:38 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 15:55:38 - newmusic.main - INFO - change_page:278 - Changed to page: dashboard +2025-07-28 15:55:38 - newmusic.main - INFO - setup_media_player_connections:230 - Media player connections established between sidebar and downloads page +2025-07-28 15:55:38 - newmusic.main - INFO - setup_settings_connections:235 - Settings change connections established +2025-07-28 15:55:38 - newmusic.main - INFO - setup_search_maintenance:91 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-28 15:55:38 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-28 15:55:38 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-28 15:55:43 - newmusic.plex_client - INFO - get_all_artists:425 - Found 3795 artists in Plex library +2025-07-28 15:55:46 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for _tillus: ['lo-fi house', 'Rap/Hip Hop'] +2025-07-28 15:55:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for !Nxght: ['Electro', 'brazilian phonk'] +2025-07-28 15:55:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $ebu: ['Electro', 'phonk', 'Dance', 'drift phonk', 'Rap/Hip Hop'] +2025-07-28 15:55:50 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['emo rap', 'horrorcore', 'Rap', 'trap metal', 'underground hip hop', 'cloud rap', 'Rap/Hip Hop'] +2025-07-28 15:55:51 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['emo rap', 'horrorcore', 'trap metal', 'underground hip hop', 'cloud rap'] +2025-07-28 15:55:52 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $YANIC: ['Electro', 'phonk', 'brazilian phonk', 'Dance', 'Soul & Funk', 'Rap/Hip Hop'] +2025-07-28 15:55:54 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyssee: ['Electro', 'lo-fi beats', 'lo-fi hip hop', 'lo-fi', 'jazz beats', 'Chill Out/Trip hop/Lounge', 'Rap/Hip Hop'] +2025-07-28 15:55:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyzon: ['Electro', 'Alternative', 'Pop', 'Dance', 'ambient', 'dark ambient'] +2025-07-28 15:55:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øneheart: ['Electro', 'Pop', 'ambient', 'Rap/Hip Hop', 'Indie Pop', 'Alternative', 'Dance', 'dark ambient'] +2025-07-28 15:55:58 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øutgrown: ['lo-fi', 'Electro', 'Alternative', 'dark ambient'] +2025-07-28 15:56:00 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for The 2 Bears: ['Electro', 'Dance', 'Pop/Rock', 'Electronic', 'Techno/House'] +2025-07-28 15:56:02 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2.brkn: ['Indie Pop', 'Alternative', 'Rap/Hip Hop'] +2025-07-28 15:56:06 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Pac: ['hip hop', 'gangster rap', 'Rap', 'Pop/Rock', 'east coast hip hop', 'old school hip hop'] +2025-07-28 15:56:07 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Rare: ['jersey club', 'philly club', 'Rap/Hip Hop'] +2025-07-28 15:56:10 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3d Blast: ['vaporwave'] +2025-07-28 15:56:11 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3LAU: ['edm', 'Electronic', 'progressive house', 'dubstep'] +2025-07-28 15:56:12 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3TEETH: ['noise rock', 'industrial', 'witch house'] +2025-07-28 15:56:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3x3cute: ['techno'] +2025-07-28 15:56:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4batz: ['alternative r&b'] +2025-07-28 15:56:17 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4Scythe: ['Alternative', 'horrorcore', 'Indie Rock', 'trap metal', 'Rap/Hip Hop'] +2025-07-28 15:56:20 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5AM: ['Electro', 'glitch', 'bass music'] +2025-07-28 15:56:22 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5MIINUST: ['Rap/Hip Hop'] +2025-07-28 15:56:23 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 6YNTHMANE: ['Electro', 'phonk', 'brazilian phonk'] +2025-07-28 15:56:24 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7-Pm: ['lo-fi', 'lo-fi beats', 'Rap/Hip Hop'] +2025-07-28 15:56:29 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7vvch: ['drift phonk', 'phonk', 'Dance'] +2025-07-28 15:56:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 9Lives: ['Rap/Hip Hop', 'nightcore', 'hyperpop'] +2025-07-28 15:56:34 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 18FEARS: ['Electro', 'ambient', 'Alternative', 'dark ambient'] +2025-07-28 15:56:40 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 50 Cent: ['hip hop', 'Rap', 'Pop/Rock', 'Rap/Hip Hop', 'rap'] +2025-07-28 15:56:43 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 81an: ['Electro', 'phonk', 'Dance'] +2025-07-28 15:56:44 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 88rising: ['Rap', 'Pop/Rock', 'Stage & Screen', 'R&B'] +2025-07-28 15:56:52 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 1788-L: ['Electronic', 'dubstep', 'Dance'] +2025-07-28 15:56:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 121569: ['Electro', 'Chill Out/Trip hop/Lounge'] +2025-07-28 15:56:58 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for a-ha: ['Pop/Rock', 'new wave', 'synthpop'] +2025-07-28 15:56:59 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A-Trak: ['Electronic', 'downtempo', 'french house', 'french indie pop'] +2025-07-28 15:57:00 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A. G. Cook: ['Pop/Rock', 'Electronic', 'hyperpop'] +2025-07-28 15:57:01 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.e.r.o.: ['space music', 'Electro', 'Chill Out/Trip hop/Lounge', 'ambient'] +2025-07-28 15:57:04 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.L.I.S.O.N: ['Electro', 'synthwave', 'vaporwave', 'Dance', 'chillwave'] +2025-07-28 15:57:07 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Ferg: ['Rap', 'Rap/Hip Hop', 'rap'] +2025-07-28 15:57:08 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Rocky: ['Rap', 'rap'] +2025-07-28 15:57:22 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abakus: ['Electro', 'Dance', 'Electronic', 'downtempo', 'Chill Out/Trip hop/Lounge', 'Rap/Hip Hop'] +2025-07-28 15:57:24 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abe M Beats: ['Rap/Hip Hop'] +2025-07-28 15:57:25 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abigail Washburn: ['newgrass', 'Country', 'bluegrass', 'Folk', 'americana', 'folk'] +2025-07-28 15:57:27 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Above & Beyond: ['progressive trance', 'trance', 'progressive house'] +2025-07-28 15:57:28 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abra Cadabra: ['drill', 'grime', 'Rap', 'R&B', 'uk drill', 'Rap/Hip Hop', 'afroswing', 'uk grime'] +2025-07-28 15:57:30 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Absolute Valentine: ['synthwave', 'vaporwave'] +2025-07-28 15:57:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AC/DC: ['Stage & Screen', 'Pop/Rock', 'rock', 'classic rock'] +2025-07-28 15:57:33 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Accomplice: ['dubstep', 'Rap/Hip Hop'] +2025-07-28 15:57:36 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Acedox: ['merengue', 'Rap/Hip Hop'] +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:57:38 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Acey: ['Electro', 'Alternative', 'Pop', 'R&B', 'African Music', 'Indie Pop', 'Rap/Hip Hop'] +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:57:38 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:57:38 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:57:39 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for achorda: ['Electro', 'ambient', 'Alternative', 'dark ambient'] +2025-07-28 15:57:41 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for acidcrvsh: ['Electro', 'breakcore', 'jungle', 'Dance'] +2025-07-28 15:57:45 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adam Beyer: ['Electro', 'Dance'] +2025-07-28 15:57:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adam Ford: ['Electro', 'synthwave', 'vaporwave', 'Alternative', 'chillwave', 'Indie Rock'] +2025-07-28 15:57:54 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adeki: ['afro r&b', 'afro soul', 'Electro', 'Pop', 'afrobeats', 'afrobeat', 'afropop', 'afropiano', 'Humor', 'alté'] +2025-07-28 15:57:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adekunle Gold: ['afropop', 'R&B', 'African Music', 'afrobeats', 'afrobeat', 'afropiano'] +2025-07-28 15:57:57 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adele: ['soft pop', 'Pop/Rock'] +2025-07-28 15:58:01 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adieu Aru: ['Electro', 'synthwave', 'vaporwave', 'Dance', 'chillwave'] +2025-07-28 15:58:02 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for ADIV CULTURE: ['brazilian trap', 'Rap/Hip Hop'] +2025-07-28 15:58:03 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Admo: ['Electro', 'synthwave', 'vaporwave', 'Dance', 'chillwave', 'Techno/House'] +2025-07-28 15:58:04 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Admo: ['Electro', 'synthwave', 'vaporwave', 'chillwave', 'Alternativo', 'Techno/House'] +2025-07-28 15:58:06 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adrian Quesada: ['Latin', 'R&B', 'retro soul'] +2025-07-28 15:58:08 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adrian Underhill: ['Indie Pop', 'Alternative', 'Pop', 'R&B'] +2025-07-28 15:58:14 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for aespa: ['International', 'Pop/Rock', 'k-pop'] +2025-07-28 15:58:21 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Aexion: ['Electro', 'vaporwave', 'Dance'] +2025-07-28 15:58:23 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Affectwave: ['witch house'] +2025-07-28 15:58:26 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Afrojack: ['edm', 'Electronic', 'Dance'] +2025-07-28 15:58:27 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for after noon: ['lo-fi', 'lo-fi beats', 'Rap/Hip Hop'] +2025-07-28 15:58:38 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Air: ['downtempo', 'trip hop'] +2025-07-28 15:58:39 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Air: ['Comedy/Spoken', 'Pop/Rock', 'Electronic', 'downtempo', 'trip hop'] +2025-07-28 15:58:42 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Aisha Badru: ['Electro', 'Alternative', 'Folk', 'Pop/Rock', 'Singer & Songwriter'] +2025-07-28 15:58:44 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AiYo: ['Pop', 'R&B', 'Rap/Hip Hop'] +2025-07-28 15:58:45 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AJ Suede: ['underground hip hop'] +2025-07-28 15:58:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AK420: ['lo-fi beats', 'jazz rap', 'Rap/Hip Hop', 'jazz beats', 'boom bap'] +2025-07-28 15:58:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AkaHendy: ['Dubstep', 'Electro', 'chillstep', 'Dance', 'Chill Out/Trip hop/Lounge'] +2025-07-28 15:58:50 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Akal Dub: ['Electro', 'Chill Out/Trip-Hop/Lounge', 'Techno/House'] +2025-07-28 15:58:51 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Akhmedov: ['Electro', 'phonk', 'brazilian phonk', 'Dance'] +2025-07-28 15:58:58 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Akira The Don: ['Rock', 'spoken word', 'Electro', 'Pop', 'Rap/Hip Hop'] +2025-07-28 15:58:59 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for akitakita: ['Electro', 'breakcore', 'jungle', 'Alternative', 'Dance', 'Indie Pop'] +2025-07-28 15:59:04 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Al'Tarba: ['Electro', 'Chill Out/Trip-Hop/Lounge', 'Dance', 'Rap/Hip Hop'] +2025-07-28 15:59:06 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alan: ['Electro', 'Dance'] +2025-07-28 15:59:07 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alan Walker: ['edm', 'Electronic'] +2025-07-28 15:59:09 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alanis Morissette: ['Pop/Rock', 'Stage & Screen', 'Pop', 'New Age'] +2025-07-28 15:59:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Albee Al: ['Rap/Hip Hop'] +2025-07-28 15:59:14 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Albert Collins: ['blues rock', 'classic blues', 'blues'] +2025-07-28 15:59:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alberta Cross: ['Indie Pop', 'Alternative'] +2025-07-28 15:59:16 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alberto Droguett: ['lo-fi beats', 'lo-fi hip hop', 'lo-fi', 'jazz beats', 'Rap/Hip Hop'] +2025-07-28 15:59:19 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for alcinous: ['Electro', 'lo-fi beats', 'Alternative', 'Pop', 'lo-fi', 'Rap/Hip Hop', 'dark ambient'] +2025-07-28 15:59:24 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alecs Delarge: ['lo-fi beats', 'jazz beats', 'Rap/Hip Hop'] +2025-07-28 15:59:25 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alejandro Sanz: ['Pop internacional', 'italo dance', 'Pop'] +2025-07-28 15:59:29 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alesso: ['Pop/Rock', 'Electronic'] +2025-07-28 15:59:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Aletta Vilkier: ['Electro', 'vaporwave', 'Alternative', 'Pop', 'Dance', 'Latin Music'] +2025-07-28 15:59:35 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alex Boychuk: ['chillwave', 'synthwave', 'vaporwave'] +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 15:59:38 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 15:59:38 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 15:59:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alex Sensation: ['Rap', 'reggaeton'] +2025-07-28 15:59:48 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alex Somers: ['Electro', 'Electronic', 'ambient', 'Pop/Rock', 'Alternativo', 'post-rock'] +2025-07-28 15:59:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alex The Flipper: ['Electro', 'Pop', 'Rap/Hip Hop'] +2025-07-28 15:59:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alfie-Jay Winters: ['Alternative'] +2025-07-28 16:00:01 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Algiers: ['Pop/Rock', 'Alternativo', 'post-punk'] +2025-07-28 16:00:02 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ali Gatie: ['Pop/Rock', 'Pop', 'R&B', 'Rap/Hip Hop'] +2025-07-28 16:00:03 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ali Whales: ['german hip hop', 'Rap/Hip Hop'] +2025-07-28 16:00:06 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alien Cake Music: ['Pop', 'grunge', 'lo-fi', 'Film Scores', 'Alternative', 'pop punk', 'Films/Games', 'Rap/Hip Hop'] +2025-07-28 16:00:08 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Alina Baraz: ['Electro', 'Electronic', 'Dance'] +2025-07-28 16:00:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for alixe.: ['Electro', 'ambient', 'Alternative', 'dark ambient'] +2025-07-28 16:00:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for All But 6: ['cloud rap', 'emo rap', 'horrorcore', 'underground hip hop', 'trap metal', 'Rap/Hip Hop'] +2025-07-28 16:00:20 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for The All-American Rejects: ['Pop/Rock', 'emo', 'pop punk'] +2025-07-28 16:00:21 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Allan Rayman: ['Rock', 'Alternative', 'R&B', 'Rap', 'Pop/Rock', 'Indie Rock'] +2025-07-28 16:00:25 - newmusic.main - INFO - closeEvent:295 - Closing application... +2025-07-28 16:00:25 - newmusic.main - INFO - closeEvent:300 - Cleaning up Downloads page threads... +2025-07-28 16:00:25 - newmusic.main - INFO - closeEvent:305 - Stopping status monitoring thread... +2025-07-28 16:00:27 - newmusic.main - INFO - closeEvent:310 - Stopping search maintenance timer... +2025-07-28 16:00:27 - newmusic.main - INFO - closeEvent:315 - Closing Soulseek client... +2025-07-28 16:00:27 - newmusic.main - INFO - closeEvent:321 - Application closed successfully +2025-07-28 16:00:31 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-28 16:00:31 - newmusic.main - INFO - main:335 - Starting NewMusic application +2025-07-28 16:00:31 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:00:31 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 16:00:36 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:00:36 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:00:36 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 16:00:36 - newmusic.main - INFO - change_page:278 - Changed to page: dashboard +2025-07-28 16:00:36 - newmusic.main - INFO - setup_media_player_connections:230 - Media player connections established between sidebar and downloads page +2025-07-28 16:00:36 - newmusic.main - INFO - setup_settings_connections:235 - Settings change connections established +2025-07-28 16:00:36 - newmusic.main - INFO - setup_search_maintenance:91 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-28 16:00:36 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-28 16:00:36 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-28 16:01:42 - newmusic.plex_client - INFO - get_all_artists:425 - Found 3795 artists in Plex library +2025-07-28 16:01:44 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for _tillus: ['lo-fi house', 'Rap/Hip Hop'] +2025-07-28 16:01:45 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for !Nxght: ['Electro', 'brazilian phonk'] +2025-07-28 16:01:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $ebu: ['Electro', 'drift phonk', 'phonk', 'Dance', 'Rap/Hip Hop'] +2025-07-28 16:01:48 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['cloud rap', 'emo rap', 'trap metal', 'horrorcore', 'Rap', 'underground hip hop', 'Rap/Hip Hop'] +2025-07-28 16:01:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['cloud rap', 'emo rap', 'trap metal', 'horrorcore', 'underground hip hop'] +2025-07-28 16:01:50 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $YANIC: ['Electro', 'phonk', 'brazilian phonk', 'Dance', 'Rap/Hip Hop', 'Soul & Funk'] +2025-07-28 16:01:52 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyssee: ['Electro', 'lo-fi', 'lo-fi hip hop', 'Chill Out/Trip hop/Lounge', 'lo-fi beats', 'Rap/Hip Hop', 'jazz beats'] +2025-07-28 16:01:53 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyzon: ['Electro', 'dark ambient', 'Alternative', 'ambient', 'Dance', 'Pop'] +2025-07-28 16:01:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øneheart: ['Electro', 'Indie Pop', 'dark ambient', 'Alternative', 'ambient', 'Dance', 'Pop', 'Rap/Hip Hop'] +2025-07-28 16:01:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øutgrown: ['Electro', 'lo-fi', 'Alternative', 'dark ambient'] +2025-07-28 16:01:58 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for The 2 Bears: ['Electro', 'Electronic', 'Dance', 'Techno/House', 'Pop/Rock'] +2025-07-28 16:02:00 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2.brkn: ['Rap/Hip Hop', 'Indie Pop', 'Alternative'] +2025-07-28 16:02:04 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Pac: ['old school hip hop', 'gangster rap', 'Rap', 'hip hop', 'Pop/Rock', 'east coast hip hop'] +2025-07-28 16:02:05 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Rare: ['Rap/Hip Hop', 'jersey club', 'philly club'] +2025-07-28 16:02:07 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3d Blast: ['vaporwave'] +2025-07-28 16:02:09 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3LAU: ['edm', 'Electronic', 'dubstep', 'progressive house'] +2025-07-28 16:02:10 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3TEETH: ['industrial', 'noise rock', 'witch house'] +2025-07-28 16:02:11 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3x3cute: ['techno'] +2025-07-28 16:02:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4batz: ['alternative r&b'] +2025-07-28 16:02:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4Scythe: ['Alternative', 'Indie Rock', 'trap metal', 'horrorcore', 'Rap/Hip Hop'] +2025-07-28 16:02:17 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5AM: ['Electro', 'glitch', 'bass music'] +2025-07-28 16:02:19 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5MIINUST: ['Rap/Hip Hop'] +2025-07-28 16:02:20 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 6YNTHMANE: ['Electro', 'phonk', 'brazilian phonk'] +2025-07-28 16:02:21 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7-Pm: ['Rap/Hip Hop', 'lo-fi', 'lo-fi beats'] +2025-07-28 16:02:25 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7vvch: ['phonk', 'Dance', 'drift phonk'] +2025-07-28 16:02:28 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 9Lives: ['Rap/Hip Hop', 'hyperpop', 'nightcore'] +2025-07-28 16:02:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 18FEARS: ['Electro', 'dark ambient', 'ambient', 'Alternative'] +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 16:02:36 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 50 Cent: ['rap', 'Rap', 'hip hop', 'Pop/Rock', 'Rap/Hip Hop'] +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 16:02:36 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 16:02:36 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 16:02:39 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 81an: ['Electro', 'phonk', 'Dance'] +2025-07-28 16:02:40 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 88rising: ['Pop/Rock', 'R&B', 'Rap', 'Stage & Screen'] +2025-07-28 16:02:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 1788-L: ['Electronic', 'dubstep', 'Dance'] +2025-07-28 16:02:53 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for a-ha: ['Pop/Rock', 'new wave', 'synthpop'] +2025-07-28 16:02:54 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A-Trak: ['downtempo', 'Electronic', 'french house', 'french indie pop'] +2025-07-28 16:02:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A. G. Cook: ['Pop/Rock', 'hyperpop', 'Electronic'] +2025-07-28 16:02:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.e.r.o.: ['Electro', 'Chill Out/Trip hop/Lounge', 'ambient', 'space music'] +2025-07-28 16:02:59 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.L.I.S.O.N: ['Electro', 'chillwave', 'Dance', 'synthwave', 'vaporwave'] +2025-07-28 16:03:01 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Ferg: ['Rap/Hip Hop', 'rap', 'Rap'] +2025-07-28 16:03:02 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Rocky: ['rap', 'Rap'] +2025-07-28 16:03:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abakus: ['Electro', 'Electronic', 'Chill Out/Trip hop/Lounge', 'Dance', 'downtempo', 'Rap/Hip Hop'] +2025-07-28 16:03:17 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abe M Beats: ['Rap/Hip Hop'] +2025-07-28 16:03:18 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abigail Washburn: ['Folk', 'newgrass', 'folk', 'americana', 'bluegrass', 'Country'] +2025-07-28 16:03:20 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Above & Beyond: ['trance', 'progressive house', 'progressive trance'] +2025-07-28 16:03:22 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Abra Cadabra: ['drill', 'R&B', 'afroswing', 'grime', 'uk grime', 'Rap', 'Rap/Hip Hop', 'uk drill'] +2025-07-28 16:03:23 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Absolute Valentine: ['synthwave', 'vaporwave'] +2025-07-28 16:03:25 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AC/DC: ['Pop/Rock', 'classic rock', 'Stage & Screen', 'rock'] +2025-07-28 16:03:26 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Accomplice: ['Rap/Hip Hop', 'dubstep'] +2025-07-28 16:03:29 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Acedox: ['Rap/Hip Hop', 'merengue'] +2025-07-28 16:03:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Acey: ['Electro', 'Indie Pop', 'R&B', 'Alternative', 'Pop', 'African Music', 'Rap/Hip Hop'] +2025-07-28 16:03:32 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for achorda: ['Electro', 'dark ambient', 'ambient', 'Alternative'] +2025-07-28 16:03:33 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for acidcrvsh: ['Electro', 'breakcore', 'Dance', 'jungle'] +2025-07-28 16:03:37 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adam Beyer: ['Electro', 'Dance'] +2025-07-28 16:03:41 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adam Ford: ['Electro', 'Alternative', 'chillwave', 'Indie Rock', 'synthwave', 'vaporwave'] +2025-07-28 16:03:46 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adeki: ['alté', 'afrobeats', 'afro soul', 'Electro', 'afropiano', 'afroswing', 'afropop', 'Películas/Juegos', 'Pop', 'afrobeat'] +2025-07-28 16:03:47 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adekunle Gold: ['afrobeats', 'R&B', 'afropiano', 'afropop', 'afrobeat', 'African Music'] +2025-07-28 16:03:49 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adele: ['Pop/Rock', 'soft pop'] +2025-07-28 16:03:52 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adieu Aru: ['Electro', 'chillwave', 'Dance', 'synthwave', 'vaporwave'] +2025-07-28 16:03:53 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for ADIV CULTURE: ['Rap/Hip Hop', 'brazilian trap'] +2025-07-28 16:03:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Admo: ['Electro', 'chillwave', 'Dance', 'synthwave', 'Techno/House', 'vaporwave'] +2025-07-28 16:03:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Admo: ['Electro', 'chillwave', 'Alternativo', 'synthwave', 'Techno/House', 'vaporwave'] +2025-07-28 16:03:57 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adrian Quesada: ['retro soul', 'Latin', 'R&B'] +2025-07-28 16:03:59 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Adrian Underhill: ['Indie Pop', 'R&B', 'Alternative', 'Pop'] +2025-07-28 16:04:05 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for aespa: ['Pop/Rock', 'k-pop', 'International'] +2025-07-28 16:04:11 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Aexion: ['Electro', 'Dance', 'vaporwave'] +2025-07-28 16:04:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Affectwave: ['witch house'] +2025-07-28 16:04:17 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Afrojack: ['edm', 'Electronic', 'Dance'] +2025-07-28 16:04:18 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for after noon: ['Rap/Hip Hop', 'lo-fi', 'lo-fi beats'] +2025-07-28 16:04:28 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Air: ['trip hop', 'downtempo'] +2025-07-28 16:04:29 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Air: ['trip hop', 'Electronic', 'Comedy/Spoken', 'downtempo', 'Pop/Rock'] +2025-07-28 16:04:32 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Aisha Badru: ['Electro', 'Folk', 'Singer & Songwriter', 'Alternative', 'Pop/Rock'] +2025-07-28 16:04:34 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AiYo: ['Rap/Hip Hop', 'R&B', 'Pop'] +2025-07-28 16:04:35 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AJ Suede: ['underground hip hop'] +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - _make_request:255 - Response text: [{"endedAt":"2025-07-27T21:28:19.7264233Z","fileCount":13,"id":"41b335b7-58a3-4201-8506-22e0954564eb","isComplete":true,"lockedFileCount":0,"responseCount":12,"responses":[],"searchText":"Tommy Cash Baba Yaga","startedAt":"2025-07-27T21:28:02.1709869Z","state":"Completed, TimedOut","token":80},{"endedAt":"2025-07-27T21:28:20.4645342Z","fileCount":5,"id":"7e66f9a9-00ac-451b-a199-5f6a7f18930c","isComplete":true,"lockedFileCount":0,"responseCount":5,"responses":[],"searchText":"Tommy Cash SugaSuga"... +2025-07-28 16:04:36 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 106 searches from slskd +2025-07-28 16:04:36 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (106) within limit (200), no maintenance needed +2025-07-28 16:04:37 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AK420: ['jazz rap', 'boom bap', 'lo-fi beats', 'Rap/Hip Hop', 'jazz beats'] +2025-07-28 16:04:39 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for AkaHendy: ['Electro', 'Chill Out/Trip hop/Lounge', 'Dance', 'chillstep', 'Dubstep'] +2025-07-28 16:04:40 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Akal Dub: ['Electro', 'Chill Out/Trip-Hop/Lounge', 'Techno/House'] +2025-07-28 16:04:41 - newmusic.main - INFO - closeEvent:295 - Closing application... +2025-07-28 16:04:41 - newmusic.main - INFO - closeEvent:300 - Cleaning up Downloads page threads... +2025-07-28 16:04:41 - newmusic.main - INFO - closeEvent:305 - Stopping status monitoring thread... +2025-07-28 16:04:43 - newmusic.main - INFO - closeEvent:310 - Stopping search maintenance timer... +2025-07-28 16:04:43 - newmusic.main - INFO - closeEvent:315 - Closing Soulseek client... +2025-07-28 16:04:43 - newmusic.main - INFO - closeEvent:321 - Application closed successfully +2025-07-28 16:04:51 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-28 16:04:51 - newmusic.main - INFO - main:335 - Starting NewMusic application +2025-07-28 16:04:51 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:04:51 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 16:04:51 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:04:51 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-28 16:04:51 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-28 16:04:51 - newmusic.main - INFO - change_page:278 - Changed to page: dashboard +2025-07-28 16:04:51 - newmusic.main - INFO - setup_media_player_connections:230 - Media player connections established between sidebar and downloads page +2025-07-28 16:04:51 - newmusic.main - INFO - setup_settings_connections:235 - Settings change connections established +2025-07-28 16:04:51 - newmusic.main - INFO - setup_search_maintenance:91 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-28 16:04:51 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-28 16:04:51 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-28 16:04:57 - newmusic.plex_client - INFO - get_all_artists:425 - Found 3795 artists in Plex library +2025-07-28 16:04:59 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for _tillus: ['Rap/Hip Hop', 'lo-fi house'] +2025-07-28 16:05:00 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for !Nxght: ['brazilian phonk', 'Electro'] +2025-07-28 16:05:02 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $ebu: ['phonk', 'drift phonk', 'Electro', 'Dance', 'Rap/Hip Hop'] +2025-07-28 16:05:03 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['horrorcore', 'emo rap', 'Rap', 'cloud rap', 'Rap/Hip Hop', 'underground hip hop', 'trap metal'] +2025-07-28 16:05:04 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $uicideboy$: ['horrorcore', 'emo rap', 'cloud rap', 'underground hip hop', 'trap metal'] +2025-07-28 16:05:05 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for $YANIC: ['phonk', 'Electro', 'Rap/Hip Hop', 'Dance', 'brazilian phonk', 'Soul & Funk'] +2025-07-28 16:05:07 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyssee: ['lo-fi', 'Chill Out/Trip hop/Lounge', 'jazz beats', 'lo-fi beats', 'Electro', 'lo-fi hip hop', 'Rap/Hip Hop'] +2025-07-28 16:05:08 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Ødyzon: ['Electro', 'ambient', 'Alternative', 'Dance', 'Pop', 'dark ambient'] +2025-07-28 16:05:09 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øneheart: ['Indie Pop', 'Electro', 'ambient', 'Alternative', 'Dance', 'Pop', 'Rap/Hip Hop', 'dark ambient'] +2025-07-28 16:05:10 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for Øutgrown: ['lo-fi', 'Alternative', 'dark ambient', 'Electro'] +2025-07-28 16:05:13 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for The 2 Bears: ['Electronic', 'Electro', 'Dance', 'Pop/Rock', 'Techno/House'] +2025-07-28 16:05:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2.brkn: ['Rap/Hip Hop', 'Alternative', 'Indie Pop'] +2025-07-28 16:05:18 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Pac: ['hip hop', 'gangster rap', 'Rap', 'east coast hip hop', 'Pop/Rock', 'old school hip hop'] +2025-07-28 16:05:20 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 2Rare: ['philly club', 'Rap/Hip Hop', 'jersey club'] +2025-07-28 16:05:22 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3d Blast: ['vaporwave'] +2025-07-28 16:05:23 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3LAU: ['dubstep', 'Electronic', 'progressive house', 'edm'] +2025-07-28 16:05:24 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3TEETH: ['witch house', 'industrial', 'noise rock'] +2025-07-28 16:05:25 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 3x3cute: ['techno'] +2025-07-28 16:05:27 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4batz: ['alternative r&b'] +2025-07-28 16:05:29 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 4Scythe: ['horrorcore', 'Indie Rock', 'Alternative', 'Rap/Hip Hop', 'trap metal'] +2025-07-28 16:05:31 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5AM: ['glitch', 'bass music', 'Electro'] +2025-07-28 16:05:33 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 5MIINUST: ['Rap/Hip Hop'] +2025-07-28 16:05:34 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 6YNTHMANE: ['brazilian phonk', 'phonk', 'Electro'] +2025-07-28 16:05:35 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7-Pm: ['lo-fi beats', 'lo-fi', 'Rap/Hip Hop'] +2025-07-28 16:05:40 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 7vvch: ['phonk', 'Dance', 'drift phonk'] +2025-07-28 16:05:42 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 9Lives: ['nightcore', 'Rap/Hip Hop', 'hyperpop'] +2025-07-28 16:05:46 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 18FEARS: ['Alternative', 'dark ambient', 'Electro', 'ambient'] +2025-07-28 16:05:52 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 50 Cent: ['rap', 'hip hop', 'Rap', 'Rap/Hip Hop', 'Pop/Rock'] +2025-07-28 16:05:55 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 81an: ['phonk', 'Dance', 'Electro'] +2025-07-28 16:05:56 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 88rising: ['R&B', 'Pop/Rock', 'Stage & Screen', 'Rap'] +2025-07-28 16:06:03 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for 1788-L: ['dubstep', 'Electronic', 'Dance'] +2025-07-28 16:06:09 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for a-ha: ['new wave', 'Pop/Rock', 'synthpop'] +2025-07-28 16:06:10 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A-Trak: ['french house', 'Electronic', 'downtempo', 'french indie pop'] +2025-07-28 16:06:11 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A. G. Cook: ['Pop/Rock', 'Electronic', 'hyperpop'] +2025-07-28 16:06:12 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.e.r.o.: ['space music', 'Chill Out/Trip hop/Lounge', 'Electro', 'ambient'] +2025-07-28 16:06:15 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A.L.I.S.O.N: ['Electro', 'synthwave', 'Dance', 'chillwave', 'vaporwave'] +2025-07-28 16:06:17 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Ferg: ['Rap/Hip Hop', 'rap', 'Rap'] +2025-07-28 16:06:19 - newmusic.plex_client - INFO - update_artist_genres:442 - Updated genres for A$AP Rocky: ['rap', 'Rap'] +2025-07-28 16:06:48 - newmusic.main - INFO - closeEvent:295 - Closing application... +2025-07-28 16:06:48 - newmusic.main - INFO - closeEvent:300 - Cleaning up Downloads page threads... +2025-07-28 16:06:48 - newmusic.main - INFO - closeEvent:305 - Stopping status monitoring thread... +2025-07-28 16:06:49 - newmusic.main - INFO - closeEvent:310 - Stopping search maintenance timer... +2025-07-28 16:06:49 - newmusic.main - INFO - closeEvent:315 - Closing Soulseek client... +2025-07-28 16:06:49 - newmusic.main - INFO - closeEvent:321 - Application closed successfully diff --git a/ui/pages/__pycache__/dashboard.cpython-312.pyc b/ui/pages/__pycache__/dashboard.cpython-312.pyc index a15033cf7c8dae7a3f79207c3c737953b225f75a..2f87c4113880059badd8ca0745bed54f06a5edc8 100644 GIT binary patch delta 23497 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 delta 8443 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 diff --git a/ui/pages/dashboard.py b/ui/pages/dashboard.py index b673cf0a..4af881aa 100644 --- a/ui/pages/dashboard.py +++ b/ui/pages/dashboard.py @@ -15,6 +15,276 @@ import os from typing import Optional, Dict, Any from datetime import datetime from dataclasses import dataclass +import requests +from PIL import Image +import io + +class MetadataUpdateWorker(QThread): + """Worker thread for updating Plex artist metadata using Spotify data""" + progress_updated = pyqtSignal(str, int, int, float) # current_artist, processed, total, percentage + artist_updated = pyqtSignal(str, bool, str) # artist_name, success, details + finished = pyqtSignal(int, int, int) # total_processed, successful, failed + error = pyqtSignal(str) # error_message + artists_loaded = pyqtSignal(int, int) # total_artists, artists_to_process + + def __init__(self, artists, plex_client, spotify_client): + super().__init__() + self.artists = artists + self.plex_client = plex_client + self.spotify_client = spotify_client + self.should_stop = False + self.processed_count = 0 + self.successful_count = 0 + self.failed_count = 0 + + def stop(self): + self.should_stop = True + + def run(self): + """Process all artists one by one""" + try: + # Load artists in background if not provided + if self.artists is None: + all_artists = self.plex_client.get_all_artists() + if not all_artists: + self.error.emit("No artists found in Plex library") + return + + # Filter artists that need processing + artists_to_process = [artist for artist in all_artists if self.artist_needs_processing(artist)] + self.artists = artists_to_process + + # Emit loaded signal + self.artists_loaded.emit(len(all_artists), len(artists_to_process)) + + if not artists_to_process: + self.finished.emit(0, 0, 0) + return + + total_artists = len(self.artists) + + for i, artist in enumerate(self.artists): + if self.should_stop: + break + + artist_name = getattr(artist, 'title', 'Unknown Artist') + self.progress_updated.emit(artist_name, i, total_artists, (i / total_artists) * 100) + + try: + success, details = self.update_artist_metadata(artist) + self.processed_count += 1 + + if success: + self.successful_count += 1 + else: + self.failed_count += 1 + + self.artist_updated.emit(artist_name, success, details) + + except Exception as e: + self.failed_count += 1 + self.artist_updated.emit(artist_name, False, f"Error: {str(e)}") + + # Small delay to prevent overwhelming the APIs + self.msleep(500) + + self.finished.emit(self.processed_count, self.successful_count, self.failed_count) + + except Exception as e: + self.error.emit(f"Metadata update failed: {str(e)}") + + def artist_needs_processing(self, artist): + """Check if an artist needs metadata processing using smart detection""" + try: + # Check if artist has a valid photo + has_valid_photo = self.artist_has_valid_photo(artist) + + # Check if artist has genres (more than just basic ones) + existing_genres = set(genre.tag if hasattr(genre, 'tag') else str(genre) + for genre in (artist.genres or [])) + has_good_genres = len(existing_genres) >= 2 # At least 2 genres indicates Spotify processing + + # Process if missing photo OR insufficient genres + return not has_valid_photo or not has_good_genres + + except Exception as e: + print(f"Error checking artist {getattr(artist, 'title', 'Unknown')}: {e}") + return True # Process if we can't determine status + + def update_artist_metadata(self, artist): + """Update a single artist's metadata""" + try: + artist_name = getattr(artist, 'title', 'Unknown Artist') + + # Search for artist on Spotify + spotify_artists = self.spotify_client.search_artists(artist_name, limit=1) + if not spotify_artists: + return False, "Not found on Spotify" + + spotify_artist = spotify_artists[0] + changes_made = [] + + # Update photo if needed + photo_updated = self.update_artist_photo(artist, spotify_artist) + if photo_updated: + changes_made.append("photo") + + # Update genres + genres_updated = self.update_artist_genres(artist, spotify_artist) + if genres_updated: + changes_made.append("genres") + + if changes_made: + return True, f"Updated {', '.join(changes_made)}" + else: + return True, "Already up to date" + + except Exception as e: + return False, str(e) + + def update_artist_photo(self, artist, spotify_artist): + """Update artist photo from Spotify""" + try: + # Check if artist already has a good photo + if self.artist_has_valid_photo(artist): + return False + + # Get the largest image from Spotify + if not spotify_artist.get('images'): + return False + + largest_image = max(spotify_artist['images'], key=lambda x: x['width'] * x['height']) + image_url = largest_image['url'] + + # Download and validate image + response = requests.get(image_url, timeout=10) + response.raise_for_status() + + # Validate and convert image + image_data = self.validate_and_convert_image(response.content) + if not image_data: + return False + + # Upload to Plex + return self.upload_artist_poster(artist, image_data) + + except Exception as e: + print(f"Error updating photo for {getattr(artist, 'title', 'Unknown')}: {e}") + return False + + def update_artist_genres(self, artist, spotify_artist): + """Update artist genres from Spotify and albums""" + try: + # Get existing genres + existing_genres = set(genre.tag if hasattr(genre, 'tag') else str(genre) + for genre in (artist.genres or [])) + + # Get Spotify artist genres + spotify_genres = set(spotify_artist.get('genres', [])) + + # Get genres from all albums + album_genres = set() + try: + for album in artist.albums(): + if hasattr(album, 'genres') and album.genres: + album_genres.update(genre.tag if hasattr(genre, 'tag') else str(genre) + for genre in album.genres) + except Exception: + pass # Albums might not be accessible + + # Combine all genres (prioritize Spotify genres) + all_genres = spotify_genres.union(album_genres) + + # Filter out empty/invalid genres + all_genres = {g for g in all_genres if g and g.strip() and len(g.strip()) > 1} + + print(f"[DEBUG] Artist '{artist.title}': Existing={existing_genres}, Spotify={spotify_genres}, Albums={album_genres}, Combined={all_genres}") + + # Only update if we have new genres and they're different + if all_genres and (not existing_genres or all_genres != existing_genres): + # Convert to list and limit to 10 genres + genre_list = list(all_genres)[:10] + + print(f"[DEBUG] Updating genres for '{artist.title}' to: {genre_list}") + + # Use Plex API to update genres + success = self.plex_client.update_artist_genres(artist, genre_list) + if success: + print(f"[DEBUG] Successfully updated genres for '{artist.title}'") + return True + else: + print(f"[DEBUG] Failed to update genres for '{artist.title}'") + return False + else: + print(f"[DEBUG] No genre update needed for '{artist.title}' - already has good genres") + return False + + except Exception as e: + print(f"Error updating genres for {getattr(artist, 'title', 'Unknown')}: {e}") + return False + + def artist_has_valid_photo(self, artist): + """Check if artist has a valid photo""" + try: + if not hasattr(artist, 'thumb') or not artist.thumb: + return False + + thumb_url = str(artist.thumb) + if 'default' in thumb_url.lower() or len(thumb_url) < 50: + return False + + return True + + except Exception: + return False + + def validate_and_convert_image(self, image_data): + """Validate and convert image for Plex compatibility""" + try: + # Open and validate image + image = Image.open(io.BytesIO(image_data)) + + # Check minimum dimensions + width, height = image.size + if width < 200 or height < 200: + return None + + # Convert to JPEG for consistency + if image.format != 'JPEG': + buffer = io.BytesIO() + image.convert('RGB').save(buffer, format='JPEG', quality=95) + return buffer.getvalue() + + return image_data + + except Exception: + return None + + def upload_artist_poster(self, artist, image_data): + """Upload poster to Plex""" + try: + # Use Plex client's update method if available + if hasattr(self.plex_client, 'update_artist_poster'): + return self.plex_client.update_artist_poster(artist, image_data) + + # Fallback: direct Plex API call + server = self.plex_client.server + upload_url = f"{server._baseurl}/library/metadata/{artist.ratingKey}/posters" + headers = { + 'X-Plex-Token': server._token, + 'Content-Type': 'image/jpeg' + } + + response = requests.post(upload_url, data=image_data, headers=headers) + response.raise_for_status() + + # Refresh artist to see changes + artist.refresh() + return True + + except Exception as e: + print(f"Error uploading poster: {e}") + return False @dataclass class ServiceStatus: @@ -884,17 +1154,121 @@ class DashboardPage(QWidget): def toggle_metadata_update(self): """Toggle metadata update process""" - # This will be implemented with actual functionality later - # For now, just show placeholder behavior current_text = self.metadata_widget.start_button.text() if "Begin" in current_text: - # Start metadata update (placeholder) - self.metadata_widget.update_progress(True, "Sample Artist", 0, 100, 0.0) - self.add_activity_item("🎵", "Metadata Update", "Started Plex metadata update process", "Now") + # Start metadata update + self.start_metadata_update() else: - # Stop metadata update (placeholder) - self.metadata_widget.update_progress(False, "", 0, 0, 0.0) - self.add_activity_item("â¹ï¸", "Metadata Update", "Stopped metadata update process", "Now") + # Stop metadata update + self.stop_metadata_update() + + def start_metadata_update(self): + """Start the Plex metadata update process""" + if not hasattr(self, 'data_provider') or not self.data_provider.service_clients.get('plex'): + self.add_activity_item("âŒ", "Metadata Update", "Plex client not available", "Now") + return + + if not self.data_provider.service_clients.get('spotify'): + self.add_activity_item("âŒ", "Metadata Update", "Spotify client not available", "Now") + return + + try: + # Start the metadata update worker (it will handle artist retrieval in background) + self.metadata_worker = MetadataUpdateWorker( + None, # Artists will be loaded in the worker thread + self.data_provider.service_clients['plex'], + self.data_provider.service_clients['spotify'] + ) + + # Connect signals + self.metadata_worker.progress_updated.connect(self.on_metadata_progress) + self.metadata_worker.artist_updated.connect(self.on_artist_updated) + self.metadata_worker.finished.connect(self.on_metadata_finished) + self.metadata_worker.error.connect(self.on_metadata_error) + self.metadata_worker.artists_loaded.connect(self.on_artists_loaded) + + # Update UI and start + self.metadata_widget.update_progress(True, "Loading artists...", 0, 0, 0.0) + self.add_activity_item("🎵", "Metadata Update", "Loading artists from Plex library...", "Now") + + self.metadata_worker.start() + + except Exception as e: + self.add_activity_item("âŒ", "Metadata Update", f"Failed to start: {str(e)}", "Now") + + def on_artists_loaded(self, total_artists, artists_to_process): + """Handle when artists are loaded and filtered""" + if artists_to_process == 0: + self.add_activity_item("✅", "Metadata Update", "All artists already have good metadata", "Now") + else: + self.add_activity_item("🎵", "Metadata Update", f"Processing {artists_to_process} of {total_artists} artists", "Now") + + def stop_metadata_update(self): + """Stop the metadata update process""" + if hasattr(self, 'metadata_worker') and self.metadata_worker.isRunning(): + self.metadata_worker.stop() + self.metadata_worker.wait(3000) # Wait up to 3 seconds + if self.metadata_worker.isRunning(): + self.metadata_worker.terminate() + + self.metadata_widget.update_progress(False, "", 0, 0, 0.0) + self.add_activity_item("â¹ï¸", "Metadata Update", "Stopped metadata update process", "Now") + + def artist_needs_processing(self, artist): + """Check if an artist needs metadata processing using smart detection""" + try: + # Check if artist has a valid photo + has_valid_photo = self.artist_has_valid_photo(artist) + + # Check if artist has genres (more than just basic ones) + existing_genres = set(genre.tag if hasattr(genre, 'tag') else str(genre) + for genre in (artist.genres or [])) + has_good_genres = len(existing_genres) >= 2 # At least 2 genres indicates Spotify processing + + # Process if missing photo OR insufficient genres + return not has_valid_photo or not has_good_genres + + except Exception as e: + print(f"Error checking artist {getattr(artist, 'title', 'Unknown')}: {e}") + return True # Process if we can't determine status + + def artist_has_valid_photo(self, artist): + """Check if artist has a valid photo""" + try: + if not hasattr(artist, 'thumb') or not artist.thumb: + return False + + # Quick check for suspicious URLs (default Plex placeholders often contain 'default' or are very short) + thumb_url = str(artist.thumb) + if 'default' in thumb_url.lower() or len(thumb_url) < 50: + return False + + return True + + except Exception: + return False + + def on_metadata_progress(self, current_artist, processed, total, percentage): + """Handle metadata update progress""" + self.metadata_widget.update_progress(True, current_artist, processed, total, percentage) + + def on_artist_updated(self, artist_name, success, details): + """Handle individual artist update completion""" + if success: + self.add_activity_item("✅", "Artist Updated", f"'{artist_name}' - {details}", "Now") + else: + self.add_activity_item("âŒ", "Artist Failed", f"'{artist_name}' - {details}", "Now") + + def on_metadata_finished(self, total_processed, successful, failed): + """Handle metadata update completion""" + self.metadata_widget.update_progress(False, "", 0, 0, 0.0) + summary = f"Processed {total_processed} artists: {successful} updated, {failed} failed" + self.add_activity_item("🎵", "Metadata Complete", summary, "Now") + + def on_metadata_error(self, error_message): + """Handle metadata update error""" + self.metadata_widget.update_progress(False, "", 0, 0, 0.0) + self.add_activity_item("âŒ", "Metadata Error", error_message, "Now") def on_service_status_updated(self, service: str, connected: bool, response_time: float, error: str): """Handle service status updates from data provider"""