Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@atomicZAMURAI

【LINE MessagingAPI】アクションが増えすぎてindex.jsがもたない。。

More than 1 year has passed since last update.

今回のお題

module化して一つ一つの処理を分けたい。

hello -> helloを返すmoduleにするような感じにしてメインのJsをすっきりさせたい。

環境

  • heroku
  • nodejs

以前までの私

switch ~ caseを使った方法でのアクションの実装を行っていました。
しかし、見てわかるようにコードが間延びしていき、すごく見づらくなってしまいました。
少しのアクションメソッドだけなら対応できますが、より多くのイベントを個別にとなってくるとコードが破綻しました。

app.post('/webhook', line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(eventHandler))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err)
      res.status(500).end()
    })
})
function eventHandler(event) {
  let client = new line.Client(this.config)
  ...
  switch(event.message) {
   case "":
     return client.replyMessage(token, {
      type: "text",
      text: replyText
    })
   break
  }
  ...
}

ディレクトリ構成

破綻しないためにはどうすればいいか,悩みに悩んだ挙句ディレクトリごとに処理を切り分けたら切ではないかと思い、以下のようなディレクトリ構成を実装しました。
実際に動くアクションの部分を毎回作り替えることで一から書くプログラムの量も少なくなり、他との差別化が測れるのではないかと考えました。

├── message
│   ├── message.js
│   ├── text
│       ├── action
│       │   ├── action1
│       │   │   └── action1.js
│       ├── reply.json
│       └── text.js
├── postback
│   ├── action
│   │   └── template.js
│   └── postback.js
└── replyModule.js  // message typeによる実行moduleの変更
index.js  // webhookの受け取り

イベントタイプごとにディレクトリを区切り、そのイベントがあった際に受け取る窓口を各ディレクトリに用意しておく。

index.js

nodeでexpressを使ってwebhookを用意します。
オリジナルのReplyModuleを読み込み、そこでイベントタイプごとに実行するjsを変更するようにします。

const line = require('@line/bot-sdk')
const express = require('express')
/**
 * オリジナルのリプライモジュールを読み込む
 */
const ReplyModule = require('./event/replyModule')
const app = express()

/**
 * LINEのチャンネルアクセストークンとチャンネルシークレットを適用させる
 */
const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET
}
app.post('/webhook', line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(eventHandler))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err)
      res.status(500).end()
    })
})

function eventHandler(event) {
  let replyModule = new ReplyModule(event)
  return replyModule.replyHandller()
}

 replyModule.js

イベントタイプごとに実行するModuleを切り替えます。
中身は単純に連想配列で実行する関数を切り替えているだけです。
switch文ではなく、LINEのイベントごとに実行する関数を切り替えることで、どのイベントで何をやるを明確に分けることができるので使いやすいのではないかとおもいます。

replyModule.js
"use strict"
const line = require('@line/bot-sdk')
/**
 * @constructor
 */
const ReplyModule = function(req)
{
  this.event = req;
  this.execFunc = {
    ...
    "message": this.execMessage.bind(ReplyModule, this.event),
    "follow": this.execFollow.bind(ReplyModule, this.event),
    ...
  }
}
/**
 * exec message function
 * @return json
 */
ReplyModule.prototype.execMessage = (event) => {
  // 別moduleにするもよし
  let MessageModule = require('./message/message')
  let messageModule = new MessageModule(event)
  return messageModule.messageHandller()
}
/**
 * exec follow function
 * @return json
 */
ReplyModule.prototype.execFollow = (event) => {
  // そのままリプライするもよし
  let config = {
    channelAccessToken: ...,
    channelSecret: ...
  }
  let client = new line.Client(config)
  return client.replyMessage(event.replyToken, {
    type: "text",
    text: "登録してくれてありがとう!"
  }
}
/**
 * @return json
 */
ReplyModule.prototype.replyHandller = function() {
  let type = this.event.type
  return this.execFunc[type]()
}
module.exports = ReplyModule;

あとは、message typeごとに切り分けたりすることでそれぞれのModuleを実行してくれるので,このイベントはこれ!のようにうまく分けられたりするのではないかと思います。
postbackイベントとtextイベントはそれぞれ似たような作りにできるかと思います。
おそらく言語解析系のサービスに接続されると思いますので、各サービスに合わせた形でtextModuleのようなものを作成し、
言語解析系のアクションごとに切り分ける方法も有用かと思います。

学び始めて日が浅いので拙いコーディングですが、誰かの参考になれば幸いです。

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
atomicZAMURAI
AR / VR / MR Hololens / HoloLens2 Developer Web Frontend Engineer

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?