【第二回】Rubyで作ったSlack BotとSpotify APIで遊んでみた
この記事はCAMPHOR- Advent Calendar 2016の17日目の記事です
謝罪
いきなり謝罪です。Advent Calendar上で予告していたタイトル「Rubyで作ったSlack BotとRhymerで遊んでみた」ですが、大嘘であることをここに謝罪します。ごめんなさい。
もともとは今年の中頃に一部界隈をおおいに賑わせたRhymerを使って遊ぼうと思っていたのですが、諸般の事情(スベりそう)から止むを得ず内容を変更させていただきました。興味のある方は以下のリンクより Rhymer
をお楽しみください↓↓
ごあいさつ
先日の記事は多くの方に読んでいただけたようで非常に嬉しく思います。本日は予告通り2本立ての2本目にあたる内容です。
みなさん、Spotify使ってますか?
Subscription系の音楽サービスとしては近年「Apple Music」「AWA」「LINE Music」など多くのプレイヤーが参入してきましたが、特に洋楽好きの方などはまだまだ「Spotify」人気が根強いのではないでしょうか。今回はみんな大好きSpotifyのAPIを使ってSlack Botを強化していきたいと思います。
概要
- Bot本体は前回の記事で使用したファイルをそのまま使ってます
bgm
というコマンドを入力することでSlackのタイムライン上にSpotifyの埋め込みリンクを表示するBotを作ります- 楽曲、アーティスト、アルバム、プレイリストのそれぞれで検索機能を実装
- ジャンルをもとにしたレコメンド機能を実装
- より複雑な機能を実装しようとおもったけど断念(後述)
- 正規表現の理解度がダメダメなのでツッコミお待ちしています
目次
- RSpotify
- 検索機能の実装
- レコメンド機能の実装
- 個人利用のためのカスタマイズ(断念)
環境
- macOS Sierra 10.12.2 Beta
- MacBook Air (13-inch, Early 2014)
- ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
参考
やっていくぞ!!
1. RSpotify
RSpotifyはGuilherme Sad氏によるSpotify Web APIのRubyラッパーです
1.1. 開発用キーの設定
Spotify Developer Pageから新規アプリケーションを作成し、 Client ID
と Client Secret
の2つのトークンを取得します。
トークンを取得したらそれぞれ SPOTIFY_CLIENT_ID
および SPOTIFY_CLIENT_SECRET
という環境変数として保存します。方法は前回の記事を参考にしてください。
1.2. RSpotifyのインストール
前回作成した Gemfile
に追記
# Gemfile source 'https://rubygems.org' ruby "2.3.1" gem 'http' gem 'json' gem 'faye-websocket' gem 'eventmachine' gem 'rspotify'
$ bundle
コマンドでGemをインストール
1.3. RSpotifyの動作確認
RSpotify
と関連するGemのインストールが完了したら動作をテストしてみましょう。前回同様、 bot.rb
に追記していきます。
# bot.rb require 'http' require 'json' require 'eventmachine' require 'faye/websocket' require 'rspotify' # RSpotifyの読み込み # アプリの認証情報 RSpotify.authenticate(ENV['SPOTIFY_CLIENT_ID'], ENV['SPOTIFY_CLIENT_SECRET']) (省略) ws.on :message do |event| data = JSON.parse(event.data) # data['text']が存在しなければスキップし、存在すればmsg変数に代入 next if data['text'].nil? msg = data['text'] p [:message, data] if msg == 'こんばんは' ws.send({ type: 'message', text: "こんばんは <@#{data['user']}> さん"+data['text'].split(" ").first, channel: data['channel'] }.to_json) end # "bgm"という単語から始まるテキストが入力された時の処理 if msg.match(/^bgm/) test_url = RSpotify::Track.find('5CwhBU7eqQgkOVMnRNuzzT').external_urls['spotify'] ws.send({ type: 'message', text: test_url, channel: data['channel'] }.to_json) end end (省略)
bgm
という単語から始まるテキストがSlackに投稿された時に Spotify
から 5CwhBU7eqQgkOVMnRNuzzT
というIDに該当する曲を探し、その埋め込み用リンクを返すような処理です。
このコードを実行してみましょう。
ID: 5CwhBU7eqQgkOVMnRNuzzT
の曲、つまりGet Wildの埋め込みリンクが無事タイムラインに投稿されました!
2. 検索機能
2.1. 楽曲を検索できるようにする
無限にGet Wildを聴き続けるのもよいですが、せっかくなら楽曲を検索して表示したいものです。
bgm song (クエリ)
というテキストが入力されたらクエリに該当する楽曲を検索
# bot.rb ... if msg.match(/^bgm/) text = "No result" if matched_msg = msg.match(/^bgm song (.*)/) track = RSpotify::Track.search(matched_msg[1]).first text = track.external_urls['spotify'] unless track.nil? end ws.send({ type: 'message', text: text, channel: data['channel'] }.to_json) end ...
実行
2.2 アーティスト、アルバム、プレイリストの検索機能
上記のコードと同じ要領でアーティストやアルバム、プレイリストについても検索機能を実装していきます
# bot.rb ... if msg.match(/^bgm/) text = "No result" if matched_msg = msg.match(/^bgm song (.*)/) track = RSpotify::Track.search(matched_msg[1]).first text = track.external_urls['spotify'] unless track.nil? elsif matched_msg = msg.match(/^bgm artist (.*)/) artist = RSpotify::Artist.search(matched_msg[1]).first text = artist.external_urls['spotify'] unless artist.nil? elsif matched_msg = msg.match(/^bgm album (.*)/) album = RSpotify::Album.search(matched_msg[1]).first text = album.external_urls['spotify'] unless album.nil? elsif matched_msg = msg.match(/^bgm playlist (.*)/) playlist = RSpotify::Playlist.search(matched_msg[1]).first text = playlist.external_urls['spotify'] unless playlist.nil? end ws.send({ type: 'message', text: text, channel: data['channel'] }.to_json) end ...
実行!
YOSAGE(ガッツポーズの絵文字)
3. レコメンド機能
音楽のジャンルごとに楽曲をレコメンドしてくれる機能を実装します。 bot.rb
に追記
# bot.rb ... if msg.match(/^bgm/) text = "No result" if matched_msg = msg.match(/^bgm song (.*)/) track = RSpotify::Track.search(matched_msg[1]).first text = track.external_urls['spotify'] unless track.nil? elsif matched_msg = msg.match(/^bgm artist (.*)/) artist = RSpotify::Artist.search(matched_msg[1]).first text = artist.external_urls['spotify'] unless artist.nil? elsif matched_msg = msg.match(/^bgm album (.*)/) album = RSpotify::Album.search(matched_msg[1]).first text = album.external_urls['spotify'] unless album.nil? elsif matched_msg = msg.match(/^bgm playlist (.*)/) playlist = RSpotify::Playlist.search(matched_msg[1]).first text = playlist.external_urls['spotify'] unless playlist.nil? # 追記部分 elsif matched_msg = msg.match(/^bgm recommend (.*)/) result = RSpotify::Recommendations.generate(seed_genres: [matched_msg[1]]).tracks.sample text = result.external_urls['spotify'] unless result.nil? end ws.send({ type: 'message', text: text, channel: data['channel'] }.to_json) end ...
bot recommend
から始まる入力が与えられたときに RSpotify::Recommendations.generate
を実行しています。 RSpotify::Recommendations.generate
からはおすすめの track
20曲分(デフォルト時)の配列が得られるため、その中からランダムで1曲を抜き出して埋め込みリンクを表示するような処理です。
レコメンド機能を試してみましょう。
こちらもYOSAGEですね。ちなみに2016年12月16日現在レコメンド機能がカバーしているジャンルは以下の通りです
{ "genres" : [ "acoustic", "afrobeat", "alt-rock", "alternative", "ambient", "anime", "black-metal", "bluegrass", "blues", "bossanova", "brazil", "breakbeat", "british", "cantopop", "chicago-house", "children", "chill", "classical", "club", "comedy", "country", "dance", "dancehall", "death-metal", "deep-house", "detroit-techno", "disco", "disney", "drum-and-bass", "dub", "dubstep", "edm", "electro", "electronic", "emo", "folk", "forro", "french", "funk", "garage", "german", "gospel", "goth", "grindcore", "groove", "grunge", "guitar", "happy", "hard-rock", "hardcore", "hardstyle", "heavy-metal", "hip-hop", "holidays", "honky-tonk", "house", "idm", "indian", "indie", "indie-pop", "industrial", "iranian", "j-dance", "j-idol", "j-pop", "j-rock", "jazz", "k-pop", "kids", "latin", "latino", "malay", "mandopop", "metal", "metal-misc", "metalcore", "minimal-techno", "movies", "mpb", "new-age", "new-release", "opera", "pagode", "party", "philippines-opm", "piano", "pop", "pop-film", "post-dubstep", "power-pop", "progressive-house", "psych-rock", "punk", "punk-rock", "r-n-b", "rainy-day", "reggae", "reggaeton", "road-trip", "rock", "rock-n-roll", "rockabilly", "romance", "sad", "salsa", "samba", "sertanejo", "show-tunes", "singer-songwriter", "ska", "sleep", "songwriter", "soul", "soundtracks", "spanish", "study", "summer", "swedish", "synth-pop", "tango", "techno", "trance", "trip-hop", "turkish", "work-out", "world-music" ] }
4. 個人利用のためのカスタマイズ(...だがしかし断念)
当初の予定ではここからユーザー情報で OAuth
認証してSlackから個人のプレイリストに曲追加したりいろいろやりたいことがあったけど、Advent Calendar担当日のタイムリミットが来たので断念...
近いうちにリベンジしたいです。
おわりに
日本でのサービスイン以前からSpotifyを利用しているヘビーユーザーなのでAPIを叩くだけで遊べるのはとてもありがたいです。 Slack Botに限らず今後もいろんな機会で使っていきたいと思います。
明日はmurata_atsumiの記事です
Let's Get Wild!