普段、TV・ラジオ・CDショップ・音楽雑誌・店頭BGMなどで発売されたばかりの良い音楽に出会った際に、メモに残しておいて後からSpotifyで検索して聞いています。しかし、メモに残したアーティスト名を1つ1つ検索していくのは面倒だなあと感じていました。
ということで、Slackにアーティスト名を投稿するだけで、入力したアーティストの最新アルバムがSpotifyのプレイリストに追加されるようにします。
前提
- 実行環境にAmazon Web ServiceのLambdaを利用します。
- Pythonのバージョンは3.6を利用しています。
1. 準備
Amazon Web Service(AWS)
SlackからAPI Gatewayに対してPOSTしたアーティスト名を、Lambdaで処理する構成とします。勉強がてら、取得した最新のtokenをDynamoDBに保管する構成としています。
以下を参考としました。LambdaやAPI Gatewayの設定方法は、本稿では割愛します。
Spotify
-
https://developer.spotify.com/my-applications でCREATE AN APPを行い、
CLIENT_ID
とCLIENT_PW
を取得します。 - 楽曲を追加するプレイリストの
PLAYLIST_ID
を取得します。プレイリストURLの{playlist_id}
の部分です。https://open.spotify.com/user/{user_id}/playlist/{playlist_id}
-
pip install spotipy
でPython用のSpotifyライブラリを取得しておきます。
Slack
- 利用するチャンネルに対して、Outgoing Webhooksを適用します。URL(s)にはPOSTを受け取ることができるよう設定したAPI GatewayのAPIエンドポイントを入力します。
- アーティスト名を検索して見つからなかった際に、チャンネルに「見つかりませんでした。」のメッセージを返すためのAppを作っておき、Webhook URLを取得します。
-
pip install slackweb
でPython用のSlackライブラリを取得しておきます。
2. token取得とDB格納
Spotifyのプレイリスト操作を行うために、access_token
を取得する必要があります。Spotifyのaccess_token
は1時間でリセットされてしまうため、Slackでアーティスト名を投稿をする度に、新しいaccess_token
を取得するような設計にします。
tokenの取得
初めてのtoken取得時には、確認画面が立ち上がり確認を求められるため、最初だけローカル環境でOAuth認証を通します。以後はtoken再発行用の文字列であるrefresh_token
が与えられるため、こちらを利用してaccess_token
を再取得します。
先ずは、以下をローカル環境にて実行します。
import spotipy.util as util
# SpotifyTokenに必要となるパラメータ情報を全て格納します
class SpotifyToken(object):
def __init__(self):
self.username = 'username' # Spotifyに登録しているユーザーネーム
self.client_id = 'CLIENT_ID'
self.client_secret = 'CLIENT_PW'
self.redirect_url = 'http://localhost:8080/'
self.scope = 'playlist-modify-public'
self.playlist_id = 'PLAYLIST_ID'
self.slack_channel_url = "https://hooks.slack.com/services/XXX~" # Slackに「見つかりませんでした」を返すためのWebhook URL
user = SpotifyToken()
token = util.prompt_for_user_token(username=user.username, scope=user.scope,
client_id=user.client_id, client_secret=user.client_secret,
redirect_uri=uesr.redirect_uri)
上記を実施後、確認画面が立ち上がるので、OKをクリックしてください。
tokenをDynamoDBに格納
その後、tokenの内容を確認します。
{
"access_token": "XXXXXX",
"token_type": "Bearer",
"expires_in": 3600,
"scope": null,
"expires_at": XXXXXX,
"refresh_token": "XXXXXXX"
}
tokenの再取得に必要となるのは、refresh_token
だけなので、DBを利用する必要はないのですが、今回は勉強のためDynamoDBにtokenを格納してみます。
プライマリパーテションキーをtoken
と定め、"token":'key'
を要素の1つとして加えて、jsonファイル内のデータを1つずつ1行でAWSコンソールから格納していきます。

次に、DynamoDBからrefresh_token
を読み込み、新しいaccess_token
を取得するコードを記述します。また、DynamoDBに格納されている内容も、新しいtokenの内容に書き換えます。
import boto3
from spotipy.oauth2 import SpotifyOAuth
# AWSコンソールから作成したテーブルを指定します。
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('your_table_name')
class SpotifyToken(object):
# --- getToken.pyと同内容のため省略 ---
def lambda_handler(event, context):
user = SpotifyToken()
oauth = SpotifyOAuth(client_id=user.client_id, client_secret=user.client_secret,
redirect_uri=None)
access_token = get_new_access_token(oauth)
# 新しいtokenを取得する関数
def get_new_access_token(oauth):
refresh_token = load_dynamodb()
new_token = oauth.refresh_access_token(refresh_token)
update_dynamodb(new_token)
access_token = new_token['access_token']
return access_token
# DynamoDBからrefresh_token読み込む関数
def load_dynamodb():
response = table.scan()
refresh_token = response['Items'][0]['refresh_token']
return refresh_token
# DynamoDBの内容を更新する関数
def update_dynamodb(new_token):
table.put_item(
Item={
'token':'key',
'access_token': new_token['access_token'],
'token_type': new_token['token_type'],
'expires_in': new_token['expires_in'],
'scope': new_token['scope'],
'expires_at': new_token['expires_at'],
'refresh_token': new_token['refresh_token']
})
3. プレイリスト操作
ここからは、本題のプレイリストへ楽曲を登録する操作の部分です。
Slackから投稿されたアーティスト名は、API Gatewayを経由して、lambda_handler関数の引数であるevent
に渡されます。
event['text']
に格納されたアーティスト名をSpotifyで検索を行い、アーティストの最新作を取得して、プレイリストへ加えます。
また、該当のアーティストが見つからない場合は、Slackへ「見つかりませんでした」と投稿します。
import spotipy
import slackweb
def lambda_handler(event, context):
# --- (1)の内容は省略 ---
# (1)で取得したaccess_tokenからSporifyオブジェクトを生成
sp = spotipy.Spotify(auth=access_token)
sp.trace = False
# API Gatewayから渡されたアーティスト名を取り出す
search_word = event['text']
add_tracks(sp, user.username, user.playlist_id, user.slack_channel_url, search_word)
# アーティストの最新のアルバムをプレイリストに投稿する関数
def add_tracks(sp, username, playlist_id, slack_channel_url, search_word):
# アーティスト名で検索を実施
try:
result = sp.search(q='artist:' + search_word, type='artist')
# アーティストIDの取得
artist_id = result['artists']['items'][0]['id']
# アーティストの最新のアルバムを取得
albums = sp.artist_albums(artist_id)
most_latest_album = albums['items'][0]['id']
# 最新アルバムに収録されている全曲のURIを取得
album_tracks = sp.album_tracks(most_latest_album)
track_uris =[]
for i in range(len(album_tracks['items'])):
track_id = album_tracks['items'][i]['uri']
track_uris.append(track_id)
# プレイリストへ楽曲を登録
sp.user_playlist_add_tracks(username, playlist_id, track_uris)
# アーティスト名が見つからない場合、Slackへ通知
except:
post_to_slack(slack_channel_url)
# Slackに「見つかりませんでした」を投稿する関数
def post_to_slack(slack_channel_url):
slack = slackweb.Slack(url=slack_channel_uri)
slack.notify(text="見つかりませんでした")
4. 完成
出来上がったコードを利用するライブラリと一緒に、zip形式でLambdaにアップロードしたら完成です。
アーティスト名が見つからない場合、「見つかりませんでした」と帰ってきます。
これで、お出掛け中に街で出会った新しい音楽をSlackから投稿しておくだけで、帰りの電車の中で既に出来あがったプレイリストを楽しむことができます。