6
5

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 3 years have passed since last update.

LINEWORKSAdvent Calendar 2019

Day 25

LINE WORKS Bot APIをひと通り触ってみる(node.js)#2

Last updated at Posted at 2019-12-24

LINEWORKS Advent Calendar 2019 / 25日目の最終日の記事です。

本記事では、LINE WORKS Bot のメッセージ送信 API をnode.jsでひと通り触ってみたいと思います。

前回:LINE WORKS Bot APIをひと通り触ってみる(node.js)#1

#0. はじめに
記事の流れになります。

  1. こんなの作ります
  2. 環境準備
  3. 作ってみる
  4. 動かしてみる
  5. 気づいたこと
  6. まとめ

#1. こんなの作ります
LINE WORKS Botのメッセージ送信には下表のタイプが存在し、そのタイプをすべて網羅するBotを作ります。
また、quick reply (クイックリプライ)も使用します。

送信タイプ 説明
text テキストメッセージ送信
image 画像送信
link リンク送信
sticker スタンプ送信
button_template ボタンテンプレート送信
list_template リストテンプレート送信
carousel カルーセル送信
image_carousel 画像カルーセル送信
  • LINE WORKS アプリより、下記の値を入力するとそれぞれのメッセージを Bot が返します。
入力値(※1) Botが返すメッセージ
Q クイックリプライ
B ボタンテンプレート
L リストテンプレート
C カルーセル
I 画像カルーセル
U リンク + クイックリプライ
スタンプ(※2) 同じスタンプ + クイックリプライ
画像 同じ画像 + クイックリプライ
場所 住所、経度緯度の文字 + クイックリプライ
その他の文字 テキストメッセージ

  ※1)入力値は大文字小文字を意識しません
  ※2)使用できるスタンプはこちら

  • クイックリプライ、ボタンテンプレート、リストテンプレート、カルーセル、画像カルーセルが使用できる Action Object もすべて網羅します。
04.png
05.png
07.png
10.png

#2. 環境準備

LINE WORKS Bot APIをひと通り触ってみる(node.js)#1 」の 「2. 環境準備 」を参照。

#3. 作ってみる

LINE WORKS Bot APIをひと通り触ってみる(node.js)#1 」の 「メッセージの送受信制御 (BotMessageService.js) 」の BotMessageService クラスをカスタマイズします。
ベタ書き&すべての機能を網羅するため長いプログラムになってすいません。

BotMessageService.js
const request = require('request');

/**
 * コールバックタイプ
 */
const CALL_BACK_TYPE = {
  /**
   * メンバーからのメッセージ
   */
  message : 'message',
  /**
   * Bot が複数人トークルームに招待された
   * このイベントがコールされるタイミング
   *  ・API を使って Bot がトークルームを生成した
   *  ・API を使って Bot がトークルームを生成した
   *  ・メンバーが Bot を含むトークルームを作成した
   *  ・Bot が複数人のトークルームに招待された
   * ※メンバー1人と Bot のトークルームに他のメンバーを招待したらjoinがコールされる(最初の1回だけ)
   *  招待したメンバーを退会させ、再度他のメンバーを招待するとjoinedがコールされるこれ仕様?
   *  たぶん、メンバー1人と Botの場合、トークルームIDが払い出されてないことが原因だろう。。。
   */
  join : 'join',
  /**
   * Bot が複数人トークルームから退室した
   * このイベントがコールされるタイミング
   *  ・API を使って Bot を退室させた
   *  ・メンバーが Bot をトークルームから退室させた
   *  ・何らかの理由で複数人のトークルームが解散した
   */
  leave : 'leave',
  /**
   * メンバーが Bot のいるトークルームに参加した
   * このイベントがコールされるタイミング
   *  ・Bot がトークルームを生成した
   *  ・Bot が他のメンバーをトークルームに招待した
   *  ・トークルームにいるメンバーが他のメンバーを招待した
   */
  joined : 'joined',
  /**
   * メンバーが Bot のいるトークルームから退室した
   * このイベントがコールされるタイミング
   *  ・Bot が属するトークルームでメンバーが自ら退室した、もしくは退室させられた
   *  ・何らかの理由でトークルームが解散した
   */
  left : 'left',
  /**
   * postback タイプのメッセージ
   * このイベントがコールされるタイミング
   *  ・メッセージ送信(Carousel)
   *  ・メッセージ送信(Image Carousel)
   *  ・トークリッチメニュー
   */
  postback : 'postback',
};

/**
 * コールバックコンテンツタイプ
 */
const CALL_BACK_MESSAGE_CONTENT_TYPE = {
  /**
   * テキスト
   */
  text : 'text',
  /**
   * 場所
   */
  location : 'location',
  /**
   * スタンプ
   */
  sticker : 'sticker',
  /**
   * 画像
   */
  image : 'image'
};

/**
 * メッセージコンテンツタイプ
 */
const MESSAGE_CONTENT_TYPE = {
  /**
   * テキスト
   */
  text : 'text',
  /**
   * 画像
   */
  image : 'image',
  /**
   * リンク
   */
  link : 'link',
  /**
   * スタンプ
   */
  sticker : 'sticker',
  /**
   * ボタンテンプレート
   */
  buttonTemplate : 'button_template',
  /**
   * リストテンプレート
   */
  listTemplate : 'list_template',
  /**
   * カルーセル
   */
  carousel : 'carousel',
  /**
   * 画像カルーセル
   */
  imageCarousel : 'image_carousel'
};

/**
 * BotMessageServiceクラス
 */
module.exports = class BotMessageService {

  /**
   * BotMessageServiceを初期化します。
   * @param {string} serverToken Serverトークン
   */
  constructor (serverToken) {
    this._serverToken = serverToken;
    this.imageIndex = 0;
  }

  /**
   * LINE WORKS にBotメッセージを送信します。
   * @param {object} callbackEvent リクエストのコールバックイベント
   */
  async send(callbackEvent) {
    let res = this._getResponse(callbackEvent);
    if (!res) return;
    return new Promise((resolve, reject) => {
      // LINE WORKS にメッセージを送信するリクエスト
      request.post(this._createMessage(res), (error, response, body) => {
          if (error) {
            console.log('BotService.send error');
            console.log(error);
          }
          console.log(body);
          // 揉み消してます!
          resolve();
      });
    });
  }

  /**
   * LINE WORKS に送信するBotメッセージを作成して返します。
   * @param {object} res レスポンスデータ
   */
  _createMessage(res) {
    return {
      url: `https://apis.worksmobile.com/r/${process.env.API_ID}/message/v1/bot/${process.env.BOT_NO}/message/push`,
      //url: `https://apis.worksmobile.com/${process.env.API_ID}/message/sendMessage/v2`,
      headers: {
        'Content-Type': 'application/json;charset=UTF-8',
        consumerKey: process.env.CONSUMER_KEY,
        Authorization: `Bearer ${this._serverToken}`
      },
      json: res
    };
  }

  /**
   * メンバーIDを連結して返します。
   * @param {Array} memberList メンバーリスト
   * @return {string} メンバーIDリスト文字列
   */
  _buildMember(memberList) {
    let result = '';
    if (!memberList) return result;
    memberList.forEach(m => {
      if (result.length > 0) result += ',';
      result += m;
    });
    return result;
  }
  
  /**
   * Bot実装部
   * @param {object} callbackEvent リクエストのコールバックイベント
   * @return {string} レスポンスメッセージ
   */
  _getResponse(callbackEvent) {
    console.log(callbackEvent);

    let res = {};

    if (callbackEvent.source.roomId) {
      // 受信したデータにトークルームIDがある場合は、送信先にも同じトークルームIDを指定します。
      res.roomId = callbackEvent.source.roomId;
    } else {
      // トークルームIDがない場合はBotとユーザーとの1:1のチャットです。
      res.accountId = callbackEvent.source.accountId;
    }

    switch (callbackEvent.type) {
      case CALL_BACK_TYPE.message:

        switch (callbackEvent.content.type) {
          case CALL_BACK_MESSAGE_CONTENT_TYPE.text:
            if (callbackEvent.content.postback == 'start') {
              // メンバーと Bot との初回トークを開始する画面で「利用開始」を押すと、自動的に「利用開始」というメッセージがコールされる
              console.log(`start`);
              res.content = { type: MESSAGE_CONTENT_TYPE.text, text: 'ト〜クルームに〜〜。ボトやまが〜くる〜!\n下記を入力するとボトやまが特別な応答をします(大文字小文字を区別しません)。\n・b:button template\n・l:List template\n・c:carousel\n・i:image carousel\n・q:quick reply' };
              return res;
            }

            let content = this._getButtonTemplateContent(callbackEvent.content.postback, callbackEvent.content.text)
              || this._getListTemplateContent(callbackEvent.content.postback, callbackEvent.content.text)
              || this._getCarouselContent(callbackEvent.content.postback, callbackEvent.content.text)
              || this._getImageCarouselContent(callbackEvent.content.postback, callbackEvent.content.text)
              || this._getQuickReplyContent(callbackEvent.content.postback, callbackEvent.content.text)
              || this._getLinkContent(callbackEvent.content.postback, callbackEvent.content.text);
            if (content) {
              res.content = content;
            } else {
              console.log(CALL_BACK_TYPE.message);
              res.content = { type: MESSAGE_CONTENT_TYPE.text, text: `ですよね〜〜〜。\n(受信データ:${callbackEvent.content.text})` };
            }
            break;
    
          case CALL_BACK_MESSAGE_CONTENT_TYPE.location:
            // 場所のコールバックは場所データをテキストで返す
            res.content = { 
              type: MESSAGE_CONTENT_TYPE.text, 
              text: `住所:${callbackEvent.content.address}\n緯度:${callbackEvent.content.latitude}\n経度:${callbackEvent.content.longitude}`,
              quickReply: this._getQuickReplyItems()
             };
            break;
    
          case CALL_BACK_MESSAGE_CONTENT_TYPE.sticker:
            // スタンプのコールバックはおうむ返し(同じスタンプを返す)
            // ※使えないスタンプがあるようです(LINE WORKSぽいスタンプは使えない。。。)
            res.content = { 
              type: MESSAGE_CONTENT_TYPE.sticker, 
              packageId: callbackEvent.content.packageId, 
              stickerId: callbackEvent.content.stickerId,
              quickReply: this._getQuickReplyItems()
            };
            break;
    
          case CALL_BACK_MESSAGE_CONTENT_TYPE.image:
            // 画像のコールバックはおうむ返し(同じ画像を返す)
            res.content = { 
              type: MESSAGE_CONTENT_TYPE.image, 
              resourceId: callbackEvent.content.resourceId,
              quickReply: this._getQuickReplyItems()
            };
            break;
          
          default:
            console.log('知らないcontent.typeですね。。。');
            return null;
        }
        break;

      case CALL_BACK_TYPE.join:
        console.log(CALL_BACK_TYPE.join);
        res.content = { type: MESSAGE_CONTENT_TYPE.text, text: 'うぃーん!' };
        break;

      case CALL_BACK_TYPE.leave:
        console.log(CALL_BACK_TYPE.leave);
        break;

      case CALL_BACK_TYPE.joined: {
        console.log(CALL_BACK_TYPE.joined);
        res.content = { type: MESSAGE_CONTENT_TYPE.text, text: `${this._buildMember(callbackEvent.memberList)} いらっしゃいませ〜そのせつは〜` };
        break;
      }

      case CALL_BACK_TYPE.left: {
        console.log(CALL_BACK_TYPE.left);
        res.content = { type: MESSAGE_CONTENT_TYPE.text, text: `${this._buildMember(callbackEvent.memberList)} そうなります?` };
        break;
      }

      case CALL_BACK_TYPE.postback:
        // QuickReply, Carousel, ImageCarouselからのPostback(このコールバック後、CALL_BACK_TYPE.messageのコールバックがコールされる)
        console.log(CALL_BACK_TYPE.postback);
        let content = this._getButtonTemplateContent(callbackEvent.data) 
        || this._getListTemplateContent(callbackEvent.data)
        || this._getCarouselContent(callbackEvent.data)
        || this._getImageCarouselContent(callbackEvent.data)
        || this._getQuickReplyContent(callbackEvent.data);
        if (content) res.content = content;
        break;

      default:
        console.log('知らないコールバックですね。。。');
        return null;
    }

    return res;
  }
  
  /**
   * Link コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getLinkContent(...conditions) {
    if (!conditions.some(condition => condition && condition.toUpperCase() === 'U')) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.link, 
      contentText: 'Link からの〜〜〜。',
      linkText: 'LINE WORKS',
      link: 'https://line.worksmobile.com/jp/',
      quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * Quick reply コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getQuickReplyContent(...conditions) {
    if (!conditions.some(condition => condition && condition.toUpperCase() === 'Q')) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.text, 
      text: 'QuickReply からの〜〜〜。',
      quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * Quick reply アイテムリストを返します。
   * @return {Array} アイテムリスト
   */
  _getQuickReplyItems() {
    return {
      items: [
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/giraffe01.png`,
          action: {
            type: 'postback',
            label: 'ButtonTemp',
            data: 'button_template',
            displayText: 'button_template ください'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/panda01.png`,
          action: {
            type: 'postback',
            label: 'ListTemp',
            data: 'list_template',
            displayText: 'list_template ください'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/giraffe02.png`,
          action: {
            type: 'postback',
            label: 'Carousel',
            data: 'carousel',
            displayText: 'carousel ください'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/panda02.png`,
          action: {
            type: 'postback',
            label: 'ImageCarousel',
            data: 'image_carousel',
            displayText: 'image_carousel ください'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/sushi.png`,
          action: {
            type: 'postback',
            label: 'QuickReply',
            data: 'q',
            displayText: 'QuickReply ください'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/sushi.png`,
          action: {
            type: 'message',
            label: 'すし',
            text: 'すし'
          }
        },
        {
          imageUrl: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
          action: {
            type: 'uri',
            label: 'LINE WORKS',
            uri: 'https://line.worksmobile.com/jp/'
          }
        },
        {
          action: {
            type: 'camera',
            label: 'カメラ'
          }
        },
        {
          action: {
            type: 'cameraRoll',
            label: 'カメラロール'
          }
        },
        {
          action: {
            type: 'location',
            label: '場所'
          }
        }
      ]
    }
  }

  /**
   * Button template コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getButtonTemplateContent(...conditions) {
    if (!conditions.some(condition => condition && (condition.toUpperCase() === 'B' || condition === MESSAGE_CONTENT_TYPE.buttonTemplate))) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.buttonTemplate, 
      contentText: 'ButtonTemplate からの〜〜〜。',
      actions: this._getButtonActions(),
      //quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * Buttonアクションリストを返します。
   * @return {Array} アクションリスト
   */
  _getButtonActions() {
    return [
      // button_templateのactionでは typeはmessageとuriしか使えない。つまり postback、camera、cameraRoll、locationは使えない
      {
        type: 'message',
        label: 'Message lable',
        text: 'Message text'
      },
      {
        type: 'message',
        label: 'Button postback',
        text: 'button_template ください',
        postback: 'button_template' 
      },
      {
        type: 'message',
        label: 'List postback',
        text: 'list_template ください',
        postback: 'list_template'
      },
      {
        type: 'message',
        label: 'Carousel postback',
        text: 'carousel ください',
        postback: 'carousel'
      },
      {
        type: 'message',
        label: 'Image carousel pb',
        text: 'image_carousel ください',
        postback: 'image_carousel'
      },
      {
        type: 'message',
        label: 'QuickReply postback',
        text: 'QuickReply ください',
        postback: 'q'
      },
      {
        type: 'uri',
        label: 'LINE WORKS',
        uri: 'https://line.worksmobile.com/jp/'
      }
    ];
  }

  /**
   * List template コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getListTemplateContent(...conditions) {
    if (!conditions.some(condition => condition && (condition.toUpperCase() === 'L' || condition === MESSAGE_CONTENT_TYPE.listTemplate))) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.listTemplate, 
      coverData: {
        backgroundImage: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
        //backgroundResourceId: '',
        title: 'ListTemplate からの〜〜〜。(title)',
        subtitle: 'サブタイトル',
      },
      // 最大4つの要素を指定可能
      elements: this._getListElements(),
      // 最大2*2の配列でアクションを指定可能
      actions: this._getListActions(),
      //quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * List要素リストを返します。
   * @return {Array} 要素リスト
   */
  _getListElements() {
    // list_template.elementsのactionでは typeはmessageとuriしか使えない。つまり postback、camera、cameraRoll、locationは使えない
    return [
      {
        title: 'List message title',
        subtitle: 'List message subtitle',
        image: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
        //resourceId: '',
        action: {
          type: 'message',
          label: 'Message',
          text: 'Message text'
        }
      },
      {
        title: 'Button postback title',
        subtitle: 'Button postback subtitle',
        image: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
        //resourceId: '',
        action: {
          type: 'message',
          label: 'Button',
          text: 'button_template ください',
          postback: 'button_template'
        }
      },
      {
        title: 'List postback title',
        subtitle: 'List postback subtitle',
        image: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
        //resourceId: '',
        action: {
          type: 'message',
          label: 'List',
          text: 'list_template ください',
          postback: 'list_template'
        }
      },
      {
        title: 'List uri title',
        subtitle: 'List uri subtitle',
        image: `${process.env.IMAGE_FILE_HOST}/images/security.png`,
        //resourceId: '',
        action: {
          type: 'uri',
          label: 'LINE WORKS',
          uri: 'https://line.worksmobile.com/jp/'
        }
      }
    ];
  }

  /**
   * Listアクションリストを返します。
   * @return {Array} アクションリスト
   */
  _getListActions() {
    // list_template.actionsのactionでは typeはmessageとuriしか使えない。つまり postback、camera、cameraRoll、locationは使えない
    return [
      [
        {
          type: 'message',
          label: 'Carousel postback',
          text: 'carousel ください',
          postback: 'carousel'
        },
        {
          type: 'message',
          label: 'Image Car postback',
          text: 'image_carousel ください',
          postback: 'image_carousel'
        }
      ],
      [
        {
          type: 'message',
          label: 'QuickReply',
          text: 'QuickReply ください',
          postback: 'q'
        },
        {
          type: 'message',
          label: 'No',
          text: 'No'
        }
      ]
    ];
  }

  /**
   * Carousel コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getCarouselContent(...conditions) {
    if (!conditions.some(condition => condition && (condition.toUpperCase() === 'C' || condition === MESSAGE_CONTENT_TYPE.carousel))) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.carousel,
      //imageAspectRatio: '',
      //imageSize: '',
      columns: this._getCarouselColumns(),
      //quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * Carousel カラムリストを返します。
   * @return {Array} カラムリスト
   */
  _getCarouselColumns() {
    // carousel.columnsのactionでは typeはmessageとuri、postbackしか使えない。つまり camera、cameraRoll、locationは使えない
    // carouselは、postbackをつかえる!!!!
    return [
      {
        thumbnailImageUrl: `${process.env.IMAGE_FILE_HOST}/images/giraffe01.png`,
        //thumbnailImageResourceId: '',
        title: 'Carousel postback title',
        text: 'Carousel postback text (default button)',
        defaultAction: {
          type: 'postback',
          label: 'ButtonTemp',
          data: 'button_template',
          displayText: 'button_template ください'
        },
        actions: [
          {
            type: 'postback',
            label: 'ListTemp',
            data: 'list_template',
            displayText: 'list_template ください'
          },
          {
            type: 'postback',
            label: 'Carousel',
            data: 'carousel',
            displayText: 'carousel ください'
          },
          {
            type: 'postback',
            label: 'QuickReply',
            data: 'q',
            displayText: 'QuickReply ください'
          }
        ]
      },
      {
        thumbnailImageUrl: `${process.env.IMAGE_FILE_HOST}/images/panda01.png`,
        //thumbnailImageResourceId: '',
        title: 'Carousel uri title',
        text: 'Carousel uri text',
        defaultAction: {
          type: 'uri',
          label: 'LINE WORKS',
          uri: 'https://line.worksmobile.com/jp/'
        },
        actions: [
          {
            type: 'uri',
            label: 'LINE WORKS',
            uri: 'https://line.worksmobile.com/jp/'
          },
          {
            type: 'uri',
            label: 'bot Action Objects',
            uri: 'https://developers.worksmobile.com/jp/document/1005050?lang=ja'
          }
        ]
      },
      {
        thumbnailImageUrl: `${process.env.IMAGE_FILE_HOST}/images/sushi.png`,
        //thumbnailImageResourceId: '',
        title: 'Carousel message title',
        text: 'Carousel message text',
        defaultAction: {
          type: 'message',
          label: 'Message',
          text: 'Message text'
        },
        actions: [
          {
            type: 'message',
            label: 'Yes',
            text: 'Yes'
          },
          {
            type: 'message',
            label: 'No',
            text: 'No'
          }
        ]
      }
    ];
  }

  /**
   * Image carousel コンテンツを返します。
   * @param {Array} conditions 条件
   * @return {object} コンテンツ
   */
  _getImageCarouselContent(...conditions) {
    if (!conditions.some(condition => condition && (condition.toUpperCase() === 'I' || condition === MESSAGE_CONTENT_TYPE.imageCarousel))) return;
    return { 
      type: MESSAGE_CONTENT_TYPE.imageCarousel,
      columns: this._getImageCarouselColumns(),
      //quickReply: this._getQuickReplyItems()
    };
  }

  /**
   * Image carousel カラムリストを返します。
   * @return {Array} カラムリスト
   */
  _getImageCarouselColumns() {
    // image_carousel.columnsのactionでは typeはmessageとuri、postbackしか使えない。つまり camera、cameraRoll、locationは使えない
    // image_carousellは、postbackを使える!!!!
    // 最大3つまでのカラムしか使えない!!!
    return [
      {
        imageUrl: `${process.env.IMAGE_FILE_HOST}/images/giraffe01.png`,
        //imageResourceId: '',
        action: {
          type: 'postback',
          label: 'ButtonTemp',
          data: 'button_template',
          displayText: 'button_template ください'
        }
      },
      {
        imageUrl: `${process.env.IMAGE_FILE_HOST}/images/lw.png`,
        //imageResourceId: '',
        action: {
          type: 'postback',
          label: 'ListTemp',
          data: 'list_template',
          displayText: 'list_template ください'
        }
      },
      {
        imageUrl: `${process.env.IMAGE_FILE_HOST}/images/sushi.png`,
        //imageResourceId: '',
        action: {
          type: 'postback',
          label: 'Carousel',
          data: 'carousel',
          displayText: 'carousel ください'
        }
      }
    ];
  }
}

##環境変数 (.env)

  1. .env.sample ファイルを .env に変更する
  2. 「LINE WORKS Bot APIの利用準備」で発行した接続情報を設定する
  3. 「IMAGE_FILE_HOST」に ngrog で取得したホスト ( https://xxxxx.io ) を指定する
.env
API_ID="API ID"
CONSUMER_KEY="Consumer key"
SERVER_ID="Server ID"
PRIVATE_KEY="認証キー"
BOT_NO="Bot No"
IMAGE_FILE_HOST="ホスト名(ngrogで取得したホスト https://xxxxx.io)"

#4. 動かしてみる

LINE WORKS Bot APIをひと通り触ってみる(node.js)#1 」の 「いざデバッグ開始!」を参照して、Botを起動し、LINE WORKSアプリにBotを追加した状態にする。

##シナリオ

  1. Botの利用開始
  2. 「I」を入力し送信(画像カルーセル要求)
  3. 画像カルーセルの「ButtonTemp」をクリック(ボタンテンプレート要求)
  4. ボタンテンプレートの「List postback」をクリック(リストテンプレート要求)
  5. リストテンプレートの「QuickReply」をクリック(クイックリプライ要求)
  6. クイックリプライの「場所」をクリック(マップ要求)
  7. マップの「位置を共有」をクリック
  8. クイックリプライの「Calousel」をクリック(カルーセル要求)
aaa.gif

#5. 気づいたこと

##camera、cameraRoll、location、postback Action は、すべての 送信タイプで指定できるわけではない

送信タイプ camera cameraRoll location postback
quick reply (共通プロパティ) :ok_woman_tone1: :ok_woman_tone1: :ok_woman_tone1: :ok_woman_tone1:
text
image
link
sticker
button_template :no_good_tone1: :no_good_tone1: :no_good_tone1: :no_good_tone1:
list_template :no_good_tone1: :no_good_tone1: :no_good_tone1: :no_good_tone1:
carousel :no_good_tone1: :no_good_tone1: :no_good_tone1: :ok_woman_tone1:
image_carousel :no_good_tone1: :no_good_tone1: :no_good_tone1: :ok_woman_tone1:
※ ー は Action Object を使用できない送信タイプです

##postback には2つの種類がある

  • 送信タイプ: button_template、list_template の Action Object の場合、type:message で postback プロパティにデータを乗せる
ActionObject
{
  type: 'message',
  label: 'Button',
  text: 'button_template ください',
  postback: 'button_template'
}
  • 送信タイプ: quick reply(共通プロパティ)、carousel、image_carousel の Action Object の場合、type:postback で data プロパティにデータを乗せる

(この Action が実行された場合、postback と message の2つのイベントが Bot 側にコールバックされる)

ActionObject
{
  type: 'postback',
  label: 'ImageCarousel',
  data: 'image_carousel',
  displayText: 'image_carousel ください'
}

#6. まとめ

LINE WORKS Bot APIのメッセージ送信部分の動作をひと通り確認できました。
ベタ書きのコードですいません。でも、一通りは網羅したつもりです。
今回作成たコードは GitHub の line-works-bot01-node の tag:v2.0 で公開してま〜す。(issueがあればお知らせください。修正します。)

次回は、トーク固定メニューとリッチメニューをやってみたい!

#Link

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?