グローバルIPをSlackに通知したい


## やりたいこと
自宅サーバーのグローバルIPが変わったらSlackに通知する。

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/924d6ba7-ba99-7ddb-8122-a2cc9ab45114.jpeg)

## やったこと

1. Slack APIを使うためのトークンを取得
2. グローバルIPの取得方法を確立
3. シェルスクリプトで実装・動作確認

### Slack APIを使うためのトークンを取得

#### Slack アプリを作成

APIを使うためにはSlackアプリを作成する必要があります。
アプリ？ APIを叩きたいだけなんだけど...と思う人もいるでしょうが、APIを叩くために必要なのでとりあえず作りましょう。慣れると数分でアプリ(=Tokenを取得)を作れます。

![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/9adaf4cd-1b51-d3ea-8e29-1789e8a5b019.jpeg)


1. https://api.slack.com/apps にアクセス。
1. `Create New App` をクリック。

slackにサインインしていないとこのボタンは出ずに、サインインしてくださいボタンが出ます。サインインをしたらまたアクセスし直しましょう。


![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/3410ab65-b8ee-1841-4a21-1d779261ac01.jpeg)


1. `App name` に自分の好きなアプリ名を入力。今回はnotification_gipとしました。
1. `Development Slack workspace` にグローバルIPを通知したいワークスペース名を選択。今回は私の個人slackであるmsrx9を選択します。
1. `Create App` をクリック

#### 作成したアプリ notification_gip のスコープ（どの機能を使うか）を設定

スコープを選択することで、使用できる機能を選択することができます。

![04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/11904e08-6538-3cc2-3baf-55a1234f3127.jpeg)


Basic Informationページに遷移しますので、左メニューの`OAuth & Permissions`をクリックします。

![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/24b31f66-7376-9fc8-d1d3-dae8b63af396.jpeg)


`Scopes`が出てくるまでスクロールしましょう。

![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/ef573746-9d9a-b1ed-40fe-139b6f21ced8.jpeg)

Select Permission Scopes で、利用できる機能を指定します。今回はメッセージを書き込む機能を利用しますので、`Send messages as notification_gip` を選択してください。

![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/042bb8c5-faf6-3ce9-5593-2d8dfa94b877.jpeg)


`Save Changes`　をクリック。ボタンの色が緑色から灰色に変わったらセーブ完了です。

#### ワークスペースに notification_gip をインストール

![08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/cb886d22-7fee-8c07-20c0-5d4b076ff93b.jpeg)

`Install App to Workspace` をクリックしてください。

![09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/7bff07b9-1879-3764-1bd6-b27bc24080c7.jpeg)

`許可する` をクリックしてください。

#### tokenを入手！

![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/5a1d9aa2-3a2f-3887-5568-b3e678a79cfc.jpeg)

グレーアウトしている `OAuth Access Token` を使う事でSlack APIを叩く事ができるようになります。


## グローバルIPの取得方法を調べる

次は実際にSlackに通知するためのグローバルIPを取得する方法を考えます。

自分のPCのグローバルIPアドレスを知るためのサービスとして https://www.cman.jp/network/support/go_access.cgi があります。
アクセスすると`あなたの利用しているIPアドレス`と大きく表示されていると思います。これがアクセスしているPCのグローバルIPアドレスです。

このページからグローバルIPだけを抽出すれば良さそうですね。
curlコマンドを使って取得したHTMLを眺めているとグローバルIPを特定しやすそうなタグを見つけました。

```
<div class="outIp">192.xxx.xxx.xxx</div>
```
`class="outIp"`と記載されている行のIPアドレスを取得する処理を考えましょう。

```
curl -s https://www.cman.jp/network/support/go_access.cgi | grep class..outIp| grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
```

このワンライナーは以下のようなことをしています。

1. `curl -s https://www.cman.jp/network/support/go_access.cgi` でHTMLを文字列として取得
1. `grep class..outIp` で、取得したHTML文字列から `class="outIp"`が書いてある行を抽出
1. `grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'`で、IPアドレス(xxx.xxx.xxx.xxx)の箇所だけを抽出


これでグローバルIPが取得できるようになりました。

### slackに書き込むためのAPIは？

slackに書き込むためのAPIは [chat.postMessage](https://api.slack.com/methods/chat.postMessage) を使えばいいみたいです。

必須パラメータは`token`、`channel`、`text`の三つで、POSTメソッドでアクセスすれば良いと書いてありますね。

これ、ブラウザ経由だとGETメソッドでも通るので、最初に実装した時にブラウザだとOKなのに、curlを使うとNGになる。。と少し悩んでしまいました。


## 実装

Slackにアクセスするために事前に必要な情報は`token`と`channel`です。
tokenは上記で作成したOAuth Access Tokenです。channelは投稿したいチャンネルのURLの末尾部分(下図オレンジ枠)になります。

![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/a885b6c8-8fdb-7022-c17a-071ea80dd990.jpeg)


#### gip2slack.sh - グローバルIPをslackに通知
以下のようなシェルスクリプトを組んでみました。
実行するとgipチャンネルに現在のグローバルIPが通知されます。
これで出先でも自宅サーバへアクセスするためのアドレスがわかりますね！

```
#!/bin/sh

# 設定
TOKEN="xxxx-xxxx-xxxxx"   # 上記で作成したOAuth Access Tokenを指定
CHANNEL="Cxxxxxxx5" # slackのチャンネルIDを指定

# グローバルIPアドレス取得
GIPADDR=$(curl -s https://www.cman.jp/network/support/go_access.cgi | grep class..outIp| grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')

# IP通知
curl -XPOST https://slack.com/api/chat.postMessage -d "token=${TOKEN}" -d "channel=${CHANNEL}" -d "text=${GIPADDR}"

```

実行するとこんな感じでSlackに通知されます！やったね！

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27090/924d6ba7-ba99-7ddb-8122-a2cc9ab45114.jpeg)


## 運用とこれから

毎日通知されるのも面倒臭いので、前回取得したグローバルIPと変化がなければ通知しない処理などを追加する予定です。
そして、このシェルスクリプトを1日1回起動するようにcrondに登録すればOK（のはずです。まだ自宅サーバも構築中なので運用試験まではできていません）



## 参考文献
- [【画像で説明】SLACKの推奨アクセストークン（レガシートークンじゃない方）を取得する方法 - GUIで取得編 -](https://qiita.com/komiya_____/items/0e988239ed3f5145a22c)
- [slack API - chat.postMessage](https://api.slack.com/methods/chat.postMessage)