LoginSignup
2
6

More than 5 years have passed since last update.

インフラエンジニアだけどLINE Botを作りたい

Last updated at Posted at 2019-04-17

はじめに

お仕事的にはインフラエンジニアですが、昨今の技術の進歩からインフラエンジニアいらないんじゃない的なことを感じたり感じなかったりなので、インフラエンジニアでもある程度コードかけないとまずいとは思ってるけど、じゃいざ何作るの?って段階になるとなかなかアイデアで出ない人は多いのではないのでしょうか。

そんな人は簡単なLINE Botを作ってみるとこから初めて見たらいかがでしょうか?という記事です。

環境

何かしらでBotサーバーを用意しなければなりません。
選択肢としては、GASやHerokuなどが思いつくと思いますが、普段私がAWSしかいじってないのでAPI Gateway + Lambda(Ruby)をserverless frameworkでデプロイします。

普段AWSをいじってる人はこの構成でやることを是非オススメします

手順

ここからはLINE Botが定型文を返すまでの手順となります

1. LINE@アカウントの取得

まずは以下のリンクからLINE@アカウント(一般アカウント)を取得する必要があります。

一般アカウントとは?

「一般アカウント」は審査なしで作成できるアカウントです。
一般アカウントの作成後に認証済みアカウントを申し込むことも可能です。
ご利用可能なプランはお住まいの国によって異なります。

2. チャネルの作成

LINE@アカウントを作成したらチャネルを作成する必要があります。

チャネルとは?

チャネルは、LINEプラットフォームが提供する機能を、プロバイダーが開発するサービスで利用するための通信路です。LINEプラットフォームを利用するには、チャネルを作成し、サービスをチャネルに関連付けます。チャネルを作成するには、名前、説明文、およびアイコン画像が必要です。チャネルを作成すると、固有のチャネルIDが識別用に発行されます。

チャネル作成の詳細な手順は以下の通りです。

2-1. LINEアカウントでLINE Developersコンソールにログイン

2-2. 開発者として登録する(初回ログイン時のみ)

2-3. 新規プロバイダーを作成する

2-4. チャネルの作成

このとき以下のどちらかのプランを選ぶ必要がありますが、お遊びの範囲であればDeveloper Trialを選択してください。

Developer Trial

MessagingAPIを利用したBotを試すプランです。友だちとメッセージの送受信を行うことができます。
※追加可能友だち数は50人に制限されています。また、Developer Trialからプランの切り替えやプレミアムIDの購入はできません。

フリー

MessagingAPIを利用したBotを開発するプランです。友だちの人数に制限はありませんが、Push messagesを利用してBotから友だちにメッセージを送信することはできません。
※サービス拡張に向けプラン変更が可能です。

3. Botの作成

BotはServerless Frameworkを使って、API gatewayとLambda(ruby)で作成してみます。

serverless frameworkがインストールされている前提で進みますが、インストールからという方は以下を参照してインストールしてください。
https://serverless.com/framework/docs/providers/aws/guide/installation/

3-1. serverlessコマンドでテンプレート作成

$ serverless create --template aws-ruby --path line-bot-test

3-2. serverless.ymlの編集

とりあえず最低限としてこんな感じにしておきます

service: line-bot-test # NOTE: update this with your service name

provider:
  name: aws
  runtime: ruby2.5
  region: ap-northeast-1
  memorySize: 512
  timeout: 900

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: bot/hello
          method: get

3-3. デプロイ

$ serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: WARNING: Function hello has timeout of 900 seconds, however, it's attached to API Gateway so it's automatically limited to 30 seconds.
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service line-bot-test.zip file to S3 (686 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.......................
Serverless: Stack update finished...
Service Information
service: line-bot-test
stage: dev
region: ap-northeast-1
stack: line-bot-test-dev
resources: 11
api keys:
  None
endpoints:
  GET - https://xxxxxx/dev/bot/hello
functions:
  hello: line-bot-test-dev-hello
layers:
  None

とりあえずAPI GatewayとLambda関数がデプロイされました。

4. LINE Developersコンソールからボットを設定する

4-1. チャンネルアクセストークンを発行する

コンソール画面上はChannel Secretのことでコンソール上からこれを発行します。

チャネルアクセストークンとは?

チャネルアクセストークンは長期間有効なアクセストークンで、APIを呼び出すときにAuthorizationヘッダーに設定する必要があります。チャネルアクセストークンはいつでもコンソールで再発行できます。

4-2. Webhook URLを設定する

先ほど作ったAPI gatewayのURLをWebhook URLとして設定します。

Webhook URLとは?

Webhook URLはボットアプリケーションのサーバーのエンドポイントで、Webhookペイロードの送信先です。

コンソール上から接続確認をすると...

スクリーンショット 2019-04-12 22.15.06.png

原因はAPI Gateway側のメソッドがGETになっていることでした...

よくよく考えたらPOSTですよね...

API Gateway側のメソッドをPOSTに直して再デプロイ

$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service line-bot-test.zip file to S3 (686 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...................
Serverless: Stack update finished...
Service Information
service: line-bot-test
stage: dev
region: ap-northeast-1
stack: line-bot-test-dev
resources: 11
api keys:
  None
endpoints:
  POST - https://xxxxxxx/dev/bot/hello
functions:
  hello: line-bot-test-dev-hello
layers:
  None

再度、接続確認

今後はうまくいきました!!

スクリーンショット 2019-04-12 22.23.50.png

これで一旦LINEからBotにメッセージを送ってみます

Image from iOS.png

こんな感じで変なメッセージが返ってきちゃいます...

これはチャネル基本設定 > LINE@基本機能の利用 > 自動応答メッセージを利用しないにする必要があるそうです

スクリーンショット 2019-04-13 0.56.06.png

自動応答メッセージを利用しないにしたので再度試してみます

Image from iOS 2.png

とりあえず自動応答メッセージはなくなりました

5. Lambda関数の作成

Lambda関数がserverless createコマンドで作られたものままなのでちゃんと返信するようにしてきます

とりあえずLINEからどんなリクエストが来るかeventの中身を見てみます

{
    "resource": "/bot/hello",
=================途中省略=================
    "body": "{\"events\":[{\"type\":\"message\",\"replyToken\":\"7e36bf04b9104b26b11b0a2a7df2336c\",\"source\":{\"userId\":\"xxxxccccc\",\"type\":\"user\"},\"timestamp\":1555321188152,\"message\":{\"type\":\"text\",\"id\":\"9697231865658\",\"text\":\"\"}}],\"destination\":\"xxxxxxxx\"}",
    "isBase64Encoded": false
}

肝心なのはbody部分のみです

bodyのみ抽出

{
  "body": "{\"events\":[{\"type\":\"message\",\"replyToken\":\"7e36bf04b9104b26b11b0a2a7df2336c\",\"source\":{\"userId\":\"xxxxxxxx\",\"type\":\"user\"},\"timestamp\":1555321188152,\"message\":{\"type\":\"text\",\"id\":\"9697231865658\",\"text\":\"\"}}],\"destination\":\"xxxxxxx\"}"
}

メッセージイベントの詳細は以下にあります
https://developers.line.biz/ja/reference/messaging-api/#message-event

rubyなのでnet/httpで対応することも可能ですが、LINE公式のline-bot-sdk-rubyが存在することのでこちらを使ってみたいと思います。

def client
  @client ||= Line::Bot::Client.new { |config|
    config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
    config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
  }
end

こんな感じでなんか簡単に作れそうなのでnet/httpでやるより良さそうです

channel_secretchannel_tokenって??

channel_secretとは?

これはLINE Developersコンソールのチャネル基本設定 > 基本情報 > Channel Secret  
から確認出来ます

channel_tokenとは?

これは2種類あるようです。

注:この方法では、30日間有効な短期のチャネルアクセストークンが発行されます。長期のチャネルアクセストークンを発行するには、コンソールにある[再発行]ボタンを使います。長期のアクセストークンは、アカウントの種類やプランによってはご利用いただけません。

長期的なものと短期的なものがあります。

短期的なものはLINE messageing APIにアクセスして発行してもらえます。

長期的なものはLINE Developersコンソールのチャネル基本設定 > メッセージ送受信設定 > アクセストークン(ロングターム)から発行することが出来ます。

channel_secretとchannel_tokenはLambdaの環境変数として設定したいのですが、serverless.ymlに書いちゃうとgithubのリポジトリに残ってしまうのでどうしましょ?
※githubのパブリックリポジトリを使ってる前提です

serverless.yml内で秘匿情報を扱う方法

serverless.yml内で環境変数を参照することが出来ます。
今回はこの方法でいきます。
https://serverless.com/framework/docs/providers/aws/guide/variables/#referencing-environment-variables

こんな感じで使えます。

service: new-service
provider: aws
functions:
  hello:
    name: ${env:FUNC_PREFIX}-hello
    handler: handler.hello

Lambdaのrubyランタイムでgemを使う方法

色々方法はあるかと思いますが、serverless-ruby-packageというserverlessのプラグインを見つけたのでこれを利用したいと思います。

使い方はREADMEを読めば簡単です。

注意点はローカルのrubyのバージョンをLambdaに合わせて2.5.0にしておいてください。
もしくはdockerを使ってgemをインストールするのもありです。

むしろdockerを使ってgemをインストールすることをオススメします。

なぜrubyのバージョンを2.5.0にする必要があるかはvendor/bundle/bundler/setup.rbを見るとわかります

定型文を返すようにする

ほとんどLINE公式のline-bot-sdk-rubyのサンプルのままですが、以下のようなLambda関数で定型文が返ってくるようになりました

load "vendor/bundle/bundler/setup.rb"

require 'json'
require 'line/bot'

def hello(event:, context:)
  message = {
    type: 'text',
    text: 'hello'
  }

  client = Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
  }

  body = event["body"]
  requests = client.parse_events_from(body)
  requests.each do |req|
    case req
    when Line::Bot::Event::Message
      case req.type
      when Line::Bot::Event::MessageType::Text
        response = client.reply_message(req['replyToken'], message)
        p response
      end
    end
  end
end

LINEから試してみるとこんな感じです。

Image from iOS (1).png

とりあえず定型文を返すとこまでいけました。

まとめ

インフラエンジニアだけどコードを書きたいということでしたが、serverless frameworkとの格闘がほとんどでした...

なのでここから役に立つBotとして進化させて、この続編として記事を書きたいと思います。

2
6
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
2
6