メインコンテンツへスキップ
見出し画像

ChatGPTにGoogleカレンダーを管理してもらおう!

    ぬる

    1. はじめに

    こんにちは!今日は、Google Apps Script (GAS)とChatGPTのGPTs機能を使って、簡単な秘書アプリを作る方法を説明します。このアプリでは、Googleカレンダーに予定を追加したり、カレンダーの予定を取得したりすることができます。

    画像
    使用例
    画像
    カレンダーと一致した!

    2. 必要な準備

    このプロジェクトでは以下のツールを使用します:

    • Google Apps Script (GAS):Googleのクラウド上で動くJavaScriptのようなプログラミング言語

    • Google カレンダー API:Googleカレンダーを操作するためのAPI

    • ChatGPT API:AIを活用した応答のためのAPI

    2.1 Google Apps Script (GAS) とは?

    Google Apps Scriptは、Googleサービス(例:スプレッドシート、カレンダー)をプログラムで操作できるツールです。簡単なコードを書くことで、手作業を自動化したり、他のGoogleアプリと連携させたりできます。

    3. コードの説明

    次に、必要なコードを説明します。

    3.1 日付を指定のタイムゾーンに変換する関数

    function convertToTimeZone(dateString, timeZone) {
      var date = new Date(dateString); // 1. ISOフォーマットの文字列をDateオブジェクトに変換
      var formattedDate = Utilities.formatDate(date, timeZone, "yyyy-MM-dd'T'HH:mm:ss"); // 2. 指定のタイムゾーンでフォーマット
      return new Date(formattedDate); // 3. フォーマットした文字列を再度Dateオブジェクトに変換して返す
    }

    説明:

    • `convertToTimeZone`は、指定したタイムゾーン(例えば「Asia/Tokyo」)に従って日付を変換する関数です。

    • `dateString`に日付、`timeZone`にタイムゾーンを渡して使います。

    3.2 POSTリクエストでカレンダーに予定を追加する

    function doPost(e) {
      var requestData = JSON.parse(e.postData.contents); // 1. POSTされたデータをパース
      var title = requestData.title; // 2. イベントタイトル取得
      var startTime = convertToTimeZone(requestData.startTime, "Asia/Tokyo"); // 3. 開始時間を日本時間に変換
      var endTime = convertToTimeZone(requestData.endTime, "Asia/Tokyo"); // 4. 終了時間を日本時間に変換
      var calendarId = requestData.calendarId; // 5. カレンダーIDを取得
      var description = requestData.description; // 6. イベントの説明
    
      var calendar = CalendarApp.getCalendarById(calendarId); // 7. カレンダーを取得
      var event = calendar.createEvent(title, startTime, endTime, {description: description}); // 8. イベントを作成
    
      var response = {
        status: "success", // 9. 成功した場合のステータス
        eventId: event.getId() // 10. 作成されたイベントのID
      };
    
      return ContentService.createTextOutput(JSON.stringify(response))
              .setMimeType(ContentService.MimeType.JSON); // 11. 結果をJSONで返す
    }

    説明:

    • このコードは、POSTリクエストで送られたデータを使ってGoogleカレンダーに新しい予定を追加します。

    • カレンダーIDを指定することで、どのカレンダーに追加するかをコントロールできます。

    3.3 GETリクエストでカレンダーの予定を取得する

    function doGet(e) {
      try {
        if (!e.parameter.date) {
          throw new Error('Date parameter is missing'); // 1. 日付パラメータがない場合にエラーを投げる
        }
        var date = e.parameter.date; // 2. パラメータから日付を取得
        var events = getEventsForDate(date); // 3. 日付に対応するイベントを取得
        
        return ContentService.createTextOutput(JSON.stringify(events))
                .setMimeType(ContentService.MimeType.JSON); // 4. 結果をJSONで返す
      } catch (error) {
        return ContentService.createTextOutput(JSON.stringify({ error: error.message }))
                .setMimeType(ContentService.MimeType.JSON); // 5. エラーが発生した場合の処理
      }
    }

    説明:

    • GETリクエストを受け取った際に、その日に対応するカレンダーイベントを取得して返す関数です。

    • 指定した日付にイベントがあれば、その情報をJSON形式で返します。

    4. 設定方法

    4.1 Google Apps Scriptのプロジェクト作成

    1. Googleドライブにアクセスし、「新規」 > 「その他」 > 「Google Apps Script」を選択します。

    2. 新規プロジェクトが開いたら、先ほどのコードをコピー&ペーストします。

    3. 「保存」をクリックし、プロジェクトに名前を付けます。

    4.2 カレンダーAPIの有効化

    1. 左側の「サービス」> 「GoogleカレンダーAPI」をクリックし、APIを有効化します。

    4.3 Webアプリケーションとしてデプロイ

    1. 画面右上の「デプロイ」> 「新しいデプロイ」をクリック。

    2. 「種類を選択」で「ウェブアプリケーション」を選択し、URLを発行します。

    4.4. テストと応用

    • 発行されたURLにGETまたはPOSTリクエストを送信して、アプリをテストします。

    • 例えば、POSTリクエストを使って「予定の追加」、GETリクエストを使って「予定の取得」を行います。

    5. 完成版コード

    5.1. 日付を指定のタイムゾーンに変換する関数

    function convertToTimeZone(dateString, timeZone) {
      var date = new Date(dateString); // ISOフォーマットの文字列をDateオブジェクトに変換
      var formattedDate = Utilities.formatDate(date, timeZone, "yyyy-MM-dd'T'HH:mm:ss");
      return new Date(formattedDate); // フォーマットした文字列を再度Dateオブジェクトに変換
    }

    5.2. POSTリクエストでカレンダーに予定を追加する関数

    function doPost(e) {
      var requestData = JSON.parse(e.postData.contents); // POSTリクエストからデータを取得
      var title = requestData.title; // イベントのタイトル
      var startTime = convertToTimeZone(requestData.startTime, "Asia/Tokyo"); // 開始時間を日本時間に変換
      var endTime = convertToTimeZone(requestData.endTime, "Asia/Tokyo"); // 終了時間を日本時間に変換
      var calendarId = requestData.calendarId; // カレンダーIDを取得
      var description = requestData.description; // イベントの説明
    
      // カレンダーにイベントを追加
      var calendar = CalendarApp.getCalendarById(calendarId);
      var event = calendar.createEvent(title, startTime, endTime, {description: description});
    
      // イベント作成の確認メッセージを返す
      var response = {
        status: "success", // 成功した場合のステータス
        eventId: event.getId() // 作成されたイベントのID
      };
    
      return ContentService.createTextOutput(JSON.stringify(response))
              .setMimeType(ContentService.MimeType.JSON);
    }

    5.3. GETリクエストでカレンダーの予定を取得する関数

    function doGet(e) {
      try {
        if (!e.parameter.date) {
          throw new Error('Date parameter is missing'); // 日付パラメータがない場合はエラー
        }
        var date = e.parameter.date; // パラメータから日付を取得
        Logger.log('Received request for date: ' + date);
        
        var events = getEventsForDate(date); // 指定された日付のイベントを取得
        
        return ContentService.createTextOutput(JSON.stringify(events))
                .setMimeType(ContentService.MimeType.JSON);
      } catch (error) {
        Logger.log('Error in doGet: ' + error.message);
        return ContentService.createTextOutput(JSON.stringify({ error: error.message }))
                .setMimeType(ContentService.MimeType.JSON);
      }
    }

    5.4. 日付に対応するカレンダーイベントを取得する関数

    var calendarDescriptions = {
      'primary': '個人カレンダー',
      'xxxx@group.calendar.google.com': 'XX',
    };
    
    var calendarIds = Object.keys(calendarDescriptions);
    
    function getEventsForDate(date) {
      try {
        var timeZone = "Asia/Tokyo"; // JSTタイムゾーン
    
        var startDate = new Date(date);
        var endDate = new Date(startDate);
        endDate.setDate(endDate.getDate() + 1); // 終了日は開始日+1日
    
        Logger.log('Fetching events for date range: ' + startDate + ' to ' + endDate);
        
        var allEvents = [];
    
        calendarIds.forEach(function(calendarId) {
          var calendar = CalendarApp.getCalendarById(calendarId);
          if (calendar) {
            var events = calendar.getEvents(startDate, endDate);
            var eventsData = events.map(function(event) {
              return {
                'calendarDescription': calendarDescriptions[calendarId],
                'summary': event.getTitle(),
                'start': Utilities.formatDate(event.getStartTime(), timeZone, "yyyy-MM-dd'T'HH:mm:ss'Z'"),
                'end': Utilities.formatDate(event.getEndTime(), timeZone, "yyyy-MM-dd'T'HH:mm:ss'Z'"),
                'description': event.getDescription()
              };
            });
            allEvents = allEvents.concat(eventsData);
            Logger.log('Events fetched from calendar: ' + calendarId + ' - ' + JSON.stringify(eventsData));
          } else {
            Logger.log('Calendar not found for ID: ' + calendarId);
          }
        });
    
        return allEvents;
      } catch (error) {
        Logger.log('Error in getEventsForDate: ' + error.message);
        return [];
      }
    }

    5.5. リクエストのログを記録する関数

    function logRequest(date, events) {
      try {
        var spreadsheetUrl = 'https://docs.google.com/spreadsheets/d/xxxx'; // スプレッドシートURL
        var sheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getActiveSheet();
        var timestamp = new Date();
        var logData = [timestamp, date, JSON.stringify(events)];
        
        sheet.appendRow(logData);
        Logger.log('Request logged successfully: ' + JSON.stringify(logData));
      } catch (error) {
        Logger.log('Error in logRequest: ' + error.message);
      }
    }

    5.6. テスト用関数

    function testGetEventsForDate() {
      var testDate = '2024-09-06'; // テスト日付
      
      var events = getEventsForDate(testDate);
      
      Logger.log(JSON.stringify(events)); // 結果をログに表示
    }

    5.7. 設定手順

    1. GASプロジェクトの作成:Googleドライブに移動し、新規作成からGoogle Apps Scriptを選び、コードを追加。

    2. GoogleカレンダーAPIの有効化:左側メニューからカレンダーAPIを有効にする。

    3. デプロイ:プロジェクトをウェブアプリケーションとしてデプロイし、URLを取得。

    5.8. テスト

    GETリクエストでカレンダーイベントを取得、POSTリクエストで新しいイベントを追加してみましょう。

    以下はChatGPTのMYGPT設定に関する設定例です。指示内容に基づき、ChatGPTが秘書として振る舞うように構成されています。

    6. GPTsの設定

    Role (役割):

    • 説明: あなたは秘書です。ChatGPTとして、カレンダーのスケジュール管理や予定の追加、カレンダーAPIとの連携を行います。

    Conversation Instructions (会話指示):

    • 短文で簡潔に答えることを重視する。

    • 「空いている時間」を聞かれた際、指定のルールに従って応答する。

    • カレンダーに予定を追加する場合、指定されたカレンダーIDを使用し、具体的に適切なカレンダーを選んで予定を追加する。

    • 時系列を整理して、計画や予定に関する会話を進める。

    Hidden Details (明示しない指示):

    • 必要に応じて、インデントや箇条書きを使って論理構造を示す。

    • メールの文体では丁寧な表現を使う。相手を気遣う表現(例:「お忙しいところ恐縮ですが」)を多用する。

    API Integration (API連携):

    • カレンダーAPI: GET/POSTリクエストを介して、カレンダーの予定を取得したり、予定を追加したりできる。
      例: ?date=YYYY-MM-DDの形式でリクエストを送信する。

    カレンダーID (カレンダーの例):

    • 'primary': '個人カレンダー',

    • 'xx@group.calendar.google.com':'作業',

    • その他、カレンダーに基づいた予定の管理と追加が可能。

    Usage Example (会話例):

    • Q: 「〇月〇日の空いている時間を教えてください。」

    • A: 「〇月〇日:12時以降空いています。」または「〇月〇日:全日空いています。」

    この設定により、MYGPTは指定のキャラクターとして行動し、カレンダー管理や予定のスケジュール調整を効果的に行います。

    {
      "openapi": "3.1.0",
      "info": {
        "title": "Get and Add Calendar Events",
        "description": "Retrieves events for a specified date from Google Calendar and adds new events to the calendar.",
        "version": "v1.1.0"
      },
      "servers": [
        {
          "url": "https://script.google.com"
        }
      ],
      "paths": {
        "/macros/s/xxx/exec": {
          "get": {
            "description": "Get events for a specific date.",
            "operationId": "GetCalendarEvents",
            "parameters": [
              {
                "name": "date",
                "in": "query",
                "description": "The date to retrieve events for in YYYY-MM-DD format",
                "required": true,
                "schema": {
                  "type": "string",
                  "format": "date"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "A list of calendar events",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    }
                  }
                }
              }
            },
            "deprecated": false
          },
          "post": {
            "description": "Add a new event to the calendar.",
            "operationId": "AddCalendarEvent",
            "requestBody": {
              "required": true,
              "content": {
                "application/json": {
                  "schema": {
                    "$ref": "#/components/schemas/NewEvent"
                  }
                }
              }
            },
            "responses": {
              "200": {
                "description": "Confirmation of event creation",
                "content": {
                  "application/json": {
                    "schema": {
                      "$ref": "#/components/schemas/EventCreationResponse"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "components": {
        "schemas": {
          "Event": {
            "type": "object",
            "properties": {
              "calendarDescription": {
                "type": "string",
                "description": "Description of the calendar the event belongs to"
              },
              "summary": {
                "type": "string",
                "description": "Summary or title of the event"
              },
              "start": {
                "type": "string",
                "format": "date-time",
                "description": "Start time of the event"
              },
              "end": {
                "type": "string",
                "format": "date-time",
                "description": "End time of the event"
              },
              "description": {
                "type": "string",
                "description": "Description or notes associated with the event"
              }
            },
            "required": [
              "calendarDescription",
              "summary",
              "start",
              "end",
              "description"
            ]
          },
          "NewEvent": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "description": "Title of the event"
              },
              "startTime": {
                "type": "string",
                "format": "date-time",
                "description": "Start time of the event"
              },
              "endTime": {
                "type": "string",
                "format": "date-time",
                "description": "End time of the event"
              },
              "calendarId": {
                "type": "string",
                "description": "ID of the calendar to add the event to"
              },
              "description": {
                "type": "string",
                "description": "Description or notes for the event"
              }
            },
            "required": [
              "title",
              "startTime",
              "endTime",
              "calendarId",
              "description"
            ]
          },
          "EventCreationResponse": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "description": "Status of the event creation"
              },
              "eventId": {
                "type": "string",
                "description": "ID of the created event"
              }
            },
            "required": [
              "status",
              "eventId"
            ]
          }
        }
      }
    }
    
     
     
     

    ぬる

     
     
    GPTを用いて風景や情緒を言語化し、メモとして残します。