LoginSignup
14
12

More than 5 years have passed since last update.

Vapor + LINE Messaging API で Bot を開発する

Posted at

LINE Messaging APIが公開されて、面白そうだったので Swift Server Side Framework 「Vapor」 を使って実装してみました。

環境

  • Sakura VPS Ubuntu 14.04
  • Swift 3.0 Release
  • Vapor 1.0.3
  • Apache 2.4

LINE@の管理画面の使い方やMessaging APIの設定等については説明しません。
この記事では、Vaporを使ったBotアプリケーションの開発方法を紹介します。

とりあえず、送られてきたメッセージをそのまま返すだけのBotを作ってみましょう。

Vaporの基本的な使い方は https://vapor.codes/ を参照してください。

証明書の準備

Messaging API を 使用するサーバーはHTTPSに対応していないといけないっぽいので、Let's Encrypt等を使って証明書をサクッと準備します。Vaporはherokuへのデプロイも簡単にできるのでherokuでも良いでしょう。とりあえず私は、テキトーなVPSにテキトーなドメインとって証明書を発行してもらいました。

VaporのSSL周りの仕様がよくわからないのでとりあえずApacheのリバースプロキシでどうにかしました。

Vapor アプリケーションの作成

開発する環境はmacOSでもUbuntuでも良いですが、Xcodeが使えると便利なのでmacOSがオススメです。また、Swift Package Managerのプロジェクト構成も自分でやると面倒臭いのでVaporのToolboxを使用することをオススメします。

Vapor Toolbox の導入

$ vapor new LineBot #SPMプロジェクト作成
$ cd LineBot
$ vapor xcode #Xcodeプロジェクト生成

webhookのハンドリング

Botへのイベントを受け取る先の実装をします。URLは何でも良いですが私は以下のようにしました。

drop.post("/callback"){ request in
// イベントを見て色々してレスポンス返す
}

送られてくるデータは「Webhook Event Object」というもので、https://devdocs.line.me/ja/#webhook-event-object に詳細なデータ構造が書かれています。

あまり詳しく見ていないですが、とりあえずはmessageのtextとreplyTokenさえ分かれば返信できそうなので取り出します。細かくイベントを判断して処理したいという場合は、ここのロジックをもう少し変える必要があります。

guard let object = req.data["events"]?.array?.first?.object else{
    return Response(status: .ok, body: "this message is not supported")
}

guard let message = object["message"]?.object?["text"]?.string, let replyToken = object["replyToken"]?.string else{
    return Response(status: .ok, body: "this message is not supported")
}

こんな感じ(もっと良い取り出し方ないですかね)

あとは、取り出したmessageとreplyTokenをAPIに投げるだけです。

Reply Message API を使う

次に Reply Message API を使って返信してみます。APIを使用するためには「Channel Access Token」が必要になるので取得しておきましょう。

Vapor Toolkitでプロジェクトを作成した場合、「Config/secrets」が.gitignoreに追加されているはずなのでsecretsディレクトリに「Channel Access Token」を記述したjsonファイルを配置してアプリケーションから取得すると良いでしょう。取得方法は、

let accessToken = drop.config["line_config", "access_token"]?.string 

こんな感じです。

あとはAPIを呼ぶだけです。

let endpoint = "https://api.line.me/v2/bot/message/reply"

var request = URLRequest(url: URL(string: endpoint)!)

request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

let payload: [String: Any] = [
    "replyToken": replyToken,
    "messages": [
            ["type": "text", "text": message]
     ]
]

request.httpBody = try? JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted)

あとはこのリクエストをURLSessionに投げれば・・・と思ったのですが、UbuntuでURLSessionを使うと何故か正しく機能しないので(corelib-foundationのバグですかね?)、実際にはcurlをTask(Process)を使って叩くようにしています。Dropletのclientを使ってPOSTしてもダメだったのでよく分からない。

Bot と遊ぶ

友達に追加して、話しかけてみましょう。同じ内容のメッセージが返信されるはずです。

ソースコード

処理を色々整理したものをGithubにて公開しています。

https://github.com/rb-de0/vapor-linebot

14
12
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
14
12