-
Notifications
You must be signed in to change notification settings - Fork 61
/
api.py
291 lines (260 loc) 路 11.8 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
import pathlib
import uuid
import time
from pydub import AudioSegment
from typing import Dict, Any, Union
from .misc import Request
from .misc import ShazamUrl
from .signature import DecodedMessage
from .enums import GenreMusic
from .converter import Converter, Geo
from .typehints import CountryCode
from .utils import get_song
class Shazam(Converter, Geo):
"""Is a asynchronous framework for reverse engineered Shazam API written in Python 3.7 with
asyncio and aiohttp."""
async def top_world_tracks(
self, limit: int = 200, start_from: int = 0
) -> Dict[str, Any]:
"""
Search top world tracks
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict tracks
"""
return await self.request(
"GET",
ShazamUrl.TOP_TRACKS_WORLD.format(limit, start_from),
headers=Request.HEADERS,
)
async def artist_about(self, artist_id: int) -> Dict[str, Any]:
"""
Retrieving information from an artist profile
:param artist_id: Artist number. Example (203347991) :
https://www.shazam.com/artist/203347991/
:return: dict about artist
"""
return await self.request(
"GET", ShazamUrl.ARTIST_ABOUT.format(artist_id), headers=Request.HEADERS
)
async def artist_top_tracks(
self, artist_id: int, limit: int = 200, start_from: int = 0
) -> Dict[str, Any]:
"""
Get the top songs according to Shazam
:param artist_id: Artist number. Example: (203347991)
https://www.shazam.com/artist/203347991/
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict tracks
"""
return await self.request(
"GET",
ShazamUrl.ARTIST_TOP_TRACKS.format(artist_id, start_from, limit),
headers=Request.HEADERS,
)
async def track_about(self, track_id: int) -> Dict[str, Any]:
"""
Get track information
:param track_id: Track number. Example: (549952578)
https://www.shazam.com/track/549952578/
:return: dict about track
"""
return await self.request(
"GET", ShazamUrl.ABOUT_TRACK.format(track_id), headers=Request.HEADERS
)
async def top_country_tracks(
self,
country_code: Union[CountryCode, str],
limit: int = 200,
start_from: int = 0,
) -> Dict[str, Any]:
"""
Get the best tracks by country code
https://www.shazam.com/charts/discovery/netherlands
:param country_code: ISO 3166-3 alpha-2 code. Example: RU,NL,UA
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict songs
"""
return await self.request(
"GET",
ShazamUrl.TOP_TRACKS_COUNTRY.format(country_code, limit, start_from),
headers=Request.HEADERS,
)
async def top_city_tracks(
self,
country_code: Union[CountryCode, str],
city_name: str,
limit: int = 200,
start_from: int = 0,
) -> Dict[str, Any]:
"""
Retrieving information from an artist profile
https://www.shazam.com/charts/top-50/russia/moscow
:param country_code: ISO 3166-3 alpha-2 code. Example: RU,NL,UA
:param city_name: City name from https://github.com/dotX12/dotX12/blob/main/city.json
Example: Budapest, Moscow
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict songs
"""
city_id = await self.city_id_from(country=country_code, city=city_name)
return await self.request(
"GET",
ShazamUrl.TOP_TRACKS_CITY.format(city_id, limit, start_from),
headers=Request.HEADERS,
)
async def top_world_genre_tracks(
self, genre: Union[GenreMusic, int], limit: int = 100, start_from: int = 0
) -> Dict[str, Any]:
"""
Get world tracks by certain genre
https://www.shazam.com/charts/genre/world/rock
:param genre: Genre name or ID:
POP = 1, HIP_HOP_RAP = 2, DANCE = 3, ELECTRONIC = 4, RNB_SOUL = 5, ALTERNATIVE =
6, ROCK = 7
LATIN = 8, FILM_TV_STAGE = 9, COUNTRY = 10, AFRO_BEATS = 11, WORLDWIDE = 12,
REGGAE_DANCE_HALL = 13
HOUSE = 14, K_POP = 15, FRENCH_POP = 16, SINGER_SONGWRITER = 17,
REGIONAL_MEXICANO = 18
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter
to your own.
:return: dict songs
"""
return await self.request(
"GET",
ShazamUrl.GENRE_WORLD.format(genre, limit, start_from),
headers=Request.HEADERS,
)
async def top_country_genre_tracks(
self,
country_code: str,
genre: Union[GenreMusic, int],
limit: int = 200,
start_from: int = 0,
) -> Dict[str, Any]:
"""
The best tracks by a genre in the country
https://www.shazam.com/charts/genre/spain/hip-hop-rap
:param country_code: ISO 3166-3 alpha-2 code. Example: RU,NL,UA
:param genre: Genre name or ID:
POP = 1, HIP_HOP_RAP = 2, DANCE = 3, ELECTRONIC = 4, RNB_SOUL = 5, ALTERNATIVE =
6, ROCK = 7
LATIN = 8, FILM_TV_STAGE = 9, COUNTRY = 10, AFRO_BEATS = 11, WORLDWIDE = 12,
REGGAE_DANCE_HALL = 13
HOUSE = 14, K_POP = 15, FRENCH_POP = 16, SINGER_SONGWRITER = 17,
REGIONAL_MEXICANO = 18
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict songs
"""
return await self.request(
"GET",
ShazamUrl.GENRE_COUNTRY.format(country_code, genre, limit, start_from),
headers=Request.HEADERS,
)
async def related_tracks(
self, track_id: int, limit: int = 20, start_from: int = 0
) -> Dict[str, Any]:
"""
Similar songs based song id
https://www.shazam.com/track/546891609/2-phu%CC%81t-ho%CC%9Bn-kaiz-remix
:param track_id: Track number. Example: (549952578)
https://www.shazam.com/track/549952578/
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs
:param start_from: A parameter that determines with which song to display the request.
The default is 0. If you want to skip the first few songs, set this parameter to
your own.
:return: dict tracks
"""
return await self.request(
"GET",
ShazamUrl.RELATED_SONGS.format(track_id, start_from, limit),
headers=Request.HEADERS,
)
async def search_artist(self, query: str, limit: int = 10) -> Dict[str, Any]:
"""
Search all artists by prefix or fullname
:param query: Artist name or search prefix
:param limit: Determines how many artists the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 artists.
:return: dict artists
"""
return await self.request(
"GET", ShazamUrl.SEARCH_ARTIST.format(query, limit), headers=Request.HEADERS
)
async def search_track(self, query: str, limit: int = 10) -> Dict[str, Any]:
"""
Search all tracks by prefix
:param query: Track full title or prefix title
:param limit: Determines how many songs the maximum can be in the request.
Example: If 5 is specified, the query will return no more than 5 songs.
:return: dict songs
"""
return await self.request(
"GET", ShazamUrl.SEARCH_MUSIC.format(query, limit), headers=Request.HEADERS
)
async def listening_counter(self, track_id: int) -> Dict[str, Any]:
"""
Returns the total track listener counter.
:param track_id: Track number. Example: (559284007)
https://www.shazam.com/track/559284007/rampampam
:return: The data dictionary that contains the listen counter.
"""
return await self.request(
"GET", ShazamUrl.LISTENING_COUNTER.format(track_id), headers=Request.HEADERS
)
async def get_youtube_data(self, link: str) -> Dict[str, Any]:
return await self.request("GET", link, headers=Request.HEADERS)
async def recognize_song(
self, data: Union[str, pathlib.Path, bytes, bytearray, AudioSegment]
) -> Dict[str, Any]:
"""
Creating a song signature based on a file and searching for this signature in the shazam
database.
:param data: Path to song file or bytes
:return: Dictionary with information about the found song
"""
song = await get_song(data=data)
audio = self.normalize_audio_data(song)
signature_generator = self.create_signature_generator(audio)
signature = signature_generator.get_next_signature()
while not signature:
signature = signature_generator.get_next_signature()
results = await self.send_recognize_request(signature)
return results
async def send_recognize_request(self, sig: DecodedMessage) -> Dict[str, Any]:
data = Converter.data_search(
Request.TIME_ZONE,
sig.encode_to_uri(),
int(sig.number_samples / sig.sample_rate_hz * 1000),
int(time.time() * 1000),
)
return await self.request(
"POST",
ShazamUrl.SEARCH_FROM_FILE.format(
str(uuid.uuid4()).upper(), str(uuid.uuid4()).upper()
),
headers=Request.HEADERS,
json=data,
)