Insert Event in Google Calendar With Javascript - javascript

My client ID is correct but hidden in this example.
I need help posting an event to my calendar. I believe I have the code correct but I need someone else's eyes.
I just need to post a event to the calendar.
SCOPES = ["https://www.googleapis.com/auth/calendar"]
function checkAuth() {
gapi.auth.authorize(
{
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true
}, handleAuthResult);
}
/**
* Handle response from authorization server.
*
* #param {Object} authResult Authorization result.
*/
function handleAuthResult(authResult) {
var authorizeDiv = document.getElementById('authorize-div');
if (authResult && !authResult.error) {
// Hide auth UI, then load client library.
authorizeDiv.style.display = 'none';
loadCalendarApi();
} else {
// Show auth UI, allowing the user to initiate authorization by
// clicking authorize button.
authorizeDiv.style.display = 'inline';
}
}
/**
* Initiate auth flow in response to user clicking authorize button.
*
* #param {Event} event Button click event.
*/
function handleAuthClick(event) {
gapi.auth.authorize(
{client_id: CLIENT_ID, scope: SCOPES, immediate: false},
handleAuthResult);
return false;
}
/**
* Load Google Calendar client library. List upcoming events
* once client library is loaded.
*/
function loadCalendarApi() {
gapi.client.load('calendar', 'v3', listUpcomingEvents);
}
/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
function listUpcomingEvents() {
var event = {
"summary":"Here"
"description":"Now"
"start":
{
"dateTime":"2016-04-21T12:00:00.000-07:00"
"timeZone":"America/Los_Angeles"
}
"end":
{
"dateTime":"2016-04-21T12:30:00.000-07:00"
"timeZone":"America/Los_Angeles"
}
};
var request = gapi.client.calendar.events.insert({
'calendarId': 'primary',
'resource': event
});
request.execute(function(event) {
appendPre('Event created: ' + event.htmlLink);
});
}

Related

How to access my own Google Calendar permanently via Google Calendar API v3?

I want to build an interface on my website (frontend) to enable clients to create events in my own Google Calendar (backend). I want to achieve this with the technologies JavaScript and/or PHP via Google Calendar API v3.
While working with this API is totally new for me I started with the code below which is a slightly modificated version of this mockup. It actually works like a charm but doesn't do what I need.
What I need is to authorize my particular site (lets say "axel.com/calendar" for example) to have "permanent" access to the events of my Google Calendar and to be able to add events based on particular actions of the user. The actual user of the interface doesn't have to authorize anything at all.
For the UI I tend to use FullCalendar by now.
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API Quickstart</title>
<meta charset='utf-8' />
</head>
<body>
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>
<pre id="content"></pre>
<script type="text/javascript">
var CLIENT_ID = '<YOUR_CLIENT_ID>';
var API_KEY = '<YOUR_API_KEY>';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listUpcomingEvents();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
function listUpcomingEvents() {
gapi.client.calendar.events.list({
'calendarId': 'primary',
'timeMin': (new Date()).toISOString(),
'showDeleted': false,
'singleEvents': true,
'maxResults': 10,
'orderBy': 'startTime'
}).then(function(response) {
var events = response.result.items;
appendPre('Upcoming events:');
if (events.length > 0) {
for (i = 0; i < events.length; i++) {
var event = events[i];
var when = event.start.dateTime;
if (!when) {
when = event.start.date;
}
appendPre(event.summary + ' (' + when + ')')
}
} else {
appendPre('No upcoming events found.');
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
Instead of using OAuth key you may use Service account credentials.
OAuth is used to access a client's calendar which requires the consent of the user.
Rather you should use Service account credentials to modify events in your own calendar which would be shared with the user.
On Google API developer console select the project and choose Service account for credentials instead of OAuth.
You will get a corresponding json credential file which you may use for authentication on Backend.
This link will help you out here
(particularly if you are using PHP Laravell)
https://github.com/spatie/laravel-google-calendar
Documentation is lacking for JS/TS. Firstly install the googleApi.
npm install googleapis
As stated elsewhere you'll have to do this with a service account - make your service account (make sure you keep the json file that is provided) and add the Domain-wide Delegation. It will look something like this (... for omitted parts):
{
"type": "service_account",
"project_id": ...,
"private_key_id": ...,
"private_key": "-----BEGIN PRIVATE KEY-----/n ...",
"client_email": "... # ... aim.gserviceaccount.com,
"client_id": ...,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2//v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ ...",
}
Typically, for backend applications which I find the main use case for skipping user auth, you'll have an auth manager. The following example assumes that you place the info from the downloaded json file in an external source:
import {google, calendar_v3} from "googleapis";
export class GoogleClient {
private static instance: GoogleClient;
private calendar: calendar_v3.Calendar;
private constructor() {}
static async getClient(): Promise<GoogleClient> {
if (!GoogleClient.instance) {
GoogleClient.instance = new GoogleClient();
const config = <CONFIG FILE FETCH>
const auth = new google.auth.GoogleAuth({
scopes:["https://www.googleapis.com/auth/calendar.events.readonly"],
credentials: {
private_key: config.private_key.replace(/\\n/g, "\n"),
client_email: config.client_email,
},
projectId: config.project_id,
});
GoogleClient.instance.calendar = google.calendar({
version: "v3",
auth,
});
}
return GoogleClient.instance;
}
// Other methods here that use your instance
}
The scopes above should match the scopes given on your Domain-wide Delegation. Some useful links to check your generated token (if you get an error you can go into the header to see your token):
www.googleapis.com/oauth2/v1/tokeninfo?access_token=<YOUR TOKEN>
an example of a method using the instance:
await this.calendar.events.list({
calendarId: <SOME EMAIL>
}).then((calendar) => calendar.data.items.map((item) => item.summary);
If you have an authorized account on your domain you can use the google playground for most API calls to test different query parameters. Note that the AUTH in these will use redirect urls instead of the service account.

how to link a new user to google analytics property/view using javascript

My requirement is, I need to add a new email id to an existing google analytics account's property.
function insertPropertyUserLink() {
var request = gapi.client.analytics.management.webpropertyUserLinks.insert(
{
'accountId': '123456',
'webPropertyId': 'UA-123456-1',
'resource': {
'permissions': {
'local': [
'EDIT',
'MANAGE_USERS'
]
},
'userRef': {
'email': 'liz#gmail.com'
}
}
});
request.execute(function (response) { // Handle the response. });
}
Above code i got from google documentation and i am using the following code for authorization:
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/analytics.manage.users';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// Retrieve the discovery document for version 3 of Google Drive API.
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/analytics/v3/management/accounts/';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from API Console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'mykey',
'discoveryDocs': [discoveryUrl],
'clientId': 'myclientId',
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function () {
handleAuthClick();
});
$('#revoke-access-button').click(function () {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked 'Sign out' button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus(isSignedIn) {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus(isSignedIn) {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">
Sign In/Authorize
</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">
Revoke access
</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
I have changed the API key and client id with mine and enabled the Analytics API for the app in console. Can anyone help me to integrate the above two code snippets to a single one and can be able to add a new user to analytics property.
To solve this: **gapi.client.analytics is undefined**
Change:
`gapi.load(**'client:auth2'**, initClient);`
to
gapi.load(**'client:analytics'**, initClient);
It worked for me.

Google Sign-in: how to avoid popup dialog if user is already signed in by using listeners?

Right now I'm using auth2.attachClickHandler(element, {}, onSuccess, onError);. It works, but if I've already signed in, the dialog box opens and closes right away which is rather ugly. Is there a way around this using listeners?
I played around the example but I'm not sure if listening for changes to current user is all I need, and my check of googleUser seems risky.
auth2 = gapi.auth2.init({client_id: 'xxxxx'});
auth2.currentUser.listen(function (user) {
googleUser = user;
if (typeof(googleUser.getBasicProfile()) !== 'undefined')
document.getElementById('signupAsGoogle').addEventHandler('click', popuplateForm);
else
auth2.attachClickHandler(document.getElementById('signupAsGoogle'), {}, onSuccess, onError);
Is there a better way? Thanks
Here is what I did to solve the same problem!
auth2 = gapi.auth2.init({
clientid: '${clientId}',
cookiepolicy: '${cookie_policy}',
});
auth2.currentUser.listen(function (googleUser) {
if (googleUser.isSignedIn()) {
// do your login(googleUser) function
} else {
auth2.attachClickHandler("your button", {},
function (googleUser) {
// do your login(googleUser) function
}, function (error) {
});
}
});

Make google auth request gapi.auth without a popup

Need to make auth request in js but the browser does not support popups. Is there any way to redirect to a new url or show the request in the in html5 page of the application
By using this code check if user authorized your app
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, callbackAuthResult);
Note: immediate:true
if you set immediate true then it wont show popup.
You see? You don't open the popup, and manage the stuff in the callback. This callback is usually used for post-processes. Here we use it for authenticating.
in callbackAuthResult:
callbackAuthResult = function (authResult) {
var authorizeButton = document.getElementById('authorize-button');
if (authResult && !authResult.error) {
authorizeButton.style.display = 'none';
// do your processing here
} else {
authorizeButton.style.display = 'block';
authorizeButton.onclick = callbackAuthClick;
}
}
callbackAuthClick = function (event) {
gapi.auth.authorize({
client_id: clientId,
scope: scopes,
immediate: false
}, handleAuthResult);
return false;
}

Google Calendar Api Intermittent 401

I have a simple code that Logs into to Google to use the Google Calendar API and creates and event for the user. The code works fine but every so often I get a 401 - Login Required error from Google. If I open the developer console in the browser and try again it works... which is very odd
var scopes = 'https://www.googleapis.com/auth/calendar';
var clientId = 'CLIENT_ID';
var apiKey = 'API_KEY';
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeButton = $('#calendarAuth');
var calendarFrame = $('#calendarFrame');
if (authResult && !authResult.error) {
authorizeButton.remove();
calendarFrame.show();
calendarFrame.attr('src', calendarFrame.attr('src')); //Hack to reload the iframe
} else {
authorizeButton.show();
calendarFrame.hide();
}
}
function Authorize() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
function GoogleScheduleFollowup(followup) {
gapi.client.load('calendar', 'v3', function () {
var request = gapi.client.calendar.events.insert({
"calendarId": "primary",
resource: {
"summary": followup.title,
"start": {
"dateTime": window.GetFullDateString(followup.date, followup.time)
},
"end": {
"dateTime": window.GetFullDateString(followup.date, followup.time)
}
}
});
request.execute(function (resp) {
console.log(resp);
});
}
Everything seems to be well configured in the API Console, and I'm sure we haven't reached the quota (either total or requests per second). As an example today I have made 133 requests of which 36 failed with this error.
I have tried to call gapi.auth.authorize every 10 minutes to see if the problem was a session timeout, and as I read in another question I tried removing this line gapi.client.setApiKey(apiKey);, both without success

Categories