1.読まなくてもいい前書き

2017年の秋晴れを引き裂くように、そのお知らせは降ってきました。そう、サイボウズLive終了のお知らせです。
その直後、お客様から早速ご連絡が。「Liveが終わる。代替案を検討してほしい」と。「はいっ!承知でございます」。

直後に開催されたCybozu Days 2017の基調講演でサイボウズ青野社長からLive終了の事情説明やお詫びをいただき、ようやく事態の深刻さを悟った私。Daysで仕入れた情報では、移行ツールが提供されるとかされないとか。でもそれはあくまでも未確定情報。リサーチして弊社でも移行できるようにしておかないと。

そう思っていたところにkintone Advent Calendarの枠が残り少ないというご連絡を頂きまして。最後の一枠に滑り込めました。Advent Calendarへの参加は3度目なのですが、今回はサイボウズLiveをからめればネタとして旬ではなかろうか。そんなことを、サイボウズのUっ氏~にお伺いを立てたところ、歓迎いただけまして。では取り掛かってみよう、と考え始めたとたん、Advent Calendarの4日目にアップされたのが「kintoneサイボウズLive化作戦」。正直やられた、と思いましたね。けど松田さんの記事を拝見するとkintoneへのデータ移行までは触れていない様子。これは私がやるしかないでしょう。まだ出番まで3週間はあるし、案件の合間でも何とかなるはず。2019年の4月までしか賞味期限のない記事ですが、どなたかのお役に立てれば。せめてもの長井サンタの贈り物です。

目次

1.読まなくてもいい前書き

2.サイボウズLiveのデベロッパー登録を行い、APIキーを入手する。

3.APIリファレンスを読む。理解する。

4.類似の参考サイトを探す。

5.グループと個人の違いを理解する。

6.取り込み方法のインターフェース検討と実装。

7.サイボウズLive APIの制限事項と、kintoneの対応機能の検討。

8.実装。

2.サイボウズLiveのデベロッパー登録を行い、APIキーを入手する。

実は今まで、サイボウズLiveのAPIは存在こそ知っていましたが、完全スルーしていました。
なので今回はデベロッパー登録から始めました。まずはここからやってみましょう。

 ・https://developer.cybozulive.com/apps/top にアクセスします。

・APIの対象を選びます。グループZを選ばないと全データが取得できないのでグループZを選びます。アプリケーションの種類はクライアントにします。

・Consumer KeyとConsumer Secretを入手します。大切に保管しておきましょう。

・上で入手したConsumer KeyとConsumer Secretを使います。

3.APIリファレンスを読む。理解する。

続いてAPIリファレンスです。これを読まねば話になりません。
 https://developer.cybozulive.com/doc/current/

なるほどサイボウズLiveは、認証にOauthを使っているのですね。
JavaScriptだけでの実装だとちょっと面倒かな。oauth.ioとか試してみればできそうな気もするけど後回しにします。
PHPだとOauthの実装したこともあるし多分いけるでしょう。
そんなわけで、まずPHPで実装し、時間があればJavaScriptでやってみよう、と決めました。

4.類似の参考サイトを探す。

ところが、サイボウズLiveってAPIがあまり活用されていなかったのか、情報があまりウェブ上にないのです。
そんなわけで私が公式のサイボウズLive APIドキュメントページ以外で
参考にさせて頂いたのは、まだプログラマーですが何か?さんのページのみです。ありがとうございました。

こちらの情報によると、pearで Net_URL2、HTTP_Request2、HTTP_OAuthを使うのが良さげな感じ。私もそれにのっかりました。
サーバーはさくらインターネットさんのスタンダードプランが手元にあったので使ってみようとおもいます。
と思ったら、ちょっとだけ手間取りました。以下は読み飛ばしてよいです。
 ・Oauthの実装に手間取りまして。
 ・そもそもpear自体がさくらインターネットのサーバーにインストールされていなかったり。
 ・なのでgo-pear.phpを使ってインストールしようとして。
 ・そしたら、ファイルだけでなくディレクトリのパーミッションも755にしないと動かない、とか。
 ・で、pearのインストールができたと思ったら、go-pearのインストーラーからNet_URL2パッケージを入れる際、なぜか古いバージョンしか入れられず。
 ・するとHTTP_Request2、HTTP_OAuthが要求するNet_URL2のバージョンを満たさずさあ困った。
 ・仕方ないのでSSH接続でコマンドからインストールする羽目になりました。
 ・しかも後ほどftpやsocketでもはまってしまい、仕方なくあとでphpのバージョンを7.1.11に上げました。これらの処理に影響はありませんでしたが。

・というわけで、本記事の前提となるバージョンです。
  kintone :::2017/11月アップデート版
  php:::7.1.11
  jQuery:::3.2.1

5.グループと個人の違いを理解する。

さて、Oauthのライブラリをインストールしたことで、サイボウズLiveへの接続はすんなり成功しました。
ところが、上記のサイトでご提供されている情報は認証の部分とXMLのダウンロードまでです。取得したサイボウズLiveのデータをkintoneへ登録する部分はこちらで実装せねばなりません。
実装としてはphpでXMLを解析し、要素や値をkintoneにアップすればよいはず。

ここでサイボウズLiveのデータ構造をどのようにkintoneに移行するか考えないと。
つまり、個人データとグループのデータをどう関連づけ、kintoneに持ってくるか、という問題です。
例えばスケジュールのデータ。グループごとに分かれています。でも、データ構造は同一のはず。
実は個人スケジュールのデータには各グループのスケジュールも全部含まれるので、それを持ってくればよいのですが、グループ単位のスケジュールで取り込めるようにしておかねばあとで困るでしょう。

つまり考えねばならないのは以下の通り。
kintoneで、グループごとにスケジュールアプリを分けてつくるのか、それとも一つのスケジュールアプリに複数のcybozu Liveグループのデータをマージさせるのか。
言い換えれば、kintoneのアプリ単位にユーザーの権限を制御させるのがよいか、それとも同じアプリの中のレコード単位で権限を制御させるのがよいか、ということになります。

考えた結果、kintoneのグループスケジュールアプリは一つにし、グループのデータを別々に登録するようにしました。
個人スケジュールはグループスケジュールと別々にしなければ、あとでデータが混在して困るので、別にしました。ToDoも同じく個人とグループを分けています。

6.取り込み方法のインターフェース検討と実装。

個別にダウンロードするにあたっては、インターフェースを考えたほうがよいですね。
kintoneアプリの一覧画面にダウンロードリンクを貼ることにしました。ヘッダー下のスペースにセレクトボックスを二つ配置し、それに応じてphpへのリンクを切り替えるようにしています。

 取り込み部分のインターフェースはこんな感じで

・初期状態はこんな感じ。

・左側のドロップダウンがグループです。サイボウズのアカウントが属するグループをリストアップし、先頭は個人データとしています。

これらのグループは私が実際に使っている/いたものです。kintoneやcybozu界隈のグループも昔cybozu Liveにあったのですよ。懐かしい\(^o^)/

・右側のドロップダウンが対象となるデータです。左側が個人データなので、5種類のデータを取り込み対象として出しています。
 (「全て」と「テーマチャット」と「ダイレクトチャット」と「コネクション」は本記事では実装していません。)

・左側のドロップダウンをグループにすると、右側のドロップダウンの内容もかわります。4種類のデータを取り込み対象として出しています。
 (「全て」と「メンバーリスト」は本記事では実装していません)

・両方のドロップダウンの選択の値に応じて、すぐ下のリンクの文字列とurlが切り替わります。

ちなみに、各kintoneアプリはこの部分に同じJavaScriptファイルを読ませることで共通化しています。
なお、リンクをクリックした際も、それぞれ定められたアプリにデータを放り込む仕様にしています。そのため、各アプリのリンクから違うアプリの取り込み処理が可能にしています。とはいうものの、混乱はないはずです。

 この部分の実装について説明します。まずはJavaScriptの部分を。

・まず、アプリに対してJavaScriptを登録します。上にcybozu CDNからjQueryを。下にこの後説明するgetGroupList.jsを登録します。

・getGroupList.jsの先頭から。

ここはkintoneではお約束の記述ですね。
4行目のjQuery.support.cors = true;は jQueryのAjaxで他のドメインの値をとるときの呪文です。昔作ったコードを持ってきたので、今ならkintone.proxyのほうが良いと思います。kintone.proxyについてはこちらを。
その下のescapeHtml関数は、サニタイズ用です。まあ今回の案件についてはそういう心配は無用なのですが。ちなみにこのJavaScriptファイルはjswatchdogでチェックすると、三か所XSS Warningが出てしまいます。optionの部品オブジェクトを代入する際に「ちょっと自分危ないんとちゃう!?」と怒られてしまいます。放置しています。ごめんなさい。

・13行もkintoneのJavascriptではおなじみです。一覧の表示時に呼び出されるイベントです。

14-16行は、複数のドロップダウンを出さないようにするためのステップです。すでにドロップダウンがあれば処理を終了します。
19行から下は、jQueryのAjaxのお約束です。上に書いたようにkintone.proxyのほうがよいかも。
ここで、https://dummydesse.sakura.ne.jp/kintonefromcybozulive/cbl_grouplist.php を呼んでいるわけですね。このphpについては下で解説しますので、少々おまちを。

・26行から下は、データがきちんと取れた際の処理です。ここでselect部品やリンク部品を生成しています。
27行がphpから取得した値をこちらで用意した変数に代入しています。

36-37行は、初期値としてリンクに表示させる個人データ「全て」のリンクを表示しています。

・ここではphpが貢いでくれたグループのデータをselect部品のoptionに代入しています。
datalistは処理対象となるデータの種類です。初期値が個人データなので、個人データに対応するデータを配列に登録しています。

・ここでは配列のデータ種別をselecgt部品のoptionに代入しています。

さらに kintone.app.getHeaderMenuSpaceElement メソッドを使い、上で生成したselect部品やリンク部品をkintone画面に表示しています。

・66行目以下は、データ種別のselect値が変わった際に、リンクの表示文字列とurlを変更する処理です。

・78行目以下は、グループのselect値が変わった際に、リンクの表示文字列とurlを変更する処理です。個人とグループではデータの種別も変わるため、リンクの文字列やurlもあわせて変動させねばなりません。いやはや、大変ですね。

・以下は失敗した場合の処理です。ここはエラーメッセージなので、解説は割愛させてください。要するに疲れてきました・・・

 続いてphpでcybozu Liveで認証する部分です。

・といっても、この部分はまだプログラマーですが何か?さんのページを参考させてもらい、それをかなりの部分で使わせて頂きました。改めて感謝です。
とはいえ、私の実装ではcybozu Liveの認証部分は別phpファイルに切り出すなどの改良を加えています。それが5行目ですね。cbl_oauth.phpにお任せしているのです。3,4行目は上に書いたようにさくらインターネットのスタンダードプランに入れたhttp_Request2とhttp_oauthを呼び出しています。あまりサーバーに詳しくない方にとっては、この二つのインストールは厄介かもしれません。 

続いて、認証情報を格納する変数を三つ用意します。この三つの変数は以下の処理でも使うため、すぐ下のgetAccessTokenへは参照渡しをして、getAccessTokenの中で代入された値を使えるようにします。
そして、getAccessTokenを呼び出した結果をaccess_token_infoに格納します。getAccessTokenの戻り値は配列なので悪しからず。
さらに、10行に書いているとおりヘッダーでおまじないをとなえます。これはphpの中で違うドメイン(cybozu Live)のデータをとってくるときに、このおまじないを忘れると、11行目に書かれているような反撃を食らうためです。いわば白魔法の防御呪文のような感じです。

・12行目のtryで処理を開始します。
13行目のHTTP_Request2は上で読み込んだRequest2ファイルの中のクラスをインスタンスとして使いまっせ、ということです。 
14行目はssl_verify_peerをFalseにしています。つまりSSL証明書の検証を要求しませーん、という意味です。
17行目のHTTP_OAuth_Consumer_Requestは上で読み込んだOauthファイルの中のクラスをインスタンスとして使いまっせ、ということです。
18行目は、HTTP_Request2の設定に基づいて一旦つながしてーや、という意味です。まあ斥候みたいなもんです。

20行目は斥候がまず様子見した接続を、本体が認証情報を掲げて大手を振って入場するための準備です。上でとってきたcybozu Liveの認証キーをHTTP_OAuth_Consumerに渡してあげるのです。通行許可証ですな。厳重に4種類の通行許可証を渡してあげるわけです。
21行目は、上で準備した通行許可証を、18行目で斥候が先に接続のお伺いを立てて問題ないよーという情報を御旗にたてて、cybozu Live城にアクセスします。
26行目は、個人フォルダのパスです。cybozu Liveの個人Idはメールアドレスなのです。
27行目はフル許可設定で個人フォルダのパスをなければ生成します。

・34行目はcybozu LiveのAPIのエンドポイントと定められたURLあてにリクエストを送ります。
arrayの中にパラメーターを含めればいろいろとリクエストができますが、ここではグループ一覧をとりたいだけなので、パラメーターはなしで。なお、apiの仕様はこちらに載っています。

36行目でリクエストの結果が $xml0 に代入され、エラーがなければ40行に処理がいきます。
40行は、ここでcybozu Live apiに進呈されたグループ情報の配列に個人を加えるための初期値です。先に説明したインターフェースでは最初に「個人データ」がありました。
45行目では先頭に「個人データ」が入った配列がグループデータに従って生成されます。
47行目では、グループidに従って並び替えます。その際「個人データ」キーは0を指定しているので、かならず先頭です。
48行目は、JavaScriptが読めるようなjson形式でデータを返してあげています。echoで返してあげるとJavaScriptはデータとして喜ぶのです。
49行目以下はエラー処理。疲れたので割愛させてください・・・

 続いてphpでcybozu Liveで認証するコア部分です。

・ここに各種認証キーを記載します。

$consumer_keyには、cybozu Live apiのデベロッパー登録してきたキーを書き込みます。
$consumer_secretには、cybozu Live apiのデベロッパー登録してきたシークレット値を書き込みます。
$xauth_access_token_urlには、cybozu Live apiがトークン取得用としてご用意しているurlを指定します。
$authusernameには、あなたのcybozu Liveのログインアカウントを書きます。
$authpasswordには、あなたのcybozu Liveのログインパスワードを書きます。

・続いて認証リクエストの部分です。先ほどの説明と重複する部分もあるので、21-28行までの処理は説明を割愛しますね。 

30行目では、OauthのsendRequestのメソッドに対して、urlや認証情報のつまったパラメータを渡してあげます。
するとレスポンスにアクセストークンが戻ってくるのですね。あとは、phpのparse_str関数で$access_token_infoにトークン文字列を代入してあげるだけ。簡潔です。

・エラーハンドリングの部分は、割愛でお願いします。

ちなみに今回はkintoneのアプリ一覧画面上に実装しましたが、本当ならばポータルからダウンロードさせるのが親切な気がします。
多分、同じように実装すればいけるはずです。
お時間のあるかた、おもちとみかん食べながら、いかがでしょうか?

7.サイボウズLive APIの制限事項と、kintoneの対応機能の検討。

ところが、こうやって移行の検討を深めてみると、いくつか問題が出てきます。

Q1.サイボウズLiveのユーザーをそっくりkintoneのユーザーとして移行できない。なぜなら開発者ライセンスは5ユーザーしか作れないから。無料だからとたくさんアカウントを作ったはよいが、kintoneアカウントは有料ですから。
     ↓
 A1.kintoneのユーザーやグループの利用はあきらめ、ドロップダウンか文字列(一行)にデータを入れるしかない。またはユーザー一覧のアプリを作ってルックアップや関連レコードで連携させるとか。今回の記事ではドロップダウンか文字列(一行)か複数選択でお茶を濁しています。

Q2.サイボウズLiveのAPIに用意されているファイルダウンロードがそもそも画像のみ。
     ↓
 A2.画像しかとりこまないようにする。
 (ところが、今回は画像のアップロードの実装はしていません。以下は言い訳です。
  ・さくらインターネットのphpがftpサポート外だということをうかつにも忘れていまして。
  ・sshでログインし、コマンドからphpのconfigureやmakeを行ってftpやsocketを有効化した。参考サイト参考サイト
  ・ところがそれにも関わらずダウンロードができない。調べてみたらさくらのftpサーバーがRETR未対応ということで、サーバー自体がphpのftpを頑として受け付けないということに気がつき万策尽きる。
  ・curlだとローカル経由でアップロードした場合はfilekeyの取得ができるが、リモートURL経由ではresponseがNullになってしまう。
  ・処理の一貫性の観点では、ファイルがローカルに自動的にダウンロードされる実装を加えないと、ダウンロードの時点で一度別処理を挟み、それ以降のkintoneアプリに添付ファイルを登録するためのfilekey取得をあらためて行う必要が・・・・

Q3.サイボウズLiveのコメントをkintoneに移したい。ところが、APIトークン利用でのコメント追加だとコメント追加者がAdministrator扱いになってしまう。コメントの記載を各ユーザーで書かせるには、毎回認証ユーザーを切り替えねばならず、実装が面倒。
     ↓
 A3.コメントについてはサブテーブルで実装しました。松田さんのご提供アプリでも一部サブテーブルでしたし。

Q4.マイカレンダーにグループスケジュールへのリンクを実装するのが面倒。
     ↓
 A4.アプリ間の連携を円滑にするには、リンクの設定が不可欠ですが、今回の記事では実装していません。いずれやります。

Q5.スケジュールの日付範囲の取得がサイボウズLiveのAPIの仕様だと制限がある。(FromからToが365日以内でなければならないとか)
     ↓
 A5.他にも、cybozu Liveのスケジュールには通常予定と期間予定、繰り返し予定があります。その実装がちょっとひと手間必要なので、今回の記事では実装していません。いずれやります。

Q6.cybozu LiveのAPIの仕様では、一回当たりのデータ取得件数が最大100件になっている。
     ↓
 A6.これは再帰処理などで、実装可能だと思います。が、今回の記事では実装していません。いずれやります。

8.実装。

あとは、個別のプログラムごとに移行をわけ、それぞれのアプリごとに取り込むだけです。
せっかくなのでアプリは松田さんのご提供いただいたテンプレートをベースに使わせて頂き、適宜修正するようにします。

・今回ここで呼び出すurlとは、右下のリンクのUrlのことです。
 

 まずはxmlを配列に読み込むためのphpの中身です。

・では個人スケジュールから始めてみましょう。cbl_schedule.phpというファイルです。
20行目までは、グループ一覧を取得する処理とほぼ同じなので、割愛します。

・続いて認証処理からの流れです。こちらも32行目まではグループ一覧の取得時の処理と同じなので、割愛しますね。

重要なのは33行目です。ここではcybozu Live apiの個人スケジュールのエンドポイントurlを呼び出しています。
個人スケジュール情報のapiの仕様はこちらに載っています。
ここで、array内に取得する情報の条件をパラメーターで渡します。パラメーターのうち、個人スケジュールについては必須なのはありません。が、期間を指定しないと、思ったデータがとれません。条件の指定方法については、上のapi仕様に載っています。
とくにterm-startとterm-endの設定が重要です。
またmax-resultsは100が基本でしょうね。
embed-commentもコメント情報を取得するためには必要なパラメータです。
cybozu Live apiの一回当たりの取得件数は max-resultの最大値が100なので100件が限度です。
そこで全データを取得するためには、start-indexの値を毎回変動させつつリクエストを投げる必要があります。
38-39行目の置換の意味ですが、cybozu Liveから帰ってくるxmlのデータに名前空間付のタグがあります。名前空間付きのタグとは、
 

<cbl:group valueString="長井家予定" id="2:65107" />
    <cbl:comments>
      <cbl:feedLink>
 

のようなコロン付きのタグですね。このタグの内容はchildren(“cbl”,true)->group といった方法でパースすればデータの取得は可能です。ただ、コメントタグの中で、各コメントごとにある <entry cbl:sequence=”2″> がうまく配列として読みないのです。なので仕方なくコロンを _ に置換する方法を採りました。
45行目の simplexml_load_string で、取得したXMLデータをオブジェクトとして扱えるようにします。
46行目は $authoremail に投稿者のemailを代入します。$list0->author->email が 下記のようなxmlのデータを取得する際の命令文です。この$list0がsimplexml_load_stringで取得してきた全体のオブジェクトにあたります。その中の author タグのさらに下にある emailを取得する際にこの命令を投げればいいのですね。
 

   <author>
     <name>長井 祥和</name>
     <uri>2:39920</uri>
     <email>kakakakaka@dummy.jp</email>
   </author>
 

48行目は 取得したデータをkintoneに放り込むためのphpを呼び出しています。

・続けて、エントリごとの中身を取得に行きます。

49行目の foreach($list0->entry as $entry0) { はエントリータグを上から順にループ(フェッチ)させる命令です。
50-51行目は、entry毎のidを取得します。cybozu Liveのデータはカンマ区切りで四つ目の値がエントリidなので、それを採りに行きます。
52行目から57行目まで、取得時に(string)という文字があります。これは強制的にオブジェクトの型を文字列として変換する処理となります。
55行目と56行目にある cbl_when->attributes()->startTime というのは、XMLでいうと

<cbl_when startTime="2011-04-06T14:55:00Z" />

 のようなstartTimeの属性の値を取得するための命令です。 
59行目はXMLでいうとcbl:facility というタグを取得する際、タグの有無を判別するための文です。
タグがあれば、その中をループします。

・続いてxmlの中身を取得していきます。このあたりのxmlの構成は、apiの仕様を確認するか、もしくは後で紹介するサーバーに保存したxmlファイルの中身を確認するとよいでしょう。

・81行目から下は、エントリ本文に添付ファイルがあった場合の処理です。
添付ファイルの有無は if ($entry0->cbl_attachment) { で判別可能です。

fileDownload の関数は以下に説明しますが、サーバーにxmlファイルを置くための関数です。
93-94行目にある get_filekey_from_kintoneはkintoneにファイルをアップロードし、その添付ファイルをレコードを紐づけるためのfilekeyを取得するための関数です。ただ、言い訳にも書いた通り、ローカルへのダウンロードがうまくいきませんでした。そのため、今回は関数の中身は恥ずかしくてお見せできません。ですが、94行目のようにローカルファイルを指定するとfilekeyの取得はできることは確認済みです。

・98行目以下は、コメントのデータ取得です。
104行目の foreach( $cbl_entry as $entry2 ){ は複数コメントを順繰りに参照するための命令です。
なお、cybozu Liveのapiが提供するXMLファイルのコメントの一つ一つには番号が振られています。それが105行目の $entry2->attributes()->cbl_sequence で取得できます。
つまり、106-110行目の処理は、コメント一つ一つの番号をキーに設定し、連想配列としてコメントのそれぞれの値を格納しているのです。

なお、132-133行目の処理も、実際はうまく動かないため、コメントアウトしています。

・ここからは上の方法のおさらいですね。

・152行目から下は、配列に、取得してきた各値を代入していく作業です。

なお、179行目でheaderを指定してます。これは、呼び出し元に戻す命令です。ここでいう呼び出し元とはkintoneの一覧画面のことですね。これでkintoneにデータを登録した後、もとの画面に何事もなかったかのように涼しい顔で戻れるのです。

・で、こちらはfileDownload関数です。
cybozu Live apiはそもそも画像ファイルしかダウンロードができず、excelやwordファイルだとエラーになってしまいます。
エラーを回避するために拡張子が画像のものしかダウンロードさせないようにしています。ここではサーバー内の場所にファイルを保存するようにしています。

 続いて取得した配列データをkintoneに投げ込むphpの中身です。

・この辺りはデータを登録するためのトークン周りの処理ですね。
念のためですが、トークンの発行時には権限にレコード追加も含めておいてくださいね。

・ここでは、コメントのデータをkintoneのサブテーブルのjsonデータに整形しています。

・ここではkintoneに投げるデータの整形部分です。上でサブテーブル用に整形したコメントのデータも登録しています。

・取り込んだデータをcurlでリクエストとしてkintoneに投げています。

・カレンダービューに取り込んだデータが表示されます。

・レコード詳細もこの通りです。
コメントの内容もサブテーブルに入っていますよね。

とまあ、今日はここまでにしておきましょう。こちらでは個人スケジュール、グループスケジュール、個人ToDo、グループToDo、グループ掲示板まではデータの取得スクリプトを作成済みです。
 実は一つ取り込みのコツがわかれば、あとはデータ形式の差だけなのです。返す返すも添付ファイルの登録ができなかったのは残念ですすが、おいおい実装してこちらのブログをアップデートする予定です。

もしcybozu Liveからデータ移行をしたいというお客様がいらっしゃいましたら、お手伝いできますのでご相談ください。お安くさせて頂きますよ。


カテゴリ: kintone.
最終更新日: 12月 27, 2017

コメントを残して頂けると嬉しいです