Schedule Google Meet Using HTML and JavaScript.
Tags: javascript, webdev, googlecloud, meet
Published: 2022-10-31 04:40:53

In order to schedule a Google Meet with the attendees, first you need to create a event in your calendar and share with all the attendees. 

For the same I had previously wrote a blog on how to create a event using HTML and JavaScript. Refer to this [Blog](https://dev.to/debopriyadey/fetch-and-create-events-in-google-calendar-with-html-and-javascript-1o6f).

In this blog I will guide you to create a website using simple HTML and JavaScript through which you can automatically schedule a Google Meet in your calendar and also share the same with the attendees.

## Creating an Event in Google Calendar.

This is a very short explanation of creating an event. To read a brief explanation go [here](https://dev.to/debopriyadey/fetch-and-create-events-in-google-calendar-with-html-and-javascript-1o6f)

1. Enable Google Calendar API
2. Create API key and Client ID
3. Configure your OAuth Consent Screen and Publish your app
4. Add the following code in your *index.html*. ```

    <!DOCTYPE html>
    <html>
    <head>
    <title>Google Calendar API Quickstart</title>
     <meta charset="utf-8" />
     <style>
       form {
         margin: 10px;
       }
 
       fieldset {
         width: fit-content;
       }
 
       input {
         margin-block: 10px;
       }
     </style>
    </head>

    <body>
    <!--Add buttons to initiate auth sequence and sign out-->
    <button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
    <button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>
    <br />
    <form id="event_form">
      <fieldset>
        <input type="text" name="title" id="title" placeholder="Add Title" class="input-title" />
        <br />
        <textarea type="text" name="desc" id="desc" placeholder="Add Descreption" class="input-title"></textarea>
        <br />
        <label>Date</label>
        <input type="date" name="date" id="date" />
        <div>
          <label>Start Time</label>
          <input type="time" name="st" id="st" />
          <label>End Time</label>
          <input type="time" name="et" id="et" />
        </div>
        <button type="button" onclick="addEvent()">Schedule</button>
      </fieldset>
    </form>
    <pre id="content" style="white-space: pre-wrap;"></pre>
    <script src="./index.js" type="text/javascript"></script>
    <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
    <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
  </body>
</html> 
```

5. Add the following code in your *index.js* and set your API key and Client Id.
```
// TODO(developer): Set to client ID and API key from the Developer Console
const CLIENT_ID = "<YOUR_CLIENT_ID>";
const API_KEY = "<YOUR_API_KEY>";

// Discovery doc URL for APIs used by the quickstart
const DISCOVERY_DOC =
  "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest";

// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
const SCOPES = "https://www.googleapis.com/auth/calendar";

let tokenClient;
let gapiInited = false;
let gisInited = false;

document.getElementById("authorize_button").style.visibility = "hidden";
document.getElementById("signout_button").style.visibility = "hidden";
document.getElementById("event_form").style.visibility = "hidden";

function gapiLoaded() {
  gapi.load("client", initializeGapiClient);
}

async function initializeGapiClient() {
  await gapi.client.init({
    apiKey: API_KEY,
    discoveryDocs: [DISCOVERY_DOC]
  });
  gapiInited = true;
  maybeEnableButtons();
}

function gisLoaded() {
  tokenClient = google.accounts.oauth2.initTokenClient({
    client_id: CLIENT_ID,
    scope: SCOPES,
    callback: "" // defined later
  });
  gisInited = true;
  maybeEnableButtons();
}

function maybeEnableButtons() {
  if (gapiInited && gisInited) {
    document.getElementById("authorize_button").style.visibility = "visible";
  }
}

function handleAuthClick() {
  tokenClient.callback = async resp => {
    if (resp.error !== undefined) {
      throw resp;
    }
    document.getElementById("signout_button").style.visibility = "visible";
    document.getElementById("event_form").style.visibility = "visible";
    document.getElementById("authorize_button").innerText = "Refresh";
    await listUpcomingEvents();
  };

  if (gapi.client.getToken() === null) {
    // Prompt the user to select a Google Account and ask for consent to share their data
    // when establishing a new session.
    tokenClient.requestAccessToken({ prompt: "consent" });
  } else {
    // Skip display of account chooser and consent dialog for an existing session.
    tokenClient.requestAccessToken({ prompt: "" });
  }
}

function handleSignoutClick() {
  const token = gapi.client.getToken();
  if (token !== null) {
    google.accounts.oauth2.revoke(token.access_token);
    gapi.client.setToken("");
    document.getElementById("content").innerText = "";
    document.getElementById("authorize_button").innerText = "Authorize";
    document.getElementById("signout_button").style.visibility = "hidden";
    document.getElementById("event_form").style.visibility = "hidden";
  }
}

async function listUpcomingEvents() {
  let response;
  try {
    const request = {
      calendarId: "primary",
      timeMin: new Date().toISOString(),
      showDeleted: false,
      singleEvents: true,
      maxResults: 10,
      orderBy: "startTime"
    };
    response = await gapi.client.calendar.events.list(request);
  } catch (err) {
    document.getElementById("content").innerText = err.message;
    return;
  }

  const events = response.result.items;
  if (!events || events.length == 0) {
    document.getElementById("content").innerText = "No events found.";
    return;
  }
  // Flatten to string to display
  const output = events.reduce(
    (str, event) =>
      `${str}${event.summary} (${event.start.dateTime || event.start.date})\n`,
    "Events:\n"
  );
  document.getElementById("content").innerText = output;
}

const addEvent = () => {
  // Refer to the JavaScript quickstart on how to setup the environment:
  // https://developers.google.com/calendar/quickstart/js
  // Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
  // stored credentials.

  const title = document.getElementById("title").value;
  const desc = document.getElementById("desc").value;
  const date = document.getElementById("date").value;
  const start = document.getElementById("st").value;
  const end = document.getElementById("et").value;
  var ISOstartdate = "";

  const startTime = new Date(date + "," + start).toISOString();
  const endTime = new Date(date + "," + end).toISOString();

  var event = {
    summary: title,
    location: "Google Meet",
    description: desc,
    start: {
      dateTime: startTime,
      timeZone: "America/Los_Angeles"
    },
    end: {
      dateTime: endTime,
      timeZone: "America/Los_Angeles"
    },
    recurrence: ["RRULE:FREQ=DAILY;COUNT=2"],
    attendees: [{ email: "abc@google.com" }, { email: "xyz@google.com" }],
    reminders: {
      useDefault: false,
      overrides: [
        { method: "email", minutes: 24 * 60 },
        { method: "popup", minutes: 10 }
      ]
    }
  };

  console.log(event);
  var request = gapi.client.calendar.events.insert({
    calendarId: "primary",
    resource: event
  });

  request.execute(function(event) {
    console.log(event.htmlLink);
  });
};
```

## Schedule Google Meet

You can associate calendar events with Google Meet conferences to allow your users to meet remotely via a phone call or a video call. 

The conferenceData field can be used to read, copy, and clear existing conference details; it can also be used to request generation of new conferences. 

To create schedule a Google Meet while creating the calendar event we require 

1. The `requestId` which can be a random string.
2. The `calendarId` of the event creator that we will get from the responce after the event is created.
3. The `eventId` which is a combination of the Id and the start date of the event created.

We need to create a new function within `addEvent` function in our *index.js*
```
 async function createMeet(calendarId, eid) {
    const eventPatch = {
      conferenceData: {
        createRequest: { requestId: "7qxalsvy0e" }
      }
    };

    await gapi.client.calendar.events
      .patch({
        calendarId: calendarId,
        eventId: eid, // id + startdate.toISOString()
        resource: eventPatch,
        sendNotifications: true,
        conferenceDataVersion: 1
      })
      .execute(function(event) {
        console.log("Conference created for event: %s", event.htmlLink);
      });
  }
```

Now we need to call the `createMeet` function in `request.execute` method inside the `addEvent` function in our *index.js* add pass `calenderId` and `eventId` as the parameter. Therefore replace the `request.execute` method with this code.

```
request.execute(function(event) {
    var ISOstartdate = new Date(event.start.dateTime).toISOString();
    var eid =
      event.id + "_" + ISOstartdate.replace(/[:-]/g, "").replace(".000Z", "Z");
    var calendarId = event.creator.email;
    createMeet(calendarId, eid);
  });
```

I have pushed my code in this [GitHub Repo](https://github.com/debopriyadey/google-calendar-api/tree/gmeet) on `gmeet` branch you can fork it and add your innovations or if you want to contribute to this repository you can create a pull request.


## Reference

- https://developers.google.com/calendar/api/guides/create-events#conferencing