LINEチャットボットをNodeJSとExpressで
NodeJSとExpressでメッセージをオウム返しするLINEのチャットボットを作ってみた。
Expressについては以下参照。
LINE部分は LINE@ と Messaging API を使用した。
作成手順
$ express express-sample --view=pug --git $ cd line-chatbot && npm install $ npm install request crypto --save $ mkdir config $ touch config/config.json
Viewはなんでもいいが、デフォルトは嫌なのでとりあえす指定してみた。
以下をそれぞれ後述の通り編集する。
routes/index.js
config/config.json
routes/index.js
config/config.json
実行
$ npm start
https
でWebサーバか何かを立てて、 http://[FQDN]:3000/
へプロキシさせる。
その後、LINEアカウントの Messaging API へ上記のWebサーバのエンドポントを Webhook URL として登録する。
ちょっと解説
LINEのMessage APIのAPI Referenceはここ。
LINEに限らずWebhookに対応するアプリケーションを作成する際には、そのWebhookのサービスに合わせたインターフェースで開発する必要がある。
ここでは以下について記載する。
- Webhook リクエスト
- エンドユーザからメッセージを受信した際、LINE側のサーバから送信されるHTTPリクエスト
- Reply message リクエスト
- Webhook リクエストを受け、メッセージを返却する場合にLINE側のサーバへ送信するHTTPリクエスト
Webhook リクエスト
{ "events": [ { "replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "type": "message", "timestamp": 1462629479859, "source": { "type": "user", "userId": "U206d25c2ea6bd87c17655609a1c37cb8" }, "message": { "id": "325708", "type": "text", "text": "Hello, world" } } ] }
X-Line-Signature:{Signature}
- リクエストの送信元がLINEであることを確認するために署名検証するためのもの
- ヘッダの値と、request body と Channel secret から計算した signature が同じものであることをリクエストごとに 必ず検証必要がある
- Channel secretを秘密鍵として、HMAC-SHA256アルゴリズムによりrequest bodyのダイジェスト値を得る。
- ダイジェスト値をBASE64エンコードした文字列が、request headerに付与されたsignatureと一致することを確認する。
Reply message リクエスト
{ "replyToken":"nHuyWiB7yP5Zw52FIkcQobQuGDXCTA", "messages":[ { "type":"text", "text":"Hello, user" }, { "type":"text", "text":"May I help you?" } ] }
replyToken
にWebhookで送られてきたボディの events[].replyToken
を付与する必要がある。
messages
の配列で複数のメッセージを返却することができる。
また、ヘッダへ以下を付与する。
Content-Type:application/json
Authorization: Bearer {ENTER_ACCESS_TOKEN}
{ENTER_ACCESS_TOKEN}
に Channel Access Token を付与する
Spring Security / Spring Session入門
Spring Securityは認証・認可の機能を持つSpringのライブラリ。
Spring Sessionを用いて Redis にセッションを格納する設定も試してみる。
ここでは、簡単なログイン画面でログインする機能を作成する。
以下の構成で記載する。
- Java Configで設定する方法
- Springの設定をJavaベースで設定する方法
- XML Configで設定する方法
- Springの設定をXMLベースで設定する方法
- 共通作成物
- Java Config、XML Configによらない共通の作成物
また、ここで紹介の作成物については以下参照のアプリケーションに対して、Thymeleaf画面・Spring Securityによる認証・Spring SessionによるRedisセッション管理機能を追加する。
Java Configで設定する方法
pom.xml
org.springframework.boot:spring-boot-starter-security
を使用しているのがポイント
com.pepese.sample.config.WebSecurityConfig
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
を継承し、@EnableWebSecurity
アノテーションを付与するconfigure
メソッドの引数により設定対象を変更できるconfigureGlobal
メソッドで認証処理ロジックのサービスクラスをSpring Securityの認証マネージャに設定している
com.pepese.sample.config.SessionConfig
- クラスに
@EnableRedisHttpSession
アノテーションを付与するとSpring Sessionの設定はほぼ完了 connectionFactory
メソッドで Redis へセッションを格納する設定- ホスト名やポートは
application.properties
に設定する
XML Configで設定する方法
pom.xml
spring-mvc.xml
ThymeleafのView Resolverを設定。
spring-security.xml
<sec:http pattern="/resources/**" security="none" />
- Spring Session処理対象外の設定
<sec:http>
- 認証周りの設定
- ユーザ認証処理ロジックのサービスクラス(
UserDetailsServiceImpl
)のBean定義 <sec:authentication-manager>
UserDetailsServiceImpl
を認証マネージャに登録
spring-session.xml
RedisHttpSessionConfiguration
のBean定義でSpring Sessionの設定LettuceConnectionFactory
のBean定義でRedis接続の設定
web.xml
contextConfigLocation
にspring-security.xml
、spring-session.xml
を追加。- Spring Securityの設定として
springSecurityFilterChain
という名前でorg.springframework.web.filter.DelegatingFilterProxy
をFilter定義しているのがポイント。 - Spring Sessionの設定として
springSessionRepositoryFilter
という名前でorg.springframework.web.filter.DelegatingFilterProxy
をFilter定義しているのがポイント。- さらに Spring SecurityのFilter定義より上 に設定する必要がある
共通作成物
com.pepese.sample.model.User
- 認証するユーザクラス
- パスワードを固定にしているのはサンプルなので
com.pepese.sample.service.security.UserDetails
- Spring Securityが提供するユーザ認証用のクラス(
org.springframework.security.core.userdetails.User
)を継承して作成 - 自作のUserクラスを認証対象のクラスとして設定する
com.pepese.sample.service.security.UserDetailsServiceImpl
- Spring Securityが提供するユーザ認証用サービスクラス(
org.springframework.security.core.userdetails.UserDetailsService
)を継承して作成 - 本来なら認証対象のユーザデータをDBなどから取得して突合するが、サンプルということで new してる
application.properties
com.pepese.sample.controller.HelloController
@AuthenticationPrincipal
でログイン済みのユーザ情報を取得できる- なお、
/logout
のパス・ロジックは Spring Security にてもつ
index.html
Viewは、Java Configの場合は resources/templates
配下、XML Configの場合は WEB-INF/templates
配下に配置する。
login.html
error.html
JenkinsでMavenレポートを出力する
JenkinsでMavenレポートを出力する。
MavenとJenkinsを使ってJavaのレポート出力をやってみた。
下記を読んだテイで書く。
Maven
mvn clean test site
をたたいてHTML形式のレポートを出力する親POMを下記に作った。
親POM
※2017年2月17日時点での最新バージョンにしている。
※ javancss-maven-plugin
はJava8未対応だったためコメントアウト。
プラグインの概要
reporting
タグの部分だけ記載する。
org.apache.maven.plugins:maven-site-plugin
mvn site
コマンドの実装- 以下の「Project Information」を出力する
Dependencies
:依存ライブラリの一覧Dependency Convergence
:同一依存ライブラリの全てのバージョンを集約して表示Dependency Information
:このプロジェクトの依存の書き方Dependency Management
:最終的に適用される依存ライブラリの一覧Distribution Management
:配布するリポジトリの情報About
:POMのdescriptionの記載Plugin Management
:最終的に適用されるプラグインの一覧Project Plugins
:buildおよびreportingに使用されるプラグインの一覧Project Summary
:プロジェクト情報のサマリ
org.apache.maven.plugins:maven-javadoc-plugin
Project Reports
の「JavaDocs」および「Test JavaDocs」を出力する
org.apache.maven.plugins:maven-surefire-report-plugin
Project Reports
の「Surefire Report」を出力する- テストの件数、エラー数、失敗数等を出力する
org.apache.maven.plugins:maven-jxr-plugin
Project Reports
の「Source Xref」および「Test Source Xref」を出力する- JavaソースコードをHTML形式で出力する
org.apache.maven.plugins:maven-pmd-plugin
Project Reports
の「PMD」を出力する- PMDはJavaコードを分析して潜在的なバグを探すツール
org.apache.maven.plugins:javancss-maven-plugin
Project Reports
の「JavaNCSS」を出力する- JavaNCSSはJavaコードの品質や複雑度に関するメトリクスを出力する
org.jacoco:jacoco-maven-plugin
Project Reports
の「JaCoCo」を出力する- JaCoCo による単体試験のカバレッジ測定結果
org.apache.maven.plugins:maven-checkstyle-plugin
Project Reports
の「Checkstyle」を出力する
org.codehaus.mojo:findbugs-maven-plugin
Project Reports
の「FindBugs」を出力する
org.apache.maven.plugins:maven-project-info-reports-plugin
- プロジェクトの情報を出力する
- cim、help、issue-tracking、license等
- プロジェクトの情報を出力する
以上の情報がHTML形式で target/site
配下へ出力される。
testFailureIgnore
について
親POMのbuild⇒plugins⇒pluginのmaven-surefire-pluginの設定で testFailureIgnore
を true にするとテストでコケてもレポート出力するようになる。
と、同時に mvn test
でコケてもSUCCESS となってしまう。
こうなってくると、Jenkinsで DailyTestで失敗しても気づかない ことになってしまう。
なので、 testFailureIgnore
はPOMで設定せず、以下のようにするといい。
- JenkinsによるDailyTest
mvn test -Dmaven.test.failure.ignore=false
- これでテストでコケたら FAILURE になる(ちなみにデフォルトfalse)
- Jenkinsによるレポート出力
mvn clean test site -Dmaven.test.failure.ignore=true
- これでテストでコケても SUCCESS になり、レポートが出力される
Jenkins
Jenkinsのジョブで mvn clean test site
をした後、Jenkinsの HTML Publisher Plugin
で下記のように設定すればJenkinsのジョブのページにSiteで出力したレポートへのリンクが作成される。
Publish HTML reports
:チェックボックスをオン- HTML directory to archive
- 例)
target/site/
- 例)
- Index page[s]
- 例)
index.html
- 例)
- Report title
- 例)
HTML Report
- 例)
- HTML directory to archive
レポートの表示が崩れている(CSS/JSが適用されていない様子)場合は下記を参照。
また、今回Mavenで出力しなかったJavaコード解析情報について、下記のJenkinsプラグインを使用するとカバーできる。
- DRY Plugin
- コピペコードのような重複したコードをチェックしてくれる
- Task Scanner Plugin
- ソースコードを任意の文字列で検索するチェックをかけることができる
- FIXME、TODO、XXX、deprecated、System.out.printlnとかスキャンしてくれる
- ソースコードを任意の文字列で検索するチェックをかけることができる
- Warnings Plugin
- コンパイラの警告をチェックしてくれる
- Step Counter Plugin
- ファイル行数をカウントしてくれる