LoginSignup
2

More than 5 years have passed since last update.

Akka HTTP で LINE bot を作ってみました

Last updated at Posted at 2016-12-26

こんにちは、Xiaoです。

最近Akka HTTPの正式版 X がで出ましたね。
自分は前からAkka HTTPに興味があって、ちょうどいい機会なので、Akka HTTPを詳しく勉強するため、簡単のWebサービスを作ってみたいと思います。

LINE Bot とは

LINE が提供する Messaging API により、LINEのトーク画面を使った対話型Botアプリケーションの開発が可能になります。

図

※ Image taken from developers.line.me

この図を説明すると、

  • サーバのURLを LINE Bot にするアカウントと繋ぎます。
  • ユーザがBotに対して、友たち追加、メッセージ送信などを行う際に、設定されたサーバにイベント情報が送られます。
  • サーバがイベント情報を基づいて、LINE Messaging API経由でユーザに返信できます。

※ LINE アカウントの設定について、LINEの公式ドキュメントに記載されているので、割愛します。

Akka HTTPについて

Akka HTTP は Akka Actor と Akka Stream をベースに作られた、HTTPサーバ/クライエント処理をサポートするためのツール、ライブラリです(フレームワークではありません!)。

LINE botを作るには、Akka HTTP みたいなツールが丁度良いと思います。

今回で作る Bot

今回は Akka HTTP の特性の紹介するため、一番シンプルな「受けたメッセージをそのまま返す」Botを例にして、Akka HTTP の特性を幾つか紹介したいと思います。

  • JSON を変換する ((un)Marshalling)
  • HTTP request を処理する
  • HTTP request を送る

最終のコードは こちら でたどり着けます。

TL;DR

JSON を変換する ((un)Marshalling)

LINE Messaging API とのやりとりは全部JSONを扱っています。これに対して、Akka HTTP の特徴の一つは、(un)Marshalling 機構によって、JSON、 XML或いはバイナリデータを簡単サポート出来ます。

◆ spray-jsonモジュールを使ため、Dependencyに"akka-http-spray-json"を追加。

"com.typesafe.akka" %% "akka-http-spray-json" % "10.0.0"

◆ 次は、スコープ内に RootJsonFormat[T] を用意する。

  • Case Class がある場合、要素の数に応じて、jsonFormatX メソッドを使えばいいです。
  • それ以外の場合、RootJsonFormat[T] を実装する必要があります。

※ 詳しい説明は spray-json を参照ください。

◆ 最後、Marshalling と Unmarshalling 機構を使うため、SprayJsonSupport を導入する。

Reply Message API のRequestをJSONに変換したい場合は、こんな感じです。

case class TextMessage(`type`: String = "text", text: String)

case class Messages(replyToken: String, messages: List[TextMessage])

trait MessagesJsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val textMessageFormat = jsonFormat2(TextMessage)
  implicit val messageFormat = jsonFormat2(Messages)
}

HTTP requestを処理する

ユーザがBotに対して、友たち追加、メッセージ送信などを行う際に、設定されたサーバにイベント情報が送られます。
HTTP サービスをシンプルに実装出来るため、Akka HTTP は High Level Routing DSL を提供しています。

こんな感じで使います。

def routes: Route = {
  path("line" / "callback") {
    (post & entity(as[Events])) { request =>

      ...

      complete {
        "OK"
      }
    }
  }
}

見た目の通り、今回は以下のDSLを使いました。

  • path("line" / "callback") はサービスのエンドポイントURLです。
  • (post & entity(as[Events])) は POST メソッドをマッチし、Requestデータを Events に変換します。
  • complete は処理成功を表します。

※ 詳しい説明は High-level Server-Side API を参照ください。

関連するコードは こちら で参照できます。

HTTP request を送る

ユーザに返信する場合、LINE の Reply Message API を経由で実現します。

Akka HTTPでは、こんな感じで書けます。

val auth = headers.Authorization(OAuth2BearerToken(accessToken))
val content = Messages(
  replyToken = token,
  messages = List(TextMessage(text = message))
)

val request = RequestBuilding.Post(
  uri = "https://api.line.me/v2/bot/message/reply",
  content = content
).withHeaders(auth)

val responseFuture: Future[HttpResponse] = Http().singleRequest(request)
  • Akka HTTPは、Authorization 機構を通じで、OAuth認証などをサポートしています。
  • RequestBuilding を使って、Requestを作成していますが、HttpRequest を直接実装するのもできる。
  • HTTPコネクションを管理したくない場合、一番簡単な Http().singleRequest を使います。

※ 詳しい説明は Consuming HTTP-based Services (Client-Side) を参照ください。

関連するコードは こちら で参照できます。

まとめ

今回はテキストベースのBotに必要のものを紹介しました。

後は、DBやAkka Presistenceを使えば、情報を保持出来るBotを作れるし、他の 3rd Party API に繋げば、いろんなサービスを提供することが出来ます。

本記事はSepteni Engineer's Blogの転載です。
http://labs.septeni.co.jp/entry/2016/12/26/120625

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
2