Giter VIP home page Giter VIP logo

spotify's People

Contributors

adamo57 avatar aditya-k2 avatar ahmed-deftoner avatar alexrs avatar brandur avatar brodin avatar bturrubiates avatar conradludgate avatar coolbaluk avatar dependabot[bot] avatar donfros avatar dsoprea avatar elivlo avatar elliotwms avatar junnishimura avatar lukehobbs avatar obrhoff avatar pebbe avatar pixelrazor avatar ptrkrlsrd avatar r0qs3t avatar roelrymenants avatar rtrox avatar samuelrey avatar strideynet avatar tobiola avatar wernerdweight avatar wndhydrnt avatar xonstone avatar zmb3 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spotify's Issues

Deprecate default client

Spotify is requiring all calls to be authenticated later this month.

Deprecate the default client and associated wrappers, and update the readme and godoc comments that mention which calls require authorization.

GetArtistAlbums panics

GetArtistAlbums(id) will call return c.GetArtistAlbumsOpt(artistID, nil, nil)
The third arg should not be supplied.

func (c *Client) GetArtistAlbumsOpt(artistID ID, options *Options, ts ...*AlbumType) (*SimpleAlbumPage, error) {
	spotifyURL := fmt.Sprintf("%sartists/%s/albums", c.baseURL, artistID)
	// add optional query string if options were specified
	values := url.Values{}
	if ts != nil {
		types := make([]string, len(ts))
		for i := range ts {
			types[i] = ts[i].encode()
		}
		values.Set("include_groups", strings.Join(types, ","))
	}

that for loops panics, since ts will not be nill, but will instead be [nil]

Adding Client credentials as authorisation option

I am trying to use your extremely useful package for a report I am writing, However the report is run as a daily job and must connect using client credentials https://developer.spotify.com/web-api/authorization-guide/#client-credentials-flow. Currently you support Authorization flow. Just wondering if its possible to use Client Credentials with your package. Using the oauth2/clientcredentials package it seems straight forward to create an authorised client. But I cannot assign it to a spotify client. Any suggestions.

import (
	"context"
	"fmt"
	"github.com/zmb3/spotify"
	"golang.org/x/oauth2/clientcredentials"
)

func main() {
		config := &clientcredentials.Config{
			ClientID:     "CLIENTID",
			ClientSecret: "SECRET",
			TokenURL:     "https://accounts.spotify.com/api/token",
	}
	//Creates an authorized *http.client
	AuthorizedClient := config.Client(context.Background())
	// need to assign authorizedClient to spotify.client

How to refresh access token?

Hi there and thanks for this great library, it saved us a lot of work :)

I do have one problem though - an access token expires after 1 hour, but can be refreshed using the refresh token:

Access tokens are deliberately set to expire after a short time, after which new tokens may be granted by supplying the refresh token originally obtained during the authorization code exchange.

(https://developer.spotify.com/documentation/general/guides/authorization-guide#4-requesting-a-refreshed-access-token-spotify-returns-a-new-access-token-to-your-app)

Is there a way to do this using this library?

Thanks in advance!

Error when authenticating user

Running the auth example of the library returns the following error:

2017/01/13 23:32:10 Post https://accounts.spotify.com/api/token: stream error: stream ID 1; REFUSED_STREAM

UPDATE:
If it is executed with GODEBUG=http2client=0 it seems to work. This is the output I get when I set GODEBUG=http2debug=2:

2017/01/13 23:33:57 http2: Transport failed to get client conn for accounts.spotify.com:443: http2: no cached connection was available
2017/01/13 23:33:57 http2: Transport creating client conn 0xc4200901a0 to 194.132.196.226:443
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote SETTINGS len=18, settings: ENABLE_PUSH=0, INITIAL_WINDOW_SIZE=4194304, MAX_HEADER_LIST_SIZE=10485760
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote WINDOW_UPDATE len=4 (conn) incr=1073741824
2017/01/13 23:33:57 http2: Transport encoding header ":authority" = "accounts.spotify.com"
2017/01/13 23:33:57 http2: Transport encoding header ":method" = "POST"
2017/01/13 23:33:57 http2: Transport encoding header ":path" = "/api/token"
2017/01/13 23:33:57 http2: Transport encoding header ":scheme" = "https"
2017/01/13 23:33:57 http2: Transport encoding header "content-type" = "application/x-www-form-urlencoded"
2017/01/13 23:33:57 http2: Transport encoding header "authorization" = "Basic NDEzZGY5N2FlOTZmNDliODgxN2Q1MzIyNzg4YjI0YzI6NDM5Mzk3Zjg1OGM4NGE3ZWJmOTUzMzFmZjA2NjA3ZDY="
2017/01/13 23:33:57 http2: Transport encoding header "content-length" = "379"
2017/01/13 23:33:57 http2: Transport encoding header "accept-encoding" = "gzip"
2017/01/13 23:33:57 http2: Transport encoding header "user-agent" = "Go-http-client/2.0"
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote HEADERS flags=END_HEADERS stream=1 len=158
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote DATA stream=1 len=379 data="client_id=MY_ID&code=AQAGHoYEEByHqEm9ecc22P9zqQTegw5D89DIswksVSmMcNFTcje5neDqJlNRpmxRyBihut-LCd7pLZr9vw5ltoXM2hRtTcE8yPnOFHEpzfhHxrsNOV-NnW77HMQku1X291AXOI8434rpv8t-B-5RxB62jJ9BTtumniPvSqondV1nG-UfaEoYsYNsN3VS3P17K96TknTlE9NSgmzX" (123 bytes omitted)
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote DATA flags=END_STREAM stream=1 len=0 data=""
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: read SETTINGS len=18, settings: MAX_CONCURRENT_STREAMS=128, INITIAL_WINDOW_SIZE=0, MAX_FRAME_SIZE=16777215
2017/01/13 23:33:57 http2: Transport received SETTINGS len=18, settings: MAX_CONCURRENT_STREAMS=128, INITIAL_WINDOW_SIZE=0, MAX_FRAME_SIZE=16777215
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: wrote SETTINGS flags=ACK len=0
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: read WINDOW_UPDATE len=4 (conn) incr=2147418112
2017/01/13 23:33:57 http2: Transport received WINDOW_UPDATE len=4 (conn) incr=2147418112
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: read SETTINGS flags=ACK len=0
2017/01/13 23:33:57 http2: Transport received SETTINGS flags=ACK len=0
2017/01/13 23:33:57 http2: Framer 0xc4202f5800: read RST_STREAM stream=1 len=4 ErrCode=REFUSED_STREAM
2017/01/13 23:33:57 http2: Transport received RST_STREAM stream=1 len=4 ErrCode=REFUSED_STREAM
2017/01/13 23:33:57 RoundTrip failure: stream error: stream ID 1; REFUSED_STREAM
2017/01/13 23:33:57 Post https://accounts.spotify.com/api/token: stream error: stream ID 1; REFUSED_STREAM
exit status 1

Using spotifyd

Hello there!
First of great work and thanks for making this package! ๐Ÿ‘ โค๏ธ

I am trying this package to control spotifyd, however, somehow spotify API always returns with HTTP 202: Accepted (body empty) instead of HTTP 204: No Content as soon as I make a call (selected spotifyd as connected device).
The commands get trough! And spotifyd does everything fine, but HTTP 202 is not expected in this package so it will aways return an error.

I know that there is an Autoretry mode, however spotify always returns 202 no matter what, so I end up in an endless loop...

My guess is that there is an issue on spotifyd's side. (Will create a ticket there as well)
However I think there should be an option to enable HTTP 202 is good enough mode

What do you think?
BTW: willing to implement that feature!

TransferPlayback doesn't work as intended.

Hi. I have recently tried to use TransferPlayback method without success. Whenever I run the code below, the change of track in the PlayOpt method works, but it does not switch playback device. I start Spotify on my phone and begin playing music. I run the code, and song switches, but it doesn't change playback device to my computer. Do I have to do something else or am I just missing something?

devices, err := client.PlayerDevices()
	if err != nil {
		log.Print("L72: ", err)
	}

	for _, device := range devices {
		if device.Name == "VictorsMacbookAir" {
			fmt.Println(device.ID)
			err = client.TransferPlayback(device.ID, true)
			if err != nil {
				log.Print("L79: ", err)
			}
			w.Header().Set("Content-Type", "text/plain")
			fmt.Fprintf(w, "Login completed, transfering playback to: %s", device.Name)
			break
		}
	}

	songs := []spotify.URI{"spotify:track:7BfiAzV3ASEK9egnfxN1v1"}
	options := &spotify.PlayOptions{
		URIs: songs,
	}
	err = client.PlayOpt(options)
	if err != nil {
		log.Print("L93: ", err)
	}

Best regards,
Victor

Segmentation violation when using PlayOpt

client.PlayOpt(&spotify.PlayOptions{PlaybackContext: &spotify.URI("SOME_URI")})
always results in a crash. Am I stupid or is this a bug?

[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x644025]

goroutine 19 [running]:
github.com/zmb3/spotify.(*Client).PlayOpt(0x0, 0xc420498030, 0x0, 0x0)
	/home/lumi/go/src/github.com/zmb3/spotify/player.go:286 +0x55
main.mgmt(0x0)
	/home/lumi/Projects/spotiman/mgmt.go:50 +0xdd
created by main.main
	/home/lumi/Projects/spotiman/main.go:39 +0x7a

Help on how to use scopes

Hello

I'm having trouble using your package to access Spotify web API, looking to retrieve recently played items:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/zmb3/spotify"
	"golang.org/x/oauth2/clientcredentials"
)

func main() {
	config := &clientcredentials.Config{
		ClientID:     "...",
		ClientSecret: "...",
		TokenURL:     spotify.TokenURL,
		Scopes:       []string{spotify.ScopeUserReadRecentlyPlayed},
	}

	token, err := config.Token(context.Background())
	if err != nil {
		log.Fatalf("unable to get token: %v", err)
	}

	client := spotify.Authenticator{}.NewClient(token)

	recent, err := client.PlayerRecentlyPlayedOpt(&spotify.RecentlyPlayedOptions{Limit: 10})
	if err != nil {
		log.Fatalf("unable to get recently played items: %v", err)
	}

	for _, item := range recent {
		fmt.Println(item)
	}
}

When I execute this code the API call for recently played items fails: 2017/10/29 15:26:53 unable to get recently played items: Insufficient client scope

Did I miss something regarding the specification of scopes?

NewReleasesOpt: Unnecessary complexity?

It seems like we're cutting ContentLength-bytes out of the body, loading it into a Buffer, and then passing that to the JSON-parser when we could just do what we did everywhere else and parse resp.Body directly. No?

Current:

func (c *Client) NewReleasesOpt(opt *Options) (albums *SimpleAlbumPage, err error) {
    spotifyURL := baseAddress + "browse/new-releases"
    if opt != nil {
        v := url.Values{}
        if opt.Country != nil {
            v.Set("country", *opt.Country)
        }
        if opt.Limit != nil {
            v.Set("limit", strconv.Itoa(*opt.Limit))
        }
        if opt.Offset != nil {
            v.Set("offset", strconv.Itoa(*opt.Offset))
        }
        if params := v.Encode(); params != "" {
            spotifyURL += "?" + params
        }
    }
    resp, err := c.http.Get(spotifyURL)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    if resp.StatusCode != http.StatusOK {
        return nil, decodeError(c, resp)
    }
    buf := bytes.NewBuffer(make([]byte, 0, resp.ContentLength+1))
    _, err = buf.ReadFrom(resp.Body)
    if err != nil {
        return nil, err
    }
    body := buf.Bytes()
    var objmap map[string]*json.RawMessage
    err = json.Unmarshal(body, &objmap)
    if err != nil {
        return nil, err
    }
    var result SimpleAlbumPage
    err = json.Unmarshal(*objmap["albums"], &result)
    if err != nil {
        return nil, err
    }
    return &result, nil
}

Proposed:

func (c *Client) NewReleasesOpt(opt *Options) (albums *SimpleAlbumPage, err error) {
    spotifyURL := baseAddress + "browse/new-releases"
    if opt != nil {
        v := url.Values{}
        if opt.Country != nil {
            v.Set("country", *opt.Country)
        }
        if opt.Limit != nil {
            v.Set("limit", strconv.Itoa(*opt.Limit))
        }
        if opt.Offset != nil {
            v.Set("offset", strconv.Itoa(*opt.Offset))
        }
        if params := v.Encode(); params != "" {
            spotifyURL += "?" + params
        }
    }
    resp, err := c.http.Get(spotifyURL)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    if resp.StatusCode != http.StatusOK {
        return nil, decodeError(c, resp)
    }
    var objmap map[string]*json.RawMessage
    err = json.NewDecoder(resp.Body).Decode(&objmap)
    if err != nil {
        return nil, err
    }

    var result SimpleAlbumPage
    err = json.Unmarshal(*objmap["albums"], &result)
    if err != nil {
        return nil, err
    }
    return &result, nil
}

ReorderPlaylistTracks userID string

It seems to me that userID should be a string in ReorderPlaylistTracks. It is expecting an ID instead

I'm learning go, and also new to the spotify API, so I might be missing something else :).
I'll gladly create the PR if you want

PlayerCurrentlyPlaying() returns error EOF when nothing is playing

Hi there!

I noticed that the function client.PlayerCurrentlyPlaying() returns an error with the message EOF when no song is currently playing.

The error occurs when trying to decode an empty response body.

if result != nil {
    if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
        return err
    }
}

Debugger Screenshot

I would offer to submit a PR to fix this, but this is actually the first project I'm working on using go, so I'm not sure how to approach this issue.

Thanks!

Spotify refresh token after 1 hour expiry

Realize this is not so much an issue with this Spotify lib, but curious if anyone has got Spotify's OAUTH token to "refresh" using the Go Ouath2 library?

I have implemented a pair of helper functions to writeToken and readToken that caches a json blob containing the auth token to disk. I am doing this so that the user isn't forced to continually authorize access to Spotify. As it stands Spotify has a very short token expiry (1 hour) but they do provide a refresh token when authenticated. Documented here -> https://developer.spotify.com/web-api/authorization-guide/#authorization_code_flow

@zmb3 if you have attempted such an oauth flow using the refresh token, would you mind adding this to the example?

App engine

app engine seems to need a custom context to work somewhy:

Post https://accounts.spotify.com/api/token: not an App Engine context

oauth2.NoContext is user for all Follow, NewClient and Unfollow methods.
Should those accept a golang.net/x/net/context as an argument ?

HTTP 204 for Client.PlayerStateOpt()

From previous issues, it looks like the HTTP 204 error has already been dealt with when it comes to playback functions, but I'm currently getting it for Client.PlayerStateOpt().

Simply substituting Client.get() with Client.execute() in Client.PlayerStateOpt() won't work, as it will result in an EOF error when reading the Body on a 204.

Since HTTP 204 seems to be a standard part of Spotify's API, could we add a check to Client.get() before decoding the Body that returns nil if the status code is 204?

Alternatively, if you don't want to mess with the Client.get() code, returning an exported error type that includes the HTTP status code would be nice.

Bad Gateway?

When I am executing my app I am receiving a Bad Gateway on a regular basis, but not on every run. The app is simply searching for tracks and manipulating playlists. Has anyone else seen this before? Retries are turned on within the API client.

Paging

It seems that e.g. getPlaylist doesn't support the paging features of the Spotify API. As Spotify limits output per page to 100, this means that the wrapper will only retrieve the first 100 items of a playlist or album. The following pages are inaccessibly through the wrapper.

PlayerCurrentlyPlaying returns err io.EOF when not playing

Sometimes, when there's no player registered (I suppose), the API returns an EOF. The token is correct and the error can be ignored.

	if ftl, err := client.PlayerCurrentlyPlaying(); err != nil {
		if err != io.EOF {
			log.Fatal(err)
		}
	} else {
		if !ftl.Playing {
			log.Println("Currently not playing...")
			return
		}
		// Do whatever
	}

TrackAttributes as exported struct

Hi, thanks for a great library wrapper!
I wonder about the TrackAttributes struct, wouldn't it be better/simpler to map a simple struct against the spotify API? at least export the fields so it can easily decode from json.
Now it is quite awkward to construct.
In my particular usecase I fetch some json trackattributes that I just want to send to the recommendation seed, and I dont see the point in looping and testing for every property. In the end its just json objects both ways.

Question regarding authentication

Is there any way to do the authentication process completely inside go, without having to use an external browser for the login part? I could not find any working solution so far.

Store token to later identify users

I'm a bit confused as to how I should store the Spotify access token in order to identify users through multiple page accesses (i.e. keep a long running "session" open, saving the user's authorization grant).

Is the token itself safe to store in a cookie? Should I create a session ID and store that in a cookie instead (and use a map to associate it with a token)? Is there a better approach that I'm not aware of?

FullArtist.Followers does not have a JSON-tag

Hey,

I see that most properties in this package have a JSON-tag to make the property lowercase when marshalling the structs, but it seems that FullArtist.Followers does not have it. Is there any reason for this?

show_dialog optional parameter for authentication

The Spotify Web API also supports the option parameter show_dialog for authentication. Right now the library does not support this parameter and it's something that I would like to use for a project. Is there any plans to add/support this?

playlists unauthorized

I don't quite understand why this is giving an "unauthorized" error.
What am I missing? The credentials work fine for some other client.

package main

import (
  "context"
  "fmt"
  "log"

  "github.com/zmb3/spotify"
  "golang.org/x/oauth2/clientcredentials"
)

func main() {
  config := &clientcredentials.Config{
    ClientID:     os.Getenv("SPOTIFY_ID"),
    ClientSecret: os.Getenv("SPOTIFY_SECRET"),
    TokenURL:     spotify.TokenURL,
  }
  token, err := config.Token(context.Background())
  if err != nil {
    log.Fatalf("couldn't get token: %v", err)
  }

  client := spotify.Authenticator{}.NewClient(token)

  page, err := client.CurrentUsersPlaylists()
  if err != nil {
    log.Fatalf("couldn't get playlists: %v", err)
  }

  for _, playlist := range page.Playlists {
    fmt.Println("  ", playlist.Name)
  }
}

Play a specific music

Hello,

I would like to know how I could play a specific music with your library.
Thanks.

Would you be interested in a method which returns all the playlists of a user?

I am working on something where I need all the playlists of a user. I am not sure if this should be part of this library or not. Anyways here is my code:

func (c *Client) CurrentUsersAllPlaylists() (*SimplePlaylistPage, error){
	var allPlaylists *SimplePlaylistPage
	var total int
	limit := 50
	offset := 0
	opt := Options{
		Limit:  &limit,
		Offset: &offset,
	}
	for {
		playlists, err := c.CurrentUsersPlaylistsOpt(&opt)
		if err != nil {
			return nil, err
		}
		total = playlists.Total
		if allPlaylists == nil {
			allPlaylists = playlists
		} else {
			allPlaylists.Playlists = append(allPlaylists.Playlists, playlists.Playlists...)
		}
		offset = offset + limit
		if total < offset {
			break
		}
	}
	return allPlaylists, nil
}

If you think this is a good idea to have this as part of spotify lib, then I would be happy to send a PR ๐Ÿ˜„

Transfer Playback Multiple IDs

I might just be missing something, but why should TransferPlayback take a slice of deviceIDs rather than just a single ID to transfer playback to?

func (c *Client) TransferPlayback(deviceIDs []ID, play bool) error {

I am still trying to figure out what is causing it, but the TransferPlayback method is very finicky for me and seems to only work when I run it in between a song change or if I start the playback through the app and not the API.

Edit: It seems like I can transfer the playback between devices but the playback gets stuck on my desktop PC running Windows 10 and then I'm unable to transfer playback from this device. This might be just an issue with my desktop client... If so I can close this if the slice of deviceIDs is purposeful.

No way to play songid

You have alot of functions but i cant find a function to play a specific songID?
Is there something i have not seen or is this not possible?

Follow type

This line is buggy
https://github.com/zmb3/spotify/blob/master/user.go#L210

ids parameter value is missing. and the type is mandatory.
https://developer.spotify.com/web-api/follow-artists-users/

this works
spotifyURL := baseAddress + "me/following?type=artist&ids=" + strings.Join(toStringSlice(ids), ",")

I can submit a PR for this, but want to know what do you consider being the best way of tackling this.

Both Follow and UNfollow use the same modifyFollowers and take ids as varaidic arguments.
Shoud them take type as an argument? I think so. Following multiple people of different types would probably fail. SHould it be documented?

Add example to get items from next page

Currently trying to list the tracks on my playlist but I can't seem to get more than 100 which is the maximum items per page returned by spotify, now how do I fetch the next page of tracks?

I think this could be added to the search example or add a new example that lists all tracks (I can make a pr for that if I can get it working).

My current code

    // list songs from playlist
    songs, err := client.GetPlaylistTracks(user.ID, playlistID)
    if err != nil {
        log.Fatal(err)
    }

    for _, item := range songs.Tracks {
        fmt.Printf("%s: %s (%s)\n", item.Track.ID, item.Track.Name, item.Track.Artists[0].Name)
    }

    fmt.Printf("This playlist has: %d songs (listed %d)\n", songs.Total, len(songs.Tracks))
    // This one outputs: `This playlist has: 144 songs (listed 100)`

ReleaseDateTime method only defined for FullAlbum struct

#71, which adds the ReleaseDate and ReleaseDatePrecision fields to the SimpleAlbum struct, was merged ages ago, but SimpleAlbum doesn't have the ReleaseDateTime method which is defined for the FullAlbum struct.

Is it possible to move the ReleaseDateTime method to the SimpleAlbum instead?
I would gladly open a PR if interested.

Tangentially related: Is there a reason why - especially in case of the Album structs - multiple fields are defined both on the "simple" as well as on the "full" variant even though the simple one is embedded?

Ascii codes in authentication Uri

Hey,

I've tried using this wrapper for authentication. It seems to work fine except for the redirectURL and state which contain a hexadecimal representation of their special characters:

auth = spotify.NewAuthenticator("http://localhost:4200/create", spotify.ScopeUserModifyPlaybackState)
config := config.ReadConfig()
auth.SetAuthInfo(config.ClientId, config.ClientSecret)
code := rest_objects.AuthorizationCode{Uri: auth.AuthURL(time.Now().Format(time.RFC3339))}
println(code.Uri)

Which prints: https://accounts.spotify...redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fcreate&...&state=2018-04-30T14%3A04%3A39%2B02%3A00

I am currently replacing these substrings but is there a way to bypass this in the first place?

invalid username for PlayerCurrentlyPlaying()

Hello!

Simply trying to retrieve the current playing song, feel like I am running into a wall with understanding the auth mechanisms here. Maybe it is that to get the currently playing song of my own account it is considered private data? and thus client credentials don't allow it?

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/zmb3/spotify"
	"golang.org/x/oauth2/clientcredentials"
)

func main() {
	config := &clientcredentials.Config{
		ClientID:     os.Getenv("SPOTIFY_ID"),
		ClientSecret: os.Getenv("SPOTIFY_SECRET"),
		TokenURL:     spotify.TokenURL,
		Scopes:       []string{spotify.ScopeUserReadCurrentlyPlaying},
	}

	token, err := config.Token(context.Background())
	if err != nil {
		log.Fatalf("unable to get token: %v", err)
	}

	client := spotify.Authenticator{}.NewClient(token)

	song, err := client.PlayerCurrentlyPlaying()
	if err != nil {
		log.Fatalf("unable to get currently playing song: %v", err)
	}

	fmt.Println(song)
}

The error here is Invalid username

Any help would be appreciated.

Cheers!

Token error

Hi,

I'm playing with the player example but I have some issue sending request just after I logging or sending 2 commands
The error I got is sometimes

2017/10/07 12:18:21 oauth2: cannot fetch token: 400 Bad Request
Response: {"error":"invalid_grant","error_description":"Authorization code expired"}

or

2017/10/07 12:21:51 oauth2: cannot fetch token: 400 Bad Request Response: {"error":"invalid_grant","error_description":"Invalid authorization code"}

Is there an issue with oauth2 lib ?

Client returns 'spotify: HTTP 204: No Content ' as an error

Up until recently it worked fine, but now some calls return the following error:

spotify: HTTP 204: No Content (body empty)

Which is not really an error if you ask me ;)

Ive identified at least these functions to do this:

p.client.PlayOpt(&spotify.PlayOptions{
	URIs: []spotify.URI{URI},
})
p.client.Repeat("off")
p.client.Shuffle(false)

But there might be more?

Allow HTTP Client and Base URL to be overrided on instantiation

I have an application that consists of two components: a persistent server that takes care of authenticating with Spotify (it stores creds and refreshes them after authenticating once), and a CLI that gets existing creds from this auth server and uses that token to make Spotify API calls. This lets me control Spotify from the command line without re-authenticating frequently. Currently the CLI portion of the app is written in Ruby while the server is in Go. I'm translating the CLI to Go right now and was hoping to use this library. However, the implementation of the Client struct here won't let me bypass this library's auth mechanism. I believe I could use this library if the Client.http field was public โ€“ I would create my own client with an http.RoundTripper that simply adds the authorization field.

Any chance these fields could be exposed?

x509: certificate signed by unknown authority

Hello,

While trying to receive a token, to make subsequent requests, I get the following error :

2019/01/13 18:33:09 couldn't get token: Post https://accounts.spotify.com/api/token: x509: certificate signed by unknown authority

This of course implies that the certificate, that is offered, is signed by a (to my computer) unknown authority.
However, this did work sometime in November last year. So spotify changed something up I'm guessing.

Would you have an Idea how to get this working, besides authorizing the certificate?

The following code was used:

config := &clientcredentials.Config{
	ClientID:     os.Getenv("SPOTIFY_ID"),
	ClientSecret: os.Getenv("SPOTIFY_SECRET"),
	TokenURL:     spotify.TokenURL,
}
token, err := config.Token(context.Background())
if err != nil {
	log.Fatalf("couldn't get token: %v", err)
}

client := spotify.Authenticator{}.NewClient(token)

Result of New Releases is empty

Code:

results, err := client.NewReleases()
if err != nil {
	log.Fatal(err)
}
spew.Dump(results)

The result is an empty SimpleAlbumPage struct and there is no raised error:

(*spotify.SimpleAlbumPage)(0xc04222f320)({
 basePage: (spotify.basePage) {
  Endpoint: (string) "",
  Limit: (int) 0,
  Offset: (int) 0,
  Total: (int) 0,
  Next: (string) "",
  Previous: (string) ""
 },
 Albums: ([]spotify.SimpleAlbum) <nil>
})

Other functions that need authentication work as expected with my client.

Stop using http.Request for token recovery

Hello,

I'm actually using gin, and i can't access to the http.Request object
Is it possible to add a function where i can retrieve the token without using http.request

regards,

Oauth Credential Storage

Is there a way to save the oauth credentials to the filesystem, so they can be used on a subsequent run?

Library doesn't allow other arguments to be in the redirect-URI

I'm assigning a redirect-URI like:

redirectUrl := "http://urlecho.appspot.com/echo?debugMode=1"
auth := spotify.NewAuthenticator(redirectUrl, spotify.ScopeUserReadPrivate)

..but the produced authorization URL looks like:

https://accounts.spotify.com/authorize?client_id=CLIENTID&redirect_uri=http%3A%2F%2Furlecho.appspot.com%2Fecho&response_type=code&scope=user-read-private&state=arbitrary-state-data

When I add the argument to the URL directly, Spotify accepts it (though I have to make sure to white-list the whole thing, including the query portion) and then redirects to it. So, it is definitely supported.

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.