627
620

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 1 year has passed since last update.

1時間でLINE Botを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest

Last updated at Posted at 2017-11-26

last updated 2023/6/04

記事アップデート履歴
  • 2018/3/14 ngrokのインストールをnpm経由に変更
  • 2018/8/28 本体のディベロッパー画面が更新されてるので変更
  • 2018/11/24 nowのバージョンアップに伴ってnow.jsonの記述を追加
  • 2019/5/14 LINE@アカウントのLINE公式アカウントへの統合に伴ったフロー変更などを適用、事例に市川市追加、nowのデプロイ方法の更新
  • 2019/6/11 疎通確認でエラーが出るのは問題ないですが、そこで接続できないと問い合わせが多いためserver.jsに疎通確認用のコードを追加。
  • 2019/6/14 nowをv2に対応
  • 2019/7/31 ngrokでのトンネリング箇所をserveoにも対応
  • 2019/8/24 Webhookの設定方法を公式アカウントマネージャー側へ
  • 2020/4/4 nowのデプロイ手順更新、サンプルコード更新
  • 2020/5/22 デプロイの部分をVercelに変更かつ、外部記事へ
  • 2020/6/14 天気APIのコードを微修正
  • 2021/6/14 ライブドアの天気APIの箇所を互換APIに変更
  • 2022/10/01 LINE DevelopersのUI変更に追従
  • 2023/6/4 サンプルコードにエラー出力部分を追加
  • 2023/9/1 LINE Bot管理画面のWebhook検証ボタンの処理を変更(削除)

この資料について

  • この資料をハンズオンなどに活用してNode.js普及を促進させてもらえたら幸いです。
    • 使うときにコメント欄にコメント貰えると嬉しいです!
    • ハンズオン進めてみた感想などもコメント貰えると嬉しいです!
  • 会の流れとしてはハンズオン -> もくもく会 -> (可能な人は)もくもく会で作ったBOTを発表という流れです。
  • どこまでやるか
    • 手元で確認するだけであればSTEP3まででOK
    • ホスティングしてハンズオン後も使いたいならSTEP4まで


はじめに

  • 対象者: Node.js初心者向け
  • 目的: LINE BOTを作ってNode.jsに触れる
  • ゴール目標: LINE BOTを作ってデプロイする
  • 性質上、Node.js以外の話の方が多いかも
  • 1Hしかないのでコード理解よりも動くものを
  • 早く終わった人はもくもくタイム

自己紹介


LINE Bot

  • LINE上で動作するBOT
  • 様々なプログラムと連携させることができる
  • LINE自体のユーザー数が多いことで、追加でアプリインストールがほぼ不要なことが利点
  • LINEがUIになるのでUIを考える手間が少なく、サーバーサイドエンジニア的に嬉しい

事例: みずほ、出前館


事例: ヤマト運輸


行政事例: 市川市


LINE Messaging API

LINE BOTを作るためのAPIです。

Messaging APIを利用することで、あなたのサービスをLINEのトークルーム上で提供することができます。
LINEユーザー一人一人に合わせたユーザー体験を提供できます。


スクリーンショット 2017-02-05 9.10.01.png


Push APIとReply API

スクリーンショット 2017-02-05 9.09.22.png

基本的にPushとReplyの二つのAPIがあります。

PushはBotアプリケーション側が起点となってユーザーにアクションします。
Replyはユーザーの発言を起点としてBotアプリケーションを呼び出します。


作ってみよう


1. Botアカウントを作成する

LINEのBotはTwitterなどと違い、通常のユーザーのアカウントをBot化することは出来ず、専用のアカウントを作る必要があります。


LINEディベロッパーサイトへログイン

まずはLINE developersのサイトにアクセスし、ログインしましょう。

スクリーンショット 2022-09-25.png

LINEアカウントでのログインを求められます。メールアドレスとパスワードもしくはQRコードでログインできます。ログインできない場合はLINEのスマートフォンアプリ側で設定を確認しましょう。

設定がまだの方はLINEのスマートフォンアプリ画面から 設定>アカウントでメールアドレスを設定できます。
LINEでメールアドレスを新規登録・確認・変更・登録解除(削除)する方法


プロバイダーの作成

ログインしたらプロバイダーの作成を行います。プロバイダーは自分が作るLINE BOTなどの開発者名やチーム名、企業名になります。初回だけディベロッパー登録で個人情報を聞かれると思うので回答してから進めましょう。

スクリーンショット 2022-09-25.png

新規プロバイダー作成ボタンを押して進み、プロバイダー名を入力して進めましょう。

スクリーンショット 2022-09-25.png


Messaging APIの新規チャンネルを作成

チャンネルを作成します。今回はLINE BOTを作るMessaging APIを選択します。

スクリーンショット 2022-09-25.png

Messaging API を選択しましょう。


BOTの情報入力

BOTの情報を入力していきます。

スクリーンショット 2022-09-25.png

項目 説明
チャネルの種類(必須) 変更不要です
プロバイダー(必須) 変更不要です
会社・事業者の所在国・地域(必須) 自分のいる国や地域を選択します
チャネルアイコン BOTのアイコンになる画像を選びましょう。
チャネル名(必須) BOTの名前を入力しましょう。LINEという文字列は使えなかった気がします。
チャネル説明(必須) BOTの説明を入力しましょう。取り急ぎは適当でも大丈夫
メールアドレス(必須) BOTの開発者にLINE側からお知らせがあるときに受け取るメールアドレス
大業種/小業種(必須) BOTのカテゴリを選択します。取り急ぎは適当でも大丈夫。
プライバシーポリシーURL/サービス利用規約URL(任意) 取り急ぎなくて大丈夫です

※昔はここでプラン設定(Developer Trial or FREE)をしていましたが、公式アカウントへの統合に伴って選択肢がなくなりました。

  • 規約を確認、チェックして「作成」

スクリーンショット 2022-09-25.png

  • 内容を確認して「OK」

スクリーンショット 2022-09-25.png

  • 規約を読んで「同意する」
    スクリーンショット 2022-09-25.png

BOTの設定確認

作ったBOTの設定画面が開かれます。

スクリーンショット 2022-09-25.png

「Message API設定」のタブを開き、「LINE公式アカウント機能設定」を変更します。

image.png

「編集」を押すとLINE公式アカウントマネージャーに遷移し、そちらで「応答設定」を選択します。
次のように設定を変更します。

  • あいさつメッセージ: オフ
  • 応答メッセージ: オフ
  • Webhook: オン

.png

変更は自動で保存されます。


BOTと友達になろう

LINE Developersのタブに戻り、画面上の方にあるLINEアプリへのQRコードを確認します。

image.png

ここで表示されるQRコードを使って、自分が作成したBotアカウントと友達になりましょう。

ここからはスマートフォン画面のキャプチャになります。

QRコードリーダーを開きBotを友達追加しましょう。

**「追加」**を選択します。

**「同意する」**を選択します。

Botが友達に追加されました。


2. Node.jsでBOT開発

ここからは手元のターミナルなどでの作業がメインになります。
Node.jsのインストールがまだの方は参考記事などをもとに準備をして下さい。


ちなみに、筆者の環境は以下になります。 (2019/5/14時点)

  • Node.js v12.2.0
  • npm v6.9.0
  • macOS Mojave 10.14

プロジェクトを作成とハローワールド

Node.jsのプロジェクトはpackage.jsonがあるディレクトリが起点となります。
まずはnpm initコマンドpackage.jsonを作成します。


$ mkdir mylinebot
$ cd mylinebot
$ npm init -y
Wrote to /Users/n0bisuke/dotstudio/2_events/20171125_nodefest/linebot/mylinebot/package.json:

{
  "name": "mylinebot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

次に依存モジュールを追加します。 今回はこちらのSDKを利用します。

ちなみに以前は公式のNode.js SDKが無かったので依存なしでも書いてました。

$ npm i @line/bot-sdk express

次にプログラムのメインとなるserver.jsをmylinebotフォルダ内に作成します。

  • Macだとtouchコマンド
$ touch server.js
  • windowsだとnulコマンド(らしい)
$ type nul > server.js

コマンドじゃなくてもエディタの新規作成などで大丈夫です。

ディレクトリ内は現状こんな感じです。 (Windowsの人はlsが使えないのでdirを使いましょう)

$ ls
server.js            node_modules      package-lock.json package.json

エディタでserver.jsを編集します。
以下をコピー&ペーストしましょう。

server.js
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: '作成したBOTのチャンネルシークレット',
    channelAccessToken: '作成したBOTのチャンネルアクセストークン'
};

const app = express();

app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result))
      .catch((err) => {
 	    console.error(err);
        res.status(500).end();
      });
});

const client = new line.Client(config);

async function handleEvent(event) {
	console.log(req.body.event);
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: event.message.text //実際に返信の言葉を入れる箇所
  });
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);

後ほどの書き換えに備えてfunction handleEvent()の箇所はasyncにしました。 (2020/4/4)


Channel Secretとアクセストークンの確認

先ほどの「LINE developers」の画面でチャネルシークレットチャネルアクセストークンを確認し、コピーしておきます。
この値は他の人に教えないよう注意しましょう。

  • 「チャネル基本設定」で チャネルシークレット確認
    image.png

  • 「Messaging API設定」でチャネルアクセストークン発行

「発行」を押すと次のように表示されます。

image.png


server.jsのソースコードのchannelAccessTokenchannelSecretの部分に、上でコピーしたチャネルアクセストークン、チャネルシークレットの値を指定しましょう。

アプリケーションを起動してみます。

$ node server.js

起動すると以下がターミナルに表示されることを確認しましょう。

Server running at 3000

↓↓↓↓↓↓↓ あなたの記事の内容
ここで問題なければブラウザで http://localhost:3000 にアクセスするとHello LINE BOT!と表示されると思います。
───────
ここで問題なければブラウザでhttp://localhost:3000にアクセスすると Hello LINE BOT!と表示されると思います。
↑↑↑↑↑↑↑ 編集リクエストの内容


3. ngrokでトンネリング


LINE Botを作るためにはWebhookURLをLINE developersに登録する必要があります。


この際SSLが必須になるのですが証明書取得などの手間もありますし、PaaSなどにホスティングして試すのはデバッグが大変なので、手元のPCのlocalhostにグローバルからアクセスできるようにするトンネリングツールを利用しましょう。

などが有名です。今回はngrokを利用します。


まずはngrokのサイトにいき、本体をダウンロードして解凍します。

この辺の手順を更新しました。(2018/3/14)

npm経由でngrokをインストールできます。

https://www.npmjs.com/package/ngrok

$ npm i -g ngrok

次にトンネリングサーバーを起動します。 ngrok http ポート名と指定します。
今回はNode.jsアプリケーションを3000番ポートで利用するので3000を指定しましょう。

$ ngrok http 3000

ngrok by @inconshreveable                                    (Ctrl+C to quit)

Session Status                online
Account                       n0bisuke (Plan: Free)
Version                       2.1.18
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://1148cbd9.ngrok.io -> localhost:3000
Forwarding                    https://1148cbd9.ngrok.io -> localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

起動すると表示されるhttps://で始まるアドレスを利用します。
この場合はhttps://1148cbd9.ngrok.ioです。このアドレスは起動の度に変わるため、ngrokは起動し続けて開発を行うことをおススメします。


以下のように、ngrokのプロセスとNode.jsアプリケーションのプロセスを並行して実行しての開発になります。


Webhook URLの更新

https://1148cbd9.ngrok.io/webhookがWebhook URLになります。

LINE developersに戻り、「Messaging API設定」のタブに移動して、Webhook URLを更新します。

image.png

ここに先ほどのアドレスを指定しましょう。 URLの末尾に/webhookをつけるのを忘れずに


この状態でBotに話しかけてみて下さい。

Botがおうむ返ししてくれます。

補足: serveoの利用 - ngrokのインストールがうまくいかない場合など

2019年7月頃、ngrokよりserveoがすごい。0秒で localhostを固定URLで公開
の記事がバズってました。

serveoでのやり方も紹介します。そのうちこの記事もngrokから差し替えるかもしれません。

ポリシー的にどうなん?みたいな会話もあるのでとりまこれくらいの追記で......笑

serveoはインストールなど不要です。利用したいドメイン名を指定してngrokを立ち上げるようにNode.jsのプロセスとは別タブや別ウィンドウを新規に立ち上げて以下を実行しましょう。

$ ssh -o ServerAliveInterval=60 -R <利用したいドメイン名>:80:localhost:<Node.jsなどのプログラムを立ち上げてるポート> serveo.net

例えばlocalhost:3000https://n0bisuke.serveo.netで利用したい。とかであれば以下のように実行します。

$ ssh -o ServerAliveInterval=60 -R n0bisuke:80:localhost:3000 serveo.net
Forwarding HTTP traffic from https://n0bisuke.serveo.net
Press g to start a GUI session and ctrl-c to quit.

あとは今回のプログラムだとhttps://n0bisuke.serveo.net/webhookをLINEの管理画面に設定すればOKです。


4. プログラムをデプロイして永続化する

ngrokだと、手元のパソコン上でプログラムが動作するため、パソコンを閉じると動作しなくなってしまいます。

永続的にLINE BOTを動かすために何かしらのサーバーにデプロイしましょう。

Vercelにデプロイ (2020/5/22更新)

今回は、Vercelを使ってみます。

Vercelとは

  • Node.js向けのPaaS / FaaS
    • RubyやGoなども使える
    • Docker対応した模様なのでかなり色々使える
  • 旧名称はnow.sh
  • CLIからコマンド一つでデプロイできる
  • Herokuなどよりもデプロイ手順が簡単

こちらの手順↓で進めてみましょう。

VercelでLINE BOTを動かす 2020年5月版


補足資料

補足内容です。

補足資料その1 - if文で条件分岐

  • event.message.textがユーザーから送られてきた文字列
  • こんにちはとBOTに送るとこんばんわの時間ですよと言われて、それ以外だとうざと返されるプログラムが以下になります。
  • client.replyMessage()でBOTのリプライになります。
server.js

省略


async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  let replyText = '';
  if(event.message.text === 'こんにちは'){
    replyText = 'こんばんわの時間ですよ';
  }else{
    replyText = 'うざ';
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: replyText
  });
}

省略



補足資料その2 - 天気APIを使う応用 (2021/6/14更新)

天気を教えてくれるBOTを作ってみましょう。

ライブドアの天気APIを利用してみます。

http://weather.livedoor.com/weather_hacks/webservice

ライブドアの天気APIが2020年7月にサービス終了してしまい、利用できなくなっていたのですが、互換APIを公開してくれている方がいました。こちらのAPIを利用してみましょう。

https://weather.tsukumijima.net/
livedoor 天気互換の天気予報 API をリリースした話

  • axiosのインストール

外部のAPIにアクセスするためにaxiosをmylinebotのプロジェクトにインストールします。

npm i axios
  • server.jsの冒頭箇所にconst axios = require('axios');を追記します。
server.js
'use strict';

const axios = require('axios'); //追記
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;



(省略)
  • server.jsの該当箇所(async function hendleEvent(){}の中)を書き換えます。
server.js


省略



async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  //"天気教えて"以外の場合は反応しない
  if(event.message.text !== '天気教えて') {
    return client.replyMessage(event.replyToken, {
      type: 'text',
      text: '"天気教えて"と言ってね'
    });
  }

  let replyText = '';
  replyText = 'ちょっと待ってね'; //"ちょっと待ってね"ってメッセージだけ先に処理
  await client.replyMessage(event.replyToken, {
      type: 'text',
      text: replyText
  });

  //axiosを使って天気APIにアクセス
  const CITY_ID = `400040`; //取得したい地域のIDを指定
      const URL = `https://weather.tsukumijima.net/api/forecast?city=${CITY_ID}`;
  const res = await axios.get(URL);
  const pushText = res.data.description.text;
  return client.pushMessage(event.source.userId, {
      type: 'text',
      text: pushText,
  });
}



省略


地域ごとのIDもライブドアのAPIで利用されていた値がそのまま使えるように作られてるAPIなのでドキュメントページを元に利用したい地域のIDを調べましょう。


補足資料その3 - スクレイピングと組み合わせる

APIが無いサイトでもスクレイピングすると情報を取得できます。
が、ご利用は自己責任でお願いします。

花粉ボットと実装サンプル


応用


応用回答例: Node.jsの最新を教えてくれるBOT 答え合わせ

  • Node.jsの最新バージョン教えて!と言われたらとりあえずちょっと待ってねとリプライメッセージ
  • https://nodejs.org/ja/ にスクレイピングしにいって、完了したらプッシュメッセージで教えてくれる
  • async/awaitでaxiosのHTTPリクエストとLINE MASSAGING APIへのリクエストを同期処理的に記述

axiosを追加インストール

npm i axios
server.js
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: '',
    channelAccessToken: ''
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  let mes = ''
  if(event.message.text === 'Node.jsの最新バージョン教えて!'){
    mes = 'ちょっとまってね'; //待ってねってメッセージだけ先に処理
    getNodeVer(event.source.userId); //スクレイピング処理が終わったらプッシュメッセージ
  }else{
    mes = event.message.text;
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: mes
  });
}

const getNodeVer = async (userId) => {
    const res = await axios.get('https://nodejs.org/ja/');
    const item = res.data;
    const version = item.match(/最新版"  data-version="(.*?)">/)[1]; //正規表現で(無理やり)取得
    console.log(version);

    await client.pushMessage(userId, {
        type: 'text',
        text: `今の最新は${version}だよ!`,
    });
}

app.listen(PORT);
console.log(`Server running at ${PORT}`);

レポート: 参加者の方々が作ったBOTを紹介(ハンズオン後に追記)

もくもくタイムは20min程度でしたが、皆さんすごいです。

1. Node.jsの最新バージョン+ヤフー検索ができるBOT

応用課題で出していたNode.jsのバージョンを教えてくれる機能もLTSと最新版の両方に対応してくれました。
スクレイピングの勢いでヤフー検索まで繋いでいます。

2. 調べたい単語を入れるとWikipediaの検索結果を返してくれるBOT

これめっちゃ便利です。
Wikipediaまでわざわざ調べに行かなくても色々な言葉の概要を知ることができます。

3. URLを入れると話題のdev.toとどっちが速いかを教えてくれるBOT

話題ですね。

dev.toと阿部寛のホームページについてちゃんと計測させてくれ

dev.toと入力したサイトのどちらが早いか計測してくれます。
トレンドを捉えるアイディアの柔軟性がすごい。

4. 今日のご飯何にするかを絵文字で提案してくれるBOT!

ご飯何にしようか迷いますよね。
絵文字で推薦してくれるのでもう迷わない......!

コード指定すればNode.jsからも絵文字扱えるんだよっていう良い例だと思います。

5. 何でも人に聞く人にググらせるBOT

**「調べる前になんでも人に聞く人を駆逐したい」**らしいです笑

検索ワードを入れるとググれってことでGoogleに飛ばされます。
ハンズオンで触れていないリッチメニューまで活用してくれました。

6. Polymerと会話?できるBOT

Polymerが好きすぎてPolymerちゃんと会話できるBOTを作ったそうです笑

7.検索ワードを入れるとunsplash.comから画像を取得してくるBOT

画像検索も出て来ました。
画像扱えるとビジュアルが圧倒的に良くなりますね。


まとめと所感

Node.jsとNowを使うと爆速でLINE BOTを作れますし、細かいものを作るときにこの組み合わせはかなり使えます。 (デバッグの際はngrokがおすすめ)

応用してどんどん開発していきましょう。

見て回った限り、大半の人がデプロイまでたどり着くことができて、7人もオリジナルBOTを作って発表までできるのはさすがの学園祭的なレベルの高さを感じます。

時間内に終わらなかった人もこの記事を見直してチャレンジしてもらえたら幸いです。

参加してくださった皆さんありがとうございました!

627
620
11

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
627
620

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?