LoginSignup
1
1

More than 3 years have passed since last update.

【② Slack編】当日の天気を知らせてくれるSlack Botを作ってみた(Python + Selenium + Slack + AWS ECS + Github Actions)

Last updated at Posted at 2019-08-12

毎日、当日の天気を能動的に調べるのは面倒なので、天気を知らせてくれるSlack Botを作ってみました。
処理の流れは以下のようになっています。

天気予報のWebページを取得 --> 当日の天気予報のスクリーンショットを撮る --> Slackへアップロード

天気予報のAPIから情報を取得・整形してSlackへ通知するようなBotでもよかったのですが、いい感じのAPIがなかったのと、リッチな通知にしたかったのでこのようになりました。
実装からAWS ECSへのデプロイ・スケジューリングまでを技術ごとに分けて、どのように作成したかを説明していこうと思います。
今回は【Slack編】です。

構成

  • Selenium編
  • ② Slack編 <-- いまここ
  • ③ Github Actions編
  • ④ AWS ECS編

実装

環境

  • Python 3.7
  • pipenv
  • requests 2.22.0

Slack Botの用意

Slack Botをこちらを参考にして用意してください。Botを作成するとBot User OAuth Access Tokenが取得できます。今回はこのアクセストークンを使用してSlackへスクショを投稿します。

ソースコード

SlackのAPIを簡単にPythonから利用できるSDKもありますが、スクショした画像をSlackへ送信するだけなので今回は使用しません。
まず、Slack Bot用のACCESS_TOKENとCHANNELは環境変数から取得します。CHANNELの方は特に指定がなければデフォルトでgeneralチャンネルが設定されますが、ACCESS_TOKENは設定が必須となっています。
次に、SlackのファイルアップロードAPIの仕様に合わせてHTTPリクエストを作成します。今回設定したパラメーターは以下の通りです。Slack APIの仕様詳細はこちらを参照してください。

設定項目
URL https://slack.com/api/files.upload
メソッド POST
Content-Type multipart/form-data
token ACCESS_TOKEN
channel(option) CHANNEL
filetype(option) binary

requests.postの引数のfilesに{'filename': open(filepath, 'rb')}を渡してあげると、Content-Typeにmultipart/form-dataが自動的にセットされるのでheaders引数を指定する必要はありません。中でどのように処理されているかはrequests/models.pyurllib3/filepost.pyを読むと分かります。
最後にファイルのアップロードが成功したかどうかをチェックします。Slackからのレスポンスが{"ok": true}であればアップロード完了です。{"ok": false, "error": "error_message"}であればアップロード失敗となるので例外を発生させます。

slack.py
import os
import sys
import requests


URI = 'https://slack.com/api/files.upload'
CHANNEL = os.getenv('CHANNEL', 'general')

try:
    ACCESS_TOKEN = os.environ['ACCESS_TOKEN']
except KeyError:
    sys.exit('You need to set evironment variable called "ACCESS_KEY"')


def upload(filepath):
    """upload filepath to slack

    Args:
        filepath: relative or absolute path of png file

    Returns:
        True
        Exception
    """

    try:
        files = {'file': open(filepath, 'rb')}
        params = {
            'token': ACCESS_TOKEN,
            'channels': CHANNEL,
            'filetype': 'binary',
        }

        res = requests.post(URI, params=params, files=files, timeout=10)

        if not res.ok:
            raise Exception(res.error)

        return True

    except Exception as err:
        raise err

if __name__ == '__main__':
    try:
        filepath = sys.argv[1]
    except Exception:
        sys.exit('Error: Please specify a filepath')

    upload(filepath)

以下のようなコマンドを実行するとSlackへtest.pngがアップロードされます。

$ pipenv run python3 slack.py test.png

終わりに

Selenium編とSlack編で紹介したソースコードはあえて個々で独立して動作するようにしていました。一つのアプリケーションとしての完成形のソースコードはこちらを参照してください。

次は【Github Actions編】です。 Github Actionsを使ってCI/CDを実現する方法を説明します。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1