Search code examples
google-apps-scriptcalendargoogle-oauth

Sharing a Calendar in Google App Script


I am trying to build calendars from a spreadsheet and then share them with the appropriate people within the domain. I am doing this as a script attached to the spreadsheet.

So far I can read the right cells and build the calendars with the events, but where I am having problems is figuring out how to share specific calendars with the right people(s).

I have searched around and found the same general code to manually request the web pages to allow access which I have tried using to no avail. Am I missing a step everyone else is assuming you have done? All I have done is write a script on a spreadsheet, is there some setting somewhere to get it to work?

If it is not possible via scripting, what is the best way to approach such a thing? Would I be better off using PHP and a cron job?

My code to share a calendar is currently:

function onEdit() {
 calendarSharing('[email protected]', '[email protected]');
};

function calendarSharing(user1,user2){

    var scope = 'https://www.google.com/calendar/feeds/';
    var fetchArgs = googleOAuth_('calenders', scope);
    var rawXml= "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>"+
      "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>"+
      "<gAcl:scope type='user' value='"+user2+"'></gAcl:scope>"+
      "<gAcl:role value='http://schemas.google.com/gCal/2005#owner'>  </gAcl:role></entry>"
    fetchArgs.method = 'POST';
    fetchArgs.payload = rawXml
    fetchArgs.contentType = 'application/atom+xml';

    try{
         var url='https://www.google.com/calendar/feeds/'+user1+'/acl/full'        
         var urlFetch=UrlFetchApp.fetch(url,fetchArgs)                         //Giving Permission To personal account as a owner
       }
    catch(err){
        var err1=err.toString()
        var ex='Exception: Request failed for  returned code 302'
        if(ex==err1.split('.')[0]){
              var tempCalenderUrl=[]
              tempCalenderUrl.id = err1.split('<A HREF="')[1];
              tempCalenderUrl.id = tempCalenderUrl.id.split('"')[0];
              var url=tempCalenderUrl.id
              try{
                  var urlFetch=UrlFetchApp.fetch(url,fetchArgs)   
                 }
              catch(err){}
         }         
     }
}

function googleOAuth_(name,scope) {
  var oAuthConfig = UrlFetchApp.addOAuthService(name);
  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oAuthConfig.setConsumerKey('anonymous');
  oAuthConfig.setConsumerSecret('anonymous');
  return {oAuthServiceName:name, oAuthUseToken:"always"};
}

Solution

  • You can read and write calendar sharing information using the Advanced Calendar Service.

    This utility function will insert or update the sharing permissions for the given user on any calendar that you have writer privileges on. For example:

    // Add user as reader
    var rule = shareCalendar( '[email protected]',
                              '[email protected]');
    

    Code

    This function is also available as part of this gist.

    /**
     * Set up calendar sharing for a single user. Refer to 
     * https://developers.google.com/google-apps/calendar/v3/reference/acl/insert.
     *
     * @param {string} calId   Calendar ID
     * @param {string} user    Email address to share with
     * @param {string} role    Optional permissions, default = "reader":
     *                         "none, "freeBusyReader", "reader", "writer", "owner"
     *
     * @returns {aclResource}  See https://developers.google.com/google-apps/calendar/v3/reference/acl#resource
     */
    function shareCalendar( calId, user, role ) {
      role = role || "reader";
    
      var acl = null;
    
      // Check whether there is already a rule for this user
      try {
        var acl = Calendar.Acl.get(calId, "user:"+user);
      }
      catch (e) {
        // no existing acl record for this user - as expected. Carry on.
      }
    
      if (!acl) {
        // No existing rule - insert one.
        acl = {
          "scope": {
            "type": "user",
            "value": user
          },
          "role": role
        };
        var newRule = Calendar.Acl.insert(acl, calId);
      }
      else {
        // There was a rule for this user - update it.
        acl.role = role;
        newRule = Calendar.Acl.update(acl, calId, acl.id)
      }
    
      return newRule;
    }