SlackのステータスをAPI経由で設定（例：現在iTunes再生中の曲を表示する）

![Screen Shot 2017-05-15 at 3.19.28.png](https://qiita-image-store.s3.amazonaws.com/0/19148/208e23a8-b9f7-8018-4f55-c70b62147e99.png)

Spotify版はこちら: https://qiita.com/keiya/items/06d40e67219e8b8bb841

# 準備1：Slackでアプリを作成
- アプリをまず作成する。 https://api.slack.com/apps
    - チーム用のtokenが取得できるが、これは利用できない。
- アプリの詳細設定"**OAuth & Permissions**"で、リダイレクトURLを `http://localhost` で設定
    - （実際に使うわけではないダミー）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/063552b3-a388-2721-491b-59b1da0787c7.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/d98fc66d-310e-5065-0bae-6d80b8d84b3f.png)

- 公式ドキュメント https://api.slack.com/docs/presence-and-status を眺めながら、以下を設定
- パーミッションスコープに `users.profile:write` を設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/73da4d81-d3a8-58dc-9acb-bda249655040.png)

# 準備2: OAuthで認証（自動化してない）
## アプリのAuthorization Request && ユーザーのAuthorization Grant

- 公式ドキュメント https://api.slack.com/docs/slack-button を見ながら、OAuthの一番最初のステップを行う
- `https://slack.com/oauth/authorize?scope=incoming-webhook,commands,bot,users.profile:write&client_id=<クライアントID>` にブラウザでアクセスする
    - ローカルにWebサーバを立ててるなら止めておくこと
- すると、ダミーの `localhost` にリダイレクトされる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/aa5fe7e1-213c-b120-dfdd-9fc91efbd33c.png)

- リダイレクトされた先のクエリの code を取ってくる

## アプリのAuthorization Grant && Access Token取得
### slack-oauth.sh

- 以下のスクリプトを実行する

```bash
oauth="https://slack.com/api/oauth.access"
client_id="nnn.nnn"
client_secret="asdf1234asdf1234"
code="nnnnn.nnnn.nnnxxxnn"
curl $oauth --data "client_id=${client_id}&client_secret=${client_secret}&code=${code}"
```

```bash
bash slack-oauth.sh
```

- client_id と client_secret はアプリのページで取得
- code はさっきの**準備2**で取ってきたやつ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/a452787d-44bf-0c67-4c01-38f20bec75ea.png)

- このようにアクセストークンが取得できる

# ステータスを設定するアプリを動かす
## slack.sh
- iTunesの現在の曲を取ってくる。
- song の部分を変えれば曲以外にもつかえるかと

```bash
token="アクセストークンを設定"

rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER) 
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

song=$(osascript -e 'tell application "iTunes" to if player state is playing then name of current track & " - " & artist of current track')
json="{\"status_text\":\"${song}\",\"status_emoji\":\":musical_note:\"}"
profile=$(rawurlencode "$json")

curl https://slack.com/api/users.profile.set \
        --data "token=${token}&profile=${profile}"
```

```bash
bash slack.sh
```

![Screen Shot 2017-05-15 at 3.19.28.png](https://qiita-image-store.s3.amazonaws.com/0/19148/208e23a8-b9f7-8018-4f55-c70b62147e99.png)

## 自動で回すワンライナー
![image.png](https://qiita-image-store.s3.amazonaws.com/0/19148/83211507-a13e-55ce-e9cb-e76248cd4284.png)

```bash
while true; do bash slack.sh; sleep 60 ; done
```


http://stackoverflow.com/questions/296536/how-to-urlencode-data-for-curl-command


## (追記) 機能強化バージョン
- 自動でループを回す (コマンド単体で使えるようにした)
- 1秒おきに取得するが、前回の曲と比較することにより曲が変わった時だけAPI問い合わせ
    - → 反応が早くなった(1秒以内)
    - APIの無駄遣いは無い
- 曲停止時にステータスをクリアするようにした

```bash
token="アクセストークンを設定"

rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER) 
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

while true
do
  sleep 1
  song=$(osascript -e 'tell application "iTunes" to if player state is playing then name of current track & " - " & artist of current track')
  if [[ ${song} = ${lastsong} ]]; then
    continue
  fi
  status_emoji=":musical_note:"
  if [[ ${song} = "" ]]; then
    status_emoji=""
  fi
  json="{\"status_text\":\"${song}\",\"status_emoji\":\"${status_emoji}\"}"
  profile=$(rawurlencode "$json")
  
  curl https://slack.com/api/users.profile.set \
          --data "token=${token}&profile=${profile}"
  lastsong=$song
done
```

```bash
bash slack.sh
```
これはこのコマンドだけで良い。

# バージョン2 (Unicode対応版)
- Pure BashだけだとUnicodeのエンコードがおかしいのでPerlの助けを借りて日本語や多言語対応。
- バージョン2.1(may 19 2017)
    - ダブルクォーテーションをスラッシュでエスケープするようにした

```bash
token="アクセストークンを設定"
while true
do
  sleep 1
  songraw=$(osascript -e 'tell application "iTunes" to if player state is playing then name of current track & " - " & artist of current track & " [" & album of current track & "]"')
  song=${songraw//\"/\\\"}

  if [[ "${song}" = "${lastsong}" ]]; then
    continue
  fi
  status_emoji=":musical_note:"
  if [[ ${song} = "" ]]; then
    status_emoji=""
  fi
  json="{\"status_text\":\"${song:0:100}\",\"status_emoji\":\"${status_emoji}\"}"
  profile="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "${json}")"
  
  curl https://slack.com/api/users.profile.set \
          --data "token=${token}&profile=${profile}"
  lastsong=$song
done
```