スマートスピーカーAmazonEcho×Garoon連携

記事:Amazon Echoでスマートに予定の管理をしよう!にもコメントさせていただきましたが、コミュニティ:Garoon カスタマイズ フォーラムでもあらためて質問させていただきます。

kintone Tips & サンプル >> 外部連携 >> IoTのサンプルプログラムを参考に、Alexaから音声認識でキントーンのカレンダーアプリを操作するスキルを作成しました。

  • 「予定を教えて」→レコード検索、読み上げ
  • 「予定を登録して」→レコード追加

同じような動作を、ガルーンのスケジュールに対しても行いたいのですが、可能でしょうか?

外部システムからGaroonのカレンダーに対してアクションを試みるサンプルプログラムを発見できなかったため、参考になりそうなページがありましたら教えてください。

kintoneカスタマイズ経験はありますが、Garoonカスタマイズは初心者のため、ヒントをご教示いただけましたら幸いです。

本記事の方で、cybozu developer network運営事務局さんから回答をいただきました。

ありがとうございました。引き続き、関連情報募集しています。

tomomo85 さん

 

Garoon REST APIをNode.jsで実行する場合、kintoneと違い専用のライブラリ(kintone Node.js SDK)がないため少し面倒です。

Node.jsでREST APIを実行するためのモジュールは代表的なものでrequestモジュールがあります。

Node.jsのrequestモジュールを使ってHTTPSでPOSTリクエストを行う(Qiita記事)
https://qiita.com/penta515/items/074b5c7694b9bcec1043

↑の記事が参考になります。

あとは、スケジュールに関するGaroon REST APIのリファレンスを参考にコーディングしていけば、Garoonでも実装できるかと思います。

予定の取得(GET)
https://developer.cybozu.io/hc/ja/articles/360000440583

予定の登録(POST)
https://developer.cybozu.io/hc/ja/articles/360000425163

HANSAさん

コメントありがとうございます!ガルーンアクセス→予定の取得(GET)まで何とか実装できそうです。

いろいろハマったところがあるので、最終的にポイントをまとめてシェアしたいと思います。

現状、予定の登録(POST)がうまくいきません。

ヘッダにCSRFトークン?リクエストトークン?というのが必要なようですが、どうやって含めればいいのか…

tomomo85 さん

実装できそうで良かったです!

CSRFトークンについては、Garoon CSRFトークン利用例の記事が参考になりそうです。

外部からはユーザー認証しかできないはず(?)なので、
リクエストヘッダの認証をユーザー認証にする必要がありそうです。

さらに、ユーザー認証の場合はCSRFトークンは必要ないはずです。

外部からの接続処理を実装する前に、Garoon内でレコード登録リクエストが通ることを確認したかったのですが、うまくいきません。
説明を見る限り、CSRFトークンは必要なさそうなので、他のところに原因があるのかも?
ヘッダ情報の書き方は、“headers”:{“X-Cybozu-Authorization”: …}で合っているでしょうか?
既に両方試してみたのですが、

"headers"の中に"X-Cybozu-Authorization"を含めると、
 POST 415 (Unsupported Media Type)
 responseJSON:
 error:
 cause: "Content-Typeが指定されていない、または指定に誤りがあります。"
 errorCode: "GRN_REST_API_00103"
 message: "ヘッダーの指定が正しくありません。"

"headers": {…}の枠をコメントアウトすると、
 POST 520 (Garoon Error)
 responseJSON:
 error:
 cause: "不正なリクエストが行われた可能性があります。"
 errorCode: "FW00043"
 message: "ページを表示できません。"
…と、どちらにしてもエラーになります。
また、これをPOSTすると、いちいちGaroonサイトからログアウトされてしまいます。

**test.js**
(function($) {
 "use strict";
 // グループ週画面
 garoon.events.on('schedule.calendar.groupWeekIndex.show', function(event) {
  var query = {
   "type": 'POST',
   "url": 'https://sub_domain.cybozu.com/g/api/v1/schedule/events',
   "data": {
    "eventType": 'REGULAR', // REGULAR or ALL_DAY
    "subject": eventName,
    "attendees": [
     {
      "id": '1',
      "code": 'garoon@gmail.com',
      "type": 'USER'
     }
    ],
    "start": {
     "dateTime": stDateTime
    },
    "end": {
     "dateTime": endDateTime
    }
   },
   "dataType": 'json',
   "Content-Type": 'application/json',
   "X-Requested-With": 'XMLHttpRequest',
   //"headers": {
    "X-Cybozu-Authorization": 'Z2Fyb29uQGdtYWlsLmNvbTpwYXNzd29yZA==' // garoon@gmail.com:password
   //}
  };
  // Garoonにリクエストを送る
  $.ajax(query).done(function(resp) {
   // 成功の場合の処理
   console.log(resp);
  }).fail(function(error) {
   // エラーの場合処理
   console.log(error);
  });
 });
})(jQuery);

tomomo さん

Content-Typeはリクエストヘッダに含める必要があります。

https://developer.cybozu.io/hc/ja/articles/360000503306#step4

"headers" : {
"X-Cybozu-Authorization": 'Z2Fyb29uQGdtYWlsLmNvbTpwYXNzd29yZA==',
"Content-Type": 'application/json'
}

でどうでしょうか。

HANSAさん

たびたびすみません、ありがとうございます。

responseJSON:
error:
cause: “入力内容が正しくありません。”
errorCode: “GRN_REST_API_00105”
message: “GRN_REST_API_00105”

のエラーになってしまいました。

POSTしているデータは下記のとおりです。

var query = {
"type": 'POST',
"url": 'https://' + SUB_DOMAIN + '.cybozu.com/g/api/v1/schedule/events',
"data": {
"eventType": 'REGULAR', // REGULAR or ALL_DAY
"subject": 'イベント名',
// "attendees": [
// {
// "id": '2',
// "code": 'garoon@gmail.com',
// "type": 'USER'
// }
// ],
"facilities": [
{
"id": '1',
"code": 'Web会議室',
"name": 'Web会議室'
}
],
"start": {
"dateTime": '2018-12-19T07:44:27+09:00'
},
"end": {
"dateTime": '2018-12-19T08:44:00+09:00'
}
},
"dataType": 'json',
"headers": {
"Content-Type": 'application/json',
"X-Requested-With": 'XMLHttpRequest',
"X-Cybozu-Authorization": 'Z2Fyb29uQGdtYWlsLmNvbTpwYXNzd29yZA==' //garoon@gmail.com:password
}
};

入力内容のどの箇所が正しくないのでしょうか?やはりヘッダ?それともPOSTしているデータの構造?

予定の登録の記事にはサンプルコードが載っていませんが、リクエストボディの構造の説明を参考にしています。

ちなみに、ログイン認証文字列を変えてみると、

responseJSON:
error:
errorCode: “SLASH_LO02”
message: “ログイン名またはパスワードが間違っています。”

とエラーが変わるので、ログイン認証自体はできてるっぽいです。

tomomo さん

query.dateの中身をJSON.stringify()する必要がありそうです。

var param = {
"eventType": 'REGULAR', // REGULAR or ALL_DAY
"subject": 'イベント名',
// "attendees": [
// {
// "id": '2',
// "code": 'garoon@gmail.com',
// "type": 'USER'
// }
// ],
"facilities": [
{
"id": '1',
"code": 'Web会議室',
"name": 'Web会議室'
}
],
"start": {
"dateTime": '2018-12-19T07:44:27+09:00'
},
"end": {
"dateTime": '2018-12-19T08:44:00+09:00'
}
}

このparamを宣言した後で

var query = {
"type": 'POST',
"url": 'https://' + SUB_DOMAIN + '.cybozu.com/g/api/v1/schedule/events',
"data": JSON.stringify(param),
"dataType": 'json',
"headers": {
"Content-Type": 'application/json',
"X-Requested-With": 'XMLHttpRequest',
"X-Cybozu-Authorization": 'Z2Fyb29uQGdtYWlsLmNvbTpwYXNzd29yZA==' //garoon@gmail.com:password
}
};

でどうでしょう。

HANSAさん

できました!(ToT)
ご指摘ありがとうございます!!!
dataの中身だけJSON.stringify()が必要だったんですね!
ひとりでは気づくことができませんでした、ありがとうございます。

ハマってあれこれした結果、いろんなエラーコード発見してしまいました笑

「dateTime」の記法を変えた場合
responseJSON:
error:
cause: “start.dateTimeの日付の指定が不正です。”
errorCode: “GRN_REST_API_00220”
message: “パラメーターの指定が正しくありません。”

「timeZone: “Asia/Tokyo”」の記述を削った場合
responseJSON:
error:
cause: “start.timeZoneは必須パラメーターです。”
errorCode: “GRN_REST_API_00201”
message: “パラメーターの指定が正しくありません。”

片手間作業でなかなか進みませんが、年内にはGaroon×Alexa連携完成させたいと思います…!

tomomo さん

おめでとうございます!

これはjQueryのajax()の仕様だったりします。
実は私も過去にそれでつまづいたことがあったので回答できました。
参考:https://qiita.com/QUANON/items/dd39be7602f9e7226e8e

おお~
エラーメッセージ親切ですねー

完成したらぜひナレッジノートでの共有待ってます!
https://developer.cybozu.io/hc/ja/community/topics/115000025163