diff --git a/deezer/client.py b/deezer/client.py index 761ae826..d0ca4c91 100644 --- a/deezer/client.py +++ b/deezer/client.py @@ -323,6 +323,34 @@ def remove_user_album(self, album_id: int) -> bool: """ return self.request("DELETE", "user/me/albums", album_id=album_id) + def get_user_artists(self, user_id: Optional[int] = None) -> List[Artist]: + """ + Get the favourites artists for the given user_id if provided or current user if not. + + :param user_id: the user ID to get favourites artists. + :return: a list of :class:`~deezer.resources.Artist` instances. + """ + user_id_str = str(user_id) if user_id else "me" + return self.request("GET", f"user/{user_id_str}/artists") + + def add_user_artist(self, artist_id: int) -> bool: + """ + Add an artist to the user's library + + :param artist_id: the ID of the artist to add. + :return: boolean whether the operation succeeded. + """ + return self.request("POST", "user/me/artists", artist_id=artist_id) + + def remove_user_artist(self, artist_id: int) -> bool: + """ + Remove an artist from the user's library + + :param artist_id: the ID of the artist to remove. + :return: boolean whether the operation succeeded. + """ + return self.request("DELETE", "user/me/artists", artist_id=artist_id) + def search(self, query, relation=None, index=0, limit=25, **kwargs): """ Search track, album, artist or user diff --git a/tests/cassettes/TestClient.test_add_user_artist.yaml b/tests/cassettes/TestClient.test_add_user_artist.yaml new file mode 100644 index 00000000..9748fbfb --- /dev/null +++ b/tests/cassettes/TestClient.test_add_user_artist.yaml @@ -0,0 +1,62 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - identity + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - python-requests/2.26.0 + method: POST + uri: https://api.deezer.com/user/me/artists?artist_id=243&access_token=dummy + response: + body: + string: 'true' + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-Requested-With, Content-Type, Authorization, Origin, Accept, Accept-Encoding + Access-Control-Allow-Methods: + - POST, GET, OPTIONS, DELETE, PUT + Access-Control-Expose-Headers: + - Location + Access-Control-Max-Age: + - '86400' + Cache-Control: + - no-store, no-cache, must-revalidate + Connection: + - keep-alive + Content-Length: + - '4' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 09 Oct 2021 17:43:02 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + P3P: + - policyref="/w3c/p3p.xml" CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - dzr_uniq_id=dzr_uniq_id_frb734f69afd1d53c8c9deb697d7f2c51fc622ce; expires=Thu, + 07-Apr-2022 17:43:02 GMT; Max-Age=15552000; path=/; domain=.deezer.com; secure; + HttpOnly; SameSite=None + X-Content-Type-Options: + - nosniff + X-Host: + - blm-web-156 + x-org: + - FR + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/TestClient.test_get_user_artists[args0].yaml b/tests/cassettes/TestClient.test_get_user_artists[args0].yaml new file mode 100644 index 00000000..2b3140b7 --- /dev/null +++ b/tests/cassettes/TestClient.test_get_user_artists[args0].yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - identity + Connection: + - keep-alive + User-Agent: + - python-requests/2.26.0 + method: GET + uri: https://api.deezer.com/user/me/artists?access_token=dummy + response: + body: + string: '{"data":[{"id":243,"name":"Wax Tailor","link":"https:\/\/www.deezer.com\/artist\/243","picture":"https:\/\/api.deezer.com\/artist\/243\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/1000x1000-000000-80-0-0.jpg","nb_album":24,"nb_fan":224408,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/243\/top?limit=50","time_add":1258243200,"type":"artist"},{"id":641,"name":"Vitalic","link":"https:\/\/www.deezer.com\/artist\/641","picture":"https:\/\/api.deezer.com\/artist\/641\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/1000x1000-000000-80-0-0.jpg","nb_album":22,"nb_fan":280646,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/641\/top?limit=50","time_add":1254700800,"type":"artist"},{"id":901,"name":"Morcheeba","link":"https:\/\/www.deezer.com\/artist\/901","picture":"https:\/\/api.deezer.com\/artist\/901\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/1000x1000-000000-80-0-0.jpg","nb_album":66,"nb_fan":310559,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/901\/top?limit=50","time_add":1265846400,"type":"artist"},{"id":93914,"name":"Tribute + Stars","link":"https:\/\/www.deezer.com\/artist\/93914","picture":"https:\/\/api.deezer.com\/artist\/93914\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/1000x1000-000000-80-0-0.jpg","nb_album":359,"nb_fan":539,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/93914\/top?limit=50","time_add":1265241600,"type":"artist"}],"checksum":"5230dd6b9680d69aaaed5671ed5e120f","total":4}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-Requested-With, Content-Type, Authorization, Origin, Accept, Accept-Encoding + Access-Control-Allow-Methods: + - POST, GET, OPTIONS, DELETE, PUT + Access-Control-Expose-Headers: + - Location + Access-Control-Max-Age: + - '86400' + Cache-Control: + - no-store, no-cache, must-revalidate + Connection: + - keep-alive + Content-Length: + - '5623' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 09 Oct 2021 17:38:22 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + P3P: + - policyref="/w3c/p3p.xml" CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - dzr_uniq_id=dzr_uniq_id_frc1a4d385950ad34b80210bb999e069407b3351; expires=Thu, + 07-Apr-2022 17:38:22 GMT; Max-Age=15552000; path=/; domain=.deezer.com; secure; + HttpOnly; SameSite=None + Vary: + - Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Host: + - blm-web-121 + x-org: + - FR + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/TestClient.test_get_user_artists[args1].yaml b/tests/cassettes/TestClient.test_get_user_artists[args1].yaml new file mode 100644 index 00000000..5c264420 --- /dev/null +++ b/tests/cassettes/TestClient.test_get_user_artists[args1].yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - identity + Connection: + - keep-alive + User-Agent: + - python-requests/2.26.0 + method: GET + uri: https://api.deezer.com/user/359622/artists?access_token=dummy + response: + body: + string: '{"data":[{"id":243,"name":"Wax Tailor","link":"https:\/\/www.deezer.com\/artist\/243","picture":"https:\/\/api.deezer.com\/artist\/243\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5f88782f666ff52a234a1dafc7c640e6\/1000x1000-000000-80-0-0.jpg","nb_album":24,"nb_fan":224408,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/243\/top?limit=50","time_add":1258243200,"type":"artist"},{"id":641,"name":"Vitalic","link":"https:\/\/www.deezer.com\/artist\/641","picture":"https:\/\/api.deezer.com\/artist\/641\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/5e970ce2f5c52fe2b036f088eb4a7bef\/1000x1000-000000-80-0-0.jpg","nb_album":22,"nb_fan":280646,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/641\/top?limit=50","time_add":1254700800,"type":"artist"},{"id":901,"name":"Morcheeba","link":"https:\/\/www.deezer.com\/artist\/901","picture":"https:\/\/api.deezer.com\/artist\/901\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/190c679b4e5d665339e8f60857917a6f\/1000x1000-000000-80-0-0.jpg","nb_album":66,"nb_fan":310559,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/901\/top?limit=50","time_add":1265846400,"type":"artist"},{"id":93914,"name":"Tribute + Stars","link":"https:\/\/www.deezer.com\/artist\/93914","picture":"https:\/\/api.deezer.com\/artist\/93914\/image","picture_small":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/56x56-000000-80-0-0.jpg","picture_medium":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/250x250-000000-80-0-0.jpg","picture_big":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/500x500-000000-80-0-0.jpg","picture_xl":"https:\/\/cdns-images.dzcdn.net\/images\/artist\/dc825c91bf2fcbda8b964be1102d4e71\/1000x1000-000000-80-0-0.jpg","nb_album":359,"nb_fan":539,"radio":true,"tracklist":"https:\/\/api.deezer.com\/artist\/93914\/top?limit=50","time_add":1265241600,"type":"artist"}],"checksum":"5230dd6b9680d69aaaed5671ed5e120f","total":4}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-Requested-With, Content-Type, Authorization, Origin, Accept, Accept-Encoding + Access-Control-Allow-Methods: + - POST, GET, OPTIONS, DELETE, PUT + Access-Control-Expose-Headers: + - Location + Access-Control-Max-Age: + - '86400' + Cache-Control: + - no-store, no-cache, must-revalidate + Connection: + - keep-alive + Content-Length: + - '5623' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 09 Oct 2021 17:38:22 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + P3P: + - policyref="/w3c/p3p.xml" CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - dzr_uniq_id=dzr_uniq_id_fr0b3ccc63f1fef6367026159c8d82996a3d3048; expires=Thu, + 07-Apr-2022 17:38:22 GMT; Max-Age=15552000; path=/; domain=.deezer.com; secure; + HttpOnly; SameSite=None + Vary: + - Accept-Encoding + X-Content-Type-Options: + - nosniff + X-Host: + - blm-web-135 + x-org: + - FR + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/TestClient.test_remove_user_artist.yaml b/tests/cassettes/TestClient.test_remove_user_artist.yaml new file mode 100644 index 00000000..6877c206 --- /dev/null +++ b/tests/cassettes/TestClient.test_remove_user_artist.yaml @@ -0,0 +1,62 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - identity + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - python-requests/2.26.0 + method: DELETE + uri: https://api.deezer.com/user/me/artists?artist_id=243&access_token=dummy + response: + body: + string: 'true' + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-Requested-With, Content-Type, Authorization, Origin, Accept, Accept-Encoding + Access-Control-Allow-Methods: + - POST, GET, OPTIONS, DELETE, PUT + Access-Control-Expose-Headers: + - Location + Access-Control-Max-Age: + - '86400' + Cache-Control: + - no-store, no-cache, must-revalidate + Connection: + - keep-alive + Content-Length: + - '4' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 09 Oct 2021 17:43:32 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + P3P: + - policyref="/w3c/p3p.xml" CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - dzr_uniq_id=dzr_uniq_id_frd7b2eb37b1a3451792ba47c2c45505db432cc6; expires=Thu, + 07-Apr-2022 17:43:32 GMT; Max-Age=15552000; path=/; domain=.deezer.com; secure; + HttpOnly; SameSite=None + X-Content-Type-Options: + - nosniff + X-Host: + - blm-web-52 + x-org: + - FR + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_client.py b/tests/test_client.py index 2ac2240f..8ba9c2c0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -219,6 +219,32 @@ def test_remove_user_album(self, client_token): result = client_token.remove_user_album(302127) assert result is True + @pytest.mark.parametrize( + "args", + [ + (), + (359622,), + ], + ) + def test_get_user_artists(self, client_token, args): + user_artists = client_token.get_user_artists(*args) + assert len(user_artists) == 4 + assert all(isinstance(a, deezer.resources.Artist) for a in user_artists) + assert [a.name for a in user_artists] == [ + "Wax Tailor", + "Vitalic", + "Morcheeba", + "Tribute Stars", + ] + + def test_add_user_artist(self, client_token): + result = client_token.add_user_artist(243) + assert result is True + + def test_remove_user_artist(self, client_token): + result = client_token.remove_user_artist(243) + assert result is True + def test_options_1(self, client): """Test a query with extra arguments""" result = client.search("Billy Jean", limit=2)