defmodule Spotify.Artist do @moduledoc """ Functions for retrieving information about artists and for managing a user’s followed artists. There are two functions for each endpoint, one that actually makes the request, and one that provides the endpoint: Spotify.Playist.create_playlist(conn, "foo", "bar") # makes the POST request. Spotify.Playist.create_playlist_url("foo", "bar") # provides the url for the request. https://developer.spotify.com/web-api/artist-endpoints/ """ import Spotify.Helpers use Spotify.Responder alias Spotify.{ Artist, Client, Paging, Track } defstruct ~w[ external_urls followers genres href id images name popularity type uri ]a @doc """ Get Spotify catalog information for a single artist identified by their unique Spotify ID. [Spotify Documenation](https://developer.spotify.com/web-api/get-artist/) **Method**: `GET` Spotify.Artist.get_artist(conn, "4") # => { :ok, %Artist{}} """ def get_artist(conn, id) do url = get_artist_url(id) conn |> Client.get(url) |> handle_response end @doc """ Get Spotify catalog information for a single artist identified by their unique Spotify ID. iex> Spotify.Artist.get_artist_url("4") "https://api.spotify.com/v1/artists/4" """ def get_artist_url(id) do "https://api.spotify.com/v1/artists/#{id}" end @doc """ Get Spotify catalog information for several artists based on their Spotify IDs. [Spotify Documenation](https://developer.spotify.com/web-api/get-several-artists/) **Method**: `GET` **Required Params**: `ids` Spotify.Artist.get_artists(conn, ids: "1,4") # => { :ok, [%Artist{}, ...] } """ def get_artists(conn, params = [ids: _ids]) do url = get_artists_url(params) conn |> Client.get(url) |> handle_response end @doc """ Get Spotify catalog information for several artists based on their Spotify IDs. iex> Spotify.Artist.get_artists_url(ids: "1,4") "https://api.spotify.com/v1/artists?ids=1%2C4" """ def get_artists_url(params) do "https://api.spotify.com/v1/artists" <> query_string(params) end @doc """ Get Spotify catalog information about an artist’s top tracks by country. [Spotify Documenation](https://developer.spotify.com/web-api/get-artists-top-tracks/) **Method**: `GET` **Required Params**: `country` Spotify.get_top_tracks(conn, "4", country: "US") # => { :ok, [%Track{}, ...] } """ def get_top_tracks(conn, id, params) do url = get_top_tracks_url(id, params) conn |> Client.get(url) |> handle_response end @doc """ Get Spotify catalog information about an artist’s top tracks by country. iex> Spotify.Artist.get_top_tracks_url("4", country: "US") "https://api.spotify.com/v1/artists/4/top-tracks?country=US" """ def get_top_tracks_url(id, params) do "https://api.spotify.com/v1/artists/#{id}/top-tracks" <> query_string(params) end @doc """ Get Spotify catalog information about artists similar to a given artist. [Spotify Documenation](https://developer.spotify.com/web-api/get-related-artists/) ** Method **: `GET` Spotify.Artist.get_related_artists(conn, "4") # => { :ok, [ %Artist{}, ... ] } """ def get_related_artists(conn, id) do url = get_related_artists_url(id) conn |> Client.get(url) |> handle_response end @doc """ Get Spotify catalog information about artists similar to a given artist. iex> Spotify.Artist.get_related_artists_url("4") "https://api.spotify.com/v1/artists/4/related-artists" """ def get_related_artists_url(id) do "https://api.spotify.com/v1/artists/#{id}/related-artists" end @doc """ Get the current user’s followed artists. **Method**: `GET` **Optional Params**: `type`, `limit`, `after` Spotify.Artist.artists_I_follow_url(conn) # => { :ok, %Paging{items: [%Artist{}, ...]} } """ def artists_I_follow(conn, params \\ []) do url = artists_I_follow_url(params) conn |> Client.get(url) |> handle_response end @doc """ Get the current user’s followed artists. iex> Spotify.Artist.artists_I_follow_url(limit: 5) "https://api.spotify.com/v1/me/following?type=artist&limit=5" """ def artists_I_follow_url(params) do "https://api.spotify.com/v1/me/following?type=artist&" <> URI.encode_query(params) end @doc """ Implements the hook expected by the Responder behaviour """ def build_response(body) do case body do %{"artists" => %{"items" => _items}} = response -> build_paged_artists(response) %{"artists" => artists} -> build_artists(artists) %{"tracks" => tracks} -> Track.build_tracks(tracks) %{"name" => _} -> to_struct(Artist, body) booleans_or_error -> booleans_or_error end end @doc false defp build_paged_artists(%{"artists" => response}) do %Paging{ items: build_artists(response["items"]), next: response["next"], total: response["total"], cursors: response["cursors"], limit: response["limit"], href: response["href"] } end @doc false def build_artists(artists) do Enum.map(artists, &to_struct(Artist, &1)) end end