yutipy 0.1.0__py3-none-any.whl → 1.0.0__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/__init__.py +2 -2
- yutipy/deezer.py +8 -9
- yutipy/itunes.py +2 -2
- yutipy/models.py +55 -55
- yutipy/musicyt.py +1 -1
- yutipy/spotify.py +33 -32
- {yutipy-0.1.0.dist-info → yutipy-1.0.0.dist-info}/LICENSE +21 -21
- {yutipy-0.1.0.dist-info → yutipy-1.0.0.dist-info}/METADATA +140 -119
- yutipy-1.0.0.dist-info/RECORD +14 -0
- {yutipy-0.1.0.dist-info → yutipy-1.0.0.dist-info}/WHEEL +1 -1
- yutipy/__pycache__/__init__.cpython-312.pyc +0 -0
- yutipy/__pycache__/deezer.cpython-312.pyc +0 -0
- yutipy/__pycache__/exceptions.cpython-312.pyc +0 -0
- yutipy/__pycache__/itunes.cpython-312.pyc +0 -0
- yutipy/__pycache__/models.cpython-312.pyc +0 -0
- yutipy/__pycache__/musicyt.cpython-312.pyc +0 -0
- yutipy/__pycache__/spotify.cpython-312.pyc +0 -0
- yutipy/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- yutipy/utils/__pycache__/cheap_utils.cpython-312.pyc +0 -0
- yutipy-0.1.0.dist-info/RECORD +0 -23
- {yutipy-0.1.0.dist-info → yutipy-1.0.0.dist-info}/top_level.txt +0 -0
yutipy/__init__.py
CHANGED
|
@@ -2,12 +2,12 @@ from .deezer import Deezer
|
|
|
2
2
|
from .itunes import Itunes
|
|
3
3
|
from .models import MusicInfo
|
|
4
4
|
from .musicyt import MusicYT
|
|
5
|
-
from .spotify import
|
|
5
|
+
from .spotify import Spotify
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
8
|
"Deezer",
|
|
9
9
|
"Itunes",
|
|
10
10
|
"MusicInfo",
|
|
11
11
|
"MusicYT",
|
|
12
|
-
"
|
|
12
|
+
"Spotify",
|
|
13
13
|
]
|
yutipy/deezer.py
CHANGED
|
@@ -30,7 +30,7 @@ class Deezer:
|
|
|
30
30
|
"""Exits the runtime context related to this object."""
|
|
31
31
|
self._close_session()
|
|
32
32
|
|
|
33
|
-
def
|
|
33
|
+
def close_session(self) -> None:
|
|
34
34
|
"""Closes the current session."""
|
|
35
35
|
if not self.is_session_closed:
|
|
36
36
|
self._session.close()
|
|
@@ -54,7 +54,7 @@ class Deezer:
|
|
|
54
54
|
|
|
55
55
|
Returns
|
|
56
56
|
-------
|
|
57
|
-
Optional[
|
|
57
|
+
Optional[MusicInfo_]
|
|
58
58
|
The music information if found, otherwise None.
|
|
59
59
|
"""
|
|
60
60
|
if not is_valid_string(artist) or not is_valid_string(song):
|
|
@@ -104,13 +104,12 @@ class Deezer:
|
|
|
104
104
|
Optional[Dict]
|
|
105
105
|
A dictionary containing UPC and ISRC information.
|
|
106
106
|
"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
raise DeezerException(f"Invalid music type: {music_type}")
|
|
107
|
+
if music_type == "track":
|
|
108
|
+
return self._get_track_info(music_id)
|
|
109
|
+
elif music_type == "album":
|
|
110
|
+
return self._get_album_info(music_id)
|
|
111
|
+
else:
|
|
112
|
+
raise DeezerException(f"Invalid music type: {music_type}")
|
|
114
113
|
|
|
115
114
|
def _get_track_info(self, music_id: int) -> Optional[Dict]:
|
|
116
115
|
"""
|
yutipy/itunes.py
CHANGED
|
@@ -31,7 +31,7 @@ class Itunes:
|
|
|
31
31
|
"""Exits the runtime context related to this object."""
|
|
32
32
|
self._close_session()
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def close_session(self) -> None:
|
|
35
35
|
"""Closes the current session."""
|
|
36
36
|
if not self.is_session_closed:
|
|
37
37
|
self._session.close()
|
|
@@ -55,7 +55,7 @@ class Itunes:
|
|
|
55
55
|
|
|
56
56
|
Returns
|
|
57
57
|
-------
|
|
58
|
-
Optional[
|
|
58
|
+
Optional[MusicInfo_]
|
|
59
59
|
The music information if found, otherwise None.
|
|
60
60
|
"""
|
|
61
61
|
if not is_valid_string(artist) or not is_valid_string(song):
|
yutipy/models.py
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@dataclass
|
|
6
|
-
class MusicInfo:
|
|
7
|
-
"""
|
|
8
|
-
A data class to store music information.
|
|
9
|
-
|
|
10
|
-
Attributes
|
|
11
|
-
----------
|
|
12
|
-
album_art : Optional[str]
|
|
13
|
-
URL to the album art.
|
|
14
|
-
album_title : Optional[str]
|
|
15
|
-
Title of the album.
|
|
16
|
-
album_type : Optional[str]
|
|
17
|
-
Type of the album (e.g., album, single).
|
|
18
|
-
artists : str
|
|
19
|
-
Name(s) of the artist(s).
|
|
20
|
-
genre : Optional[str]
|
|
21
|
-
Genre of the music.
|
|
22
|
-
id : str
|
|
23
|
-
Unique identifier for the music.
|
|
24
|
-
isrc : Optional[str]
|
|
25
|
-
International Standard Recording Code.
|
|
26
|
-
lyrics : Optional[str]
|
|
27
|
-
Lyrics of the song.
|
|
28
|
-
release_date : Optional[str]
|
|
29
|
-
Release date of the music.
|
|
30
|
-
tempo : Optional[float]
|
|
31
|
-
Tempo of the music in BPM.
|
|
32
|
-
title : str
|
|
33
|
-
Title of the music.
|
|
34
|
-
type : Optional[str]
|
|
35
|
-
Type of the music (e.g., track, album).
|
|
36
|
-
upc : Optional[str]
|
|
37
|
-
Universal Product Code.
|
|
38
|
-
url : str
|
|
39
|
-
URL to the music on the platform.
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
album_art: Optional[str]
|
|
43
|
-
album_title: Optional[str]
|
|
44
|
-
album_type: Optional[str]
|
|
45
|
-
artists: str
|
|
46
|
-
genre: Optional[str]
|
|
47
|
-
id: str
|
|
48
|
-
isrc: Optional[str]
|
|
49
|
-
lyrics: Optional[str]
|
|
50
|
-
release_date: Optional[str]
|
|
51
|
-
tempo: Optional[float]
|
|
52
|
-
title: str
|
|
53
|
-
type: Optional[str]
|
|
54
|
-
upc: Optional[str]
|
|
55
|
-
url: str
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class MusicInfo:
|
|
7
|
+
"""
|
|
8
|
+
A data class to store music information.
|
|
9
|
+
|
|
10
|
+
Attributes
|
|
11
|
+
----------
|
|
12
|
+
album_art : Optional[str]
|
|
13
|
+
URL to the album art.
|
|
14
|
+
album_title : Optional[str]
|
|
15
|
+
Title of the album.
|
|
16
|
+
album_type : Optional[str]
|
|
17
|
+
Type of the album (e.g., album, single).
|
|
18
|
+
artists : str
|
|
19
|
+
Name(s) of the artist(s).
|
|
20
|
+
genre : Optional[str]
|
|
21
|
+
Genre of the music.
|
|
22
|
+
id : str
|
|
23
|
+
Unique identifier for the music.
|
|
24
|
+
isrc : Optional[str]
|
|
25
|
+
International Standard Recording Code.
|
|
26
|
+
lyrics : Optional[str]
|
|
27
|
+
Lyrics of the song.
|
|
28
|
+
release_date : Optional[str]
|
|
29
|
+
Release date of the music.
|
|
30
|
+
tempo : Optional[float]
|
|
31
|
+
Tempo of the music in BPM.
|
|
32
|
+
title : str
|
|
33
|
+
Title of the music.
|
|
34
|
+
type : Optional[str]
|
|
35
|
+
Type of the music (e.g., track, album).
|
|
36
|
+
upc : Optional[str]
|
|
37
|
+
Universal Product Code.
|
|
38
|
+
url : str
|
|
39
|
+
URL to the music on the platform.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
album_art: Optional[str]
|
|
43
|
+
album_title: Optional[str]
|
|
44
|
+
album_type: Optional[str]
|
|
45
|
+
artists: str
|
|
46
|
+
genre: Optional[str]
|
|
47
|
+
id: str
|
|
48
|
+
isrc: Optional[str]
|
|
49
|
+
lyrics: Optional[str]
|
|
50
|
+
release_date: Optional[str]
|
|
51
|
+
tempo: Optional[float]
|
|
52
|
+
title: str
|
|
53
|
+
type: Optional[str]
|
|
54
|
+
upc: Optional[str]
|
|
55
|
+
url: str
|
yutipy/musicyt.py
CHANGED
yutipy/spotify.py
CHANGED
|
@@ -2,7 +2,7 @@ import base64
|
|
|
2
2
|
import os
|
|
3
3
|
import time
|
|
4
4
|
from pprint import pprint
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Optional, Union
|
|
6
6
|
|
|
7
7
|
import requests
|
|
8
8
|
from dotenv import load_dotenv
|
|
@@ -23,41 +23,41 @@ from yutipy.utils.cheap_utils import (
|
|
|
23
23
|
|
|
24
24
|
load_dotenv()
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
SPOTIFY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
|
|
27
|
+
SPOTIFY_CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class Spotify:
|
|
31
31
|
"""
|
|
32
32
|
A class to interact with the Spotify API.
|
|
33
33
|
|
|
34
|
-
This class reads the
|
|
35
|
-
Alternatively,
|
|
34
|
+
This class reads the ``SPOTIFY_CLIENT_ID`` and ``SPOTIFY_CLIENT_SECRET`` from environment variables or the ``.env`` file by default.
|
|
35
|
+
Alternatively, you can manually provide these values when creating an object.
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
38
|
def __init__(
|
|
39
|
-
self, client_id: str =
|
|
39
|
+
self, client_id: str = SPOTIFY_CLIENT_ID, client_secret: str = SPOTIFY_CLIENT_SECRET
|
|
40
40
|
) -> None:
|
|
41
41
|
"""
|
|
42
|
-
Initializes the
|
|
42
|
+
Initializes the Spotify class and sets up the session.
|
|
43
43
|
|
|
44
44
|
Parameters
|
|
45
45
|
----------
|
|
46
46
|
client_id : str, optional
|
|
47
|
-
The
|
|
47
|
+
The Client ID for the Spotify API. Defaults to ``SPOTIFY_CLIENT_ID`` from .env file.
|
|
48
48
|
client_secret : str, optional
|
|
49
|
-
The
|
|
49
|
+
The Client secret for the Spotify API. Defaults to ``SPOTIFY_CLIENT_SECRET`` from .env file.
|
|
50
50
|
"""
|
|
51
51
|
if not client_id or not client_secret:
|
|
52
52
|
raise SpotifyException(
|
|
53
|
-
"Failed to read
|
|
53
|
+
"Failed to read `SPOTIFY_CLIENT_ID` and `SPOTIFY_CLIENT_SECRET` from environment variables. Client ID and Client Secret must be provided."
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
self.client_id = client_id
|
|
57
57
|
self.client_secret = client_secret
|
|
58
58
|
self._session = requests.Session()
|
|
59
59
|
self.api_url = "https://api.spotify.com/v1"
|
|
60
|
-
self.__header = self.__authenticate()
|
|
60
|
+
self.__header, self.__expires_in = self.__authenticate()
|
|
61
61
|
self.__start_time = time.time()
|
|
62
62
|
self._is_session_closed = False
|
|
63
63
|
|
|
@@ -69,7 +69,7 @@ class Spotipy:
|
|
|
69
69
|
"""Exits the runtime context related to this object."""
|
|
70
70
|
self._close_session()
|
|
71
71
|
|
|
72
|
-
def
|
|
72
|
+
def close_session(self) -> None:
|
|
73
73
|
"""Closes the current session."""
|
|
74
74
|
if not self.is_session_closed:
|
|
75
75
|
self._session.close()
|
|
@@ -80,7 +80,7 @@ class Spotipy:
|
|
|
80
80
|
"""Checks if the session is closed."""
|
|
81
81
|
return self._is_session_closed
|
|
82
82
|
|
|
83
|
-
def __authenticate(self) ->
|
|
83
|
+
def __authenticate(self) -> tuple:
|
|
84
84
|
"""
|
|
85
85
|
Authenticates with the Spotify API and returns the authorization header.
|
|
86
86
|
|
|
@@ -90,14 +90,14 @@ class Spotipy:
|
|
|
90
90
|
The authorization header.
|
|
91
91
|
"""
|
|
92
92
|
try:
|
|
93
|
-
token = self.__get_spotify_token()
|
|
94
|
-
return {"Authorization": f"Bearer {token}"}
|
|
93
|
+
token, expires_in = self.__get_spotify_token()
|
|
94
|
+
return {"Authorization": f"Bearer {token}"}, expires_in
|
|
95
95
|
except Exception as e:
|
|
96
96
|
raise AuthenticationException(
|
|
97
97
|
"Failed to authenticate with Spotify API"
|
|
98
98
|
) from e
|
|
99
99
|
|
|
100
|
-
def __get_spotify_token(self) ->
|
|
100
|
+
def __get_spotify_token(self) -> tuple:
|
|
101
101
|
"""
|
|
102
102
|
Gets the Spotify API token.
|
|
103
103
|
|
|
@@ -125,14 +125,16 @@ class Spotipy:
|
|
|
125
125
|
raise NetworkException(f"Network error occurred: {e}")
|
|
126
126
|
|
|
127
127
|
try:
|
|
128
|
-
|
|
128
|
+
response_json = response.json()
|
|
129
|
+
return response_json.get("access_token"), response_json.get("expires_in")
|
|
129
130
|
except (KeyError, ValueError) as e:
|
|
130
131
|
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
131
132
|
|
|
132
133
|
def __refresh_token_if_expired(self):
|
|
133
134
|
"""Refreshes the token if it has expired."""
|
|
134
|
-
if time.time() - self.__start_time >=
|
|
135
|
-
self.__header = self.__authenticate()
|
|
135
|
+
if time.time() - self.__start_time >= self.__expires_in:
|
|
136
|
+
self.__header, self.__expires_in = self.__authenticate()
|
|
137
|
+
self.__start_time = time.time()
|
|
136
138
|
|
|
137
139
|
def search(self, artist: str, song: str) -> Optional[MusicInfo]:
|
|
138
140
|
"""
|
|
@@ -147,7 +149,7 @@ class Spotipy:
|
|
|
147
149
|
|
|
148
150
|
Returns
|
|
149
151
|
-------
|
|
150
|
-
Optional[
|
|
152
|
+
Optional[MusicInfo_]
|
|
151
153
|
The music information if found, otherwise None.
|
|
152
154
|
"""
|
|
153
155
|
if not is_valid_string(artist) or not is_valid_string(song):
|
|
@@ -166,12 +168,11 @@ class Spotipy:
|
|
|
166
168
|
except requests.RequestException as e:
|
|
167
169
|
raise NetworkException(f"Network error occurred: {e}")
|
|
168
170
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
except (KeyError, ValueError) as e:
|
|
172
|
-
raise InvalidResponseException(f"Invalid response received: {e}")
|
|
171
|
+
if response.status_code != 200:
|
|
172
|
+
raise SpotifyException(f"Failed to search for music: {response.json()}")
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
artist_ids = self._get_artists_ids(artist)
|
|
175
|
+
return self._find_music_info(artist, song, response.json(), artist_ids)
|
|
175
176
|
|
|
176
177
|
def search_advanced(
|
|
177
178
|
self, artist: str, song: str, isrc: str = None, upc: str = None
|
|
@@ -192,7 +193,7 @@ class Spotipy:
|
|
|
192
193
|
|
|
193
194
|
Returns
|
|
194
195
|
-------
|
|
195
|
-
Optional[
|
|
196
|
+
Optional[MusicInfo_]
|
|
196
197
|
The music information if found, otherwise None.
|
|
197
198
|
"""
|
|
198
199
|
if not is_valid_string(artist) or not is_valid_string(song):
|
|
@@ -224,7 +225,7 @@ class Spotipy:
|
|
|
224
225
|
artist_ids = self._get_artists_ids(artist)
|
|
225
226
|
return self._find_music_info(artist, song, response.json(), artist_ids)
|
|
226
227
|
|
|
227
|
-
def _get_artists_ids(self, artist: str) -> list
|
|
228
|
+
def _get_artists_ids(self, artist: str) -> Union[list, None]:
|
|
228
229
|
"""
|
|
229
230
|
Retrieves the IDs of the artists.
|
|
230
231
|
|
|
@@ -235,7 +236,7 @@ class Spotipy:
|
|
|
235
236
|
|
|
236
237
|
Returns
|
|
237
238
|
-------
|
|
238
|
-
list
|
|
239
|
+
Union[list, None]
|
|
239
240
|
A list of artist IDs or None if not found.
|
|
240
241
|
"""
|
|
241
242
|
artist_ids = []
|
|
@@ -403,11 +404,11 @@ class Spotipy:
|
|
|
403
404
|
|
|
404
405
|
|
|
405
406
|
if __name__ == "__main__":
|
|
406
|
-
|
|
407
|
+
Spotify = Spotify(SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET)
|
|
407
408
|
|
|
408
409
|
try:
|
|
409
410
|
artist_name = input("Artist Name: ")
|
|
410
411
|
song_name = input("Song Name: ")
|
|
411
|
-
pprint(
|
|
412
|
+
pprint(Spotify.search(artist_name, song_name))
|
|
412
413
|
finally:
|
|
413
|
-
|
|
414
|
+
Spotify.close_session()
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Cheap Nightbot
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Cheap Nightbot
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,119 +1,140 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: yutipy
|
|
3
|
-
Version:
|
|
4
|
-
Summary: A simple package for retrieving music information from various music platforms APIs.
|
|
5
|
-
Author: Cheap Nightbot
|
|
6
|
-
Author-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
|
|
7
|
-
Maintainer-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
|
|
8
|
-
License: MIT License
|
|
9
|
-
|
|
10
|
-
Copyright (c) 2025 Cheap Nightbot
|
|
11
|
-
|
|
12
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
-
in the Software without restriction, including without limitation the rights
|
|
15
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
-
furnished to do so, subject to the following conditions:
|
|
18
|
-
|
|
19
|
-
The above copyright notice and this permission notice shall be included in all
|
|
20
|
-
copies or substantial portions of the Software.
|
|
21
|
-
|
|
22
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
-
SOFTWARE.
|
|
29
|
-
|
|
30
|
-
Project-URL: Homepage, https://github.com/CheapNightbot/yutipy
|
|
31
|
-
Project-URL: Documentation, https://yutipy.readthedocs.io/
|
|
32
|
-
Project-URL: Repository, https://github.com/CheapNightbot/yutipy.git
|
|
33
|
-
Project-URL: Issues, https://github.com/CheapNightbot/yutipy/issues
|
|
34
|
-
Project-URL: Changelog, https://github.com/CheapNightbot/yutipy/blob/master/CHANGELOG.md
|
|
35
|
-
Project-URL: funding, https://ko-fi.com/cheapnightbot
|
|
36
|
-
Keywords: music,API,Deezer,iTunes,Spotify,YouTube Music,search,retrieve,information,yutify
|
|
37
|
-
Classifier: Development Status :: 4 - Beta
|
|
38
|
-
Classifier: Intended Audience :: Developers
|
|
39
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
40
|
-
Classifier: Programming Language :: Python :: 3
|
|
41
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
42
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
43
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
44
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
45
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
46
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
47
|
-
Classifier: Operating System :: OS Independent
|
|
48
|
-
Requires-Python: >=3.8
|
|
49
|
-
Description-Content-Type: text/markdown
|
|
50
|
-
License-File: LICENSE
|
|
51
|
-
Requires-Dist: python-dotenv==1.0.1
|
|
52
|
-
Requires-Dist: rapidfuzz==3.12.1
|
|
53
|
-
Requires-Dist: requests==2.32.3
|
|
54
|
-
Requires-Dist: ytmusicapi==1.10.1
|
|
55
|
-
Provides-Extra: dev
|
|
56
|
-
Requires-Dist: pytest
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: yutipy
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A simple package for retrieving music information from various music platforms APIs.
|
|
5
|
+
Author: Cheap Nightbot
|
|
6
|
+
Author-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
|
|
7
|
+
Maintainer-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2025 Cheap Nightbot
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
Project-URL: Homepage, https://github.com/CheapNightbot/yutipy
|
|
31
|
+
Project-URL: Documentation, https://yutipy.readthedocs.io/
|
|
32
|
+
Project-URL: Repository, https://github.com/CheapNightbot/yutipy.git
|
|
33
|
+
Project-URL: Issues, https://github.com/CheapNightbot/yutipy/issues
|
|
34
|
+
Project-URL: Changelog, https://github.com/CheapNightbot/yutipy/blob/master/CHANGELOG.md
|
|
35
|
+
Project-URL: funding, https://ko-fi.com/cheapnightbot
|
|
36
|
+
Keywords: music,API,Deezer,iTunes,Spotify,YouTube Music,search,retrieve,information,yutify
|
|
37
|
+
Classifier: Development Status :: 4 - Beta
|
|
38
|
+
Classifier: Intended Audience :: Developers
|
|
39
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
46
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
47
|
+
Classifier: Operating System :: OS Independent
|
|
48
|
+
Requires-Python: >=3.8
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
License-File: LICENSE
|
|
51
|
+
Requires-Dist: python-dotenv==1.0.1
|
|
52
|
+
Requires-Dist: rapidfuzz==3.12.1
|
|
53
|
+
Requires-Dist: requests==2.32.3
|
|
54
|
+
Requires-Dist: ytmusicapi==1.10.1
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Requires-Dist: pytest; extra == "dev"
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="https://raw.githubusercontent.com/CheapNightbot/yutipy/main/docs/_static/yutipy_header.png" alt="yutipy" />
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
<p align="center">
|
|
63
|
+
<a href="https://github.com/CheapNightbot/yutipy/actions/workflows/tests.yml">
|
|
64
|
+
<img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/cheapnightbot/yutipy/pytest-unit-testing.yml?style=for-the-badge&label=Pytest">
|
|
65
|
+
</a>
|
|
66
|
+
<a href="https://pypi.org/project/yutipy/">
|
|
67
|
+
<img src="https://img.shields.io/pypi/v/yutipy?style=for-the-badge" alt="PyPI" />
|
|
68
|
+
</a>
|
|
69
|
+
<a href="https://yutipy.readthedocs.io/en/latest/">
|
|
70
|
+
<img src="https://img.shields.io/readthedocs/yutipy?style=for-the-badge" alt="Documentation Status" />
|
|
71
|
+
</a>
|
|
72
|
+
<a href="https://github.com/CheapNightbot/yutipy/blob/master/LICENSE">
|
|
73
|
+
<img src="https://img.shields.io/github/license/CheapNightbot/yutipy?style=for-the-badge" alt="License" />
|
|
74
|
+
</a>
|
|
75
|
+
<a href="https://github.com/CheapNightbot/yutipy/stargazers">
|
|
76
|
+
<img src="https://img.shields.io/github/stars/CheapNightbot/yutipy?style=for-the-badge" alt="Stars" />
|
|
77
|
+
</a>
|
|
78
|
+
<a href="https://github.com/CheapNightbot/yutipy/issues">
|
|
79
|
+
<img src="https://img.shields.io/github/issues/CheapNightbot/yutipy?style=for-the-badge" alt="Issues" />
|
|
80
|
+
</a>
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
A _**simple**_ Python package for searching and retrieving music information from various music platforms APIs, including Deezer, iTunes, Spotify, and YouTube Music.
|
|
84
|
+
|
|
85
|
+
## Table of Contents
|
|
86
|
+
|
|
87
|
+
- [Features](#features)
|
|
88
|
+
- [Installation](#installation)
|
|
89
|
+
- [Usage Example](#usage-example)
|
|
90
|
+
- [Contributing](#contributing)
|
|
91
|
+
- [License](#license)
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
- Simple & Easy integration with popular music APIs.
|
|
96
|
+
- Search for music by artist and song title across multiple platforms.
|
|
97
|
+
- It uses `RapidFuzz` to compare & return the best match so that you can be sure you got what you asked for without having to worry and doing all that work by yourself.
|
|
98
|
+
- Retrieve detailed music information, including album art, release dates, lyrics, ISRC, and UPC codes.
|
|
99
|
+
|
|
100
|
+
## Installation
|
|
101
|
+
|
|
102
|
+
You can install the package using pip. Make sure you have Python 3.8 or higher installed.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install -U yutipy
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Usage Example
|
|
109
|
+
|
|
110
|
+
Here's a quick example of how to use the `yutipy` package to search for a song:
|
|
111
|
+
|
|
112
|
+
### Deezer
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from yutipy.deezer import Deezer
|
|
116
|
+
|
|
117
|
+
with Deezer() as deezer:
|
|
118
|
+
result = deezer.search("Artist Name", "Song Title")
|
|
119
|
+
print(result)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
For more usage examples, see the [Usage Examples](https://yutipy.readthedocs.io/en/latest/usage_examples.html) page in docs.
|
|
123
|
+
|
|
124
|
+
## Contributing
|
|
125
|
+
|
|
126
|
+
Contributions are welcome! Please follow these steps:
|
|
127
|
+
|
|
128
|
+
1. Fork the repository.
|
|
129
|
+
2. Optionally, create an issue to discuss the changes you plan to make.
|
|
130
|
+
3. Create a new branch linked to that issue.
|
|
131
|
+
4. Make your changes in the new branch.
|
|
132
|
+
5. Write tests if you add new functionality.
|
|
133
|
+
6. Ensure all tests pass before opening a pull request.
|
|
134
|
+
7. Open a pull request for review.
|
|
135
|
+
|
|
136
|
+
Thank you for your contributions!
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
yutipy/__init__.py,sha256=t0w-pRLjIGD3UtDyd-JpeL-RrMona7YTV_0lZCpGLEc,232
|
|
2
|
+
yutipy/deezer.py,sha256=TbPk6f1ytrtk9GHXOoRZ948fcgOi0619-rQC9xfTYu0,8641
|
|
3
|
+
yutipy/exceptions.py,sha256=QDfOkaeZtSNg1lhXZ872yNJwbof68eVHDezZeZh8DiU,1029
|
|
4
|
+
yutipy/itunes.py,sha256=NhrllA3U0PUY3dNoMyiG1oZuyvdMQKYRBHzYSkt8ikM,5843
|
|
5
|
+
yutipy/models.py,sha256=RnfWjoNO1UoNsRvNRYd-4TpkU-4jHKu5t394vIqOOgw,1360
|
|
6
|
+
yutipy/musicyt.py,sha256=kvRYuhlNVuvy-WahJq895T3JAzmGTTiKB89r_uTMTAI,7155
|
|
7
|
+
yutipy/spotify.py,sha256=ZFn73iHtXczO4Dq3ZfYquwtP_fyfHBK2sJTFrcv_xYE,13232
|
|
8
|
+
yutipy/utils/__init__.py,sha256=7UFcFZ7fBtNXOTngjnRD3MeobT3x5UT2Gag94TXVgLk,169
|
|
9
|
+
yutipy/utils/cheap_utils.py,sha256=LIuEHib_97NuLahXxdHJUD9v-ccXNUc3NrLYk8EQ52A,1652
|
|
10
|
+
yutipy-1.0.0.dist-info/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
|
|
11
|
+
yutipy-1.0.0.dist-info/METADATA,sha256=b8VSSJH__Ii-QJOfCszX4pBWEx6sKAmHcL9t4_qPVHQ,5897
|
|
12
|
+
yutipy-1.0.0.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
13
|
+
yutipy-1.0.0.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
14
|
+
yutipy-1.0.0.dist-info/RECORD,,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
yutipy-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
yutipy/__init__.py,sha256=GKMg-aksc_2IAjcKAogGCe_aeSstuwAexjVdJRPS0mE,232
|
|
2
|
-
yutipy/deezer.py,sha256=h2ZeOyzS0L0--qmowkNsFXUl0Nbk30x447bapTV10Io,8667
|
|
3
|
-
yutipy/exceptions.py,sha256=QDfOkaeZtSNg1lhXZ872yNJwbof68eVHDezZeZh8DiU,1029
|
|
4
|
-
yutipy/itunes.py,sha256=NiRGCgV5EASjkS_FPhzDwOq8oge-AeDwkVK4JHNy698,5843
|
|
5
|
-
yutipy/models.py,sha256=-UEi05on5XsKjFSqUNt1yZnLod_A9upqh2nIPWTtEEI,1415
|
|
6
|
-
yutipy/musicyt.py,sha256=fVhCFZUgv34CjyDRMIBeLNYsEuTgENxyMlGUt9Uf1JA,7154
|
|
7
|
-
yutipy/spotify.py,sha256=X8-jDFj8U5kY4zeuGoZ-hrgDbzbKKww47vpVvJev1rA,12849
|
|
8
|
-
yutipy/__pycache__/__init__.cpython-312.pyc,sha256=hnQz69yUeXB3mK1j0EiIsKfFRm1ywiQF170VggBhjdc,392
|
|
9
|
-
yutipy/__pycache__/deezer.cpython-312.pyc,sha256=w5LdiOePHf0NLLDQfj__FxsuplJ4dN5JLnCAK0MXD9I,10578
|
|
10
|
-
yutipy/__pycache__/exceptions.cpython-312.pyc,sha256=Zc73Tr79emWJ9pmpAVoL12YnBBOWJulV1hxtSso4hy8,2096
|
|
11
|
-
yutipy/__pycache__/itunes.cpython-312.pyc,sha256=PvXlgEp6uWzAR_VlPYP-bmQQPmkURz2237AOgFiD5o4,7511
|
|
12
|
-
yutipy/__pycache__/models.cpython-312.pyc,sha256=KJUa3-C67TMq1EAGuQlZYT99JS1AEDUi74KY8bEHkkg,1848
|
|
13
|
-
yutipy/__pycache__/musicyt.cpython-312.pyc,sha256=494-Q64MEXVwsRSZycCCp6T-h37y0RAARnv_OA2QZ-0,9175
|
|
14
|
-
yutipy/__pycache__/spotify.cpython-312.pyc,sha256=P5UXhd8g0h9EaxfPaPyQUeIIHHqLmQCcAXfJcTTKzsI,15789
|
|
15
|
-
yutipy/utils/__init__.py,sha256=7UFcFZ7fBtNXOTngjnRD3MeobT3x5UT2Gag94TXVgLk,169
|
|
16
|
-
yutipy/utils/cheap_utils.py,sha256=LIuEHib_97NuLahXxdHJUD9v-ccXNUc3NrLYk8EQ52A,1652
|
|
17
|
-
yutipy/utils/__pycache__/__init__.cpython-312.pyc,sha256=_ldEMv66ELlrY1M7fN_2r5XySvgAsqTE0U8ASGXx8bs,286
|
|
18
|
-
yutipy/utils/__pycache__/cheap_utils.cpython-312.pyc,sha256=i6nRmXcRtCkTzKQ1mWyjN7Xz4NapqgBdXA33so8xgLU,2376
|
|
19
|
-
yutipy-0.1.0.dist-info/LICENSE,sha256=Tymbhvk1F_6BDFE0X8BBiQp7cBCjbzKfRAITmvxJIyA,1092
|
|
20
|
-
yutipy-0.1.0.dist-info/METADATA,sha256=krlRAHqZqAowrWiRymP1L5pyC5IgHht8BVpQTz01qMs,4708
|
|
21
|
-
yutipy-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
22
|
-
yutipy-0.1.0.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
|
|
23
|
-
yutipy-0.1.0.dist-info/RECORD,,
|
|
File without changes
|