見出し画像

Spotifyから学ぶOAuth

今回の記事はCyberAgentの19新卒のアドベントカレンダー(21日)で書くはずだったのですが、僕の勘違いにより今日(24日)になりましたすいません。。

musiは僕の学校の授業の課題として作ったのですが、コードの解説や認証の仕組みをする記事を書いていなかったのでここで書いていこうと思います。

CyberAgent19新卒アドベントカレンダーは以下を参照してください。


musiとは

musi(ミュージ)は天気を元に楽曲を検索するWebアプリケーションです。アプリケーションの流れとしては、Spotifyで認証してその人の位置情報から天気をだして、その天気で楽曲を検索します。

今回使ったのは位置情報を取得するLocation APIと天気の取得をするOpen Weather API、楽曲の検索をするSpotify APIを使いました。


位置情報の取得の仕方

位置情報の取得に使ったLocation APIは以下のようなコードで取得できます。

navigator.geolocation.getCurrentPosition(data => {
    const { latitude, longitude } = data.coords;
});

ブラウザのJavaScriptからgeolocation.getCurrentPositionを呼びます。
すると、ブラウザに位置情報を共有するのを許可するか?というダイアログが出現します。

本来であればこのメソッドを呼ぶ前に、「アプリケーションを利用するには位置情報を許可する必要があります」といったメッセージをだしてからした方がよさそうです。例えばWeb Notification APIを使う場合なども、一度許可されないと今後モーダルもだせなくなるみたいなことも起こるようなので気をつけた方がよさそうです。


Open Wether APIを使って天気を取得する

Open Wether APIをつかうんですが、今回は簡単にさわれるように以下を使いました。

コードは簡単で

w, err := owm.NewCurrent("F", "EN", openweatherAPIKey)
if err != nil {
    return nil, err
}
w.CurrentByCoordinates(&owm.Coordinates{
	Longitude: location.Longitude,
	Latitude:  location.Latitude,
})

locationを渡してあげるだけです。すると、

w.Weather[0].Main

から、「Rain」みたいな文字列が取得できます。それをSpotifyの検索クエリーになげます。


Spotify APIを使った楽曲検索

Spotify APIは認証して、リクエストを投げる時にTokenを要します。

values := url.Values{}
values.Add("q", w.Weather[0].Main)
values.Add("type", "playlist")
req, _ := http.NewRequest("GET", "https://api.spotify.com/v1/search", nil)
req.URL.RawQuery = values.Encode()
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
	return nil, err
}
defer resp.Body.Close()

のようにリクエストする時に、Authorization HeaderにTokenを一緒になげます。すると、以下のような形のjsonで返ってきます。それをmapしたGoの構造体は以下のようになります。

type PlayList struct {
	Playlists struct {
		Href  string `json:"href"`
		Items []struct {
			Collaborative bool `json:"collaborative"`
			ExternalUrls  struct {
				Spotify string `json:"spotify"`
			} `json:"external_urls"`
			Href   string `json:"href"`
			ID     string `json:"id"`
			Images []struct {
				Height int    `json:"height"`
				URL    string `json:"url"`
				Width  int    `json:"width"`
			} `json:"images"`
			Name  string `json:"name"`
			Owner struct {
				DisplayName  interface{} `json:"display_name"`
				ExternalUrls struct {
					Spotify string `json:"spotify"`
				} `json:"external_urls"`
				Href string `json:"href"`
				ID   string `json:"id"`
				Type string `json:"type"`
				URI  string `json:"uri"`
			} `json:"owner"`
			PrimaryColor interface{} `json:"primary_color"`
			Public       interface{} `json:"public"`
			SnapshotID   string      `json:"snapshot_id"`
			Tracks       struct {
				Href  string `json:"href"`
				Total int    `json:"total"`
			} `json:"tracks"`
			Type string `json:"type"`
			URI  string `json:"uri"`
		} `json:"items"`
		Limit    int         `json:"limit"`
		Next     string      `json:"next"`
		Offset   int         `json:"offset"`
		Previous interface{} `json:"previous"`
		Total    int         `json:"total"`
	} `json:"playlists"`
}

この構造体は、愚直に自分がつかうところだけ自分で作成しましたがライブラリを使ってもよさそうです。


OAuthで認証する

OAuthで認証をするためにはSpotifyからclient_keyとclient_secretというキーをもらってそれを元にSpotifyに作ったアプリケーションとその個人との許可を経てaccess_tokenをもらいます。
それを使って認証するという仕組みが大雑把なOAuthの仕組みです。

今回これを  golang.org/x/oauth2 を使って作りました。

config = oauth2.Config{
	ClientID:     os.Getenv("client_id"),
	ClientSecret: os.Getenv("client_secret"),
	Endpoint: oauth2.Endpoint{
		AuthURL:  "https://accounts.spotify.com/authorize",
		TokenURL: "https://accounts.spotify.com/api/token",
	},
	RedirectURL: "https://musi-app.now.sh/oauth",
	Scopes:      []string{"playlist-modify", "user-read-private", "user-library-read"},
}

全体のコードは

ここに全て書いていますので、ぜひ読んで見てください。
ぜひぜひPR等もお待ちしていますのでよろしくお願いします。



この記事が気に入ったらサポートをしてみませんか?