はじめに
元々Apple Musicに加入していましたが、あとで聴きたい曲や刺さった曲に「いいね」できる機能はあっても、
「いいね」した曲を蓄積するプレイリストを作ってくれず、毎回自分で作成したプレイリストに入れていました。
(スマートプレイリストという機能を使えばできるそうです...当時は知りませんでした。 apple musicのラブ済みの曲を集めるには?)
それもあり「いいね」を自動で蓄積してくれる機能を持つSpotifyに乗り換えました。
たまに学生時代ヘビーローテーションしていた曲を聴きかえして、当時の思い出を鮮明に思い出したくなるんです。
「あの時こんな曲聴いていたなぁ〜」とか「あの時辛かったなぁ〜」とか。
そこでSpotifyが提供するWeb APIを使用して毎月「いいね」したリストを作るくんを作成してみたので紹介します。
導入や初期設定等は公式がご丁寧に用意されているのでそちらを。
日本語で要点だけみたい方は以下記事が参考になるかと思います。
Spotify Developer Platform: Spotify APIアクセスしてデータ取得してみてみた
仕組み
- 【準備】Quick Startを使ってAppの作成と認証トークンの発行
- GASを使って以下処理(毎時実行)
- あらかじめ生成しておいたリフレッシュトークンを使用してアクセストークンを発行
- 1時間以内にいいねされた曲リストを取得
- 取得した曲リストを今月のプレイリストに追加(今月のプレイリストがなければ作成して追加)
- GASの設定
【準備】Quick Start使ってAppの作成と認証トークンの発行
Web APIにリクエストを投げるに当たり、認可されたアクセストークンが必要です。
公式のQuick Startに従い、Appの作成とトークンの作成をおこないます。
App作成したらClient ID
とClient Secret
をメモしておきましょう。
(handle-liked-musicはApp名です。好きな名前でOKっす。)
トークンに以下スコープを許可しましょう。
-
user-library-read
いいねした曲の取得に必要 -
playlist-modify-public
公開プレイリスト操作(作成や更新)に必要 -
playlist-modify-private
非公開プレイリスト操作(作成や更新)に必要 -
playlist-read-private
追加対象のプレイリスト取得に必要
うまくいけばこんなページが表示されるのでRefresh token
をメモしておきましょう。
GASを使って以下処理(毎時実行)
全体のコードです。
サクッと作ったためミュータブルなコードですがご了承ください。
var refresh_token = "{メモったRefresh token}"
var username = "{Idに記される名前(私の場合tuaaasa)}"
// アクセストークンの発行
function getToken() {
var endpoint = 'https://accounts.spotify.com/api/token'
var encode = Utilities.base64Encode("{メモったClient ID}:{メモったClient Secret}", Utilities.Charset.UTF_8)
var options = {
'method': 'post',
'contentType': 'application/x-www-form-urlencoded',
'headers': {
'Authorization': 'Basic ' + encode
},
'payload': {
'grant_type': 'refresh_token',
'refresh_token': refresh_token
},
'muteHttpExceptions': true
}
var response = UrlFetchApp.fetch(endpoint, options)
var content = response.getContentText("UTF-8")
return JSON.parse(content).access_token
}
// 今月のプレイリストを作成
function makePlaylist(yyyymm, token) {
var endpoint = 'https://api.spotify.com/v1/users/' + username + '/playlists';
var data = {
'name': yyyymm,
'description': 'liked list in ' + yyyymm,
'public': false
}
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': {
'Authorization': 'Bearer ' + token
},
'payload': JSON.stringify(data)
}
var response = UrlFetchApp.fetch(endpoint, options)
return JSON.parse(response).id
}
// 今月のプレイリストを取得
function getPlaylistThisMonth(token) {
var endpoint = 'https://api.spotify.com/v1/users/'+ username +'/playlists?offset=0&limit=20';
var options = {
'method': 'get',
'headers': {
'Authorization': 'Bearer ' + token
}
}
var response = UrlFetchApp.fetch(endpoint, options)
var date = new Date()
var yyyymm = String(date.getFullYear()) + String(date.getMonth()+ 1)
var targetPlaylist = JSON.parse(response).items.filter(item => item.name === yyyymm)
if(targetPlaylist[0]){
return targetPlaylist[0].id
}else{
return makePlaylist(yyyymm, token)
}
}
// 直近1時間以内にいいねした曲を取得
function getNewSongs(token) {
var endpoint = 'https://api.spotify.com/v1/me/tracks?offset=0&limit=20';
var options = {
'method': 'get',
'headers': {
'Authorization': 'Bearer ' + token
}
}
var response = UrlFetchApp.fetch(endpoint, options)
var now = new Date()
now.setMinutes(now.getHours() - 1)
var targetItems = JSON.parse(response).items.filter(
item => {
var itemDate = new Date(item.added_at)
return itemDate > now
})
return targetItems.map(item => item.track.uri)
}
// 曲をプレイリストに追加
function addNewSongs(playlist_id, uris, token) {
var endpoint = 'https://api.spotify.com/v1/playlists/' + playlist_id + '/tracks';
var data = {
'uris': uris,
'position': 0
}
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': {
'Authorization': 'Bearer ' + token
},
'payload': JSON.stringify(data)
}
var response = UrlFetchApp.fetch(endpoint, options)
}
// メイン関数
function main() {
var token = getToken()
var uris = getNewSongs(token)
if(uris.length >= 1){
var playlistId = getPlaylistThisMonth(token)
addNewSongs(playlistId, uris, token)
}
}
あらかじめ生成しておいたリフレッシュトークンを使用してアクセストークンを発行
本処理のコードです。
// アクセストークンの発行
function getToken() {
var endpoint = 'https://accounts.spotify.com/api/token'
var encode = Utilities.base64Encode("{メモったClient ID}:{メモったClient Secret}", Utilities.Charset.UTF_8)
var options = {
'method': 'post',
'contentType': 'application/x-www-form-urlencoded',
'headers': {
'Authorization': 'Basic ' + encode
},
'payload': {
'grant_type': 'refresh_token',
'refresh_token': refresh_token
},
'muteHttpExceptions': true
}
var response = UrlFetchApp.fetch(endpoint, options)
var content = response.getContentText("UTF-8")
return JSON.parse(content).access_token
}
Basic認証のため、Client ID
とClient Secret
をエンコードします。
var encode = Utilities.base64Encode("{メモったClient ID}:{メモったClient Secret}", Utilities.Charset.UTF_8)
1時間以内にいいねされた曲リストを取得
本処理のコードです。
// 直近1時間以内にいいねした曲を取得
function getNewSongs(token) {
var endpoint = 'https://api.spotify.com/v1/me/tracks?offset=0&limit=20';
var options = {
'method': 'get',
'headers': {
'Authorization': 'Bearer ' + token
}
}
var response = UrlFetchApp.fetch(endpoint, options)
var now = new Date()
now.setMinutes(now.getHours() - 1)
var targetItems = JSON.parse(response).items.filter(
item => {
var itemDate = new Date(item.added_at)
return itemDate > now
})
return targetItems.map(item => item.track.uri)
}
GASで毎時実行するので、1時間以内を検索対象に指定します。
var now = new Date()
now.setHours(now.getHours() - 1)
フィルタ部です。
曲をプレイリストに追加する際uri
で曲を指定するため、uri
の配列を返します。
var targetItems = JSON.parse(response).items.filter(
item => {
var itemDate = new Date(item.added_at)
return itemDate > now
})
return targetItems.map(item => item.track.uri)
取得した曲リストを今月のプレイリストに追加(今月のプレイリストがなければ作成して追加)
本処理のコードです。
// 曲をプレイリストに追加
function addNewSongs(playlist_id, uris, token) {
var endpoint = 'https://api.spotify.com/v1/playlists/' + playlist_id + '/tracks';
var data = {
'uris': uris,
'position': 0
}
var options = {
'method': 'post',
'contentType': 'application/json',
'headers': {
'Authorization': 'Bearer ' + token
},
'payload': JSON.stringify(data)
}
var response = UrlFetchApp.fetch(endpoint, options)
}
ここで曲を指定しています。
position
はプレイリスト中に曲を挿入する位置です。
0
は先頭を指定しています。
var data = {
'uris': uris,
'position': 0
}
GASの設定
Apps Scriptで新規プロジェクトを作成。コーディング。
実行許可を行うため一度動作確認しましょう。
トリガー
タブ > トリガーを追加
から以下設定。
時間の間隔を選択(時間) 欄を1時間おき
にしましょう。
結果
上手にできました!
さいごに
これで思い出すのが楽になりました。
Spotify以外のサービスで曲を聴くこともあるので、できたら他のサービスでもやってみたいです。
(SoundCloudもAPIあるっぽい、作るぞ...!!!)
最後まで読んでいただきありがとうございました〜。良い音楽ライフを〜♪