16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Slimaneチュートリアル] Swift + Slimane + Docker + HerokuでLINE Botを作成する

Posted at

このドキュメントは、Swift製のウェブアプリケーションフレームワークであるSlimaneを利用した開発の流れを体験することを目的としたチュートリアルです。

このチュートリアルでは、受け取ったメッセージをそのまま返信するだけの簡単なLINE Botを作成し、Dockerを利用してHerokuへデプロイします。

事前準備

下記のアカウントが必要です。

  • Heroku
  • LINE developers (あらかじめチャンネルを作成しておく)

下記のものをあらかじめインストールしておきます。

  • Heroku toolbelt (あらかじめログインしておく)
  • Docker
  • swiftenv
  • npm

また、Swift 3.0の開発版を利用するため、下記のようにしてあらかじめインストールしておいてください。

swiftenv install swift-DEVELOPMENT-SNAPSHOT-2016-05-31-a

Slimane CLIのインストール

下記のようにしてSlimane CLIをインストールします。

npm install -g slimane-cli

##プロジェクトの作成

下記を実行することで、空のSlimaneプロジェクトを生成できます。ここではslimane-tutorial-linebotというプロジェクト名で生成します。

slimane new slimane-tutorial-linebot

slimane-tutorial-linebotというディレクトリが生成され、最低限必要なファイルが同時に生成されています。以降の作業は全てこのディレクトリの中で行います。

プロジェクトのビルドと実行

まだ何もコードを書いていませんが、一旦この空のプロジェクトをビルドしてみましょう。下記のようにすることで、Slimaneプロジェクトをビルドできます。

slimane build

しばらく待つとビルドが完了するので、下記のようにして実行します。

slimane run

無事に起動すると3000番ポートを待ち受けるようになっているため、試しにHTTPリクエストを投げてみましょう。

curl 'http://localhost:3000/'

Welcome to Slimane!というメッセージが返ってくれば成功です。

Dockerイメージのビルド

せっかくなので、このSlimaneアプリケーションをDockerで動かせるようにしてみましょう。下記の内容でDockerfile.dockerignoreを作成します。

Dockerfile
FROM takebayashi/slimane
.dockerignore
.build
.git
Packages

下記のようにしてビルドと実行をしてみます。

docker build -t slimane-tutorial-linebot .
docker run -i -p 3000:3000 -t slimane-tutorial-linebot

さきほどと同じように3000番ポートにリクエストを投げてみて、正常にレスポンスが返ってくれば成功です。

ここまでの手順を反映したものをGitHubで見る

依存パッケージの追加

このチュートリアルでは下記のパッケージを利用することにします。

SwiftLineBotはLINE Bot APIで利用されるJSONデータのシリアライズおよびデシリアライズを行うライブラリです。Botがコールバックリクエストを受ける際にはJSONデータを一緒に受け取りますが、そのデータのパースなどにこのライブラリを利用します。

HTTPSClientは、HTTPSリクエストを発行するためのライブラリです。受け取ったメッセージに対して返信を行う際にはHTTP APIをコールする必要があるため、その際にこのライブラリを利用します。

この2つのライブラリを利用できるようにするため、Package.swiftを下記のように変更します。

--- a/Package.swift
+++ b/Package.swift
@@ -3,6 +3,8 @@ import PackageDescription
 let package = Package(
     name: "slimane-tutorial-linebot",
     dependencies: [
-        .Package(url: "https://github.com/noppoMan/Slimane.git", majorVersion: 0, minor: 6)
+        .Package(url: "https://github.com/noppoMan/Slimane.git", majorVersion: 0, minor: 6),
+        .Package(url: "https://github.com/takebayashi/SwiftLineBot.git", majorVersion: 0, minor: 0),
+        .Package(url: "https://github.com/VeniceX/HTTPSClient.git", majorVersion: 0, minor: 8)
     ]
 )

ここまでの手順を反映したものをGitHubで見る

設定項目の追加

LINE Botを動かすには、Channel ID、Channel Secret、MIDの3項目が必要となるため、これらを設定値として環境変数から取得できるようにします。

main.swiftにはもともと環境変数から値を取得するコードが含まれているため、その下に上記の設定値を取得するコードを追加します。

--- a/Sources/main.swift
+++ b/Sources/main.swift
@@ -12,6 +12,9 @@ var PORT: Int {
 }
 let HOST = Process.env["HOST"] ?? "0.0.0.0"
 let SLIMANE_ENV = Process.env["SLIMANE_ENV"] ?? "development"
+let LINE_CHANNEL_ID = Process.env["LINE_CHANNEL_ID"]!
+let LINE_CHANNEL_SECRET = Process.env["LINE_CHANNEL_SECRET"]!
+let LINE_CHANNEL_MID = Process.env["LINE_CHANNEL_MID"]!

 do {
     try launchApp()

Botの実装

実際にLINEメッセージを受け取り返信する部分を実装します。

--- a/Sources/app.swift
+++ b/Sources/app.swift
@@ -1,4 +1,6 @@
 import Slimane
+import SwiftLineBot
+import HTTPSClient
 
 func launchApp() throws {
     let app = Slimane()
@@ -17,6 +19,58 @@ func launchApp() throws {
         }
     }
     
+    app.post("/") { req, responder in
+        switch req.body {
+        case let .buffer(d):
+            for message in ReceivedMessage.parseAll(json: d) {
+                switch message.content {
+                case let textMessage as ReceivedTextMessageContent:
+                    // create a message for replying
+                    let sendingMessage = SendingMessage(
+                        toUsers: [textMessage.fromUser],
+                        toChannel: 1383378250, // fixed value
+                        eventType: .sendingMessage,
+                        content: SendingTextMessageContent(
+                            contentType: .text,
+                            toType: 1, // fixed value
+                            text: "Re: " + textMessage.text
+                        )
+                    )
+                    let serialized = sendingMessage.toJSONString()
+                    
+                    // send the message
+                    let uri = URI(scheme: "https", host: "trialbot-api.line.me", port: 443)
+                    do {
+                        let client = try HTTPSClient.Client(uri: uri)
+                        let headers: Headers = [
+                            "X-Line-ChannelID": LINE_CHANNEL_ID,
+                            "X-Line-ChannelSecret": LINE_CHANNEL_SECRET,
+                            "X-Line-Trusted-User-With-ACL": LINE_CHANNEL_MID,
+                            "Content-Type": "application/json; charset=UTF-8"
+                        ]
+                        let response = try client.send(
+                            method: .post,
+                            uri: "/v1/events",
+                            headers: headers,
+                            body: Data(serialized)
+                        )
+                    }
+                    catch {
+                        print("some errors occured")
+                    }
+                    break
+                default:
+                    print("received unsupported message")
+                    break
+                }
+            }
+        default:
+            print("received unsupported request")
+        }
+        responder {
+            Response(body: "OK")
+        }
+    }
 
     print("The server is listening at \(HOST):\(PORT)")
     try app.listen(host: HOST, port: PORT)

このコードでは主に以下の処理を行っています。

  1. /へのPOSTリクエストを受け付ける
  2. 受け取ったJSONデータをパースし、受信メッセージReceivedMessageの配列として受け取る
  3. メッセージコンテントがReceivedTextMessageContentであった場合、返信用メッセージSendingMessageを作成する
  • メッセージ本文は"Re: {受信メッセージ本文}"とする
  1. 3.で作成したメッセージをJSONデータとしてシリアライズする
  2. https://trialbot-api.line.me/v1/eventsに対して返信のためのリクエストを送信する

ここまでの手順を反映したものをGitHubで見る

Herokuへのデプロイ

下記のようにしてHeroku上のアプリケーションを作成します。

heroku create

次に、環境変数を設定します。${LINE_CHANNEL_ID}${LINE_CHANNEL_SECRET}${LINE_CHANNEL_MID} には実際にはLINE developersで確認した値を入れてください。

heroku config:set LINE_CHANNEL_ID=${LINE_CHANNEL_ID}
heroku config:set LINE_CHANNEL_SECRET=${LINE_CHANNEL_SECRET}
heroku config:set LINE_CHANNEL_MID=${LINE_CHANNEL_MID}

最後に下記のコマンドを実行するとDockerイメージのビルドとHerokuへのpushが行われます(数分かかります)。

heroku container:push web

これでデプロイは完了です。heroku openを実行するとデプロイしたアプリケーションがウェブブラウザで開きます。Welcome to Slimane!と表示されていればデプロイ成功です。

Botの設定と動作確認

LINE developersのチャンネル設定画面を開き、Callback URLにheroku openで開いたURIを入力します。この時、https://xxxxxxxx.herokuapp.com:443/のようにポート番号をつけた形にします。設定後、Verifyボタンを押してSuccess.と表示されれば設定完了です。

実際にLINEでチャンネルに対してメッセージを送ってみて、返信メッセージが返ってくれば成功です。

スクリーンショット

このチュートリアルでは、Slimaneプロジェクトの作成、ビルド、Dockerイメージのビルド、Herokuへのデプロイを学びました。

完成品をGitHubで見る

16
16
1

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
16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?