LoginSignup
4
4

More than 5 years have passed since last update.

NodeJS + Expressを使ったLINE bot 開発入門(小高産業技術高校 プログラミング講座)

Last updated at Posted at 2017-06-06
1 / 46

この資料について

この資料はおもに小高産業技術高校の授業を目的に作成していますが、外部の方にも参考にしてもらえるように書いている(つもり)です。
何か不備や足りない情報などありましたら、修正・対応しますのでお気軽にコメントください。


この講座の目的

  • アプリケーションの開発を通じて、プログラミングの楽しさを学ぶこと
  • 実際につくったアプリケーションが、小さくていいから自分たちの身の回りのことや周りの人の役に立つこと
  • プログラミングを通して、「課題解決」をするトレーニングをしてもらうこと

全体の流れ(15回程度)

  • とりあえず言われるままにLINE Bot をつくってみる
  • 企画を考える
  • 自分のアイデアで作りこむ

=> できれば次の年代に継承し、どんどん拡張していくことで、汎用的な小高のナビゲーターアプリを作ることを目標にしている!!


この講座の当初目標(4-5回)

「LINE Botをつくってみよう」

  • 今の学校の授業の延長線上でつくれる
  • すぐに完成品が見える
  • 既存のアプリなのでわざわざインストールしてもらわなくても使える(=普及しやすい)
  • 知らない人からみたらそれっぽくみえる←大事!

開発のおおまかな流れ

  • Web上で返信してくれる
  • LINEにとりあえずつないでみる
  • いろいろ言わせてみる

早速動かしてみる

残念ながら学校のPCだといろいろ不便なので、開発用PCを使用する(と思う)


  • USBメモリから一式を個人用フォルダにダウンロード
  • nodejs/start.cmdを実行してみよう
  • DOS窓が立ち上がったら以下のコマンドを実行
cmd
npm init --save

色々聞かれるので次のように

- name : odk2017
- version : 0.0.0
- description : line bot application
- entry_point : index.js
- test_command: test
- git_repository: (空白のままenter)
- keywords : (空白のままenter)
- author : 自分の名前(e.g. Takashi MORIYAMA)
- lisense : MIT

確認

src/以下にpackage.jsonというファイルができていれば成功
引き続き以下のコマンドを打ってみよう

cmd
npm install express --save

image.png


image.png


エラーが出た!

  • 落ち着いて、一つ上のフォルダにあるsrc_bkというフォルダをみてみよう
  • 今回はこのファイルでやることにします。
  • 先程の作業はわすれて、srcフォルダを削除して、src_bk=>srcにリネームしよう

(学習した)
20180718追記
プロキシーを刺せばうまくいくよう
call npm -g config set proxy http://proxy1.ut.fks.ed.jp:8080
call npm -g config set https-proxy http://proxy1.ut.fks.ed.jp:8080


基本ファイルを作成する

src/にapp.jsというファイルを作成して、以下の内容を記述してみよう。

src/app.js
// expressを読み込み
var express = require("express");
var app = express();

// サーバーの設定
var server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

// 具体的な振る舞い
app.get("/", function(req, res, next){
    res.json('こんにちは');
});


サーバーを起動する

DOSにもどって以下のコードをうつ

cmd
node app.js

もしでたら許可してください

image.png


サーバーが立ち上がりました!

http://localhost:3000/
にアクセスしてみてください。


今回使ったカップ麺

Express
* マジ簡単。3分クッキング
image.png


簡易的な対話コンソールをつくってみる

LINEと連携する前に、簡単な画面を作って対話できるようにしてみましょう

※一度サーバーを終了させる必要があるのでCtrl+Cで終わります

cmd
npm install ejs --save-dev

学校の環境でうまくインストールできない場合

教材ファイルのnode_modules/以下をコピー
package.jsonのdevDependenciesの部分を追加します

package.json
{
  "name": "odk2017",
  "version": "1.0.0",
  "description": "line bot application",
  "main": "index.js",
  "scripts": {
    "test": "test"
  },
  "author": "Takashi MORIYAMA",
  "license": "MIT",
  "dependencies": {
    "express": "^4.15.3"
  },
  "devDependencies": {
    "ejs": "^2.5.6"
  }
}

画面を追加する下準備

src/app.js
var express = require("express");
var app = express();

//画面をつくるためのエンジンを追加
app.set('view engine', 'ejs'); //追加

/* 中略 */

//画面をつくってみよう
app.get("/", function(req, res, next){ //追加
    res.render('index.ejs', {text: 'こんにちは'}); //追加
}); //追加

// 具体的な振る舞い
app.get("/hello", function(req, res, next){
    res.json('こんにちは');
});

ejsファイルを記述する

HTMLという方式でレイアウトを記述しています。

views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
    <!--Import Google Icon Font-->
  <link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <!-- Compiled and minified CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/css/materialize.min.css">
    <!--Let browser know website is optimized for mobile-->
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
  <!-- Compiled and minified JavaScript -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/js/materialize.min.js"></script>

</head>
<body>
    <div class="container">
        <h1>New Bot Applicatoin</h1>
    </div>
</body>
</html>

改めてサーバーを起動する

DOSにもどって以下のコードをうつ

cmd
node app.js

http://localhost:3000/
にアクセスしてみましょう


画面を追加する

views/index.ejs
    <h1>New Bot Applicatoin</h1>
    /* ↓に以下のコードを追記 */
    <div class="row">
      <div class="row">
        <div class="input-field col s6">
          <input placeholder="なにか入力" id="text" type="text" class="validate">
          <label for="first_name">なにか入力</label>
        </div>
      </div>
      <div class="row">
        <div class="input-field col s6">
            <a class="waves-effect waves-light btn" id="submit">送信</a>
          </div>
      </div>
      <div class="row">
        <div class="col s12 m6">
          <div class="card blue-grey darken-1">
            <div class="card-content white-text">
              <span class="card-title">サーバーからの返信</span>
              <p id="return"></p>
            </div>
          </div>
        </div>
      </div>
      </div>
    </div>
    <script type="text/javascript">
        $(function() {
            $('#submit').on('click', function() {
                $.get('/hello', {
                    text: $('#text').val()
                }).done(function(res) {
                    $('#return').html(nl2br(res));
                })
            })
            function nl2br(str) {
              return str.replace(/\r\n/g, "<br />").replace(/(\n|\r)/g, "<br />");
            }
        })
    </script>

画面ができた!

画面を再読込してみよう.いろいろパーツが増えましたね。


変数を使う

src/app.js
app.get("/hello", function(req, res, next){
  var message = 'こんにちは'; //追加
  res.json(message); //'こんにちは'をmessageに書き換え
});

終わったらCtrl+C & node app.jsで再起動し、確認してみましょう。今までと結果は同じですか?


送ったテキストを取得する

src/app.js
app.get("/hello", function(req, res, next){
  var message = 'こんにちは。';
  message += ' \n' + req.query.text + '」といいましたか?'
  res.json(message); //'こんにちは'をmessageに書き換え
});

終わったらCtrl+C & node app.jsで再起動し、確認してみましょう。


条件を分岐させよう

なにかしゃべりかけたときに、時間にあわせて「おはよう」「こんにちは」「こんばんは」を分ける

src/app.js
app.get("/hello", function(req, res, next){
  var message = 'こんにちは。';
  var hour = new Date().getHours();
  if(hour < 12) {
    message = 'おはようございます';
  } else if(hour >= 16) {
    message = 'こんばんは';
  }
  message += ' \n' + req.query.text + '」といいましたか?'
  res.json(message); //'こんにちは'をmessageに書き換え
});

終わったらCtrl+C & node app.jsで再起動し、確認してみましょう。


まとめ

インタラクションが可能になりました。
if文をもう少しアレンジしてみましょう

  • 時間を変えたら?
  • 送ったテキストにあわせて反応してみるには?

LINE bot として動くようにする

image

※紹介動画は今後の拡張をイメージしやすいので、ぜひみてみよう


インターネットからアクセス可能なサーバーにアップしよう

image

今回は「Heroku」というサービスを使います。
ソースファイルをアップするだけで、自動的にサーバーまで立ち上げてくれるすごいサービス

試験的に動かすだけなら、なんと無料!で使えます。


ファイルのアップの仕方

「Git」を使う ←ネットワークでブロックされます
「Dropbox」を使う ←ネットワークでブロックされます

頼むよFKS
万策尽きたー!!(尽きたとはいっていない)


messaging apiを始める ->ログイン
認証を求められるので認証
「会社/事業者を追加する」から追加
事業所を選択-> 業種などを入力して、確認する
image


image
Messaging API の「LINE Developpers」を選択


image

Channel Secretの値は後で使います

image


Github/Herokuアカウントを作成

今回はすでにアカウントを作成済みです


デプロイ設定をする

git config --global http.proxy http://proxy1.ut.fks.ed.jp:8080

FKSを通して実行できるように、以下のコマンドを実行します。(通常のネットワーク環境では不要です)

git init 
git add .
git commit -m "最初のcommit"
git remote add origin <リポジトリ名>
git push -u origin master

サーバーを確認する

<サーバーURL>/hello
でいつものやつが表示できているはず


Procfileを作成

src以下にProcfileを作成

web: node app.js

LINEと接続する部分を書く

cd src
npm install body-parser --save
npm install request --save
npm install crypto --save
npm install async --save
npm install @line/bot-sdk --save

Procfileをアップロード


git add .
git commit -m "Procfile作成"
git push -u origin master

"dependencies": {
    "@line/bot-sdk": "^2.0.0",
    "async": "^2.5.0",
    "crypto": "^1.0.1",
    "express": "^4.15.3",
    "request": "^2.81.0",
    "body-parser": "^1.17.2",
    "ejs": "^2.5.6"
  },

var server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

var server = app.listen(process.env.PORT || 5000);


src/app.js
const line = require('@line/bot-sdk');
const config = {
  channelAccessToken: 'TNiyVqdOEV+Tt4SheNECr1+tQMuraIB/cecrXyJdU4m2/BWsI8q9mjbZVCB07Y6GnFvm4NGa/lOGGI4TZ8kx/ShG/TWdSJC5cM6NnurM6EwYPolW6KCcAQBp3/H/RUFGEkZoBBrCoKDHnhBst7f6TAdB04t89/1O/w1cDnyilFU=',
  channelSecret: '14a05618292ac080796aa15278ebcc1e'
};

app.post('/line', line.middleware(config), (req, res) => {
  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);
  }

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

channell access token と channelsecretを自分のものに書き換えます。

※注!通常こういったtokenのようなものを、コードに直接書くことは、セキュリティリスクにつながるため行いません。


コードを共通化

サンプルを見てみましょう
やっておきました。


botを進化させる

・if文で分岐させて、それっぽい会話が成立するようにしてみましょう。
・おはよう、こんにちは
・今の時間は?
・文化祭のタイムテーブルを教えて
・小高の見どころはどこ?

これらの質問に答えられるbotをつくってみよう

TIPS
「botのキャラ付け」をすると、それだけで人間味が増したりします。
(正統派、ツンデレ、年上のお姉さん・・おっとこれ以上はry)


function getMessageText(text) {
var message = '「' + text + 'といいましたか?'; //messageという変数に文字列をぶち込んで

if(text.indexOf('FGO') >= 0 ) {
message = 'でませい!でませい!'
}
else if(text.indexOf('漢字') >= 0 ) {
message = '「感じの漢字」という書籍はご存知ですか?文字の成り立ちが分かる、素敵な本です'

}
else if(text.indexOf('ペッパーランチのステーキといえば?') >= 0 ) {
message = 'ワイルドだろう?'

}
else if(text.indexOf('敬え') >= 0 ) {
message = 'ちょっと何言ってるかわかんないっす'

}
else if(text.indexOf('敬え') >= 0 ) {
message = 'お子さんピアノがお上手にならはりましたなぁ'

} else {
//どれにもマッチしない場合
message = '何言ってるかわかりません'
}
return message ; //return して返す!

}

if文だと苦しくなる

今後、たくさんif文をつくっていくと苦しくなるので、データベースやAPIなどの外部情報を使ってうまく進化させていきます。

4
4
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
4
4