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件のレコードを登録する

おわりに

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