22
20
記事投稿キャンペーン 「AI、機械学習」

Googleカレンダーを読み書きするAPIをGASで作ってGPTsのCustom Actionsから呼び出してみる

Posted at

はじめに

こんにちは、ほたるです。

Google Apps ScriptでAPIをつくり、GPTsから呼び出す方法について投稿しました。

この記事では、さらに複雑な処理にトライします。

  • Googleカレンダーに予定を追加
  • Googleカレンダーから1日分の予約を取得
  • 上記の2つの処理を一つのGPTsで会話文から判断して呼び分ける

今回は趣向を変えて、GoogleスプレッドシートではなくGoogleカレンダーを扱ってみました。

この記事の対象者

  • GPTsのCustom ActionsのAPIを自作したい方
  • Google Apps Scriptで簡単なスクリプトを作ったことがある方
  • Zapierの連携よりも複雑な処理を求めている方

APIの概要

二つのGoogle Apps Scriptを用意します。

  • カレンダーに予定を追加するスクリプト
  • カレンダーから1日分の予定を取得するスクリプト

スクリーンショット 2023-11-16 14.42.20.png

GPTsが会話文を解析して、二つの異なるスクリプトを呼び分けします。

Google Apps Scriptを作成

Google Apps Scriptにアクセスします。

スクリーンショット 2023-11-16 8.04.51.png

Apps Scriptのエディタが開きます。
スクリーンショット 2023-11-13 9.17.46.png

  • カレンダーに予定を追加するスクリプト
  • カレンダーから1日分の予定を取得するスクリプト
    の2つの別々のプロジェクト(スクリプト)を作成します。

カレンダーに予定を追加するスクリプト

AddSchedule.gs
// Googleカレンダーに予定を追加
function doPost(e) {
  try {
    console.log("start GPTs Custom Actions API Google Calendar");

    // リクエストからパラメータを取得
    console.log("e: " + JSON.stringify(e));
    var startDate = e.parameter.Date;
    var durationHours = parseInt(e.parameter.Hours, 10);
    var title = e.parameter.Title;
    console.log("e.parameter.Date: " + e.parameter.Date);
    console.log("e.parameter.Hours: " + e.parameter.Hours);
    console.log("e.parameter.Title: " + e.parameter.Title);

    // 開始日時の解析
    var year = startDate.substring(0, 4);
    var month = startDate.substring(4, 6) - 1; // JavaScriptの月は0から始まるため
    var day = startDate.substring(6, 8);
    var hour = startDate.substring(9, 11);
    var minute = startDate.substring(11, 13);
    console.log(`Year: ${year}, Month: ${month + 1}, Day: ${day}, Hour: ${hour}, Minute: ${minute}`);

    // Dateオブジェクトの作成
    var start = new Date(year, month, day, hour, minute);
    var end = new Date(start.getTime());
    end.setHours(start.getHours() + durationHours);

    // イベントの作成
    var calendar = CalendarApp.getDefaultCalendar();
    calendar.createEvent(title, start, end);

    // 成功メッセージの返送
    console.error("success");
    return ContentService.createTextOutput("success");

  } catch (error) {
    // エラー発生時の処理
    console.error("Error adding event: " + error.message);
    return ContentService.createTextOutput("Error: " + error.message);
  }
}

カレンダーから1日分の予定を取得するスクリプト

GetSchedule.gs
// Googleカレンダーから指定した日付の予定を取得
function doGet(e) {
  try {
    console.log("start Custom Actions GetSchedule");

    // リクエストからパラメータを取得
    console.log("e: " + JSON.stringify(e));
    var dateString = e.parameter.Day;
    console.log("e.parameter.Day: " + e.parameter.Day);

    // 日付の文字列から年、月、日を取得
    var year = parseInt(dateString.substring(0, 4), 10);
    var month = parseInt(dateString.substring(4, 6), 10) - 1; // JavaScriptの月は0から始まる
    var day = parseInt(dateString.substring(6, 8), 10);

    // 指定された日付の始まりと終わりを示すDateオブジェクトを作成
    var startTime = new Date(year, month, day);
    var endTime = new Date(year, month, day + 1);

    // Googleカレンダーからイベントを取得
    var calendar = CalendarApp.getDefaultCalendar();
    var events = calendar.getEvents(startTime, endTime);

    // イベントの情報を含むオブジェクトの配列を作成
    var eventsData = events.map(function(event) {
      return {
        'title': event.getTitle(),
        'startTime': event.getStartTime().toISOString() // ISO 8601形式の日付文字列
      };
    });

    // JSON形式で返す
    console.log("eventsData: " + eventsData);
    return ContentService.createTextOutput(
      JSON.stringify(eventsData)
    ).setMimeType(ContentService.MimeType.JSON);
  } catch (error) {
    // エラー発生時の処理
    console.error("Error adding event: " + error.message);
    return ContentService.createTextOutput("Error: " + error.message);
  }
}

Google Calendar APIを有効にする

Google Apps ScriptからGoogleカレンダーを読み書きするには、スクリプトでGoogle Calendar APIを有効にする必要があります。
2つのスクリプト両方に対して設定します。
スクリーンショット 2023-11-16 8.32.14.png
スクリーンショット 2023-11-16 8.32.44.png

Google Apps Scriptをデプロイ

2つのスクリプト両方に対してデプロイします。
スクリプトに対して初めてデプロイする方法はこちらを参照。

デプロイ完了した時のデプロイのURLを2つ分ひかえておきます。
→この後で使用します。

スクリプトを編集した場合は、こちらの手順でデプロイします。

GPTsを作成

特に設定はしません。
Instructionsはお好みで。
スクリーンショット 2023-11-16 10.21.22.png

GPTsのCustom Actionsを設定

スクリーンショット 2023-11-13 7.13.14.png

Schemaにこちらをコピペします。
コピペしたら、前の章でコピーしておいた、デプロイしたURLの一部(/macros以下)を貼り付けます。
今回は、関数2つ分、貼り付けますよ。

例えばデプロイしたURLが

https://script.google.com/macros/s/AKfycbzR2GGFg_9Ilnv55jzZDBQ3J_miH_OIQUn3qDJpPDBWSlnw-OT6H6rRZhkJ57EIijUYEQ/exec

の場合

/macros/s/AKfycbzR2GGFg_9Ilnv55jzZDBQ3J_miH_OIQUn3qDJpPDBWSlnw-OT6H6rRZhkJ57EIijUYEQ/exec

の部分を貼り付けます。

Schema
{
  "openapi": "3.1.0",
  "info": {
    "title": "Google Calendar Operations",
    "description": "Operations for Google Calendar",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://script.google.com"
    }
  ],
  "paths": {
    "ここにカレンダーに予定を追加するスクリプトのデプロイしたURLの /macros以下 のアドレスを設定": {
      "post": {
        "description": "Googleカレンダーに予定を追加します",
        "operationId": "AddSchedule",
        "parameters": [
          {
            "name": "Date",
            "in": "query",
            "description": "日付と時刻を指定 時刻は24時間制 例)2023年8月15日13時5分 : 20230815-1305",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Hours",
            "in": "query",
            "description": "時間数を指定 例)1時間 : 1、30分 : 0.5",
            "required": true,
            "schema": {
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "Title",
            "in": "query",
            "description": "予定に追加するタイトルを指定",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    },
    "ここにカレンダーから1日分の予定を取得するスクリプトのデプロイしたURLの /macros以下 のアドレスを設定": {
      "get": {
        "description": "Googleカレンダーから1日の予定を取得します",
        "operationId": "GetSchedule",
        "parameters": [
          {
            "name": "Day",
            "in": "query",
            "description": "日付を指定 例)2023年4月15日 : 20230415",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "deprecated": false
      }
    }
  },
  "components": {
    "schemas": {}
  }
}

Available actionsのところに、二つの関数が表示されていることを確認します。
スクリーンショット 2023-11-16 12.26.01.png

2023.11.16現在、Available actionsのTestボタンを押すと、その関数の通信テストができるようになっています。
右側のPrevewに、実際にAPIと通信したログが表示されます。
Schemaの設定に基づいていい感じにテストデータを生成して、APIと通信してテストしてくれるので助かる!

ためしてみる

スクリーンショット 2023-11-16 10.13.47.png

11月16日午後4時に「移動時間」が追加されました。
スクリーンショット 2023-11-16 10.14.05.png

複数の予定も一度に取得してくれます。
スクリーンショット 2023-11-16 12.45.53.png

スクリーンショット 2023-11-16 12.24.55.png
日本時間でなく世界標準時で回答してくることもあるので、要注意。
ここはInstructionsにプロンプトを設定すれば、なんとかなるかな。
スクリーンショット 2023-11-16 12.24.41.png

Custom ActionsがあるGPTsの公開について

ご参考までに、一般公開されることを考えている方は、こちらを参照願います。

考察

スクリプトについて

今回のスクリプトは、GoogleアカウントのデフォルトのGoogleカレンダーに予定を追加したり、予定を取得したりしました。
もし任意のカレンダーを操作したい場合は、適当にスクリプトを改造してみて下さい。
Javascriptがわからない場合でも、ChatGPT先生がスクリプトを作ってくれますよ。

Custom Actionsの設定について

Schemaで指定するAPIのエンドポイントのURLは処理ごとに別々に指定する必要があります。
なのでスクリプトが2つに分かれています。
1つのスクリプトにカレンダーに追加する処理とカレンダーを取得する処理を入れてみたりしましたが、うまく動きませんでした。
処理をかけて別のスクリプトにした方が手間は増えるかもしれませんが、わかりやすいかなと考えます。

テストボタンについて

このところはGPTsの画面や機能がどんどん改善されていくのを体感していく毎日です。
OpenAIの開発スピードに驚くばかりですね。
この機能は本当に便利で、APIの開発がはかどりました。助かりました。

Actionsについて

会話文を判断して、うまく2種類の処理を行ってもらうことに成功しました。
Scemaの設定次第では、3つ4つとかいけるでしょうね。
とは言え、処理の種類が多くなると、意地悪な会話文の内容だとうまく判断してくれない場合もあるかと考えられます。
例えば、お互いの処理自体の定義が意味的にかぶったりすると、GPTsがうまく会話文を判断できなくなるでしょう。
なので、どういう処理を行ってもらうかの仕様の検討から考えることがミソですね。

おわりに

Custom ActionsのSchema

この記事を参考にご自身でCustom ActionsのAPIを開発する際の一助になれば、幸いです。

最後までご精読いただき、ありがとうございました。

参考資料

22
20
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
22
20