yutipy 1.3.0__py3-none-any.whl → 1.3.2__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 +5 -2
- yutipy/itunes.py +5 -2
- yutipy/kkbox.py +5 -2
- yutipy/musicyt.py +5 -2
- yutipy/spotify.py +6 -3
- yutipy/yutipy_music.py +34 -14
- {yutipy-1.3.0.dist-info → yutipy-1.3.2.dist-info}/METADATA +1 -1
- yutipy-1.3.2.dist-info/RECORD +16 -0
- yutipy-1.3.0.dist-info/RECORD +0 -16
- {yutipy-1.3.0.dist-info → yutipy-1.3.2.dist-info}/WHEEL +0 -0
- {yutipy-1.3.0.dist-info → yutipy-1.3.2.dist-info}/licenses/LICENSE +0 -0
- {yutipy-1.3.0.dist-info → yutipy-1.3.2.dist-info}/top_level.txt +0 -0
yutipy/deezer.py
CHANGED
|
@@ -41,7 +41,7 @@ class Deezer:
|
|
|
41
41
|
"""Checks if the session is closed."""
|
|
42
42
|
return self._is_session_closed
|
|
43
43
|
|
|
44
|
-
def search(self, artist: str, song: str) -> Optional[MusicInfo]:
|
|
44
|
+
def search(self, artist: str, song: str, limit: int = 10) -> Optional[MusicInfo]:
|
|
45
45
|
"""
|
|
46
46
|
Searches for a song by artist and title.
|
|
47
47
|
|
|
@@ -51,6 +51,9 @@ class Deezer:
|
|
|
51
51
|
The name of the artist.
|
|
52
52
|
song : str
|
|
53
53
|
The title of the song.
|
|
54
|
+
limit: int, optional
|
|
55
|
+
The number of items to retrieve from API.
|
|
56
|
+
``limit >=1 and <= 50``. Default is ``10``.
|
|
54
57
|
|
|
55
58
|
Returns
|
|
56
59
|
-------
|
|
@@ -66,7 +69,7 @@ class Deezer:
|
|
|
66
69
|
|
|
67
70
|
for search_type in search_types:
|
|
68
71
|
endpoint = f"{self.api_url}/search/{search_type}"
|
|
69
|
-
query = f'?q=artist:"{artist}" {search_type}:"{song}"&limit=
|
|
72
|
+
query = f'?q=artist:"{artist}" {search_type}:"{song}"&limit={limit}'
|
|
70
73
|
query_url = endpoint + query
|
|
71
74
|
|
|
72
75
|
try:
|
yutipy/itunes.py
CHANGED
|
@@ -42,7 +42,7 @@ class Itunes:
|
|
|
42
42
|
"""Checks if the session is closed."""
|
|
43
43
|
return self._is_session_closed
|
|
44
44
|
|
|
45
|
-
def search(self, artist: str, song: str) -> Optional[MusicInfo]:
|
|
45
|
+
def search(self, artist: str, song: str, limit: int = 10) -> Optional[MusicInfo]:
|
|
46
46
|
"""
|
|
47
47
|
Searches for a song by artist and title.
|
|
48
48
|
|
|
@@ -52,6 +52,9 @@ class Itunes:
|
|
|
52
52
|
The name of the artist.
|
|
53
53
|
song : str
|
|
54
54
|
The title of the song.
|
|
55
|
+
limit: int, optional
|
|
56
|
+
The number of items to retrieve from API.
|
|
57
|
+
``limit >=1 and <= 50``. Default is ``10``.
|
|
55
58
|
|
|
56
59
|
Returns
|
|
57
60
|
-------
|
|
@@ -66,7 +69,7 @@ class Itunes:
|
|
|
66
69
|
entities = ["song", "album"]
|
|
67
70
|
for entity in entities:
|
|
68
71
|
endpoint = f"{self.api_url}/search"
|
|
69
|
-
query = f"?term={artist} - {song}&media=music&entity={entity}&limit=
|
|
72
|
+
query = f"?term={artist} - {song}&media=music&entity={entity}&limit={limit}"
|
|
70
73
|
query_url = endpoint + query
|
|
71
74
|
|
|
72
75
|
try:
|
yutipy/kkbox.py
CHANGED
|
@@ -134,7 +134,7 @@ class KKBox:
|
|
|
134
134
|
self.__start_time = time.time()
|
|
135
135
|
|
|
136
136
|
def search(
|
|
137
|
-
self, artist: str, song: str, territory: str = "TW"
|
|
137
|
+
self, artist: str, song: str, territory: str = "TW", limit: int = 10,
|
|
138
138
|
) -> Optional[MusicInfo]:
|
|
139
139
|
"""
|
|
140
140
|
Searches for a song by artist and title.
|
|
@@ -148,6 +148,9 @@ class KKBox:
|
|
|
148
148
|
territory : str
|
|
149
149
|
Two-letter country codes from ISO 3166-1 alpha-2.
|
|
150
150
|
Allowed values: ``HK``, ``JP``, ``MY``, ``SG``, ``TW``.
|
|
151
|
+
limit: int, optional
|
|
152
|
+
The number of items to retrieve from API.
|
|
153
|
+
``limit >=1 and <= 50``. Default is ``10``.
|
|
151
154
|
|
|
152
155
|
Returns
|
|
153
156
|
-------
|
|
@@ -161,7 +164,7 @@ class KKBox:
|
|
|
161
164
|
|
|
162
165
|
self.__refresh_token_if_expired()
|
|
163
166
|
|
|
164
|
-
query = f"?q={artist} - {song}&type=track,album&territory={territory}&limit=
|
|
167
|
+
query = f"?q={artist} - {song}&type=track,album&territory={territory}&limit={limit}"
|
|
165
168
|
query_url = f"{self.api_url}/search{query}"
|
|
166
169
|
|
|
167
170
|
try:
|
yutipy/musicyt.py
CHANGED
|
@@ -20,7 +20,7 @@ class MusicYT:
|
|
|
20
20
|
"""Initializes the YouTube Music class and sets up the session."""
|
|
21
21
|
self.ytmusic = YTMusic()
|
|
22
22
|
|
|
23
|
-
def search(self, artist: str, song: str) -> Optional[MusicInfo]:
|
|
23
|
+
def search(self, artist: str, song: str, limit: int = 10) -> Optional[MusicInfo]:
|
|
24
24
|
"""
|
|
25
25
|
Searches for a song by artist and title.
|
|
26
26
|
|
|
@@ -30,6 +30,9 @@ class MusicYT:
|
|
|
30
30
|
The name of the artist.
|
|
31
31
|
song : str
|
|
32
32
|
The title of the song.
|
|
33
|
+
limit: int, optional
|
|
34
|
+
The number of items to retrieve from API.
|
|
35
|
+
``limit >=1 and <= 50``. Default is ``10``.
|
|
33
36
|
|
|
34
37
|
Returns
|
|
35
38
|
-------
|
|
@@ -44,7 +47,7 @@ class MusicYT:
|
|
|
44
47
|
query = f"{artist} - {song}"
|
|
45
48
|
|
|
46
49
|
try:
|
|
47
|
-
results = self.ytmusic.search(query=query)
|
|
50
|
+
results = self.ytmusic.search(query=query, limit=limit)
|
|
48
51
|
except exceptions.YTMusicServerError as e:
|
|
49
52
|
raise NetworkException(f"Network error occurred: {e}")
|
|
50
53
|
|
yutipy/spotify.py
CHANGED
|
@@ -138,7 +138,7 @@ class Spotify:
|
|
|
138
138
|
self.__header, self.__expires_in = self.__authenticate()
|
|
139
139
|
self.__start_time = time.time()
|
|
140
140
|
|
|
141
|
-
def search(self, artist: str, song: str) -> Optional[MusicInfo]:
|
|
141
|
+
def search(self, artist: str, song: str, limit: int = 10) -> Optional[MusicInfo]:
|
|
142
142
|
"""
|
|
143
143
|
Searches for a song by artist and title.
|
|
144
144
|
|
|
@@ -148,6 +148,9 @@ class Spotify:
|
|
|
148
148
|
The name of the artist.
|
|
149
149
|
song : str
|
|
150
150
|
The title of the song.
|
|
151
|
+
limit: int, optional
|
|
152
|
+
The number of items to retrieve from API.
|
|
153
|
+
``limit >=1 and <= 50``. Default is ``10``.
|
|
151
154
|
|
|
152
155
|
Returns
|
|
153
156
|
-------
|
|
@@ -161,8 +164,8 @@ class Spotify:
|
|
|
161
164
|
|
|
162
165
|
music_info = None
|
|
163
166
|
queries = [
|
|
164
|
-
f"?q=artist:{artist} track:{song}&type=track&limit=
|
|
165
|
-
f"?q=artist:{artist} album:{song}&type=album&limit=
|
|
167
|
+
f"?q=artist:{artist} track:{song}&type=track&limit={limit}",
|
|
168
|
+
f"?q=artist:{artist} album:{song}&type=album&limit={limit}",
|
|
166
169
|
]
|
|
167
170
|
|
|
168
171
|
for query in queries:
|
yutipy/yutipy_music.py
CHANGED
|
@@ -22,9 +22,22 @@ class YutipyMusic:
|
|
|
22
22
|
def __init__(self) -> None:
|
|
23
23
|
"""Initializes the YutipyMusic class."""
|
|
24
24
|
self.music_info = MusicInfos()
|
|
25
|
-
self.album_art_priority = ["deezer", "kkbox", "spotify", "
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
self.album_art_priority = ["deezer", "kkbox", "spotify", "ytmusic", "itunes"]
|
|
26
|
+
self.services = {
|
|
27
|
+
"deezer": Deezer(),
|
|
28
|
+
"itunes": Itunes(),
|
|
29
|
+
"kkbox": KKBox(),
|
|
30
|
+
"ytmusic": MusicYT(),
|
|
31
|
+
"spotify": Spotify(),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def __enter__(self) -> "YutipyMusic":
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
|
|
38
|
+
self.close_sessions()
|
|
39
|
+
|
|
40
|
+
def search(self, artist: str, song: str, limit: int = 5) -> Optional[MusicInfos]:
|
|
28
41
|
"""
|
|
29
42
|
Searches for a song by artist and title.
|
|
30
43
|
|
|
@@ -34,6 +47,9 @@ class YutipyMusic:
|
|
|
34
47
|
The name of the artist.
|
|
35
48
|
song : str
|
|
36
49
|
The title of the song.
|
|
50
|
+
limit: int, optional
|
|
51
|
+
The number of items to retrieve from all APIs.
|
|
52
|
+
``limit >=1 and <= 50``. Default is ``5``.
|
|
37
53
|
|
|
38
54
|
Returns
|
|
39
55
|
-------
|
|
@@ -45,18 +61,12 @@ class YutipyMusic:
|
|
|
45
61
|
"Artist and song names must be valid strings and can't be empty."
|
|
46
62
|
)
|
|
47
63
|
|
|
48
|
-
services = [
|
|
49
|
-
(Deezer, "deezer"),
|
|
50
|
-
(Itunes, "itunes"),
|
|
51
|
-
(KKBox, "kkbox"),
|
|
52
|
-
(MusicYT, "musicyt"),
|
|
53
|
-
(Spotify, "spotify"),
|
|
54
|
-
]
|
|
55
|
-
|
|
56
64
|
with ThreadPoolExecutor() as executor:
|
|
57
65
|
futures = {
|
|
58
|
-
executor.submit(
|
|
59
|
-
|
|
66
|
+
executor.submit(
|
|
67
|
+
service.search, artist=artist, song=song, limit=limit
|
|
68
|
+
): name
|
|
69
|
+
for name, service in self.services.items()
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
for future in as_completed(futures):
|
|
@@ -64,7 +74,10 @@ class YutipyMusic:
|
|
|
64
74
|
result = future.result()
|
|
65
75
|
self._combine_results(result, service_name)
|
|
66
76
|
|
|
67
|
-
|
|
77
|
+
if len(self.music_info.url) == 0:
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
return self.music_info
|
|
68
81
|
|
|
69
82
|
def _combine_results(self, result: Optional[MusicInfo], service_name: str) -> None:
|
|
70
83
|
"""
|
|
@@ -114,9 +127,16 @@ class YutipyMusic:
|
|
|
114
127
|
self.music_info.id[service_name] = result.id
|
|
115
128
|
self.music_info.url[service_name] = result.url
|
|
116
129
|
|
|
130
|
+
def close_sessions(self) -> None:
|
|
131
|
+
"""Closes the sessions for all services."""
|
|
132
|
+
for service in self.services.values():
|
|
133
|
+
if hasattr(service, "close_session"):
|
|
134
|
+
service.close_session()
|
|
135
|
+
|
|
117
136
|
|
|
118
137
|
if __name__ == "__main__":
|
|
119
138
|
yutipy_music = YutipyMusic()
|
|
120
139
|
artist_name = input("Artist Name: ")
|
|
121
140
|
song_name = input("Song Name: ")
|
|
122
141
|
pprint(yutipy_music.search(artist_name, song_name))
|
|
142
|
+
yutipy_music.close_sessions()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
yutipy/__init__.py,sha256=UIymi9iT8s1nGuqcQcFudZYNsJDR4RzXe6LUaN9V8l0,289
|
|
2
|
+
yutipy/deezer.py,sha256=JNG9iy5xtjXwEjH-mlA0b75-MN0tswh0E3ytFskA5jI,8827
|
|
3
|
+
yutipy/exceptions.py,sha256=4L0Oe1PwFP34LoFTy-Fruipk7uB-JkaackRmkjlaZJU,1138
|
|
4
|
+
yutipy/itunes.py,sha256=cyddyZJscz7nD0mnJEimyBenZKlyjTOaMtcWKcW347w,5994
|
|
5
|
+
yutipy/kkbox.py,sha256=8rW9jzfM_RIaf0I0cOUCP_w_We25jFntQeoDl0vvbeg,12347
|
|
6
|
+
yutipy/models.py,sha256=si_qgaApAYDfSyE8cl_Yg4IfWOtxk1I5JCT8bZsmV4U,1931
|
|
7
|
+
yutipy/musicyt.py,sha256=drlAKIp5yNfEIlhp7eRJj42cJX2YxLvNashliDkdSNc,7324
|
|
8
|
+
yutipy/spotify.py,sha256=0B0SLWY1HRkC05zPMRTkSJ9bMogSRBsN9Wq7G0QW7lY,13774
|
|
9
|
+
yutipy/yutipy_music.py,sha256=jRMMbjxrlBcTI7AN0TZytLKt01ezUwzApP_byiEo_Dw,4752
|
|
10
|
+
yutipy/utils/__init__.py,sha256=7UFcFZ7fBtNXOTngjnRD3MeobT3x5UT2Gag94TXVgLk,169
|
|
11
|
+
yutipy/utils/cheap_utils.py,sha256=Yl0ssVbyvrdVeSPF7PqpGJpwTYLVa4CMgLtr6uk67v0,3104
|
|
12
|
+
yutipy-1.3.2.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
|
|
13
|
+
yutipy-1.3.2.dist-info/METADATA,sha256=Hzj9UM3ExumUN-k2r2VGVymMhbdCTHXMub5ITeXXTUA,6489
|
|
14
|
+
yutipy-1.3.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
15
|
+
yutipy-1.3.2.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
16
|
+
yutipy-1.3.2.dist-info/RECORD,,
|
yutipy-1.3.0.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
yutipy/__init__.py,sha256=UIymi9iT8s1nGuqcQcFudZYNsJDR4RzXe6LUaN9V8l0,289
|
|
2
|
-
yutipy/deezer.py,sha256=eLaDNBnpdFpvdxEQrgTZiLl-FBjSs1R0CKEgpgRi0Us,8666
|
|
3
|
-
yutipy/exceptions.py,sha256=4L0Oe1PwFP34LoFTy-Fruipk7uB-JkaackRmkjlaZJU,1138
|
|
4
|
-
yutipy/itunes.py,sha256=SmW6bCGKB9ADG2FxggGDmEOvqAIvuRi7aOkBSyHm2HQ,5841
|
|
5
|
-
yutipy/kkbox.py,sha256=9sz8eb-pu-47DTP_4kgackX1ZLijnCnz7q_1M8BqLWo,12185
|
|
6
|
-
yutipy/models.py,sha256=si_qgaApAYDfSyE8cl_Yg4IfWOtxk1I5JCT8bZsmV4U,1931
|
|
7
|
-
yutipy/musicyt.py,sha256=kvRYuhlNVuvy-WahJq895T3JAzmGTTiKB89r_uTMTAI,7155
|
|
8
|
-
yutipy/spotify.py,sha256=Oaktvdz7gLe2_PaktOmjlc8QpfhZWkmQnIZDmwoXlRE,13608
|
|
9
|
-
yutipy/yutipy_music.py,sha256=YZ_5iIjHr_QA3YAm2usR7hUqJMevu2ZVSQ59Q82Axj0,4053
|
|
10
|
-
yutipy/utils/__init__.py,sha256=7UFcFZ7fBtNXOTngjnRD3MeobT3x5UT2Gag94TXVgLk,169
|
|
11
|
-
yutipy/utils/cheap_utils.py,sha256=Yl0ssVbyvrdVeSPF7PqpGJpwTYLVa4CMgLtr6uk67v0,3104
|
|
12
|
-
yutipy-1.3.0.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
|
|
13
|
-
yutipy-1.3.0.dist-info/METADATA,sha256=p76rSDWegRztp7pl8eZ8LQh5FQsYi3aIH2eun9raX-A,6489
|
|
14
|
-
yutipy-1.3.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
15
|
-
yutipy-1.3.0.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
16
|
-
yutipy-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|