【问题标题】:Google Calendar API batch insert events with Apps Script使用 Apps 脚本的 Google Calendar API 批量插入事件
【发布时间】:2021-01-20 03:22:13
【问题描述】:

使用 Google Apps 脚本的 UrlFetchApp,我如何使用 Google Calendar v3 API 到 insert events in batches

Google 列出了this example batch request,但我不明白具体如何转换。

POST /batch/farm/v1 HTTP/1.1
Authorization: Bearer your_auth_token
Host: www.googleapis.com
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length

--batch_foobarbaz
Content-Type: application/http
Content-ID: <item1:12930812@barnyard.example.com>

GET /farm/v1/animals/pony

--batch_foobarbaz
Content-Type: application/http
Content-ID: <item2:12930812@barnyard.example.com>

PUT /farm/v1/animals/sheep
Content-Type: application/json
Content-Length: part_content_length
If-Match: "etag/sheep"

{
  "animalName": "sheep",
  "animalAge": "5"
  "peltColor": "green",
}

--batch_foobarbaz
Content-Type: application/http
Content-ID: <item3:12930812@barnyard.example.com>

GET /farm/v1/animals
If-None-Match: "etag/animals"

--batch_foobarbaz--

【问题讨论】:

    标签: http google-apps-script google-calendar-api


    【解决方案1】:

    我相信你的目标如下。

    • 您希望通过 Google Apps 脚本使用批处理请求将多个事件插入 Google 日历。

    在这种情况下,在当前阶段,需要创建请求正文,如您的问题所示。可以在the official document 看到示例请求正文。您的问题中已经提到了这一点。

    当创建请求体并请求它时,脚本变成如下。

    示例脚本:

    在使用此脚本之前,please enable Calendar API at Advanced Google services

    function myFunction() {
      const calendarId = "###";  // Please set the calendar ID.
      
      // Please set the object for inserting the calendar events. Each request body can be seen at https://developers.google.com/calendar/v3/reference/events/insert
      const events = [
        {start: {date: "2021-01-21"}, end: {date: "2021-01-21"},summary: "sample event 1"},
        {start: {date: "2021-01-22"}, end: {date: "2021-01-22"},summary: "sample event 2"}
      ];
    
      const boundary = "xxxxxxxxxx";
      const payload = events.reduce((s, e, i, a) => s += `Content-Type: application/http\r\n` +
        `Content-ID: ${i}\r\n\r\n` +
        `POST https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events\r\n` +
        `Content-Type: application/json; charset=utf-8\r\n\r\n` +
        `${JSON.stringify(e)}\r\n` +
        `--${boundary + (i == a.length - 1 ? "--" : "")}\r\n`
      , `--${boundary}\r\n`);
      const params = {
        method: "post",
        contentType: "multipart/mixed; boundary=" + boundary,
        payload: payload,
        headers: {Authorization: `Bearer ${ScriptApp.getOAuthToken()}`},
        muteHttpExceptions: true,
      };
      const res = UrlFetchApp.fetch("https://www.googleapis.com/batch/calendar/v3", params);
      console.log(res)
    
      // CalendarApp.getCalendarById();  // This is used for automatically detecting the scope of https://www.googleapis.com/auth/calendar
    }
    
    • 在此示例脚本中,示例请求正文用于events。所以请根据您的实际情况进行修改。

    注意:

    • 在当前阶段,批处理请求可以通过一次 API 调用运行 100 个请求。因此,当您使用上述脚本请求超过 100 个时,请修改它。请注意这一点。

    • 在这种情况下,我认为创建请求正文时可能会有点复杂。所以我将其创建为a Google Apps Script library。当使用这个库时,上面的脚本变成如下。在这个库中,即使请求数超过100,也可以通过内部库的处理来运行。

        const calendarId = "###";  // Please set the calendar ID.
        const requests = {
          batchPath: "batch/calendar/v3",
          requests: [
            {
              method: "POST",
              endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`,
              requestBody: {start: {date: "2021-01-21"}, end: {date: "2021-01-21"},summary: "sample event 1"},
            },
            {
              method: "POST",
              endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`,
              requestBody: {start: {date: "2021-01-22"}, end: {date: "2021-01-22"},summary: "sample event 2"},
            }
          ]
        };
        const res = BatchRequest.EDo(requests);
        console.log(res);
      

    参考资料:

    【讨论】:

    • 谢谢。我看过你的图书馆和一些我意识到回答这个问题的帖子,但我觉得我太困了。 (1)示例清楚地显示了每个部分开头重复的application/http,(2)换行很重要,(3)必须使用\r\n换行。
    • @Diego 感谢您的回复。我很高兴你的问题得到了解决。作为附加信息,在当前阶段,似乎不需要在请求正文中直接使用content-length。而且,这个存储库可能也很有用。 Ref
    【解决方案2】:

    我真的找不到执行批处理请求的文档。

    这是我对 NodeJS 的实现。这有点hacky,但似乎有效:

    const axios = require('axios');
    
    async function batchRequest({
      events,
      token,
      method = 'POST',
    }) {
      const batchSize = 50;
    
      const batchCount = Math.ceil(events.length / batchSize);
    
      const responses = [];
    
      for (let b = 0; b < batchCount; b += 1) {
        const boundary = 'xxxxxxxxxx';
        const payload = events.slice(b * batchSize, (b + 1) * batchSize).reduce((s, e, i, a) => s += 'Content-Type: application/http\r\n'
          + `Content-ID: ${i}\r\n\r\n`
          + `${method} https://www.googleapis.com/calendar/v3/calendars/${e.calendarId}/events${method === 'PATCH' ? `/${e.calendarEventId}` : ''}\r\n`
          + 'Content-Type: application/json; charset=utf-8\r\n\r\n'
          + `${JSON.stringify({ ...e, calendarEventId: undefined })}\r\n`
          + `--${boundary + (i === a.length - 1 ? '--' : '')}\r\n`,
        `--${boundary}\r\n`);
    
        const req = {
          url: 'https://www.googleapis.com/batch/calendar/v3',
          method: 'POST',
          headers: {
            'Content-Type': `multipart/mixed; boundary=${boundary}`,
            Authorization: `Bearer ${token}`,
          },
          data: payload,
        };
        const res = await axios(req);
    
        res.data.split('--batch_').forEach((batch) => {
          const resp = batch.split('\r\n\r\n');
          if (resp.length > 2) {
            try {
              responses.push(JSON.parse(resp.slice(2).join('\r\n')));
            } catch (e) {
              //
            }
          }
        });
      }
    
      return responses;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多