Cisco Webex Messagingからkintoneにレコードを登録する方法

目次

caution
警告

記事内で利用しているライブラリ「 request (External link) 」「 request-promise (External link) 」は、非推奨(deprecated)になりました。
HTTP リクエストができる他のライブラリ( axios (External link) など)や、 https.requst (External link) に書き換えることをおすすめします。

はじめに

Cisco Webex Messaging(旧称: Cisco Webex Teams)と cybozu.com の連携シリーズ第 4 弾です。
第 3 弾では、Cisco Webex Messaging の Bot を使って kintone アプリに登録されている自分のタスクを Cisco Webex Messaging に呼び出す方法を紹介しました。
第 4 弾は Cisco Webex Messaging のメンション機能をつかって、担当者を指定してタスクを kintone に登録する方法を紹介します。

似たような Tips として、Slack と kintone を連携させた Slack から手軽に kintone へレコード登録する方法 や、 Slack-kintone 連携を Azure でもやってみた があります。
連携のしくみや動作もほとんど同じですが、本 Tips ではタスクの担当者を指定できる点がポイントです。

これまでの Cisco Webex Messaging と cybozu.com の連携シリーズはこちらです。

第 1 弾(Garoon との連携) Cisco Webex Messaging から Garoon スケジュールを予約する

第 2 弾(ユーザー連携) Cisco Webex Messaging と cybozu.com でユーザー連結を行う

第 3 弾(kintone との連携) kintone のアプリデータを Cisco Webex Messaging に投稿する方法

連携イメージ

Cisco Webex Messaging にタスク投稿用 Bot を使ってタスクを投稿すると kintone のタスク管理アプリにレコードが登録されます。

Cisco Webex Messaging のメンション機能を使って人を選択すると kintone アプリの担当者欄にメンションされた人の名前が登録されます。
また、誰にもメンションをしない場合は投稿者が担当者欄に登録されるしくみです。

連携概要

Azure fuctions(Node.js)にて、以下の処理を行う。

  • Cisco Webex Messaging の Webhook から POST された投稿メッセージ、投稿者のメールアドレス、メンションされた人の Cisco Webex Messaging のユーザーID を取得する。
  • Cisco Webex Messaging と cybozu.com のユーザーをマッチングする。
  • kintone へのリクエストデータを作成する。
  • kintone REST API を実行し、タスク管理アプリにレコードを登録する。

下準備

kintone アプリ

kintone アプリのデータを Cisco Webex Messaging に投稿する方法 で作成したアプリをそのまま使うことも可能です。

誰のタスクかがわかるシンプルなタスク管理アプリを作成します。

フィールド名 フィールドタイプ フィールドコード
タスク 文字列(1行) task
ステータス ラジオボタン status
担当者 ユーザー選択 responsible
詳細 文字列(複数行) detail

cybozu.com

kintone アプリのデータを Cisco Webex Messaging に投稿する方法 で用意したユーザーを使えます。

  • Cybozu.com の管理権を有するユーザーを用意する。(ユーザー情報を取得できる権限が必要)

Cisco Webex Messaging 用 Bot

項目 設定例
Display Name InputTask(bot) 日本語可
Bot Username 任意文字列@sparkbot.io
Icon 任意(URL)

kintone アプリのデータを Cisco Webex Messaging に投稿する方法 で MyApps の画面ショット付きの説明を記載しています。

Cisco Webex Messaging

  • 任意のスペース(タスクを表示させるスペース)のユーザーに作成した Bot を追加する。
  • 上記のスペースを利用するユーザーを 1 人以上登録する。
  • 登録するユーザーのメールアドレスは、cybozu.com に登録されているメールアドレスと一致させる。 Cisco Webex Messaging と cybozu.com のユーザー連携は、メールアドレスで一致させています。

ユーザー連携の詳細は Cisco Webex Messaging と cybozu.com でユーザー連結を行う を参照してください。

環境作成

Azure Functions

Azure Functions の準備に関しては、 kintone と Microsoft Azure を連携してみよう (Azure Functions その1) の「Azure Functions の準備」欄を参考にしてください。

ここでは簡単にポイントのみ記述します。(アカウント等の準備は省略)

  • 関数を作成する。

    1. Function App の画面からクイックスタート画面を開く。
    2. シナリオ選択は、「Webhook + API」を選択する。
    3. 言語の選択は、「JavaScript」を選択する。
  • パケットモジュールのインストールする。

    1. 「Function App の設定」→「Kudu に移動」を選択する。

    2. 「site」→作成した関数のフォルダーに移動する。

    3. package.json を生成する。

    4. npm コマンドを実行し、「request」「request-promise」をインストールする。

    5. package.json を開いて下図のようになっているか確認する。(①、②、③)

      1
      2
      3
      4
      5
      6
      7
      8
      
      // npmコマンド実行
      D:\home\site\wwwroot\<function_name>> npm init
      
      // requestのインストール
      D:\home\site\wwwroot\<function_name>> npm install request --save-dev
      
      // request-promiseのインストール
      D:\home\site\wwwroot\<function_name>> npm install request-promise --save-dev

  • Node.js

    1. 次の JavaScrip プログラムをコピーし、作成した関数の「</>開発」のコード欄に貼り付ける。

    2. 「XXX」で記載されている各パラメーターをご自身の環境に合わせて記入する。

    3. 「保存」ボタンをクリックする。

        1
        2
        3
        4
        5
        6
        7
        8
        9
       10
       11
       12
       13
       14
       15
       16
       17
       18
       19
       20
       21
       22
       23
       24
       25
       26
       27
       28
       29
       30
       31
       32
       33
       34
       35
       36
       37
       38
       39
       40
       41
       42
       43
       44
       45
       46
       47
       48
       49
       50
       51
       52
       53
       54
       55
       56
       57
       58
       59
       60
       61
       62
       63
       64
       65
       66
       67
       68
       69
       70
       71
       72
       73
       74
       75
       76
       77
       78
       79
       80
       81
       82
       83
       84
       85
       86
       87
       88
       89
       90
       91
       92
       93
       94
       95
       96
       97
       98
       99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      204
      205
      206
      207
      208
      209
      210
      211
      212
      213
      214
      215
      216
      217
      218
      219
      220
      221
      222
      223
      224
      225
      226
      227
      228
      229
      230
      231
      232
      233
      234
      235
      
      /*
       * Cisco Webex Messaging と kintone の連携
       * Copyright (c) 2017 Cybozu
       *
       * Licensed under the MIT License
       * https://opensource.org/license/mit/
      */
      
      (function() {
        'use strict';
        const request = require('request-promise');
      
        /* Cisco Webex Messaging用のパラメータ*/
        // BotのID
        const botID = 'XXX';
      
        // Botの Access Token
        const BEARER = 'XXX';
      
        /* kintone用のパラメータ*/
        // API 実行用のユーザー(「ログイン名:パスワード」をBASE64エンコードしたもの)
        const CYBOZU_AUTH = 'XXX';
      
        // cybozu.com のドメイン
        const DOMAIN = '{subdomain}.cybozu.com';
      
        // アプリID
        const APP_ID = XXX;
      
        // URI
        const BASE_URL = 'https://' + DOMAIN + '/k/v1/';
      
        // アプリのAPI Token
        const APITOKEN = 'XXX';
      
        const headers = {'X-Cybozu-API-Token': APITOKEN};
      
        let context;
      
        // Cisco Webex Messaging会議室にメッセージを投稿
        function sendSpark(msg, roomid) {
      
          // 投稿する内容内容
          const body_post_spark = {
            // "roomId": ROOMID, //会議室ID
            roomId: roomid, // 会議室ID
            text: msg // 投稿内容
          };
      
          body_post_spark.roomId = roomid;
      
          // Cisco Webex Messagingに投稿するためのオブジェクト
          const postspark = {
            url: 'https://api.ciscospark.com/v1/messages/',
            method: 'POST',
            auth: {bearer: BEARER},
            'Content-type': 'multipart/form-data',
            json: body_post_spark
          };
      
          // 投稿を実行する
          return request(postspark);
        }
      
        // kitoneアプリ「【Cisco Webex Messaging連動】タスク管理」にタスクを登録する
        function setkintoneTask(task, detail, code) {
      
          // kintoneアプリに登録する内容
          const body_post_kintone = {
            app: APP_ID,
            record: {
              // 担当者
              responsible: {
                value: [{code: code}]
              },
              // タスク
              task: {
                value: task
              },
              // 詳細
              detail: {
                value: detail
              }
            }
          };
      
          // kintoneに登録するためのオブジェクト
          const postkintone = {
            url: BASE_URL + 'record.json',
            method: 'POST',
            headers: headers,
            'Content-Type': 'application/json',
            json: body_post_kintone
          };
      
          // 登録を実行する
          return request(postkintone).then((res) => {
            sendSpark('kintoneにタスクが登録されました');
            context.log('kinotneに登録されました');
      
          });
        }
      
        // cybozu.com のユーザー情報を取得する
        function getUser(opt_offset, users) {
          const offset = opt_offset || 0;
          const objUser = users || {};
      
          // ユーザー情報を取得するためのオブジェクト
          const objGetUser = {
            url: 'https://' + DOMAIN + '/v1/users.json',
            headers: {'X-Cybozu-Authorization': CYBOZU_AUTH},
            method: 'GET',
            'Content-Type': 'application/json'
          };
      
          // ユーザー情報の取得を実行する
          return request(objGetUser).then((res) => {
            const resUser = JSON.parse(res);
            // 取得したユーザー情報をオブジェクトに格納する
            for (let i = 0; i < resUser.users.length; i += 1) {
              objUser[resUser.users[i].email] = {code: resUser.users[i].code,
                name: resUser.users[i].name};
            }
      
            // 100 件取得してる場合は、offset を 100 ずらして再度ユーザー取得
            if (resUser.users.length === 100) {
              return getUser(offset + 100, objUser);
            }
      
            return objUser;
          });
        }
      
        // Cisco Webex Messaging の投稿者とメンションされた人と e-mail が一致する .com のユーザー情報を取得する
        function getPostingUser(email, roomid) {
      
          return getUser().then((rtnUser) => {
            if (!(rtnUser[email])) {
              throw Error('cybozu.com上に該当するユーザーが見つかりませんでした。');
            }
            return rtnUser[email];
          });
      
        }
      
        // Cisco Webex Messagingの投稿データkintoneに登録するデータを作成する
        function allocation(html, email, roomid) {
      
          // taskと詳細に登録するデータの作成
          // 取得したデータからtaskと詳細を抜き出す
          const temp = html.split('</spark-mention>');
          const temp2 = temp[temp.length - 1].split('</p>')[0];
      
          // taskと詳細に分割する
          const message = temp2.split('+');
          const task = message[0];
          const detail = message[1];
      
          // ユーザー情報を取得する
          return getPostingUser(email, roomid).then((rtnUser) => {
            // task、detail、投稿者の.com のユーザーのcode/メンションされたユーザーの.comのcode
            return setkintoneTask(task, detail, rtnUser.code);
          });
        }
      
        // メンションされたユーザーのemailを取得する
        function getMentionedPeopleEmail(mid) {
      
          // メンションされた人のidからemailデータを取得
          const getmentionedemail = {
            url: 'https://api.ciscospark.com/v1/people/' + mid,
            method: 'GET',
            auth: {bearer: BEARER},
            'Content-Type': 'application/json'
          };
      
          // 登録されている最初のemailを取得
          return request(getmentionedemail).then((people) => {
            const objPeople = JSON.parse(people);
            return objPeople.emails[0];
          });
        }
      
        // Webhook を受けた際の処理
        module.exports = function(ct, event) {
      
          // var objbody, ids;
          let objbody, ids, roomid;
      
          // context の情報をグローバル変数に保持する
          context = ct;
      
          context.log('start!!');
      
          // 投稿先のroomidを保持しておく
          // roomid = objbody.roomid;
      
          // event.body.data.id で投稿されたメッセージの id を取得する
          // id を利用してメッセージの詳細を取得する
          const getmessage = {
            url: 'https://api.ciscospark.com/v1/messages/' + event.body.data.id,
            method: 'GET',
            auth: {bearer: BEARER},
            'Content-Type': 'application/json'
          };
      
          // メッセージの詳細の取得を実行する
          return request(getmessage).then((body) => {
      
            objbody = JSON.parse(body);
      
            // メンションされたIDからBotのIDを除く
            ids = objbody.mentionedPeople;
            ids.splice(ids.indexOf(botID), 1);
      
            // 担当者欄に登録するユーザーのemailを取得する
            if (ids.length < 1) {
              // Bot以外のメンションが無い場合は、投稿者のEmailを取得
              return objbody.personEmail;
            }
            // Bot以外のメンションがある場合はは、メンション先の1人目のEmailを取得
            return getMentionedPeopleEmail(ids[0]);
      
          }).then((email) => {
      
            // Cisco Webex Messagingのメッセージ本文を解析し、kintoneに登録するデータを準備する
            return allocation(objbody.html, email, roomid);
      
          }).catch((err) => {
            context.log('Error: ' + err.message);
          });
      
        };
      })();

Cisco Webex Messaging Webhook の設定

項目 設定値
Authorization Bearer 「Botのアクセストークン」 *1
name 今回作成する Webhook の名前(任意)
targetUrl Azure Functionsの関数のURL *1
resource messages(固定)
event created(固定)
filter mentionedPeople=me *1

試してみよう

実際に Cisco Webex Messaging のタスク登録用 Bot が参加しているスペースからタスクを投稿してみましょう。
まず自分が担当するタスクの場合、「@InputTask(Bot)タスク + 詳細」のフォーマットで入力します。
「+」は区切り文字になっており、「+」の前後でタスクと詳細に分けて kintone に登録されます。

kintone アプリを確認してみましょう。

次に自分以外の誰かが担当する ToDo を登録してみましょう。
今度は Cisco Webex Messaging のメンション機能を使って「@InputTask(Bot)@ユーザータスク + 詳細」のフォーマットで入力します。

こちらも kintone アプリを確認してみましょう。

Cisco Webex Messaging に投稿されたメッセージ(Bot へのメンション)を取得する: Get Message Details (External link)

cybozu.com のユーザー情報を取得する: ユーザー情報をエクスポートする

kintone アプリにレコードを登録する: 1 件のレコードを登録する

おわりに

今回は、タスクの担当が一人の場合を想定した例で説明しましたが、担当者が複数いる場合などにもチャレンジしてみてください。