yutipy 2.2.3__py3-none-any.whl → 2.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of yutipy might be problematic. Click here for more details.
- yutipy/deezer.py +14 -14
- yutipy/exceptions.py +0 -5
- yutipy/itunes.py +4 -5
- yutipy/kkbox.py +4 -6
- yutipy/lastfm.py +2 -1
- yutipy/logger.py +1 -1
- yutipy/models.py +3 -0
- yutipy/musicyt.py +14 -6
- yutipy/spotify.py +34 -25
- yutipy/yutipy_music.py +22 -7
- {yutipy-2.2.3.dist-info → yutipy-2.2.4.dist-info}/METADATA +1 -1
- yutipy-2.2.4.dist-info/RECORD +22 -0
- {yutipy-2.2.3.dist-info → yutipy-2.2.4.dist-info}/WHEEL +1 -1
- yutipy-2.2.3.dist-info/RECORD +0 -22
- {yutipy-2.2.3.dist-info → yutipy-2.2.4.dist-info}/entry_points.txt +0 -0
- {yutipy-2.2.3.dist-info → yutipy-2.2.4.dist-info}/licenses/LICENSE +0 -0
- {yutipy-2.2.3.dist-info → yutipy-2.2.4.dist-info}/top_level.txt +0 -0
yutipy/deezer.py
CHANGED
|
@@ -9,11 +9,10 @@ from yutipy.exceptions import (
|
|
|
9
9
|
DeezerException,
|
|
10
10
|
InvalidResponseException,
|
|
11
11
|
InvalidValueException,
|
|
12
|
-
NetworkException,
|
|
13
12
|
)
|
|
13
|
+
from yutipy.logger import logger
|
|
14
14
|
from yutipy.models import MusicInfo
|
|
15
15
|
from yutipy.utils.helpers import are_strings_similar, is_valid_string
|
|
16
|
-
from yutipy.logger import logger
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class Deezer:
|
|
@@ -97,17 +96,17 @@ class Deezer:
|
|
|
97
96
|
logger.debug(f"Response status code: {response.status_code}")
|
|
98
97
|
response.raise_for_status()
|
|
99
98
|
except requests.RequestException as e:
|
|
100
|
-
logger.
|
|
101
|
-
|
|
99
|
+
logger.warning(f"Network error while fetching music info: {e}")
|
|
100
|
+
return None
|
|
102
101
|
except Exception as e:
|
|
103
|
-
logger.
|
|
102
|
+
logger.warning(f"Unexpected error while searching Deezer: {e}")
|
|
104
103
|
raise DeezerException(f"An error occurred while searching Deezer: {e}")
|
|
105
104
|
|
|
106
105
|
try:
|
|
107
106
|
logger.debug(f"Parsing response JSON: {response.json()}")
|
|
108
107
|
result = response.json()["data"]
|
|
109
108
|
except (IndexError, KeyError, ValueError) as e:
|
|
110
|
-
logger.
|
|
109
|
+
logger.warning(f"Invalid response structure from Deezer: {e}")
|
|
111
110
|
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
112
111
|
|
|
113
112
|
music_info = self._parse_results(artist, song, result)
|
|
@@ -164,17 +163,17 @@ class Deezer:
|
|
|
164
163
|
logger.debug(f"Response status code: {response.status_code}")
|
|
165
164
|
response.raise_for_status()
|
|
166
165
|
except requests.RequestException as e:
|
|
167
|
-
logger.
|
|
168
|
-
|
|
166
|
+
logger.warning(f"Error fetching track info: {e}")
|
|
167
|
+
return None
|
|
169
168
|
except Exception as e:
|
|
170
|
-
logger.
|
|
169
|
+
logger.warning(f"Error fetching track info: {e}")
|
|
171
170
|
raise DeezerException(f"An error occurred while fetching track info: {e}")
|
|
172
171
|
|
|
173
172
|
try:
|
|
174
173
|
logger.debug(f"Response JSON: {response.json()}")
|
|
175
174
|
result = response.json()
|
|
176
175
|
except ValueError as e:
|
|
177
|
-
logger.
|
|
176
|
+
logger.warning(f"Invalid response received from Deezer: {e}")
|
|
178
177
|
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
179
178
|
|
|
180
179
|
return {
|
|
@@ -205,17 +204,17 @@ class Deezer:
|
|
|
205
204
|
logger.info(f"Response status code: {response.status_code}")
|
|
206
205
|
response.raise_for_status()
|
|
207
206
|
except requests.RequestException as e:
|
|
208
|
-
logger.
|
|
209
|
-
|
|
207
|
+
logger.warning(f"Error fetching album info: {e}")
|
|
208
|
+
return None
|
|
210
209
|
except Exception as e:
|
|
211
|
-
logger.
|
|
210
|
+
logger.warning(f"Error fetching album info: {e}")
|
|
212
211
|
raise DeezerException(f"An error occurred while fetching album info: {e}")
|
|
213
212
|
|
|
214
213
|
try:
|
|
215
214
|
logger.debug(f"Response JSON: {response.json()}")
|
|
216
215
|
result = response.json()
|
|
217
216
|
except ValueError as e:
|
|
218
|
-
logger.
|
|
217
|
+
logger.warning(f"Invalid response received from Deezer: {e}")
|
|
219
218
|
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
220
219
|
|
|
221
220
|
return {
|
|
@@ -323,6 +322,7 @@ class Deezer:
|
|
|
323
322
|
|
|
324
323
|
if __name__ == "__main__":
|
|
325
324
|
import logging
|
|
325
|
+
|
|
326
326
|
from yutipy.logger import enable_logging
|
|
327
327
|
|
|
328
328
|
enable_logging(level=logging.DEBUG)
|
yutipy/exceptions.py
CHANGED
|
@@ -2,7 +2,6 @@ __all__ = [
|
|
|
2
2
|
"AuthenticationException",
|
|
3
3
|
"InvalidResponseException",
|
|
4
4
|
"InvalidValueException",
|
|
5
|
-
"NetworkException",
|
|
6
5
|
"YutipyException",
|
|
7
6
|
]
|
|
8
7
|
|
|
@@ -25,10 +24,6 @@ class InvalidValueException(YutipyException):
|
|
|
25
24
|
"""Exception raised for invalid values."""
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
class NetworkException(YutipyException):
|
|
29
|
-
"""Exception raised for network-related errors."""
|
|
30
|
-
|
|
31
|
-
|
|
32
27
|
# Service Exceptions
|
|
33
28
|
class DeezerException(YutipyException):
|
|
34
29
|
"""Exception raised for errors related to the Deezer API."""
|
yutipy/itunes.py
CHANGED
|
@@ -9,8 +9,7 @@ import requests
|
|
|
9
9
|
from yutipy.exceptions import (
|
|
10
10
|
InvalidResponseException,
|
|
11
11
|
InvalidValueException,
|
|
12
|
-
ItunesException
|
|
13
|
-
NetworkException,
|
|
12
|
+
ItunesException
|
|
14
13
|
)
|
|
15
14
|
from yutipy.models import MusicInfo
|
|
16
15
|
from yutipy.utils.helpers import (
|
|
@@ -100,8 +99,8 @@ class Itunes:
|
|
|
100
99
|
logger.debug(f"Response status code: {response.status_code}")
|
|
101
100
|
response.raise_for_status()
|
|
102
101
|
except requests.RequestException as e:
|
|
103
|
-
logger.
|
|
104
|
-
|
|
102
|
+
logger.warning(f"Network error while searching iTunes: {e}")
|
|
103
|
+
return None
|
|
105
104
|
except Exception as e:
|
|
106
105
|
logger.exception(f"Unexpected error while searching iTunes: {e}")
|
|
107
106
|
raise ItunesException(f"An error occurred while searching iTunes: {e}")
|
|
@@ -110,7 +109,7 @@ class Itunes:
|
|
|
110
109
|
logger.debug(f"Parsing response JSON: {response.json()}")
|
|
111
110
|
result = response.json()["results"]
|
|
112
111
|
except (IndexError, KeyError, ValueError) as e:
|
|
113
|
-
logger.
|
|
112
|
+
logger.warning(f"Invalid response structure from iTunes: {e}")
|
|
114
113
|
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
115
114
|
|
|
116
115
|
music_info = self._parse_result(artist, song, result)
|
yutipy/kkbox.py
CHANGED
|
@@ -12,10 +12,8 @@ from dotenv import load_dotenv
|
|
|
12
12
|
|
|
13
13
|
from yutipy.exceptions import (
|
|
14
14
|
AuthenticationException,
|
|
15
|
-
InvalidResponseException,
|
|
16
15
|
InvalidValueException,
|
|
17
16
|
KKBoxException,
|
|
18
|
-
NetworkException,
|
|
19
17
|
)
|
|
20
18
|
from yutipy.logger import logger
|
|
21
19
|
from yutipy.models import MusicInfo
|
|
@@ -187,15 +185,15 @@ class KKBox:
|
|
|
187
185
|
logger.debug(f"Authentication response status code: {response.status_code}")
|
|
188
186
|
response.raise_for_status()
|
|
189
187
|
except requests.RequestException as e:
|
|
190
|
-
logger.
|
|
191
|
-
|
|
188
|
+
logger.warning(f"Network error during KKBOX authentication: {e}")
|
|
189
|
+
return None
|
|
192
190
|
|
|
193
191
|
if response.status_code == 200:
|
|
194
192
|
response_json = response.json()
|
|
195
193
|
response_json["requested_at"] = time()
|
|
196
194
|
return response_json
|
|
197
195
|
else:
|
|
198
|
-
raise
|
|
196
|
+
raise AuthenticationException(
|
|
199
197
|
f"Invalid response received: {response.json()}"
|
|
200
198
|
)
|
|
201
199
|
|
|
@@ -319,7 +317,7 @@ class KKBox:
|
|
|
319
317
|
logger.debug(f"Parsing response JSON: {response.json()}")
|
|
320
318
|
response.raise_for_status()
|
|
321
319
|
except requests.RequestException as e:
|
|
322
|
-
|
|
320
|
+
return None
|
|
323
321
|
|
|
324
322
|
if response.status_code != 200:
|
|
325
323
|
raise KKBoxException(f"Failed to search for music: {response.json()}")
|
yutipy/lastfm.py
CHANGED
|
@@ -95,7 +95,7 @@ class LastFm:
|
|
|
95
95
|
response = self.__session.get(query_url, timeout=30)
|
|
96
96
|
response.raise_for_status()
|
|
97
97
|
except requests.RequestException as e:
|
|
98
|
-
logger.
|
|
98
|
+
logger.warning(f"Failed to fetch user profile: {e}")
|
|
99
99
|
return None
|
|
100
100
|
|
|
101
101
|
response_json = response.json()
|
|
@@ -110,6 +110,7 @@ class LastFm:
|
|
|
110
110
|
album_title=result.get("album", {}).get("#text"),
|
|
111
111
|
artists=", ".join(separate_artists(result.get("artist", {}).get("#text"))),
|
|
112
112
|
id=result.get("mbid"),
|
|
113
|
+
timestamp=result.get("date", {}).get("uts"),
|
|
113
114
|
title=result.get("name"),
|
|
114
115
|
url=result.get("url"),
|
|
115
116
|
is_playing=result.get("@attr", {}).get("nowplaying", False),
|
yutipy/logger.py
CHANGED
yutipy/models.py
CHANGED
|
@@ -74,8 +74,11 @@ class UserPlaying(MusicInfo):
|
|
|
74
74
|
|
|
75
75
|
Attributes
|
|
76
76
|
----------
|
|
77
|
+
timetamp : Optional[int]
|
|
78
|
+
Unix Timestamp (in seconds) when playback was started.
|
|
77
79
|
is_playing : Optional[bool]
|
|
78
80
|
Whether the music is currently playing or paused.
|
|
79
81
|
"""
|
|
80
82
|
|
|
83
|
+
timestamp: Optional[int] = None
|
|
81
84
|
is_playing: Optional[bool] = None
|
yutipy/musicyt.py
CHANGED
|
@@ -11,9 +11,9 @@ from yutipy.exceptions import (
|
|
|
11
11
|
InvalidValueException,
|
|
12
12
|
MusicYTException,
|
|
13
13
|
)
|
|
14
|
+
from yutipy.logger import logger
|
|
14
15
|
from yutipy.models import MusicInfo
|
|
15
16
|
from yutipy.utils.helpers import are_strings_similar, is_valid_string
|
|
16
|
-
from yutipy.logger import logger
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class MusicYT:
|
|
@@ -87,8 +87,8 @@ class MusicYT:
|
|
|
87
87
|
try:
|
|
88
88
|
results = self.ytmusic.search(query=query, limit=limit)
|
|
89
89
|
except exceptions.YTMusicServerError as e:
|
|
90
|
-
logger.
|
|
91
|
-
|
|
90
|
+
logger.warning(f"Something went wrong while searching YTMusic: {e}")
|
|
91
|
+
return None
|
|
92
92
|
|
|
93
93
|
for result in results:
|
|
94
94
|
if self._is_relevant_result(artist, song, result):
|
|
@@ -181,9 +181,15 @@ class MusicYT:
|
|
|
181
181
|
The extracted music information.
|
|
182
182
|
"""
|
|
183
183
|
if result["resultType"] in ["song", "video"]:
|
|
184
|
-
|
|
184
|
+
try:
|
|
185
|
+
return self._get_song(result)
|
|
186
|
+
except InvalidResponseException:
|
|
187
|
+
return None
|
|
185
188
|
else:
|
|
186
|
-
|
|
189
|
+
try:
|
|
190
|
+
return self._get_album(result)
|
|
191
|
+
except InvalidResponseException:
|
|
192
|
+
return None
|
|
187
193
|
|
|
188
194
|
def _get_song(self, result: dict) -> MusicInfo:
|
|
189
195
|
"""
|
|
@@ -200,7 +206,9 @@ class MusicYT:
|
|
|
200
206
|
The extracted music information.
|
|
201
207
|
"""
|
|
202
208
|
title = result.get("title")
|
|
203
|
-
artist_names = ", ".join(
|
|
209
|
+
artist_names = ", ".join(
|
|
210
|
+
[artist.get("name") for artist in result.get("artists", [])]
|
|
211
|
+
)
|
|
204
212
|
video_id = result.get("videoId")
|
|
205
213
|
song_url = f"https://music.youtube.com/watch?v={video_id}"
|
|
206
214
|
lyrics_id = self.ytmusic.get_watch_playlist(video_id)
|
yutipy/spotify.py
CHANGED
|
@@ -14,9 +14,7 @@ from dotenv import load_dotenv
|
|
|
14
14
|
|
|
15
15
|
from yutipy.exceptions import (
|
|
16
16
|
AuthenticationException,
|
|
17
|
-
InvalidResponseException,
|
|
18
17
|
InvalidValueException,
|
|
19
|
-
NetworkException,
|
|
20
18
|
SpotifyAuthException,
|
|
21
19
|
SpotifyException,
|
|
22
20
|
)
|
|
@@ -198,8 +196,8 @@ class Spotify:
|
|
|
198
196
|
logger.debug(f"Authentication response status code: {response.status_code}")
|
|
199
197
|
response.raise_for_status()
|
|
200
198
|
except requests.RequestException as e:
|
|
201
|
-
logger.
|
|
202
|
-
|
|
199
|
+
logger.warning(f"Network error during Spotify authentication: {e}")
|
|
200
|
+
return None
|
|
203
201
|
|
|
204
202
|
if response.status_code == 200:
|
|
205
203
|
response_json = response.json()
|
|
@@ -212,19 +210,27 @@ class Spotify:
|
|
|
212
210
|
|
|
213
211
|
def __refresh_access_token(self):
|
|
214
212
|
"""Refreshes the token if it has expired."""
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
try:
|
|
214
|
+
if time() - self.__token_requested_at >= self.__token_expires_in:
|
|
215
|
+
token_info = self.__get_access_token()
|
|
217
216
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
217
|
+
try:
|
|
218
|
+
self.save_access_token(token_info)
|
|
219
|
+
except NotImplementedError as e:
|
|
220
|
+
logger.warning(e)
|
|
222
221
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
self.__access_token = token_info.get("access_token")
|
|
223
|
+
self.__token_expires_in = token_info.get("expires_in")
|
|
224
|
+
self.__token_requested_at = token_info.get("requested_at")
|
|
226
225
|
|
|
227
|
-
|
|
226
|
+
logger.info("The access token is still valid, no need to refresh.")
|
|
227
|
+
except TypeError:
|
|
228
|
+
logger.debug(
|
|
229
|
+
f"token requested at: {self.__token_requested_at} | token expires in: {self.__token_expires_in}"
|
|
230
|
+
)
|
|
231
|
+
logger.info(
|
|
232
|
+
"Something went wrong while trying to refresh the token. Set logging level to `DEBUG` to see the issue."
|
|
233
|
+
)
|
|
228
234
|
|
|
229
235
|
def save_access_token(self, token_info: dict) -> None:
|
|
230
236
|
"""
|
|
@@ -335,7 +341,7 @@ class Spotify:
|
|
|
335
341
|
)
|
|
336
342
|
response.raise_for_status()
|
|
337
343
|
except requests.RequestException as e:
|
|
338
|
-
|
|
344
|
+
return None
|
|
339
345
|
|
|
340
346
|
if response.status_code != 200:
|
|
341
347
|
raise SpotifyException(f"Failed to search for music: {response.json()}")
|
|
@@ -402,7 +408,7 @@ class Spotify:
|
|
|
402
408
|
)
|
|
403
409
|
response.raise_for_status()
|
|
404
410
|
except requests.RequestException as e:
|
|
405
|
-
|
|
411
|
+
return None
|
|
406
412
|
|
|
407
413
|
if response.status_code != 200:
|
|
408
414
|
raise SpotifyException(
|
|
@@ -435,7 +441,7 @@ class Spotify:
|
|
|
435
441
|
)
|
|
436
442
|
response.raise_for_status()
|
|
437
443
|
except requests.RequestException as e:
|
|
438
|
-
|
|
444
|
+
return None
|
|
439
445
|
|
|
440
446
|
if response.status_code != 200:
|
|
441
447
|
return None
|
|
@@ -814,15 +820,15 @@ class SpotifyAuth:
|
|
|
814
820
|
logger.debug(f"Authentication response status code: {response.status_code}")
|
|
815
821
|
response.raise_for_status()
|
|
816
822
|
except requests.RequestException as e:
|
|
817
|
-
logger.
|
|
818
|
-
|
|
823
|
+
logger.warning(f"Network error during Spotify authentication: {e}")
|
|
824
|
+
return None
|
|
819
825
|
|
|
820
826
|
if response.status_code == 200:
|
|
821
827
|
response_json = response.json()
|
|
822
828
|
response_json["requested_at"] = time()
|
|
823
829
|
return response_json
|
|
824
830
|
else:
|
|
825
|
-
raise
|
|
831
|
+
raise AuthenticationException(
|
|
826
832
|
f"Invalid response received: {response.json()}"
|
|
827
833
|
)
|
|
828
834
|
|
|
@@ -1050,11 +1056,11 @@ class SpotifyAuth:
|
|
|
1050
1056
|
response = self.__session.get(query_url, headers=header, timeout=30)
|
|
1051
1057
|
response.raise_for_status()
|
|
1052
1058
|
except requests.RequestException as e:
|
|
1053
|
-
logger.
|
|
1059
|
+
logger.warning(f"Failed to fetch user profile: {e}")
|
|
1054
1060
|
return None
|
|
1055
1061
|
|
|
1056
1062
|
if response.status_code != 200:
|
|
1057
|
-
logger.
|
|
1063
|
+
logger.warning(f"Unexpected response: {response.json()}")
|
|
1058
1064
|
return None
|
|
1059
1065
|
|
|
1060
1066
|
response_json = response.json()
|
|
@@ -1099,16 +1105,16 @@ class SpotifyAuth:
|
|
|
1099
1105
|
response = self.__session.get(query_url, headers=header, timeout=30)
|
|
1100
1106
|
response.raise_for_status()
|
|
1101
1107
|
except requests.RequestException as e:
|
|
1102
|
-
|
|
1108
|
+
return None
|
|
1103
1109
|
|
|
1104
1110
|
if response.status_code == 204:
|
|
1105
1111
|
logger.info("Requested user is currently not listening to any music.")
|
|
1106
1112
|
return None
|
|
1107
1113
|
if response.status_code != 200:
|
|
1108
1114
|
try:
|
|
1109
|
-
logger.
|
|
1115
|
+
logger.warning(f"Unexpected response: {response.json()}")
|
|
1110
1116
|
except requests.exceptions.JSONDecodeError:
|
|
1111
|
-
logger.
|
|
1117
|
+
logger.warning(
|
|
1112
1118
|
f"Response Code: {response.status_code}, Reason: {response.reason}"
|
|
1113
1119
|
)
|
|
1114
1120
|
return None
|
|
@@ -1122,6 +1128,8 @@ class SpotifyAuth:
|
|
|
1122
1128
|
guess,
|
|
1123
1129
|
use_translation=False,
|
|
1124
1130
|
)
|
|
1131
|
+
# Spotify returns timestamp in milliseconds, so convert milliseconds to seconds:
|
|
1132
|
+
timestamp = response_json.get("timestamp") / 1000.0
|
|
1125
1133
|
return UserPlaying(
|
|
1126
1134
|
album_art=result.get("album", {}).get("images", [])[0].get("url"),
|
|
1127
1135
|
album_title=result.get("album", {}).get("name"),
|
|
@@ -1138,6 +1146,7 @@ class SpotifyAuth:
|
|
|
1138
1146
|
lyrics=None,
|
|
1139
1147
|
release_date=result.get("album", {}).get("release_date"),
|
|
1140
1148
|
tempo=None,
|
|
1149
|
+
timestamp=timestamp,
|
|
1141
1150
|
title=result.get("name"),
|
|
1142
1151
|
type=result.get("type"),
|
|
1143
1152
|
upc=result.get("external_ids", {}).get("upc"),
|
yutipy/yutipy_music.py
CHANGED
|
@@ -22,8 +22,23 @@ class YutipyMusic:
|
|
|
22
22
|
Instead of calling each service separately, you can use this class to get the information from all services at once.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
def __init__(
|
|
26
|
-
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
custom_kkbox_class = KKBox,
|
|
28
|
+
custom_spotify_class = Spotify,
|
|
29
|
+
) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Initializes the YutipyMusic class.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
custom_kkbox_class : Optional[type], optional
|
|
36
|
+
A custom class inherited from ``KKBox`` to override the default KKBox implementation.
|
|
37
|
+
This class should implement ``load_access_token()`` and ``save_access_token()`` methods. Default is ``KKBox``.
|
|
38
|
+
custom_spotify_class : Optional[type], optional
|
|
39
|
+
A custom class inherited from ``Spotify`` to override the default Spotify implementation.
|
|
40
|
+
This class should implement ``load_access_token()`` and ``save_access_token()`` methods. Default is ``Spotify``.
|
|
41
|
+
"""
|
|
27
42
|
self.music_info = MusicInfos()
|
|
28
43
|
self.normalize_non_english = True
|
|
29
44
|
self.album_art_priority = ["deezer", "ytmusic", "itunes"]
|
|
@@ -34,8 +49,8 @@ class YutipyMusic:
|
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
try:
|
|
37
|
-
self.services["kkbox"] =
|
|
38
|
-
except
|
|
52
|
+
self.services["kkbox"] = custom_kkbox_class()
|
|
53
|
+
except KKBoxException as e:
|
|
39
54
|
logger.warning(
|
|
40
55
|
f"{self.__class__.__name__}: Skipping KKBox due to KKBoxException: {e}"
|
|
41
56
|
)
|
|
@@ -44,8 +59,8 @@ class YutipyMusic:
|
|
|
44
59
|
self.album_art_priority.insert(idx, "kkbox")
|
|
45
60
|
|
|
46
61
|
try:
|
|
47
|
-
self.services["spotify"] =
|
|
48
|
-
except
|
|
62
|
+
self.services["spotify"] = custom_spotify_class()
|
|
63
|
+
except SpotifyException as e:
|
|
49
64
|
logger.warning(
|
|
50
65
|
f"{self.__class__.__name__}: Skipping Spotify due to SpotifyException: {e}"
|
|
51
66
|
)
|
|
@@ -114,7 +129,7 @@ class YutipyMusic:
|
|
|
114
129
|
result = future.result()
|
|
115
130
|
self._combine_results(result, service_name)
|
|
116
131
|
except Exception as e:
|
|
117
|
-
logger.
|
|
132
|
+
logger.warning(
|
|
118
133
|
f"Error occurred while searching with {service_name}: {e}"
|
|
119
134
|
)
|
|
120
135
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
yutipy/__init__.py,sha256=Zrw3cr_6khXp1IgQdZxGcUM9A64GYgPs-6rlqSukW5Q,294
|
|
2
|
+
yutipy/deezer.py,sha256=xI7ZDoPHES64_uRN4aYA-kj56V4tFU8xYkZYPXidl_I,11266
|
|
3
|
+
yutipy/exceptions.py,sha256=zz0XyyZr5xRcmRyw3hdTGaVRcwRn_RSYZdmwmuO0sEM,1379
|
|
4
|
+
yutipy/itunes.py,sha256=3YBLoWPhIx6ODE2G-msRppCHo0DNDGZADj-XvL_f5H0,7867
|
|
5
|
+
yutipy/kkbox.py,sha256=ZOIW8rQuiYEWmsXW3Dw9Q5mw71Jh_tMRAULvEgAuDew,19310
|
|
6
|
+
yutipy/lastfm.py,sha256=smbft17Q_wdYXH0Wb1-bfgWilO6wCwcsN3D5lCis4yI,4361
|
|
7
|
+
yutipy/logger.py,sha256=GyLBlfQZ6pLNJ5MbyQSvcD_PkxmFdX41DPq5aeG1z68,1316
|
|
8
|
+
yutipy/models.py,sha256=45M-bNHusaAan_Ta_E9DyvsWujsT-ivbJqIfy2-i3R8,2343
|
|
9
|
+
yutipy/musicyt.py,sha256=WKR4J4ru1uqNa7ORSZKlet1FxXQlHzlXTg9CIUqnsoc,9462
|
|
10
|
+
yutipy/spotify.py,sha256=NiBjaK2SUCyRhGGDsP0mGguFZOLW6DkUVoUghIH_0Ho,44395
|
|
11
|
+
yutipy/yutipy_music.py,sha256=MNNh2WT-7GTAykAabLF6p4-0uXiIIbuogswmb-_QqtQ,7272
|
|
12
|
+
yutipy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
yutipy/cli/config.py,sha256=e5RIq6RxVxxzx30nKVMa06gwyQ258s7U0WA1xvJuR_0,4543
|
|
14
|
+
yutipy/cli/search.py,sha256=8SQw0bjRzRqAg-FuVz9aWjB2KBZqmCf38SyKAQ3rx5E,3025
|
|
15
|
+
yutipy/utils/__init__.py,sha256=AZaqvs6AJwnqwJuodbGnHu702WSUqc8plVC16SppOcU,239
|
|
16
|
+
yutipy/utils/helpers.py,sha256=W3g9iqoSygcFFCKCp2sk0NQrZOEG26wI2XuNi9pgAXE,5207
|
|
17
|
+
yutipy-2.2.4.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
|
|
18
|
+
yutipy-2.2.4.dist-info/METADATA,sha256=T693it2xLgmx13Cx1N5LEZ_7fdTaZPa3Oqj83gHoJNw,6522
|
|
19
|
+
yutipy-2.2.4.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
|
20
|
+
yutipy-2.2.4.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
|
|
21
|
+
yutipy-2.2.4.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
22
|
+
yutipy-2.2.4.dist-info/RECORD,,
|
yutipy-2.2.3.dist-info/RECORD
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
yutipy/__init__.py,sha256=Zrw3cr_6khXp1IgQdZxGcUM9A64GYgPs-6rlqSukW5Q,294
|
|
2
|
-
yutipy/deezer.py,sha256=PTTTfeORh1HZ_ta7_Uu4YARouSknUnAxO9AQJPFm4v0,11402
|
|
3
|
-
yutipy/exceptions.py,sha256=oMuhNfDJ2AFsM_fJn6sayxMqIJRY_ihHRmL0U2IK6qQ,1501
|
|
4
|
-
yutipy/itunes.py,sha256=fV7KLsXWvfM_97KwVwn_KfnWM7j0cVGE7RytvnDGlZM,7929
|
|
5
|
-
yutipy/kkbox.py,sha256=7kgq0ZliiA16CeJa49faSUS8_SdqQPp6M-cKdnMFlaM,19447
|
|
6
|
-
yutipy/lastfm.py,sha256=0adVGigS8Kqnu52k-ry5eqHR6koktgKBhCNI1riUMfk,4302
|
|
7
|
-
yutipy/logger.py,sha256=4jXB-Qt2r75kpuAdxSGIwGrcpUyugxs9ROmBru9NtTw,1314
|
|
8
|
-
yutipy/models.py,sha256=_92e54uXXCw53oWZiNLBBai6C0InOZMJL7r8GJ5smbM,2215
|
|
9
|
-
yutipy/musicyt.py,sha256=6Vz8bI8hDNFoDKRh6GK90dGMRbn_d5d6eGPsaYogb_Y,9315
|
|
10
|
-
yutipy/spotify.py,sha256=pf_vaQXMxExMjIGuId4eTHaSO112hAqf-6YgWLSa5uQ,44108
|
|
11
|
-
yutipy/yutipy_music.py,sha256=cHJ95HxGILweVrnEacj8tTlU0NPxMpuDVMpngdX0mZQ,6558
|
|
12
|
-
yutipy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
yutipy/cli/config.py,sha256=e5RIq6RxVxxzx30nKVMa06gwyQ258s7U0WA1xvJuR_0,4543
|
|
14
|
-
yutipy/cli/search.py,sha256=8SQw0bjRzRqAg-FuVz9aWjB2KBZqmCf38SyKAQ3rx5E,3025
|
|
15
|
-
yutipy/utils/__init__.py,sha256=AZaqvs6AJwnqwJuodbGnHu702WSUqc8plVC16SppOcU,239
|
|
16
|
-
yutipy/utils/helpers.py,sha256=W3g9iqoSygcFFCKCp2sk0NQrZOEG26wI2XuNi9pgAXE,5207
|
|
17
|
-
yutipy-2.2.3.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
|
|
18
|
-
yutipy-2.2.3.dist-info/METADATA,sha256=GU0nDx1yzsjArFuBvjNw9LdFVmktbOFyFCjUFMklD-o,6522
|
|
19
|
-
yutipy-2.2.3.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
|
20
|
-
yutipy-2.2.3.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
|
|
21
|
-
yutipy-2.2.3.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
22
|
-
yutipy-2.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|