From 6c1c2af6851e68088420e71fb962194bde475cb7 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Sun, 27 Jul 2025 21:54:30 -0700 Subject: [PATCH] good --- .spotify_cache | 2 +- logs/app.log | 206 +++++++++ ui/pages/__pycache__/settings.cpython-312.pyc | Bin 39915 -> 58366 bytes ui/pages/settings.py | 437 +++++++++++++++++- 4 files changed, 631 insertions(+), 14 deletions(-) diff --git a/.spotify_cache b/.spotify_cache index 83e294be..dfd03def 100644 --- a/.spotify_cache +++ b/.spotify_cache @@ -1 +1 @@ -{"access_token": "BQCcjOxkyprg68XG9wIW8-EXwIERyvvMQcswcfRmvL1HxzlhSRDYybTTBfJDqt6OvKy8gYkBn2nvJkhsu8uyFautsOx8aP9dIi2nIsksvQTMAzU5DSH5_jBmeL0GJpkZ7btqlMNkzcjryWUaNQpVSZFVkJmxBjpoQbRtviQ7YTjfS9NjTwjTuX8czrmqEVCV8-8YQjE6jnjkwO-wrTReY27KBn6_iLyAX5Vh9JLyYUG-mYQhNXGa6Mii2ZSkMb7s", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753677220, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"} \ No newline at end of file +{"access_token": "BQAdyqwBcWjHXyNglSbWavYUmdxzOiQMWw57Cw-vulDpJHzqwR7GrNabHbXNRoRi17XxQ3aov7_FUiIlsBlJ2eQpRbaDMMvEld4Xo99eVnQKh3S6S6-ialTKQi6GaATUEEro2C0OQNpWml6xPLGXMZ6Oe5m48Neldipw7uE2P_3RQXMqjQurbbZ9ujGcJv6_MNOMfWhF0eZ7ix3Rj8P-lasEebj1G7uZ9YdWBgmgclApiFWQa1Z_moB0Zuomb9Ah", "token_type": "Bearer", "expires_in": 3600, "scope": "user-library-read user-read-private playlist-read-private playlist-read-collaborative user-read-email", "expires_at": 1753682064, "refresh_token": "AQDmfQkPCGObfJeTUIbW1hAAwhSqkuHRA3Qh2dqVYMRh0eCkFMQgPNJDDzF8y-BiaVbj80zePkK_XSfYH1aJutMtNbnsqRKWuxP31BTrMc7pdUdbE7Fma4oH8wpDUKdG3MM"} \ No newline at end of file diff --git a/logs/app.log b/logs/app.log index 3c7c1ff4..450999be 100644 --- a/logs/app.log +++ b/logs/app.log @@ -176670,3 +176670,209 @@ 2025-07-27 21:32:37 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music 2025-07-27 21:32:37 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE 2025-07-27 21:32:52 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:34:37 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-27 21:34:37 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-27 21:34:37 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-27 21:34:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-27 21: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-27 21:34:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 50 searches from slskd +2025-07-27 21:34:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (50) within limit (200), no maintenance needed +2025-07-27 21:36:37 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-27 21:36:37 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-27 21:36:37 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-27 21:36:37 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-27 21: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-27 21:36:37 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 50 searches from slskd +2025-07-27 21:36:37 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (50) within limit (200), no maintenance needed +2025-07-27 21:36:44 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:36:44 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:36:44 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:36:47 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:36:47 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:36:47 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:37:15 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:37:15 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:37:15 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:37:15 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:37:15 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:37:16 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:37:16 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:37:16 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:37:16 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:37:16 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:37:16 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:37:16 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:37:16 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:37:19 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:39:04 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:39:04 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:39:04 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:39:05 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:39:05 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:39:05 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:39:10 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:39:10 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:39:10 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:39:10 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:39:10 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:39:10 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:39:10 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:39:10 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:39:10 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:39:10 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:39:10 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:39:11 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:39:11 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:39:12 - newmusic.main - INFO - change_page:233 - Changed to page: downloads +2025-07-27 21:39:13 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:41:10 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-27 21:41:10 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-27 21:41:10 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-27 21:41:11 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-27 21:41:11 - 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-27 21:41:11 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 50 searches from slskd +2025-07-27 21:41:11 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (50) within limit (200), no maintenance needed +2025-07-27 21:41:33 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:41:33 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:41:33 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:41:35 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:41:35 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:41:35 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:41:38 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:41:38 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:41:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:41:38 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:41:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:41:38 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:41:38 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:41:38 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:41:38 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:41:38 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:41:38 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:41:39 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:41:39 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:41:40 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:43:26 - newmusic.main - INFO - change_page:233 - Changed to page: artists +2025-07-27 21:43:26 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:43:28 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:43:28 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:43:28 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:43:30 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:43:30 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:43:30 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:44:07 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:44:07 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:44:07 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:44:07 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:44:07 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:44:07 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:44:07 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:44:07 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:44:07 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:44:07 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:44:07 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:44:07 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:44:07 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:44:08 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:46:07 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-27 21:46:07 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-27 21:46:07 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-27 21:46:08 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-27 21:46:08 - 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-27 21:46:08 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 50 searches from slskd +2025-07-27 21:46:08 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (50) within limit (200), no maintenance needed +2025-07-27 21:46:13 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:46:13 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:46:13 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:46:14 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:46:14 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:46:14 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:46:32 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:46:32 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:46:32 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:46:32 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:46:32 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:46:32 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:46:32 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:46:32 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:46:32 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:46:32 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:46:32 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:46:33 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:46:33 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:46:34 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:47:56 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:47:56 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:47:56 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:47:57 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:47:57 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:47:57 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:48:00 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:48:00 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:48:00 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:48:00 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:48:00 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:48:01 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:48:01 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:48:01 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:48:01 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:48:01 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:48:01 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:48:01 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:48:01 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:48:02 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:49:59 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:49:59 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:49:59 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:50:01 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:50:01 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:50:01 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:50:05 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:50:05 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:50:05 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:50:05 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:50:05 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:50:06 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:50:06 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:50:06 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:50:06 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:50:06 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:50:06 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:50:06 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:50:06 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:50:08 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:50:22 - newmusic.main - INFO - on_settings_changed:214 - Settings changed: soulseek.download_path = E:/Broque Projects/newMusic/downloads +2025-07-27 21:50:22 - newmusic.main - INFO - on_settings_changed:214 - Settings changed: soulseek.transfer_path = E:/Broque Projects/newMusic/Transfer +2025-07-27 21:52:06 - newmusic.soulseek_client - DEBUG - get_all_searches:952 - Getting all searches with endpoint: searches +2025-07-27 21:52:06 - newmusic.soulseek_client - DEBUG - _make_request:242 - Making GET request to: http://localhost:5030/api/v0/searches +2025-07-27 21:52:06 - newmusic.soulseek_client - DEBUG - _make_request:243 - Headers: {'Content-Type': 'application/json', 'X-API-Key': '1234567891234567'} +2025-07-27 21:52:06 - newmusic.soulseek_client - DEBUG - _make_request:254 - Response status: 200 +2025-07-27 21:52:06 - 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-27 21:52:06 - newmusic.soulseek_client - INFO - get_all_searches:957 - Retrieved 50 searches from slskd +2025-07-27 21:52:06 - newmusic.soulseek_client - DEBUG - maintain_search_history:1058 - Search count (50) within limit (200), no maintenance needed +2025-07-27 21:53:16 - newmusic.main - INFO - closeEvent:246 - Closing application... +2025-07-27 21:53:16 - newmusic.main - INFO - closeEvent:251 - Cleaning up Downloads page threads... +2025-07-27 21:53:16 - newmusic.main - INFO - closeEvent:256 - Stopping status monitoring thread... +2025-07-27 21:53:19 - newmusic.main - INFO - closeEvent:261 - Stopping search maintenance timer... +2025-07-27 21:53:19 - newmusic.main - INFO - closeEvent:266 - Closing Soulseek client... +2025-07-27 21:53:19 - newmusic.main - INFO - closeEvent:272 - Application closed successfully +2025-07-27 21:54:05 - newmusic - INFO - setup_logging:57 - Logging initialized with level: DEBUG +2025-07-27 21:54:05 - newmusic.main - INFO - main:286 - Starting NewMusic application +2025-07-27 21:54:05 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:54:05 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:54:05 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:54:07 - newmusic.spotify_client - INFO - _setup_client:179 - Spotify client initialized (user info will be fetched when needed) +2025-07-27 21:54:07 - newmusic.soulseek_client - INFO - _setup_client:220 - Soulseek client configured with slskd at http://localhost:5030 +2025-07-27 21:54:07 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard +2025-07-27 21:54:07 - newmusic.main - INFO - setup_media_player_connections:205 - Media player connections established between sidebar and downloads page +2025-07-27 21:54:07 - newmusic.main - INFO - setup_settings_connections:210 - Settings change connections established +2025-07-27 21:54:07 - newmusic.main - INFO - setup_search_maintenance:86 - Search maintenance timer started (every 2 minutes, keeps 200 most recent searches) +2025-07-27 21:54:07 - newmusic.plex_client - INFO - _find_music_library:127 - Found music library: Music +2025-07-27 21:54:07 - newmusic.plex_client - INFO - _setup_client:113 - Successfully connected to Plex server: PLEX-MACHINE +2025-07-27 21:54:08 - newmusic.main - INFO - change_page:233 - Changed to page: settings +2025-07-27 21:54:22 - newmusic.main - INFO - change_page:233 - Changed to page: artists +2025-07-27 21:54:23 - newmusic.main - INFO - change_page:233 - Changed to page: downloads +2025-07-27 21:54:24 - newmusic.main - INFO - change_page:233 - Changed to page: sync +2025-07-27 21:54:24 - newmusic.spotify_client - INFO - _ensure_user_id:195 - Successfully authenticated with Spotify as broquethomas +2025-07-27 21:54:24 - newmusic.spotify_client - INFO - get_user_playlists_metadata_only:256 - Retrieved 8 playlist metadata (first batch) +2025-07-27 21:54:25 - newmusic.main - INFO - change_page:233 - Changed to page: dashboard diff --git a/ui/pages/__pycache__/settings.cpython-312.pyc b/ui/pages/__pycache__/settings.cpython-312.pyc index 4e329cf7e63898391cc858968f07e270ff4234ed..46460427258d0f2dad338a3d49bd1c4a4a7f1ada 100644 GIT binary patch delta 18006 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 IzqDun7oqNPs{jB1 delta 5307 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 diff --git a/ui/pages/settings.py b/ui/pages/settings.py index 52af91f5..ad21146c 100644 --- a/ui/pages/settings.py +++ b/ui/pages/settings.py @@ -5,6 +5,101 @@ from PyQt6.QtCore import Qt, QThread, pyqtSignal from PyQt6.QtGui import QFont from config.settings import config_manager +class SlskdDetectionThread(QThread): + progress_updated = pyqtSignal(int, str) # progress value, current url + detection_completed = pyqtSignal(str) # found_url (empty if not found) + + def __init__(self): + super().__init__() + self.cancelled = False + + def cancel(self): + self.cancelled = True + + def run(self): + import requests + import socket + from concurrent.futures import ThreadPoolExecutor, as_completed + + def get_local_network_range(): + """Get the local network IP range""" + try: + # Get local IP + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + local_ip = s.getsockname()[0] + s.close() + + # Generate network range (assumes /24 subnet) + ip_parts = local_ip.split('.') + network_base = f"{ip_parts[0]}.{ip_parts[1]}.{ip_parts[2]}" + return network_base, local_ip + except: + return None, None + + def test_url(url): + """Test if slskd is running at the given URL""" + try: + response = requests.get(f"{url}/api/v0/session", timeout=1) + if response.status_code in [200, 401]: + return url + except: + pass + return None + + # Build candidate list + candidates = [] + + # Local candidates + local_candidates = [ + "http://localhost:5030", + "http://127.0.0.1:5030", + "http://localhost:5031", + "http://127.0.0.1:5031", + "http://localhost:8080", + "http://127.0.0.1:8080" + ] + candidates.extend(local_candidates) + + # Network candidates + network_base, local_ip = get_local_network_range() + if network_base and local_ip: + # Common network IPs to check (router, common static IPs) + priority_ips = [1, 2, 100, 101, 102, 150, 200] + ports = [5030, 5031, 8080] + + for ip_suffix in priority_ips: + test_ip = f"{network_base}.{ip_suffix}" + if test_ip != local_ip: # Skip local IP (already tested) + for port in ports: + candidates.append(f"http://{test_ip}:{port}") + + found_url = None + + # Test candidates sequentially for more predictable progress + for i, url in enumerate(candidates): + if self.cancelled: + break + + # Emit progress update before testing + progress_percent = int((i / len(candidates)) * 100) + self.progress_updated.emit(progress_percent, url) + + # Test the URL + result = test_url(url) + if result: + found_url = result + # Emit final progress + self.progress_updated.emit(100, f"Found: {result}") + break + + # Small delay to make progress visible + import time + time.sleep(0.05) + + # Emit completion signal + self.detection_completed.emit(found_url or "") + class ServiceTestThread(QThread): test_completed = pyqtSignal(str, bool, str) # service, success, message @@ -170,6 +265,8 @@ class SettingsPage(QWidget): self.form_inputs = {} self.test_thread = None self.test_buttons = {} + self.detection_thread = None + self.detection_dialog = None self.setup_ui() self.load_config_values() @@ -282,6 +379,14 @@ class SettingsPage(QWidget): self.download_path_input.setText(soulseek_config.get('download_path', './downloads')) self.transfer_path_input.setText(soulseek_config.get('transfer_path', './Transfer')) + # Load logging config (read-only display) + logging_config = config_manager.get_logging_config() + if hasattr(self, 'log_level_display'): + self.log_level_display.setText(logging_config.get('level', 'DEBUG')) + + if hasattr(self, 'log_path_display'): + self.log_path_display.setText(logging_config.get('path', 'logs/app.log')) + except Exception as e: QMessageBox.warning(self, "Error", f"Failed to load configuration: {e}") @@ -371,6 +476,290 @@ class SettingsPage(QWidget): } self.start_service_test('soulseek', test_config) + def auto_detect_slskd(self): + """Auto-detect slskd URL using background thread""" + # Don't start new detection if one is already running + if self.detection_thread and self.detection_thread.isRunning(): + return + + # Create animated loading dialog + from PyQt6.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton + from PyQt6.QtCore import QTimer, QPropertyAnimation, QRect + from PyQt6.QtGui import QPainter, QColor + + self.detection_dialog = QDialog(self) + self.detection_dialog.setWindowTitle("Auto-detecting slskd") + self.detection_dialog.setModal(True) + self.detection_dialog.setFixedSize(350, 150) + self.detection_dialog.setWindowFlags(self.detection_dialog.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint) + + # Apply dark theme styling + self.detection_dialog.setStyleSheet(""" + QDialog { + background-color: #282828; + color: #ffffff; + border: 1px solid #404040; + border-radius: 8px; + } + QLabel { + color: #ffffff; + font-size: 14px; + } + QPushButton { + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + color: #ffffff; + padding: 8px 16px; + font-size: 11px; + } + QPushButton:hover { + background-color: #505050; + } + """) + + layout = QVBoxLayout(self.detection_dialog) + layout.setSpacing(20) + layout.setContentsMargins(20, 20, 20, 20) + + # Title label + title_label = QLabel("Searching for slskd instances...") + title_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + layout.addWidget(title_label) + + # Status label + self.status_label = QLabel("Checking local machine...") + self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.status_label.setStyleSheet("color: #b3b3b3; font-size: 12px;") + layout.addWidget(self.status_label) + + # Animated loading bar container + loading_container = QLabel() + loading_container.setFixedHeight(8) + loading_container.setStyleSheet(""" + QLabel { + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + } + """) + layout.addWidget(loading_container) + + # Animated green bar + self.loading_bar = QLabel(loading_container) + self.loading_bar.setFixedHeight(6) + self.loading_bar.setStyleSheet(""" + background-color: #1db954; + border-radius: 3px; + border: none; + """) + + # Start animation + self.loading_animation = QPropertyAnimation(self.loading_bar, b"geometry") + self.loading_animation.setDuration(1500) # 1.5 seconds + self.loading_animation.setStartValue(QRect(1, 1, 0, 6)) + self.loading_animation.setEndValue(QRect(1, 1, loading_container.width() - 2, 6)) + self.loading_animation.setLoopCount(-1) # Infinite loop + self.loading_animation.start() + + # Cancel button + button_layout = QHBoxLayout() + button_layout.addStretch() + + cancel_btn = QPushButton("Cancel") + cancel_btn.clicked.connect(self.cancel_detection) + button_layout.addWidget(cancel_btn) + + layout.addLayout(button_layout) + + # Start detection thread + self.detection_thread = SlskdDetectionThread() + self.detection_thread.progress_updated.connect(self.on_detection_progress, Qt.ConnectionType.QueuedConnection) + self.detection_thread.detection_completed.connect(self.on_detection_completed, Qt.ConnectionType.QueuedConnection) + self.detection_thread.start() + + self.detection_dialog.show() + + def cancel_detection(self): + """Cancel the ongoing detection""" + if self.detection_thread: + self.detection_thread.cancel() + + # Close dialog + if hasattr(self, 'detection_dialog') and self.detection_dialog: + if hasattr(self, 'loading_animation'): + self.loading_animation.stop() + self.detection_dialog.close() + self.detection_dialog = None + + def on_detection_progress(self, progress_value, current_url): + """Handle progress updates from detection thread""" + if hasattr(self, 'status_label') and self.status_label: + if "localhost" in current_url or "127.0.0.1" in current_url: + self.status_label.setText("Checking local machine...") + else: + self.status_label.setText("Checking network...") + + def on_detection_completed(self, found_url): + """Handle detection completion""" + # Stop animation and close dialog + if hasattr(self, 'loading_animation'): + self.loading_animation.stop() + + if hasattr(self, 'detection_dialog') and self.detection_dialog: + self.detection_dialog.close() + self.detection_dialog = None + + if self.detection_thread: + self.detection_thread.deleteLater() + self.detection_thread = None + + if found_url: + self.slskd_url_input.setText(found_url) + self.show_success_dialog(found_url) + else: + QMessageBox.warning(self, "Auto-detect Failed", + "Could not find slskd running on local machine or network.\n\n" + "Please ensure slskd is running and try:\n" + "• Check if slskd service is started\n" + "• Verify firewall allows access to slskd port\n" + "• Enter the URL manually if on a different network\n\n" + "Common URLs:\n" + "• http://localhost:5030 (local default)\n" + "• http://192.168.1.100:5030 (network example)") + + def show_success_dialog(self, found_url): + """Show custom success dialog with copy functionality""" + from PyQt6.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit + from PyQt6.QtCore import Qt + from PyQt6.QtGui import QClipboard + + dialog = QDialog(self) + dialog.setWindowTitle("Auto-detect Success") + dialog.setModal(True) + dialog.setFixedSize(380, 160) + dialog.setWindowFlags(dialog.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint) + + # Apply dark theme styling + dialog.setStyleSheet(""" + QDialog { + background-color: #282828; + color: #ffffff; + border: 1px solid #404040; + border-radius: 8px; + } + QLabel { + color: #ffffff; + font-size: 12px; + } + QTextEdit { + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + color: #ffffff; + font-size: 11px; + font-family: 'Courier New', monospace; + padding: 8px; + } + QPushButton { + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + color: #ffffff; + padding: 6px 12px; + font-size: 11px; + min-width: 50px; + min-height: 28px; + } + QPushButton:hover { + background-color: #505050; + } + #copyButton { + background-color: #1db954; + border: 1px solid #1db954; + color: #000000; + font-weight: bold; + min-height: 28px; + } + #copyButton:hover { + background-color: #1ed760; + } + """) + + layout = QVBoxLayout(dialog) + layout.setSpacing(8) + layout.setContentsMargins(15, 15, 15, 15) + + # Success message + location_type = "locally" if "localhost" in found_url or "127.0.0.1" in found_url else "on network" + success_label = QLabel(f"✓ Found slskd running {location_type}!") + success_label.setStyleSheet("color: #1db954; font-size: 13px; font-weight: bold;") + success_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + layout.addWidget(success_label) + + # URL display with copy functionality + url_label = QLabel("Detected URL:") + layout.addWidget(url_label) + + url_container = QHBoxLayout() + url_container.setSpacing(5) + + url_display = QTextEdit() + url_display.setPlainText(found_url) + url_display.setReadOnly(True) + url_display.setFixedHeight(30) + url_display.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + url_container.addWidget(url_display) + + copy_btn = QPushButton("Copy") + copy_btn.setObjectName("copyButton") + copy_btn.setFixedSize(55, 30) + copy_btn.clicked.connect(lambda: self.copy_to_clipboard(found_url, copy_btn)) + url_container.addWidget(copy_btn) + + layout.addLayout(url_container) + + # Info text + info_label = QLabel("URL automatically filled in settings above.") + info_label.setStyleSheet("color: #b3b3b3; font-size: 9px; font-style: italic;") + info_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + layout.addWidget(info_label) + + # OK button + button_layout = QHBoxLayout() + button_layout.addStretch() + + ok_btn = QPushButton("OK") + ok_btn.setFixedSize(60, 28) + ok_btn.clicked.connect(dialog.accept) + ok_btn.setDefault(True) + button_layout.addWidget(ok_btn) + + layout.addLayout(button_layout) + + dialog.exec() + + def copy_to_clipboard(self, text, button): + """Copy text to clipboard and show feedback""" + from PyQt6.QtWidgets import QApplication + from PyQt6.QtCore import QTimer + + clipboard = QApplication.clipboard() + clipboard.setText(text) + + # Show feedback + original_text = button.text() + button.setText("Copied!") + button.setEnabled(False) + + # Reset button after 1 second + QTimer.singleShot(1000, lambda: self.reset_copy_button(button, original_text)) + + def reset_copy_button(self, button, original_text): + """Reset copy button to original state""" + button.setText(original_text) + button.setEnabled(True) + def browse_download_path(self): """Open a directory dialog to select download path""" from PyQt6.QtWidgets import QFileDialog @@ -539,11 +928,20 @@ class SettingsPage(QWidget): slskd_url_label.setStyleSheet("color: #ffffff; font-size: 11px;") soulseek_layout.addWidget(slskd_url_label) + url_input_layout = QHBoxLayout() self.slskd_url_input = QLineEdit() self.slskd_url_input.setStyleSheet(self.get_input_style()) self.slskd_url_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.form_inputs['soulseek.slskd_url'] = self.slskd_url_input - soulseek_layout.addWidget(self.slskd_url_input) + + detect_btn = QPushButton("Auto-detect") + detect_btn.setFixedSize(80, 30) + detect_btn.clicked.connect(self.auto_detect_slskd) + detect_btn.setStyleSheet(self.get_test_button_style()) + + url_input_layout.addWidget(self.slskd_url_input) + url_input_layout.addWidget(detect_btn) + soulseek_layout.addLayout(url_input_layout) # API Key api_key_label = QLabel("API Key:") @@ -670,30 +1068,43 @@ class SettingsPage(QWidget): logging_layout.setContentsMargins(16, 20, 16, 16) logging_layout.setSpacing(12) - # Log level + # Log level (read-only) log_level_layout = QHBoxLayout() log_level_label = QLabel("Log Level:") log_level_label.setStyleSheet("color: #ffffff; font-size: 12px;") - log_level_combo = QComboBox() - log_level_combo.addItems(["DEBUG", "INFO", "WARNING", "ERROR"]) - log_level_combo.setCurrentText("DEBUG") - log_level_combo.setStyleSheet(self.get_combo_style()) - log_level_combo.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + self.log_level_display = QLabel("DEBUG") + self.log_level_display.setStyleSheet(""" + color: #b3b3b3; + font-size: 11px; + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + padding: 8px; + """) + self.log_level_display.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) log_level_layout.addWidget(log_level_label) - log_level_layout.addWidget(log_level_combo) + log_level_layout.addWidget(self.log_level_display) - # Log file path + # Log file path (read-only) log_path_container = QVBoxLayout() log_path_label = QLabel("Log File Path:") log_path_label.setStyleSheet("color: #ffffff; font-size: 12px;") log_path_container.addWidget(log_path_label) - log_path_input = QLineEdit("logs/app.log") - log_path_input.setStyleSheet(self.get_input_style()) - log_path_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) - log_path_container.addWidget(log_path_input) + self.log_path_display = QLabel("logs/app.log") + self.log_path_display.setStyleSheet(""" + color: #b3b3b3; + font-size: 11px; + background-color: #404040; + border: 1px solid #606060; + border-radius: 4px; + padding: 8px; + font-family: 'Courier New', monospace; + """) + self.log_path_display.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + log_path_container.addWidget(self.log_path_display) logging_layout.addLayout(log_level_layout) logging_layout.addLayout(log_path_container)