SlackでSpotifyを操作してオフィスのBGMを変更できるようにしたら便利だった話

この記事はこの記事は[SmartHR Advent Calendar 2019](https://qiita.com/advent-calendar/2019/smarthr)の11日目の記事です。

私自身はサポートチームに所属しており、サポートで利用しているIntercomのステータスをSlackから操作する実用的なSlash Commandsを作ったりもしているのですが、今回は業務とは直接関係のない、SlackとSpotifyの連携の話になります。

<img width="747" alt="Slack___feed_spotify___SmartHR.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87174/9443d70d-f377-f901-531a-9dff1bbfc685.png">

# 本題の前に

今回の記事のメインはSlackからSpotifyを操作する部分なのですが、その前に「今オフィスで流れている曲の情報をSlackに流すやつ」を作っていたので、簡単に紹介します。

## Slackの特定のチャンネルにSpotifyで再生中の曲を流す

弊社オフィスでは、執務室のスピーカーに繋がっているiPad上のSpotifyアプリでBGMを流しています。

「これ結構いいなー」と思う曲がときどきあるのですが、かといってiPadまで行って曲を確認するのは面倒くさい。

ということで、iPadのSpotifyで再生中の曲をSlackに流すようにしました。

### Spotifyで再生中の曲をGASの定期実行で取得する

SpotifyのAPIを利用する際の認証やトークンのリフレッシュ方法などは下記の記事を参考にしてください。

- [GASを使って、Spotifyで再生中の曲をSlackのステータスに反映する](https://qiita.com/nozomit/items/0bec86a08f967aaa0762)

認証ができれば、あとは再生中の曲を取得する関数をGASのトリガーで毎分実行すればOKです。

取得した結果を別途用意したスプレッドシートの最終行と比較して、同じだったら、そこで処理終わり。

最終行と違う曲だったら、曲の情報を追記して、以下のSlackに投稿する処理を走らせます。

### 再生中の曲をSlackに投稿する

再生中の曲は、Spotifyの以下のAPIを利用して取得します。

- [Get Information About The User's Current Playback](https://developer.spotify.com/documentation/web-api/reference/player/get-information-about-the-users-current-playback/)

返ってきたJSONをパースしてtrackDataとして保持。

```java:trackデータにSpotifyのデータを入れる
trackData.id = content.item.id;//曲のid
trackData.track = content.item.name;//曲名
trackData.artist = content.item.artists[0].name;//アーティスト名
trackData.album = content.item.album.name;//アルバム名
trackData.albumimg = content.item.album.images[0].url;//アルバムの画像
trackData.trackurl = content.item.external_urls.spotify;//曲のURL
trackData.albumurl = content.item.album.external_urls.spotify;//アルバムのURL
trackData.artisturl = content.item.artists[0].external_urls.spotify;//アーティストのURL
```

Spotifyのtrackオブジェクトについての詳細は以下のドキュメントを参照してください。

- [track obuject(full)](https://developer.spotify.com/documentation/web-api/reference/object-model/#track-object-full)

あとはtrackのデータを、SlackのBlock Kitの型にはめて送るだけ :smile: 

Block Kitというのは、Slackが用意しているメッセージUIフレームワークで、JSONでメッセージのUIを記述できます。

- [Block Kit](https://api.slack.com/block-kit)

[Block Kit Builder](https://api.slack.com/tools/block-kit-builder)を使うと、見た目を確認しながらBlockを作成できるので便利です :thumbsup: 


```java:Block_Kit部分の記述
slackBlocks = [
  {
    "type": "section",
    "text": {
        "type": "mrkdwn",
      "text": ":musical_note: *<" + trackData.trackurl + "|" + trackData.track + ">*"
    }
},
{
    "type": "section",
    "fields": [
        {
            "type": "mrkdwn",
            "text": "*Artist*\n<" + trackData.artisturl + "|" + trackData.artist + ">"
        },
        {
            "type": "mrkdwn",
            "text": "*Album*\n<" + trackData.albumurl + "|" + trackData.album + ">"
        }
    ],
    "accessory": {
        "type": "image",
        "image_url": trackData.albumimg,
        "alt_text": trackData.album
    }
},
{
    "type": "divider"
}
] 
```

:point_up: を送ると、 :point_down: の見た目になります。

![](https://s3-ap-northeast-1.amazonaws.com/kufutools-codimd/uploads/upload_edba58e83a4dad38bf491cdd3a8e8ecc.png)

曲名・アーティスト名・アルバム名の部分はそれぞれSpotifyのリンクになっているので、気になる曲があったらクリックしてすぐに自分の端末で再生できます :tada:

# SlackからSpotifyを操作する

ここまで書いた部分まで作って自分のtimesでニコニコしていたら、エンジニアのmeganemuraさんが

![](https://s3-ap-northeast-1.amazonaws.com/kufutools-codimd/uploads/upload_13608585c7d43da8b226d378b8358026.png)

というアイデアをくれたので、作ってみました。

ここからが本題です :pray:

## Slash Commandsを使い、GASとやりとりする
SlackのSlash CommandsでGASを叩く部分は、たくさんドキュメントあるのでそちらを参考にしてみてください。

- [Enabling interactivity with Slash Commands](https://api.slack.com/interactivity/slash-commands)

SlackからGASをWeb APIとして利用する場合、GAS側の公開設定（Who has access to the app）は `Anyone, even anonymous` にする必要がある点だけ、気づかないとハマってしまうかもしれないので、ご注意ください。

## SpotifyのAPIを使い、プレイヤーを操作する
SpotifyのAPIも公式ドキュメントがとてもわかりやすいです。

- [Web API Reference](https://developer.spotify.com/documentation/web-api/reference/)

今回はSlackで `/spotify` というSlash Commandsの後にSpotifyの曲やアルバムのURLを送ると、送った曲やアルバムを再生する機能を実装しました。

`/spotify https://open.spotify.com/{type}/{id}`

Slash Commandsで取得した情報をパースしてSpotifyのAPIに投げればOKです。

### 再生

Spotifyの再生は、Playbackを操作することで行います。

- [Start/Resume a User's Playback ](https://developer.spotify.com/documentation/web-api/reference/player/start-a-users-playback/)
 
APIに送って再生する曲やアルバムの情報は、1つだけの場合は `context_uri` 複数の場合は `uris` で指定できます。


#### trackを再生する
track（曲）の場合、idを普通に `context_uri` として送ると、指定した1曲だけ延々再生されてしまいます :sob:

そこで、Slackから送られてきたURLのtypeがtrackだった場合は、そのtrackのidをseedにしてrecommendを取得して、seed + recommendを `uris` として投げるようにしました。

- [Get Recommendations Based on Seeds](https://developer.spotify.com/documentation/web-api/reference/browse/get-recommendations/)

#### album・artist・playlistを再生する

album・artist・playlistは基本的に複数の曲が含まれているものなので、 `context_uri` としてidをそのまま投げるようにしました。

シングルなど「albumだけど1曲」のものもわりとありますが、そこは運用でカバー。

実際はこんな感じで動作します。

![](https://s3-ap-northeast-1.amazonaws.com/kufutools-codimd/uploads/upload_dcbf5ab19be3f828b766fa80fba6d6f0.png)


### 一時停止する

「ちょっと音楽止めたい」というときのために、一時停止もできるように。

- [Pause a User's Playback](https://developer.spotify.com/documentation/web-api/reference/player/pause-a-users-playback/)

### 再開する

一時停止状態からの再開もできます。

- [Start/Resume a User's Playback](https://developer.spotify.com/documentation/web-api/reference/player/start-a-users-playback/)

### 次の曲に飛ばす

Playbackの次の曲に飛ばす操作。

- [Skip User’s Playback To Next Track](https://developer.spotify.com/documentation/web-api/reference/player/skip-users-playback-to-next-track/)

### 前の曲に戻す

Playbackの前の曲に戻す操作。

- [Skip User’s Playback To Previous Track](https://developer.spotify.com/documentation/web-api/reference/player/skip-users-playback-to-previous-track/)

### 音量の操作

「ちょっと音が大きいな」と思ったときなど、音量の操作ができると便利なのですが、iOSデバイスはSpotifyのWeb APIからの音量操作を受け付けないようなので、断念しました。

# 終わりに

軽い気持ちで作ってみたら社内でまあまあ使われるようになり、いくつか要望をもらったのですが実装できていない機能があるので、今後予定として列挙して終わりたいと思います :hand_splayed: 

- 今再生している曲はそのままで。次に再生する曲として追加する機能
- genresやinstrumentalness、loudnessを指定してレコメンドを取得して再生する機能
- Slack上で曲やアルバムをブラウズする機能

いつか実装したいですね :hugging: