Code Monkey home page Code Monkey logo

spotify_ex's Introduction

Elixir CI Inline docs

SpotifyEx

Elixir Wrapper for the Spotify Web API

This is no longer under development, though I'm happy to merge bug fixes and reasonable feature additions. Please ask before adding new features so you don't waste your time.

Installation

  1. Add spotify_ex to your list of dependencies in mix.exs:
def deps do
 [{:spotify_ex, "~> 2.3.0"}]
end
  1. Ensure spotify_ex is started before your application:
def application do
  [applications: [:spotify_ex]]
end

This wrapper covers the Spotify Web API.

Follow the abovementioned link. On the left you'll notice that the API is broken into sections, such as Artists, Albums, Playlists, etc. This wrapper does its best to keep endpoints in modules mapped to their corresponding section. However, Spotify duplicates many of its endpoints. For example, there is an endpoint to obtain an artist's albums that is listed under both Artists and Albums.

Endpoints are not duplicated here, however. If you don't see an endpoint, it can be found in a module that's also related to that endpoint. In other words, if you don't see an endpoint for "get artists albums" in the Artist module, check Albums.

These duplicate endpoints may get aliased in the future to have a 1-1 mapping with the docs.

Usage

docs

A basic Phoenix example can be found at SpotifyExTest

OAuth

Oauth README

Scopes

Scopes README

Contributing

All contributions are more than welcome! I will not accept a PR without tests if it looks like something that should be tested (which is pretty much everything.) Development is done on the development branch, and moved to master for release on hexpm. Code must be formatted using hex format.

spotify_ex's People

Contributors

adamzaninovich avatar bqt1991 avatar dnlsandiego avatar dylanfareed avatar jnfoote76 avatar joe-noh avatar jsncmgs1 avatar katbow avatar kyleboe avatar lucasmedeirosleite avatar qgadrian avatar sohjiro avatar steveklebanoff avatar wolf4ood avatar ykl7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

spotify_ex's Issues

(question) Can this be used for Client Credentials Flow?

In the README and the code I see this being used with Authorization Code. I can't seem to find how to get it working with Client Credentials Flow, just wondering if this is implemented and I'm just missing it or it currently only supports Authorization Code flow?

Add tracks to playlist via body

In explaining the uris parameter of the Create Playlist API, The Spotify API docs state:

Note: it is likely that passing a large number of track URIs as a query parameter will exceed the maximum length of the request URI. When adding a large number of tracks it is recommended to pass them in the request body, see below.

It looks like the current implementation of add_tracks in spotify_ex's playlist.ex uses query parameters, but states:

You can also pass the URI param in the request body. Use `add_tracks/2`. See Spotify docs.
      Spotify.Playlist.add_tracks("123", "456", uris: "spotify:track:4iV5W9uYEdYUVa79Axb7Rh")
      # => {:ok, %{"snapshot_id" => "foo"}}

I may be missing something, but I don't see add_tracks/2 defined, and looking through the code I don't see a way to add tracks via the request body. Am I missing something obvious, or is adding support for adding tracks via the request body something that should be added?

Additionally: is there any reason to support adding tracks through a query parameter, or would it be better to just always add them through the request body?

Add support for Library API

I don't think any of the endpoints found in the library API are found in other modules (i.e. not duplicated).

Would be great to have a module for this section. I'd be happy to implement & contribute this feature.

handle expired access tokens

Hi Jason! I'm using this wrapper for a personal project, and I'm doing some work to add expiration date handling into this wrapper. Just started looking into it, but my current approach is to add spotify's 'expires_in' field to the Credentials struct and authentication flow. I'd be happy to make a PR if you're interested!

{BUG} Error for function get_recently_played

When trying to call Spotify.Player.get_recently_played/2 it throws BadMapError.

Working only if parameter 'limit' is assign to 1 like : Spotify.Player.get_recently_played(conn, limit: 1)

Error looks like @ lucasmedeirosleite issue at 22 Oct 2017.

Thx :)

Refactor test directory & naming conventions

Test directory structure & naming conventions are not idiomatic Elixir, which makes it more difficult to find things if trying to follow the norm.

Actual test structure

  • Tests for files in lib/spotify/ are directly in test/ (no subfolder)
  • Test modules are namespaced as Album (in the case of testing Spotify.Album)

Expected test structure

  • Tests for files in lib/spotify/ to be in the directory test/spotify/
  • Test modules to be namespaced as Spotify.AlbumTest (in the case of testing Spotify.Album)

Thoughts on this @jsncmgs1 ?

mix docs results in ArgumentError

➜  spotify_ex git:(main) mix docs
** (ArgumentError) expected a keyword list, but an entry in the list is not a two-element tuple with an atom as its first element, got: {{:message, 1}, [{:type, 35, :fun, [{:type, 35, :product, [{:user_type, 35, :t, []}]}, {:remote_type, 35, [{:atom, 0, String}, {:atom, 0, :t}, []]}]}]}
    (elixir 1.12.3) lib/keyword.ex:475: Keyword.keys/1
    (ex_doc 0.19.3) lib/ex_doc/retriever.ex:379: anonymous fn/2 in ExDoc.Retriever.get_impls/1
    (elixir 1.12.3) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_doc 0.19.3) lib/ex_doc/retriever.ex:378: ExDoc.Retriever.get_impls/1
    (ex_doc 0.19.3) lib/ex_doc/retriever.ex:161: ExDoc.Retriever.get_module_data/2
    (ex_doc 0.19.3) lib/ex_doc/retriever.ex:112: ExDoc.Retriever.generate_node/3
    (elixir 1.12.3) lib/enum.ex:3900: Enum.flat_map_list/2
    (elixir 1.12.3) lib/enum.ex:3901: Enum.flat_map_list/2

Clean up typos in README

There are a bunch of typos in the README that require no knowledge of this app to be corrected. I'm aware of them but would like a true first timer to submit a PR so they can get their feet wet with open source. If you are already comfortable with PR's and contributing, please leave this for the newcomers.

Add support for current version (1.0.0) of httpoison

Well hey there! I am using httpoison for my project and have it defined in my mix.exs deps for the current version, that being 1.0.0. When I went to add spotify_ex I got this:


Unchecked dependencies for environment dev:
* spotify_ex (Hex package)
  the dependency is not available, run "mix deps.get"
** (Mix) Can't continue due to errors on dependencies
➜  lean git:(master) ✗ mix deps.get
Resolving Hex dependencies...

Failed to use "httpoison" (version 1.0.0) because
  spotify_ex (version 2.0.7) requires ~> 0.13.0
  mix.lock specifies 1.0.0

** (Mix) Hex dependency resolution failed, change the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}

Everything seems to work when I add override: true to the httpoison entry, but its not ideal.

Thanks.

Expired token error comes with :ok atom

I'm trying to wrap Spotify with a little module that automatically refreshes expired tokens like so

defmodule SpotifyAgent do
  def call(conn, func) do
    result = func.(conn)
    case result do
      {:ok, response} ->
        result
      {:error,  e} ->
        refresh(conn)
        call(conn, func)
    end
  end

  defp refresh(conn) do
    Spotify.refresh(conn)
  end
end

However, 401 Expired responses are coming through as :ok. Is this expected? I'd think it'd be an :error.

{:ok, %{"error" => %{"message" => "The access token expired", "status" => 401}}}

Consider not raising an error on denied access

Hi there!

Currently, this library raises an error during the authentication phase when a user denies the library access to its resource. Is there a reason why the last clause of Spotify.Authentication.authenticate/2 raises an error(AuthenticationError) instead of returning something like {:error, :denied_access}?

This is to take into account the scenario of when a user denies an app access and by raising an error, this library forces the app to catch the error and I think goes against Elixir norm. And by returning {:error, :denied_access}, you're giving the library user a chance to handle this specific scenario.

{BUG} Error when calling artists_I_follow/2

When trying to call Spotify.Artists.artists_I_follow/2 it throws BadMapError.

This is happening because the Spotify API /me/following response uses pagination (it seems to be an update, that's why the lib crashes this way).

Spotify.Cookies.set_cookies indirectly halts redirects

It looks like Spotify.Cookies.set_cookies indirectly halts redirects because it explicitly sets the conn's HTTP response status to 200. Which causes redirects to just be stuck in a page with a "You are being redirected" message instead of actually prompting the browser to redirect to a specific page.

Any reason why Spotify.Cookies.set_cookies explicitly sets the status to 200? Is it safe to remove or move somewhere else? If so, I'd be glad to put a PR together for it.

(Another argument for removing the setting of the HTTP status in the there is that in a function named set_cookies it's quite out of scope of its responsibilities to set the http status along with setting the cookies)

BUG: tracks without audio features causes problems with the Spotify.Track.audio_features function

The Spotify.Track.audio_features function returns nil instead of an error.
An error occurs because there is a track without audio features. This is not intended as far as I know and an error on Spotify's side but it does exist. 1OegbevPjnz3BBlyzkBT4K this is an id of a track that has no audio features.

It would be nice if the function would return :error. The nil return also means that if you query lost of IDs that you cant get the info of the tracks that didn't fail.

Can't use without cookies?

It looks like any function that makes a request to Spotify needs a Plug.Conn with a cookie inside that contains the auth tokens. This effectively limits this library to be used only in conjunction with a web application.

What about providing some way to store the auth data in a process instead so that one could use this library without a browser involved?

Authentication does not fail transparently when client secret is wrong

When the client secret is configured incorrectly, attempting to authenticate should yield an error. Instead, Spotify.Authentication.authenticate still returns {:ok, conn}, but Spotify-related token cookies will be nil.

There's already some kind of check for this, in that AuthenticationClient checks if the HTTPoison.post succeeded or not. But it looks like HTTPoison.post reports success even when the response code is 400.

You can see this yourself if you configure a client secret incorrectly and add a couple IO.inspect calls:

def post(params) do
  case AuthRequest.post(params) do
    {:ok, %HTTPoison.Response{status_code: code, body: body}} ->
      with {:ok, response} <- Poison.decode(body) do
        IO.inspect(code) # todo remove
        IO.inspect(response) # todo remove
        {:ok, Spotify.Credentials.get_tokens_from_response(response)}
      else
        _unmatched ->
          raise(AuthenticationError, "Error parsing response from Spotify")
      end
    {:error, %HTTPoison.Error{reason: reason}} ->
      { :error, reason }
  end
end

With an invalid client secret, I see

400
%{"error" => "invalid_client", "error_description" => "Invalid client secret"}

in my logs.

Web API endpoints

Hi @jsncmgs1!
Thank you for your work!
I'm opening this issue to know if you're interested in extending this package to Web API endpoints (other than the authentication flow). I'm going to work a lot with spotify + elixir in the next months, and I'd like to contribute to this package more than creating a new one with another name (packages pollution is a problem nowadays :D ).
Let me know if you'd accept pull requests about api endpoints mapping and spotify entity abstractions (structs and stuff like that).

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.