アルパカログ

プログラミングの話題が中心。時々エモいことも書きます。

Slack Botで学ぶPython

Slack Botはプログラミングを学ぶ上でちょうどいい題材です。

例えば、英語のために英語を学ぶのは退屈ですが、海外旅行などで実際に英語を話す体験があるとやる気が出ますよね。

プログラミングも同じように、書いたプログラムが自分の生活をちょっと便利にするような、具体的な体験が何よりの原動力になります。

このエントリを読むと、みなさんはPythonのプログラムから、あなたではないSlackユーザー(Bot)に自由にSlackに発言させることができるようになります。

例えば次のような感じです。

f:id:otoyo0122:20190124144410p:plain:w200

ワクワクして来ましたね?

それでは早速作っていきましょう。

1.Slack App作成

まずBotを作ります。ブラウザでSlackにログインして、下記URLにアクセスします。

ここにはあなたのSlackアプリが一覧で表示されますが、当然まだ何もありません。

アプリを新規作成しましょう。

f:id:otoyo0122:20190124144526p:plain:w400

Botの名前を入力して、動かすワークスペースを選びます。

f:id:otoyo0122:20190124144648p:plain:w400

英語ばかりのページが現れますが驚かないでください。Incoming Webhooksを選びます。

f:id:otoyo0122:20190124144714p:plain:w600

初期ではOffになっているので、Incoming WebhooksをOnにします。

f:id:otoyo0122:20190124144745p:plain:w600

Onにするとページが下に伸びるので、下までスクロールして新しいWebhookを追加します。

f:id:otoyo0122:20190124144803p:plain:w600

Botにどのチャンネルで喋らせるか許可を与える画面になるので、チャンネルを選んで許可します。

f:id:otoyo0122:20190124152429p:plain:w400

これでBotに喋らせるためのあなた専用URL(Webhook URL)ができました。あとでPythonプログラムで使います。

URLは人に教えないようにしましょう。

f:id:otoyo0122:20190124144856p:plain:w800

2.Pythonプログラミング

これからどんなプログラムを書くのか、Incoming WebhooksやさっきのURLはなんなのかを説明します。

f:id:otoyo0122:20190124144913p:plain:w600

これまでは上の絵でいうポストを作りました。これから書くPythonのプログラムは、ポストに手紙(発言内容)を投函するところにあたります。

それでは下記のPythonプログラムを書いて実行してみましょう。webhook_urlは先ほどコピーした自分のURLに置き換えてください。

import json
import urllib.request

webhook_url = 'https://hooks.slack.com/services/xxxxxx'

data = {'text': 'トヤーン'}

req = urllib.request.Request(webhook_url)
req.add_header('Content-type', 'application/json')

with urllib.request.urlopen(req, json.dumps(data).encode('utf-8')) as f:
    print(f.read().decode('utf-8'))

指定したチャンネルで発言できれば成功です!

プログラムのヒント

Pythonプログラムが思ったより短いことに驚きましたか?

プログラムは短くても、理解するにはプログラムの長さ以上にたくさんのことを学ぶ必要があります。

ここではプログラムを理解する上で、どんなことを勉強すればいいかのヒントを教えるに留めて、みなさんが自分で学べるようにしたいと思います。

JSON

プログラムの冒頭でjsonモジュールを読み込んでいます。

JSONは、CSVのようなデータフォーマットの一種で、特にWebプログラミング界隈ではCSVよりも頻繁に使われます。

CSVと違っているのは、CSVは縦・横の2次元しか表わせないのに対し、JSONは多次元リストを表現できるため、何次元のデータでも表すことができます。

HTTPリクエス

urllib.request モジュールはHTTPリクエストを扱うために読み込んでいます。

HTTPリクエストには、ブラウザでURLを開くときと同じGET、フォームで送信ボタンを押した時に使うPOSTなどがあります。

フォームで送信ボタンを押したとき何が起こっているのでしょうか?

実はURLに対してデータを送っています。

今回のプログラムも同じように、Webhook URLにデータを送っているのでPOSTを使っています。

GET, POST以外にもありますが、まずはGETとPOSTを理解すると良いでしょう。

リクエストヘッダ

プログラムでは下記の部分でリクエストヘッダを追加しています。

req.add_header('Content-type', 'application/json')

HTTPリクエスト/レスポンスははHeaderとBodyから構成されています。リクエストヘッダには Content-type 以外にも色々な種類があります。

例えば、ログインセッションのやりとりもこのリクエスト/レスポンスヘッダで行われています。

HTTPヘッダによるセッションのやりとりを理解すれば、セッションハイジャックなど不正の手法について学ぶことができます。

Encode/Decode

文字コードという言葉は一度は聞いたことがあると思います。Webの世界ではUTF-8というエンコーディング(文字コード)が広く使われています。

Python3で文字列を扱うときは文字列型(str)を使いますが、今回のようにHTTPリクエストのデータとして使うときには、UTF-8のバイト列型(bytes)に変換(エンコード)しなければなりません。

急に難しくなりましたね。

それは下記に挙げる要素が絡み合っているからです。

文字コードや文字セットが混同しやすいテーマなのに加えて、文字列型とバイト列型を変換するケースの存在が、ややこしさに拍車をかけています。

すっきり理解するのに時間がかかるかもしれませんが、日本語を扱う上では避けて通れない道です。

API仕様

Slackへの投稿内容は、下記の部分で指定されているのはすぐにわかります。

data = {'text': 'トヤーン'}

しかしよく見てください。辞書型のキーが 'text' になっていますが、誰が決めたのでしょう?

それはSlack APIによって決まっています。例えば今回使ったIncoming Webhooksなら、下記のページで説明されています。

Slackの他のAPIを使ったり、別のサービスのAPIを使うときは当然、データのフォーマットが違います。

ぜひいろいろなAPIPythonから使ってみてください。

プログラムのアレンジ

今回のプログラムを自分なりに改変して遊びながら学びましょう。

例えば次のような具合です。

  • 投稿メッセージに日時を付け足す
  • 複数のメッセージを順番に投稿する
  • メッセージをCSVファイルから読み込む
  • などなど...

何かわからないことがあったら、お近くのエンジニアを捕まえて聞いてみてくださいね。

それでは Enjoy programming!