Help us understand the problem. What is going on with this article?

【Server Side Swift】VaporでSlack botを作る

More than 3 years have passed since last update.

はじめに

Server Side SwiftのwebフレームワークであるVaporのサンプルアプリケーションとして、Slack botの例があります。
そのリポジトリに倣うと、Swiftでとても簡単に Slack bot が作れたので、その方法を紹介します。

事前注意

かなり簡単に作成できた印象で、個人的にはとても面白いのですが、
Vapor自体が日々アップデートをしていっているようなフェーズなため、今回の手順でうまくいかなくなる可能性は大いにあります。
あくまで遊び程度で触るのがいいかなと思います。

サンプルコード

今回作ったサンプルコードはGithub上に上げています。
https://github.com/taji-taji/VaporSampleBot

ゴール

  • Slackに投稿したメッセージの任意のテキストに反応して発言するSlack botをVaporを使って作成する。
  • 上記をHerokuにデプロイして動かす。

筆者実行環境

  • OSX: 10.11.6(15G31)
  • Swift: DEVELOPMENT-SNAPSHOT-2016-07-25-a
  • Vapor Toolbox v0.8.0
  • heroku-toolbelt/3.43.9

前提

  • vaporコマンドが使用できること
  • Slackアカウントを持っていること
  • Herokuのアカウント・Toolbeltを持っていること
    • ローカルmac上で動かすだけなら不要です。

1. 準備

SlackでBot Userを作る

スクリーンショット 2016-08-21 8.08.46.png

  • 作成が完了すると、BotアカウントのAPI Tokenが取得できます。あとで使用するので、これをメモっておきます。(メモらなくても後からでも確認できます。)

スクリーンショット_2016-08-21_8_11_18.png

2. プロジェクトの作成

作業ディレクトリ直下でVaporのアプリケーションのプロジェクトを作成します。

$ vapor new {プロジェクト名}

作成したら、プロジェクトの直下に移動します。

$ cd {プロジェクト名}

例)筆者の場合

$ vapor new VaporSampleBot
$ cd VaporSampleBot

3. サンプルアプリのコードをダウンロード

Vaporのサンプルアプリのコードを雛形として使用するため、以下のリポジトリからサンプルアプリのコードをダウンロードし、先ほど作ったプロジェクトにコードを置き換えていきます。

https://github.com/vapor/slack-bot

Sourceコードの置き換え

2で作成したプロジェクト直下のAppフォルダ内のファイル・フォルダを全て、ダウンロードしたサンプリアプリのSourceフォルダ内のファイルに置き換えます。

↓のような感じになります。
スクリーンショット 2016-08-21 15.32.59.png

Packageファイルの変更

次に、2で作成したプロジェクトのPackage.swiftを次のように変更します。

Package.swift
import PackageDescription

let package = Package(
    name: "VaporSampleBot",
    dependencies: [
        .Package(url: "https://github.com/vapor/tls-provider", majorVersion: 0, minor: 4)
    ],
    exclude: [
        "Config",
        "Database",
        "Localization",
        "Public",
        "Resources",
        "Tests",
    ]
)

4. 設定ファイルの作成

プロジェクト直下のConfigフォルダの下にbot-config.jsonを作成し、準備の項で取得したSlack botのAPI Tokenを以下のように記述します。

bot-config.json
{
    "token": "xcxb-your-api-key-here",
}

ローカルmac上で動かす際には上のように直接文字列としてAPI Tokenを指定すればいいですが、
実際にherokuにデプロイする際には、環境変数として設定するため、次のような記述になります。

bot-config.json
{
    "token": "$BOT_TOKEN",
}

注意点

mac上で動かす際に、tokenの値を$BOT_TOKENとすると、以下のような設定値が取得できないエラーが出てしまいます。

fatal error: Error raised at top level: App.BotError.missingConfig

5. ローカルで動かしてみる

まず、ビルドしてみましょう。

$ vapor build
Fetching Dependencies [Done]
Building Project [Done]

うまくビルドできれば上のようになります。
それでは動かしてみましょう。

$ vapor run

うまくつながれば、次のような感じでwssで繋がった様子が表示されるかと思います。

Running VaporSampleBot...
Connected to wss://mpmulti-5..[略]

さあ、それではSlackのbotがいるチャンネルかbotユーザーへのダイレクトメッセージで「hello bot!」と発言してみましょう!

スクリーンショット 2016-08-21 16.22.39.png

6. Herokuへのデプロイ

Procfileの変更

プロジェクト直下のProcfileを変更します。
「web」から「worker」にすればOKです。

Procfile
worker: App --env=production --workdir="./"

Herokuでアプリケーション作成

スクリーンショット 2016-08-21 12.19.24.png

Heroku Git の設定

アプリケーション作成後の画面に従ってこの設定ができるかと思うので、設定を進めてください。

Herokuの各種設定

Slack bot の API Token

$ heroku config:set BOT_TOKEN=xoxb-00000000000-XXXXXXXXXXXXXXXXXXXXXXXXX

buildpackの設定

$ heroku buildpacks:set https://github.com/kylef/heroku-buildpack-swift

herokuへpushしてデプロイ

$ git push heroku master

デプロイには数分かかります。しばらく待ちましょう。

dynoをscale

次のコマンドでdynoを起動します。

$ heroku ps:scale worker=1

Herokuの管理画面で下のようになっていればOKです。
(画面上に反映されるまで若干のタイムラグがあるかもしれないです。)

スクリーンショット 2016-08-21 16.54.03.png

7. 動作確認

5でローカルで動作させた時と同様に、Slackのbotがいるチャンネルかbotユーザーへのダイレクトメッセージで「hello bot!」と発言してみましょう!

うまく返事が返って来ればOKです!
お疲れ様でした :smile:


Advanced

反応する言葉や返信内容を変えたい時

おそらくコード見れば分かるので書くまでもないかと思うのですが、、

App/main.swiftの次の箇所を自分好みに変えていけばいいですね。

App/main.swift
// ~略~
    ws.onText = { ws, text in
        print("[event] - \(text)")

        let event = try JSON(bytes: text.utf8.array)
        guard
            let channel = event["channel"]?.string,
            let text = event["text"]?.string
            else { return }

        if text.hasPrefix("hello") {
            let response = SlackMessage(to: channel, text: "Hi there 👋")
            try ws.send(response)
        } else if text.hasPrefix("version") {
            let response = SlackMessage(to: channel, text: "Current Version: \(VERSION)")
            try ws.send(response)
        }
    }
// ~略~

例えば、次のように変更をすると、

App/main.swift
// ~略~
    ws.onText = { ws, text in

        let event = try JSON(bytes: text.utf8.array)
        guard
            let channel = event["channel"]?.string,
            let text = event["text"]?.string
            else { return }

        if text.contains("すし") {
            let response = SlackMessage(to: channel, text: "🍣")
            try ws.send(response)
        }
    }
// ~略~

このような感じになります。

スクリーンショット 2016-08-21 19.49.22.png

その他

bot-config.jsonについて

4で作成したbot-config.jsontokenの値ですが、前述の説明では、
「ローカルで動かす時は値を直接書いて、Herokuにあげる時は $BOT_TOKEN と書く」
という説明になっていますが、ローカルのmacでも、環境変数としてBOT_TOKENを設定すればコードの書き換えを行うことなくできます。

$ export BOT_TOKEN=xoxb-00000000000-XXXXXXXXXXXXXXXXXXXXXXXXX

また、当然ただの環境変数なのでBOT_TOKENという名前でなくでも大丈夫です。
ただし、変更する場合はコード上の環境変数を表す文字列とローカル環境・リモート環境(Heroku)の環境変数も変更することを忘れないようにしないといけません。

Reference

taji-taji
植物系エンジニア。 こんなiOSアプリ作りました。 「観察日記」 https://appsto.re/jp/kHAx_.i 「My Closet」 https://appsto.re/jp/OBRIcb.i
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away