Categories
Code

Download Gmail Attachments to Google Drive with Apps Script

The Save Gmail Attachments add-on for Google Drive downloads file attachments from an email message to a specific folder in your Google Drive. Internally, it uses Google Apps Script and the Advanced Drive Service to fetch the attachments and save them to Drive.

Here’s a sample snippet from the Gmail add-on that shows how you can use GmailApp service with Google Drive in Apps Script to create a copy of any Gmail attachment inside Google Drive.

We’ve set the includeAttachments option to true and includeInlineImages to false to only download regular (non-inline) attachments and not inline images.

export const saveGmailtoGoogleDrive = () => {
  const folderId = 'Google_Drive_Folder_Id';
  const searchQuery = 'has:attachments';
  const threads = GmailApp.search(searchQuery, 0, 10);
  threads.forEach(thread => {
    const messages = thread.getMessages();
    messages.forEach(message => {
      const attachments = message.getAttachments({
          includeInlineImages: false,
          includeAttachments: true
      });
      attachments.forEach(attachment => {
        Drive.Files.insert(
          {
            title: attachment.getName(),
            mimeType: attachment.getContentType(),
            parents: [{ id: folderId }]
          },
          attachment.copyBlob()
        );
      });
    });
  });
};
Categories
Code

Generate Screenshots of Google Slides with Google Script

The new TallTweets app uses the Google Apps Script to convert Google Apps Script into GIF images. Internally, it uses the Google Slides API for generating screenshot images of individual slides of the presentation before stitching them into a GIF.

This Google Apps Script function uses the Advanced Slides API to generate high-resolution thumbnail images of the slides and uploads the individual slides to the Google Drive of the current user.

The public URLs of screenshot images are accessible for 30 minutes post which the URLs will expire automatically. The default mime type of the thumbnail image is PNG.

function generateScreenshots(presentationId) {
  var presentation = SlidesApp.openById(presentationId);
  var baseUrl =
    "https://slides.googleapis.com/v1/presentations/{presentationId}/pages/{pageObjectId}/thumbnail";
  var parameters = {
    method: "GET",
    headers: { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    contentType: "application/json",
    muteHttpExceptions: true
  };

  // Log URL of the main thumbnail of the deck
  Logger.log(Drive.Files.get(presentationId).thumbnailLink);

  // For storing the screenshot image URLs
  var screenshots = [];

  var slides = presentation.getSlides().forEach(function(slide, index) {
    var url = baseUrl
      .replace("{presentationId}", presentationId)
      .replace("{pageObjectId}", slide.getObjectId());
    var response = JSON.parse(UrlFetchApp.fetch(url, parameters));

    // Upload Googel Slide image to Google Drive
    var blob = UrlFetchApp.fetch(response.contentUrl).getBlob();
    DriveApp.createFile(blob).setName("Image " + (index + 1) + ".png");

    screenshots.push(response.contentUrl);
  });

  return screenshots;
}
Categories
Code

Upload Google Drive Files to Dropbox with Google Apps Script

Learn how to upload any Google Drive file to your Dropbox folder using Google Apps Script. To get started, create a new Dropbox app, as explained in the previous Dropbox example, and get the access token to skip the OAuth2 workflow.

Also see: Upload Drive Files to Google Cloud Storage

function uploadGoogleFilesToDropbox(googleDriveFileId) {
  
  var parameters = {
    "path": "/PDF/labnol.pdf",
    "mode": "add",
    "autorename": true,
    "mute": false
  };
  
  // Add your Dropbox Access Token
  var dropboxAccessToken = 'labnolorg-MZmqX';  
  
  var headers = {
    "Content-Type": "application/octet-stream",
    'Authorization': 'Bearer ' + dropboxAccessToken,
    "Dropbox-API-Arg": JSON.stringify(parameters)
  };
  
  var driveFile = DriveApp.getFileById(googleDriveFileId);
  
  var options = {
    "method": "POST",
    "headers": headers,
    "payload": driveFile.getBlob().getBytes()
  };
  
  var apiUrl = "https://content.dropboxapi.com/2/files/upload";
  var response = JSON.parse(UrlFetchApp.fetch(apiUrl, options).getContentText());
  
  Logger.log("File uploaded successfully to Dropbox");
  
}
Categories
Code

How to List all your Team Drives in Google Drive with Apps Script

Google Team Drives are shared spaces in your Google Drive where you can store files and they instantly become available to all members of the Team Drive.

Unlike regular folders in Google Drive where the files are owned by the individual, files in Team Drive belong to the team and, if a user is no longer part of Team Drive, their files continue to be accessible.

While Google Team Drives are only available in the business and enterprise editions of G Suite, anyone, including consumer Gmail accounts and legacy Google Apps accounts, can be invited to become members of an existing Team Drive.

This Google Apps Script snippet uses the Google Drive API (v3) to determine the list of all Team Drives that the current user is a member of.

function getGoogleTeamDrives() {
  
  try {
    
    var teamDrives = {},
        baseUrl = "https://www.googleapis.com/drive/v3/teamdrives",
        token = ScriptApp.getOAuthToken(),
        params = {
          pageSize: 10,
          fields: "nextPageToken,teamDrives(id,name)"
        };
    
    do {
      
      // Written by Amit Agarwal @labnol
      // Web: www.ctrlq.org

      var queryString = Object.keys(params).map(function(p) {
        return [encodeURIComponent(p), encodeURIComponent(params[p])].join("=");
      }).join("&");
      
      var apiUrl = baseUrl + "?" + queryString;
      
      var response = JSON.parse(
        UrlFetchApp.fetch( apiUrl, {
          method: "GET",
          headers: {"Authorization": "Bearer " + token}
        }).getContentText());
      
      response.teamDrives.forEach(function(teamDrive) {
        teamDrives[teamDrive.id] = teamDrive.name;
      })
      
      params.pageToken = response.nextPageToken;
      
    } while (params.pageToken);
    
    return teamDrives;
    
  } catch (f) {
    
    Logger.log(f.toString());
    
  }
  
  return false;
  
}

The return object includes the ID of the Team Drive which is also the ID of the top level folder for this Team Drive. You can use the existingDriveApp service of Google Apps Script to create sub-folder or add new files to this folder.

Categories
Code

Google File Picker API with Google Drive – Working Example

The Google File Picker API lets users easily upload files to Google Drive and also select existing files and folders from Drive. The File Upload Forms for Google Drive is written in Google Apps Script and it lets users upload files to the form owner’s folder through the File Picker API.

Here’s a complete working example that shows how to integrate the File Picker API with a Google Apps Script based web app. You’d need to enable the Google Picker API from your Google Console and also generate the developer’s key.


// Server.gs
function doGet() {    
  return HtmlService
  .createTemplateFromFile("picker")
  .evaluate()
  .addMetaTag("viewport", "width=device-width, initial-scale=1")
  .setTitle("Google Drive Picker")
  .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);  
}

function include(fileName) {
  return HtmlService
  .createHtmlOutputFromFile(fileName)
  .getContent();
}

function initPicker() {
  return {
    locale: 'en',
    token: ScriptApp.getOAuthToken(),
    origin: "https://script.google.com",
    parentFolder: "xyz",
    developerKey: "ctrlq.org",
    dialogDimensions: {
      width: 600, 
      height: 425
    },
    picker: {
      viewMode: "LIST",
      mineOnly: true,
      mimeTypes: "image/png,image/jpeg,image/jpg",
      multiselectEnabled: true,
      allowFolderSelect: true,
      navhidden: true,
      hideTitle: true,
      includeFolders: true,
    }
  };
}

// For Scope
// DriveApp.getStorageUsed()
// DriveApp.getFilesByName("ctrlq.org")
// picker.html
// Offers button for uploading and selecting files


  
    
    
    
        
  
  
    

// javascript.html

Categories
Code

Differences between Google Team Drive and My Drive

G Suite Enterprise and G Suite Business users get unlimited storage and they can create Team Drives inside Google Drive. Unlike files in My Drive, files in Team Drive belong to the team instead of an individual.

This table outlines the differences between My Drive and Team Drives in Google Drive. It is currently not possible to sync files stored in Team Drives with your Mac or PC using the Google Drive client.

Google Team Drives My Drive
Who owns files and folders? The team The individual who created the file or folder
Can I restore files? Yes, if you have edit access or full access. Yes, if you created it.
Can I move files? To move files between Team Drives or from My Drive into a Team Drive, drag the files into the destination Team Drive folder. When you move a folder from My Drive to Team Drive, the ID will change. To move files between Team Drives, you must have full access to the original Team Drive and at least edit access to the destination Team Drive. Yes
Can I move folders? Only the domain admin can move folders inside Team Drives. Yes
Sharing All team members see the same file set. Different users might see different files in a folder, depending on their
access to individual files.
How long do files I delete stay in Trash? Each Team Drive has its own Trash. Only members with full access to the Team Drive can delete files. Files and folders in Trash are deleted permanently after 30 days or sooner if a full-access member deletes them first. Full access and edit access members can restore content from Trash. If you own the file you delete, it’s automatically removed from Drive on all of your devices and on the web. Deleted files are moved to Trash. They still count toward your total storage until you permanently delete them from Trash. If you delete a file that you don’t own or that’s been shared with you, other people can still access it until the owner deletes it.
Categories
Code

Download Unsplash Photos to Google Drive

Unsplash is the best source for free images on the Internet. The images have the Creative Commons zero license meaning you can do anything with the photos.

This Google Script uses the Unsplash API to fetch the most recently uploaded photos and downloads them to your Google Drive. The photo details, like the height, width, creator name, full RAW link, etc. are appended to a Google Spreadsheet.

You can set this is a time-based trigger to automatically save all the new Unsplash photos in your Google Drive. Change the page parameter to download all the old pictures as well. You would however need to create your CLIENT_ID for the API call.

function getUnsplashPhotos() {

    try {

        var ss = SpreadsheetApp.getActiveSheet();

        // Fetch a maximum of 30 photos per API call
        var url = "https://api.unsplash.com/photos/?client_id=API_CLIENT_ID&per_page=30&page=1";

        // Parse the JSON response in an Array
        var photos = JSON.parse(UrlFetchApp.fetch(url).getContentText());

        for (var p = 0; p < photos.length; p++) {

            var categories = [],
                photo = photos[p];

            for (var c = 0; c < photo.categories.length; c++) {
                categories.push(photo.categories[c].title);
            }

            var blob = UrlFetchApp.fetch(photos.urls.full).getBlob();

            var file = DriveApp.createFile(blob);

            file.setName(photos.user.name);

            var row = [
                photo.id,
                photo.created_at.substr(0, 10),
                categories.join(", "),
                photo.width,
                photo.height,
                photo.color, // Main Color Hex Mode
                photo.likes, // How popular is the photograph
                photo.user.name, // Credit the photographer
                photo.user.links.html,
                photo.urls.raw, // Full high res version URL
                photo.urls.full,
                file.getUrl() // URL of the photo in Google Drive
            ];

            ss.appendRow(row);

        }

    } catch (f) {
        Logger.log(f.toString());
    }
}

Categories
Code

Move File to a Different Folder in Google Drive

Google Apps Script doesn’t offer a method for moving files from one folder in Google Drive to another one but there’s an option to add a file in Drive to multiple folders (similar to symbolic links in Unix). That can be used for moving files as well – remove the file from all existing folders and add it to the target folder.


// Move file to another Google Drive Folder

function moveFileToAnotherFolder(fileID, targetFolderID) {

  var file = DriveApp.getFileById(fileID);
  
  // Remove the file from all parent folders
  var parents = file.getParents();
  while (parents.hasNext()) {
    var parent = parents.next();
    parent.removeFile(file);
  }

  DriveApp.getFolderById(targetFolderID).addFile(file);
  
}
Categories
Code

Send Emails with Attachments with Google Apps Script and Mandrill

Gmail sending limits are restricted especially when you are sending emails programatically as in the case of Mail Merge. You can only send a few hundred emails per day and then you’ve to wait the entire day for Google to reset your limit.

If you would like to send thousands of emails but without the daily restrictions, you can consider using an email sending service like Mandrill. You need a web domain and need to verify the ownership of that domain with Mandrill so that you are allowed to send emails via Mandrill. Once verified, you get an API key from Mandrill that you can use with Apps Script to send emails in bulk without restrictions.

Here’s a sample snippet that sends emails from Google Scripts via Mandrill. You also have to option to include file attachments in your emails and these files can be placed in a Google Drive folder. The sendEmail() method accepts both plain text and HTML Mail.

function sendEmail() {
  
  var MANDRILL_API_KEY = "<>";
  
  var files = [
    "<>",  
    "<>",  
    "<>"  
  ];

  var recipients = [
    {
      "email": "ctrlq+to@labnol.org",
      "name": "Amit Agarwal",
      "type": "to"
    }, {
      "email": "ctrlq+cc@labnol.org",
      "type": "cc"
    }, {
      "email": "ctrlq+bcc@gmail.com",
      "type": "bcc"
    }
  ];
  
  var attachments = [];
  
  for (var f in files) {
    var file = DriveApp.getFileById(files[f]);
    attachments.push({
      "type": file.getMimeType(),
      "name": file.getName(),
      "content": Utilities.base64Encode(file.getBlob().getBytes())
    });
  }
  
  var params = {
    "key": MANDRILL_API_KEY,
    "message": {
      "from_email": "<>",
      "from_name": "<>",
      "to": recipients,
      "attachments": attachments,
      "headers": {
        "Reply-To": "reply@example.com"
      },
      "subject": "Enter email subject",
      "text"   : "Enter email body in plain text",
      "html"   : "Enter HTML content with tags"
    }
  };

  var response = UrlFetchApp.fetch(
    "https://mandrillapp.com/api/1.0/messages/send.json", {
      'method': 'POST',
      'payload': JSON.stringify(params),
      'contentType': 'application/json'
    });

  Logger.log(response.getContentText());
}

It may take some time to build your mail domain reputation and hence the emails are queued and not sent instantly. Go to Mandrill Dashboard – Outbound Emails – Activity to see the current status of your sent Emails.

Mandrill Email Open Report

Also, it is no longer possible to send emails from generic addresses like @gmail.com or @outlook.com since Mandrill requires domain ownership verification to reduce spam emails.

Categories
Code

Share Files in Google Drive without Email Notifications

The File.addViewer() or File.addEditor() methods of Google Apps Script allow you to share files in Google Drive programmatically. These methods will however always send an email notification to the person with whom the file is being shared.

If you would like to share a file in Google Drive silently without sending them an email notification, the advanced Google Drive API can help. The Permissions.insert() method lets you specify sharing permissions for a file. The role can be either owner, writer or editor. The additionalRoles[] should be sent to commenter to add someone as a commenter.

When calling Drive.Permissions.insert(), specify the advanced option “sendNotificationEmails” to “false”. You’ll have to enable this however in your Google Apps Script project.





 Drive.Permissions.insert(
   {
     'role': 'writer',
     'type': 'user',
     'value': 'bob@example.com'
   },
   fileId,
   {
     'sendNotificationEmails': 'false'
   });

The method can be used to disable email notification when sharing folders too.



var folderid = folder.getId();

folder.setSharing(accessinfo, permissioninfo);

if (editors.length > 0) {
  for (var i = 0; i < editorsemails.length; i++) {
    Drive.Permissions.insert(
      {
        'role': 'writer',
        'type': 'user',
        'value': editorsemails[i]
      },
      folderid,
      {
        'sendNotificationEmails': 'false'
      });
  };
};

if (viewers.length > 0) {
  for (var i = 0; i < viewersemails.length; i++) {
    Drive.Permissions.insert(
      {
        'role': 'reader',
        'type': 'user',
        'value': viewersemails[i]
      },
      folderid,
      {
        'sendNotificationEmails': 'false'
      });
  };
};
Categories
Code

Upload Files to Google Cloud Storage with Google Scripts

One of my recent project involved uploading files from Google Drive to a particular bucket in Google Cloud Storage. The front-end was created in a Google Spreadsheet where the full Google Drive path of the file is specified along with the destination bucket / folder in Google Cloud Storage.

The Google Apps Script would then automatically upload the files from Drive to Cloud Storage via a time-based trigger or can be run manually as well.

To get started, you need to go to the Google Developer’s console and enable the Google Cloud Storage API and the Google Cloud Storage JSON Data API. Also enable billing for your account to access Google Cloud Storage. Then create the API keys (OAuth 2, Web Application) with the redirect URL containing your Google Apps Script project key. The OAuth2 library for Apps Script should also be included in your project.

var params = {
  CLIENT_ID: 'xxx.apps.googleusercontent.com',
  CLIENT_SECRET: 'xyz',
  BUCKET_NAME: 'ctrlq-bucket',
  FILE_PATH: 'folder_name/filename',
  DRIVE_FILE: 'fileID'
};

/* Written by Amit Agarwal */
/* Email: amit@labnol.org   Web: ctrlq.org */

function uploadFileToGCS() {

  var service = getService();
  if (!service.hasAccess()) {
    Logger.log("Please authorize %s", service.getAuthorizationUrl());
    return;
  }

  var blob = DriveApp.getFileById(params.DRIVE_FILE).getBlob();
  var bytes = blob.getBytes();

  var url = 'https://www.googleapis.com/upload/storage/v1/b/BUCKET/o?uploadType=media&name=FILE'
    .replace("BUCKET", params.BUCKET_NAME)
    .replace("FILE", encodeURIComponent(params.FILE_PATH));

  var response = UrlFetchApp.fetch(url, {
    method: "POST",
    contentLength: bytes.length,
    contentType: blob.getContentType(),
    payload: bytes,
    headers: {
      Authorization: 'Bearer ' + service.getAccessToken()
    }
  });

  var result = JSON.parse(response.getContentText());
  Logger.log(JSON.stringify(result, null, 2));
}

function getService() {
  return OAuth2.createService('ctrlq')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setClientId(params.CLIENT_ID)
    .setClientSecret(params.CLIENT_SECRET)
    .setCallbackFunction('authCallback')
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope('https://www.googleapis.com/auth/devstorage.read_write')
    .setParam('access_type', 'offline')
    .setParam('approval_prompt', 'force')
    .setParam('login_hint', Session.getActiveUser().getEmail());
}

function authCallback(request) {
  var service = getService();
  var authorized = service.handleCallback(request);
  if (authorized) {
    return HtmlService.createHtmlOutput('Connected to Google Cloud Storage');
  } else {
    return HtmlService.createHtmlOutput('Access Denied');
  }
}

/* For support and customization, see www.ctrlq.org */
Categories
Code

Google Apps Script Library for Google Drive API

The advanced Google Drive API offers access to functionality that is not available with the Drive API inside Google Apps Script. For instance, the Drive API offers Revisions that helps you monitor file changes. Google has published a library for the Drive API that makes it easy to use the API inside Google Scripts.

Spencer has published a wrapper library that makes it easy to use the advanced Google Drive API inside Google Apps Script.

/**
* Google Apps Script Library for the drive API
*
* Credit: +SpencerEaston 
* Source: https://drive.google.com/folderview?id=0B_j9_-NbJQQDcUNEckk2WGhETms 
* 
* OAuth2 Scopes
* https://www.googleapis.com/auth/drive
* https://www.googleapis.com/auth/drive.appdata
* https://www.googleapis.com/auth/drive.apps.readonly
* https://www.googleapis.com/auth/drive.file
* https://www.googleapis.com/auth/drive.metadata
* https://www.googleapis.com/auth/drive.metadata.readonly
* https://www.googleapis.com/auth/drive.photos.readonly
* https://www.googleapis.com/auth/drive.readonly
* https://www.googleapis.com/auth/drive.scripts
*/

var BASEURL_="https://www.googleapis.com/drive/v2/";
var tokenService_;

/*
* Stores the function passed that is invoked to get a OAuth2 token;
* @param {function} service The function used to get the OAuth2 token;
*
*/
function setTokenService(service){
  tokenService_ = service;
}

/*
* Returns an OAuth2 token from your TokenService as a test
* @return {string} An OAuth2 token
*
*/
function testTokenService(){
 return tokenService_();
}

/**
 * Performs a Fetch
 * @param {string} url The endpoint for the URL with parameters
 * @param {Object.} options Options to override default fetch options
 * @returns {Object.} the fetch results
 * @private
 */
function CALL_(path,options){
  var fetchOptions = {method:"",muteHttpExceptions:true, contentType:"application/json", headers:{Authorization:"Bearer "+tokenService_()}}
  var url = BASEURL_ + path;
  
  for(option in options){
    fetchOptions[option] = options[option];
  }
  
  var response = UrlFetchApp.fetch(url, fetchOptions)
  if(response.getResponseCode() != 200){
    throw new Error(response.getContentText())
  }else{
    return JSON.parse(response.getContentText());
  }
}

/**
 * Performs a Fetch and accumulation using pageToken parameter of the returned results
 * @param {string} url The endpoint for the URL with parameters
 * @param {Object.} options Options to override default fetch options
 * @param {string} returnParamPath The path of the parameter to be accumulated
 * @returns {Array.Object.} An array of objects
 * @private
 */
function CALLPAGE_(path,options, returnParamPath){
  var fetchOptions = {method:"",muteHttpExceptions:true, contentType:"application/json", headers:{Authorization:"Bearer "+tokenService_()}}
  for(option in options){
    fetchOptions[option] = options[option];
  }
  var url = BASEURL_ + path;
  var returnArray = [];
  var nextPageToken;
  do{
    if(nextPageToken){
      url += "?pageToken=" + nextPageToken;
    }
    var results = UrlFetchApp.fetch(url, fetchOptions);
    if(results.getResponseCode() != 200){
      throw new Error(results.getContentText());
    }else{
      var resp = JSON.parse(results.getContentText())
      nextPageToken = resp.nextPageToken;
      returnArray  = returnArray.concat(resp[returnParamPath])
    }
  }while(nextPageToken);
  return returnArray;
}

/**
 * Builds a complete URL from a base URL and a map of URL parameters.
 * @param {string} url The base URL.
 * @param {Object.} params The URL parameters and values.
 * @returns {string} The complete URL.
 * @private
 */
function buildUrl_(url, params) {
  var params = params || {}; //allow for NULL options
  var paramString = Object.keys(params).map(function(key) {
    return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
  }).join('&');
  return url + (url.indexOf('?') >= 0 ? '&' : '?') + paramString;
}

/**
* Gets the information about the current user along with Drive API settings
*
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned AboutResource object
*/
function aboutGet(options){
  var path = buildUrl_("about",options);
  var callOptions = {method:"GET"};
  var AboutResource = CALL_(path,callOptions);
  return AboutResource;
}

/**
* Gets a specific app.
*
* @param {string} appId The ID of the app.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned AppResource object
*/
function appsGet(appId,options){
  var path = buildUrl_("apps/"+appId,options);
  var callOptions = {method:"GET"};
  var AppResource = CALL_(path,callOptions);
  return AppResource;
}

/**
* Lists a user's installed apps.
*
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned AppListResource object
*/
function appsList(options){
  var path = buildUrl_("apps",options);
  var callOptions = {method:"GET"};
  var AppListResource = CALL_(path,callOptions);
  return AppListResource;
}

/**
* Gets a specific change.
*
* @param {string} changeId The ID of the change.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChangeResource object
*/
function changesGet(changeId,options){
  var path = buildUrl_("changes/"+changeId,options);
  var callOptions = {method:"GET"};
  var ChangeResource = CALL_(path,callOptions);
  return ChangeResource;
}

/**
* Lists the changes for a user.
*
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChangeListResource object
*/
function changesList(options){
  var path = buildUrl_("changes",options);
  var callOptions = {method:"GET"};
  var ChangeListItems = CALLPAGE_(path,callOptions,"items");
  return ChangeListItems;
}

/**
* Subscribe to changes for a user.
*
* @param {object} ChannelResource An object containing the ChannelResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChannelResource object
*/
function changesWatch(ChannelResource,options){
  var path = buildUrl_("changes/watch",options);
  var callOptions = {method:"POST",payload:JSON.stringify(ChannelResource)};
  var ChannelItems = CALLPAGE_(path,callOptions,"items");
  return ChannelItems;
}

/**
* Stop watching resources through this channel
*
* @param {object} ChannelResource An object containing the ChannelResource for this method
* @param {object} options Keypair of all optional parameters for this call
*/
function channelsStop(ChannelResource,options){
  var path = buildUrl_("channels/stop",options);
  var callOptions = {method:"POST",payload:JSON.stringify(ChannelResource)};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Removes a child from a folder.
*
* @param {string} folderId The ID of the folder.
* @param {string} childId The ID of the child.
* @param {object} options Keypair of all optional parameters for this call
*/
function childrenDelete(folderId,childId,options){
  var path = buildUrl_("files/"+folderId+"/children/"+childId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a specific child reference.
*
* @param {string} folderId The ID of the folder.
* @param {string} childId The ID of the child.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChildReferenceResource object
*/
function childrenGet(folderId,childId,options){
  var path = buildUrl_("files/"+folderId+"/children/"+childId,options);
  var callOptions = {method:"GET"};
  var ChildReferenceResource = CALL_(path,callOptions);
  return ChildReferenceResource;
}

/**
* Inserts a file into a folder.
*
* @param {string} folderId The ID of the folder.
* @param {object} ChildReferenceResource An object containing the ChildReferenceResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChildReferenceResource object
*/
function childrenInsert(folderId,ChildReferenceResource,options){
  var path = buildUrl_("files/"+folderId+"/children",options);
  var callOptions = {method:"POST",payload:JSON.stringify(ChildReferenceResource)};
  var ChildReferenceResource = CALL_(path,callOptions);
  return ChildReferenceResource;
}

/**
* Lists a folder's children.
*
* @param {string} folderId The ID of the folder.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChildListResource object
*/
function childrenList(folderId,options){
  var path = buildUrl_("files/"+folderId+"/children",options);
  var callOptions = {method:"GET"};
  var ChildListItems = CALLPAGE_(path,callOptions,"items");
  return ChildListItems;
}

/**
* Deletes a comment.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} options Keypair of all optional parameters for this call
*/
function commentsDelete(fileId,commentId,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a comment by ID.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentResource object
*/
function commentsGet(fileId,commentId,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId,options);
  var callOptions = {method:"GET"};
  var CommentResource = CALL_(path,callOptions);
  return CommentResource;
}

/**
* Creates a new comment on the given file.
*
* @param {string} fileId The ID of the file.
* @param {object} CommentResource An object containing the CommentResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentResource object
*/
function commentsInsert(fileId,CommentResource,options){
  var path = buildUrl_("files/"+fileId+"/comments",options);
  var callOptions = {method:"POST",payload:JSON.stringify(CommentResource)};
  var CommentResource = CALL_(path,callOptions);
  return CommentResource;
}

/**
* Lists a file's comments.
*
* @param {string} fileId The ID of the file.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentListResource object
*/
function commentsList(fileId,options){
  var path = buildUrl_("files/"+fileId+"/comments",options);
  var callOptions = {method:"GET"};
  var CommentListItems = CALLPAGE_(path,callOptions,"items");
  return CommentListItems;
}

/**
* Updates an existing comment. This method supports patch semantics.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} CommentResource An object containing the CommentResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentResource object
*/
function commentsPatch(fileId,commentId,CommentResource,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(CommentResource)};
  var CommentResource = CALL_(path,callOptions);
  return CommentResource;
}

/**
* Updates an existing comment.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} CommentResource An object containing the CommentResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentResource object
*/
function commentsUpdate(fileId,commentId,CommentResource,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(CommentResource)};
  var CommentResource = CALL_(path,callOptions);
  return CommentResource;
}

/**
* Creates a copy of the specified file.
*
* @param {string} fileId The ID of the file to copy.
* @param {object} FileResource An object containing the FileResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesCopy(fileId,FileResource,options){
  var path = buildUrl_("files/"+fileId+"/copy",options);
  var callOptions = {method:"POST",payload:JSON.stringify(FileResource)};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Permanently deletes a file by ID. Skips the trash. The currently authenticated user must own the file.
*
* @param {string} fileId The ID of the file to delete.
* @param {object} options Keypair of all optional parameters for this call
*/
function filesDelete(fileId,options){
  var path = buildUrl_("files/"+fileId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Permanently deletes all of the user's trashed files.
*
* @param {object} options Keypair of all optional parameters for this call
*/
function filesEmptyTrash(options){
  var path = buildUrl_("files/trash",options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Generates a set of file IDs which can be provided in insert requests.
*
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned GeneratedIdsResource object
*/
function filesGenerateIds(options){
  var path = buildUrl_("files/generateIds",options);
  var callOptions = {method:"GET"};
  var GeneratedIdsResource = CALL_(path,callOptions);
  return GeneratedIdsResource;
}

/**
* Gets a file's metadata by ID.
*
* @param {string} fileId The ID for the file in question.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesGet(fileId,options){
  var path = buildUrl_("files/"+fileId,options);
  var callOptions = {method:"GET"};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Insert a new file.
*
* @param {object} FileResource An object containing the FileResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesInsert(FileResource,options){
  var path = buildUrl_("files",options);
  var callOptions = {method:"POST",payload:JSON.stringify(FileResource)};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Lists the user's files.
*
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileListResource object
*/
function filesList(options){
  var path = buildUrl_("files",options);
  var callOptions = {method:"GET"};
  var FileListItems = CALLPAGE_(path,callOptions,"items");
  return FileListItems;
}

/**
* Updates file metadata and/or content. This method supports patch semantics.
*
* @param {string} fileId The ID of the file to update.
* @param {object} FileResource An object containing the FileResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesPatch(fileId,FileResource,options){
  var path = buildUrl_("files/"+fileId,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(FileResource)};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Set the file's updated time to the current server time.
*
* @param {string} fileId The ID of the file to update.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesTouch(fileId,options){
  var path = buildUrl_("files/"+fileId+"/touch",options);
  var callOptions = {method:"POST"};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Moves a file to the trash. The currently authenticated user must own the file.
*
* @param {string} fileId The ID of the file to trash.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesTrash(fileId,options){
  var path = buildUrl_("files/"+fileId+"/trash",options);
  var callOptions = {method:"POST"};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Restores a file from the trash.
*
* @param {string} fileId The ID of the file to untrash.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesUntrash(fileId,options){
  var path = buildUrl_("files/"+fileId+"/untrash",options);
  var callOptions = {method:"POST"};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Updates file metadata and/or content.
*
* @param {string} fileId The ID of the file to update.
* @param {object} FileResource An object containing the FileResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned FileResource object
*/
function filesUpdate(fileId,FileResource,options){
  var path = buildUrl_("files/"+fileId,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(FileResource)};
  var FileResource = CALL_(path,callOptions);
  return FileResource;
}

/**
* Subscribe to changes on a file
*
* @param {string} fileId The ID for the file in question.
* @param {object} ChannelResource An object containing the ChannelResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ChannelResource object
*/
function filesWatch(fileId,ChannelResource,options){
  var path = buildUrl_("files/"+fileId+"/watch",options);
  var callOptions = {method:"POST",payload:JSON.stringify(ChannelResource)};
  var ChannelResource = CALL_(path,callOptions);
  return ChannelResource;
}

/**
* Removes a parent from a file.
*
* @param {string} fileId The ID of the file.
* @param {string} parentId The ID of the parent.
* @param {object} options Keypair of all optional parameters for this call
*/
function parentsDelete(fileId,parentId,options){
  var path = buildUrl_("files/"+fileId+"/parents/"+parentId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a specific parent reference.
*
* @param {string} fileId The ID of the file.
* @param {string} parentId The ID of the parent.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ParentReferenceResource object
*/
function parentsGet(fileId,parentId,options){
  var path = buildUrl_("files/"+fileId+"/parents/"+parentId,options);
  var callOptions = {method:"GET"};
  var ParentReferenceResource = CALL_(path,callOptions);
  return ParentReferenceResource;
}

/**
* Adds a parent folder for a file.
*
* @param {string} fileId The ID of the file.
* @param {object} ParentReferenceResource An object containing the ParentReferenceResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ParentReferenceResource object
*/
function parentsInsert(fileId,ParentReferenceResource,options){
  var path = buildUrl_("files/"+fileId+"/parents",options);
  var callOptions = {method:"POST",payload:JSON.stringify(ParentReferenceResource)};
  var ParentReferenceResource = CALL_(path,callOptions);
  return ParentReferenceResource;
}

/**
* Lists a file's parents.
*
* @param {string} fileId The ID of the file.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned ParentListResource object
*/
function parentsList(fileId,options){
  var path = buildUrl_("files/"+fileId+"/parents",options);
  var callOptions = {method:"GET"};
  var ParentListResource = CALL_(path,callOptions);
  return ParentListResource;
}

/**
* Deletes a permission from a file.
*
* @param {string} fileId The ID for the file.
* @param {string} permissionId The ID for the permission.
* @param {object} options Keypair of all optional parameters for this call
*/
function permissionsDelete(fileId,permissionId,options){
  var path = buildUrl_("files/"+fileId+"/permissions/"+permissionId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a permission by ID.
*
* @param {string} fileId The ID for the file.
* @param {string} permissionId The ID for the permission.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionResource object
*/
function permissionsGet(fileId,permissionId,options){
  var path = buildUrl_("files/"+fileId+"/permissions/"+permissionId,options);
  var callOptions = {method:"GET"};
  var PermissionResource = CALL_(path,callOptions);
  return PermissionResource;
}

/**
* Returns the permission ID for an email address.
*
* @param {string} email The email address for which to return a permission ID
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionIdResource object
*/
function permissionsGetIdForEmail(email,options){
  var path = buildUrl_("permissionIds/"+email,options);
  var callOptions = {method:"GET"};
  var PermissionIdResource = CALL_(path,callOptions);
  return PermissionIdResource;
}

/**
* Inserts a permission for a file.
*
* @param {string} fileId The ID for the file.
* @param {object} PermissionResource An object containing the PermissionResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionResource object
*/
function permissionsInsert(fileId,PermissionResource,options){
  var path = buildUrl_("files/"+fileId+"/permissions",options);
  var callOptions = {method:"POST",payload:JSON.stringify(PermissionResource)};
  var PermissionResource = CALL_(path,callOptions);
  return PermissionResource;
}

/**
* Lists a file's permissions.
*
* @param {string} fileId The ID for the file.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionListResource object
*/
function permissionsList(fileId,options){
  var path = buildUrl_("files/"+fileId+"/permissions",options);
  var callOptions = {method:"GET"};
  var PermissionListResource = CALL_(path,callOptions);
  return PermissionListResource;
}

/**
* Updates a permission using patch semantics.
*
* @param {string} fileId The ID for the file.
* @param {string} permissionId The ID for the permission.
* @param {object} PermissionResource An object containing the PermissionResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionResource object
*/
function permissionsPatch(fileId,permissionId,PermissionResource,options){
  var path = buildUrl_("files/"+fileId+"/permissions/"+permissionId,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(PermissionResource)};
  var PermissionResource = CALL_(path,callOptions);
  return PermissionResource;
}

/**
* Updates a permission.
*
* @param {string} fileId The ID for the file.
* @param {string} permissionId The ID for the permission.
* @param {object} PermissionResource An object containing the PermissionResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PermissionResource object
*/
function permissionsUpdate(fileId,permissionId,PermissionResource,options){
  var path = buildUrl_("files/"+fileId+"/permissions/"+permissionId,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(PermissionResource)};
  var PermissionResource = CALL_(path,callOptions);
  return PermissionResource;
}

/**
* Deletes a property.
*
* @param {string} fileId The ID of the file.
* @param {string} propertyKey The key of the property.
* @param {object} options Keypair of all optional parameters for this call
*/
function propertiesDelete(fileId,propertyKey,options){
  var path = buildUrl_("files/"+fileId+"/properties/"+propertyKey,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a property by its key.
*
* @param {string} fileId The ID of the file.
* @param {string} propertyKey The key of the property.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PropertyResource object
*/
function propertiesGet(fileId,propertyKey,options){
  var path = buildUrl_("files/"+fileId+"/properties/"+propertyKey,options);
  var callOptions = {method:"GET"};
  var PropertyResource = CALL_(path,callOptions);
  return PropertyResource;
}

/**
* Adds a property to a file.
*
* @param {string} fileId The ID of the file.
* @param {object} PropertyResource An object containing the PropertyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PropertyResource object
*/
function propertiesInsert(fileId,PropertyResource,options){
  var path = buildUrl_("files/"+fileId+"/properties",options);
  var callOptions = {method:"POST",payload:JSON.stringify(PropertyResource)};
  var PropertyResource = CALL_(path,callOptions);
  return PropertyResource;
}

/**
* Lists a file's properties.
*
* @param {string} fileId The ID of the file.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PropertyListResource object
*/
function propertiesList(fileId,options){
  var path = buildUrl_("files/"+fileId+"/properties",options);
  var callOptions = {method:"GET"};
  var PropertyListResource = CALL_(path,callOptions);
  return PropertyListResource;
}

/**
* Updates a property. This method supports patch semantics.
*
* @param {string} fileId The ID of the file.
* @param {string} propertyKey The key of the property.
* @param {object} PropertyResource An object containing the PropertyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PropertyResource object
*/
function propertiesPatch(fileId,propertyKey,PropertyResource,options){
  var path = buildUrl_("files/"+fileId+"/properties/"+propertyKey,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(PropertyResource)};
  var PropertyResource = CALL_(path,callOptions);
  return PropertyResource;
}

/**
* Updates a property.
*
* @param {string} fileId The ID of the file.
* @param {string} propertyKey The key of the property.
* @param {object} PropertyResource An object containing the PropertyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned PropertyResource object
*/
function propertiesUpdate(fileId,propertyKey,PropertyResource,options){
  var path = buildUrl_("files/"+fileId+"/properties/"+propertyKey,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(PropertyResource)};
  var PropertyResource = CALL_(path,callOptions);
  return PropertyResource;
}

/**
* Exports the contents of the Realtime API data model associated with this file as JSON.
*
* @param {string} fileId The ID of the file that the Realtime API data model is associated with.
* @param {object} options Keypair of all optional parameters for this call
*/
function realtimeGet(fileId,options){
  var path = buildUrl_("files/"+fileId+"/realtime",options);
  var callOptions = {method:"GET"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Overwrites the Realtime API data model associated with this file with the provided JSON data model.
*
* @param {string} fileId The ID of the file that the Realtime API data model is associated with.
* @param {object} options Keypair of all optional parameters for this call
*/
function realtimeUpdate(fileId,options){
  var path = buildUrl_("files/"+fileId+"/realtime",options);
  var callOptions = {method:"PUT"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Deletes a reply.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {string} replyId The ID of the reply.
* @param {object} options Keypair of all optional parameters for this call
*/
function repliesDelete(fileId,commentId,replyId,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies/"+replyId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a reply.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {string} replyId The ID of the reply.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentReplyResource object
*/
function repliesGet(fileId,commentId,replyId,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies/"+replyId,options);
  var callOptions = {method:"GET"};
  var CommentReplyResource = CALL_(path,callOptions);
  return CommentReplyResource;
}

/**
* Creates a new reply to the given comment.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} CommentReplyResource An object containing the CommentReplyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentReplyResource object
*/
function repliesInsert(fileId,commentId,CommentReplyResource,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies",options);
  var callOptions = {method:"POST",payload:JSON.stringify(CommentReplyResource)};
  var CommentReplyResource = CALL_(path,callOptions);
  return CommentReplyResource;
}

/**
* Lists all of the replies to a comment.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentReplyListResource object
*/
function repliesList(fileId,commentId,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies",options);
  var callOptions = {method:"GET"};
  var CommentReplyListItems = CALLPAGE_(path,callOptions,"items");
  return CommentReplyListItems;
}

/**
* Updates an existing reply. This method supports patch semantics.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {string} replyId The ID of the reply.
* @param {object} CommentReplyResource An object containing the CommentReplyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentReplyResource object
*/
function repliesPatch(fileId,commentId,replyId,CommentReplyResource,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies/"+replyId,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(CommentReplyResource)};
  var CommentReplyResource = CALL_(path,callOptions);
  return CommentReplyResource;
}

/**
* Updates an existing reply.
*
* @param {string} fileId The ID of the file.
* @param {string} commentId The ID of the comment.
* @param {string} replyId The ID of the reply.
* @param {object} CommentReplyResource An object containing the CommentReplyResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned CommentReplyResource object
*/
function repliesUpdate(fileId,commentId,replyId,CommentReplyResource,options){
  var path = buildUrl_("files/"+fileId+"/comments/"+commentId+"/replies/"+replyId,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(CommentReplyResource)};
  var CommentReplyResource = CALL_(path,callOptions);
  return CommentReplyResource;
}

/**
* Removes a revision.
*
* @param {string} fileId The ID of the file.
* @param {string} revisionId The ID of the revision.
* @param {object} options Keypair of all optional parameters for this call
*/
function revisionsDelete(fileId,revisionId,options){
  var path = buildUrl_("files/"+fileId+"/revisions/"+revisionId,options);
  var callOptions = {method:"DELETE"};
  var removeResource = CALL_(path,callOptions);
  return removeResource;
}

/**
* Gets a specific revision.
*
* @param {string} fileId The ID of the file.
* @param {string} revisionId The ID of the revision.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned RevisionResource object
*/
function revisionsGet(fileId,revisionId,options){
  var path = buildUrl_("files/"+fileId+"/revisions/"+revisionId,options);
  var callOptions = {method:"GET"};
  var RevisionResource = CALL_(path,callOptions);
  return RevisionResource;
}

/**
* Lists a file's revisions.
*
* @param {string} fileId The ID of the file.
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned RevisionListResource object
*/
function revisionsList(fileId,options){
  var path = buildUrl_("files/"+fileId+"/revisions",options);
  var callOptions = {method:"GET"};
  var RevisionListResource = CALL_(path,callOptions);
  return RevisionListResource;
}

/**
* Updates a revision. This method supports patch semantics.
*
* @param {string} fileId The ID for the file.
* @param {string} revisionId The ID for the revision.
* @param {object} RevisionResource An object containing the RevisionResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned RevisionResource object
*/
function revisionsPatch(fileId,revisionId,RevisionResource,options){
  var path = buildUrl_("files/"+fileId+"/revisions/"+revisionId,options);
  var callOptions = {method:"PATCH",payload:JSON.stringify(RevisionResource)};
  var RevisionResource = CALL_(path,callOptions);
  return RevisionResource;
}

/**
* Updates a revision.
*
* @param {string} fileId The ID for the file.
* @param {string} revisionId The ID for the revision.
* @param {object} RevisionResource An object containing the RevisionResource for this method
* @param {object} options Keypair of all optional parameters for this call
* @return {object} The returned RevisionResource object
*/
function revisionsUpdate(fileId,revisionId,RevisionResource,options){
  var path = buildUrl_("files/"+fileId+"/revisions/"+revisionId,options);
  var callOptions = {method:"PUT",payload:JSON.stringify(RevisionResource)};
  var RevisionResource = CALL_(path,callOptions);
  return RevisionResource;
}
Categories
Code

Get the Full Path of a File in Google Drive

In Google Drive, you can have a file inside a folder which can be located inside another folder and so on. Thus Google Script will print (writes to the console log) the full folder path of any file in your Google Drive starting from the root folder which is called “My Drive” in Google Drive.

If the Drive folder path is blank or missing, it is likely because the file is shared with you but not added to your Drive yet.


// Provide the file name
function getFullFolderPath(fileName) {

  // Search for the file with that name and process the first result
  var files = DriveApp.getFilesByName(fileName);

  if (files.hasNext()) {

    var file = files.next(),
      folders = [],
      parent = file.getParents();

    if (parent) {
      // Display the URL of the containing folder
      Logger.log("Folder URL: " + parent.getUrl());
    }

    while (parent.hasNext()) {

      parent = parent.next();

      folders.push(parent.getName());

      parent = parent.getParents();

    }

    if (folders.length) {
      // Display the full folder path
      Logger.log("Folder path: " + folders.reverse().join("/"));
    }

  }

}

Categories
Code

Upload Files to Google Drive with Google Apps Script

Google Forms do not offer the file uploads feature but you can use Google Apps Script and let anyone upload files to Google Drive through an HTML web form.

For instance, you can share the form with your class, or with your clients, and they can directly upload school assignments, photographs, and other documents to a specific folder in your Google Drive.

There are two steps involved here. First you need to create an HTML form using HTML and CSS.

Here’s a sample form that uses the Materialize CSS library to give the standard Google Forms like material look to your file upload form.










 




The server side Google Script code includes a function for processing the form input. It reads the uploaded file as a blob and saves the blob as a new file into your Google Drive. The file name, extension, and content type are preserved.

[*] The premium version of the file upload form (demo form) lets you visually create forms and allow file uploads of any size via the Google File Picker API.

/* The script is deployed as a web app and renders the form */
function doGet(e) {
  return HtmlService
    .createHtmlOutputFromFile('forms.html')
    .setTitle("Google File Upload by CTRLQ.org");
}

function uploadFileToGoogleDrive(data, file, name, email) {

  try {

    var dropbox = "My Dropbox";
    var folder, folders = DriveApp.getFoldersByName(dropbox);

    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }

    var contentType = data.substring(5,data.indexOf(';')),
        bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
        blob = Utilities.newBlob(bytes, contentType, file);

    folder.createFolder([name, email].join(" ")).createFile(blob);

    return "OK";

  } catch (f) {
    return f.toString();
  }

}

You can save the two files and deploy the Google script as a web app with access to anyone, including anonymous as shown in this GIF.

Categories
Code

Automatically Print Files Placed in Drive with Google Cloud Print and Apps Script

With Google Cloud Print, you can manage your printers and create print jobs from any computer or mobile device even if they are not connected to the printer or they are on a different network. Cloud Printer also includes a special “Save to Google Docs” virtual printer that lets you save web pages and documents as PDFs in your Google Drive.

In this tutorial, you’ll learn how to use the Google Cloud Print API from Google Apps Scripts. You can use such a system to enable auto-printing, i.e., print a file as soon as it is uploaded in your Google Drive or print an email thread from Gmail. Remote printing is also possible via Dropbox but Cloud Print runs on Google Servers and all you need is a Mac or Windows computer running the Chrome browser (the connector).

To get started, create a new Google Apps Script project and include the OAuth2 library. Next go to the developer console of that project and create a new web application. Set the Redirect URL as below and set the allowed domains as script.google.com (the Project Key is under File – Project Properties).

https://script.google.com/macros/d/{PROJECT KEY}/usercallback

Add this code to the Apps Script project, replace the Client ID and Client Secret with the actual values from Developer Console and save the project. Go to Run – ShowURL and authorize the script. Open the Logger (Cmd + Enter), copy the URL and paste it in a new browser tab to complete the authorization.


function showURL() {
  var cpService = getCloudPrintService();
  if (!cpService.hasAccess()) {
    Logger.log(cpService.getAuthorizationUrl());
  }
}

function getCloudPrintService() {
  return OAuth2.createService('print')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setClientId('CLIENT_ID')
    .setClientSecret('CLIENT_SECRET')
    .setCallbackFunction('authCallback')
    .setPropertyStore(PropertiesService.getUserProperties())
    .setScope('https://www.googleapis.com/auth/cloudprint')
    .setParam('login_hint', Session.getActiveUser().getEmail())
    .setParam('access_type', 'offline')
    .setParam('approval_prompt', 'force');
}

function authCallback(request) {
  var isAuthorized = getCloudPrintService().handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('You can now use Google Cloud Print from Apps Script.');
  } else {
    return HtmlService.createHtmlOutput('Cloud Print Error: Access Denied');
  }
}

Now that your Cloud Print API script is authorized, we can send print jobs or run queries. For instance, if you are to retrieve a list of printers connected to Google Cloud Print, the code would be something like this:

function getPrinterList() {

  var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/search', {
    headers: {
      Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
    },
    muteHttpExceptions: true
  }).getContentText();

  var printers = JSON.parse(response).printers;

  for (var p in printers) {
    Logger.log("%s %s %s", printers[p].id, printers[p].name, printers[p].description);
  }

Similarly, to print a file in your Google Drive, you can write a routine like this. The docID is the ID of your Google Document that resides in Drive.

function printGoogleDocument(docID, printerID, docName) {

  var ticket = {
    version: "1.0",
    print: {
      color: {
        type: "STANDARD_COLOR",
        vendor_id: "Color"
      },
      duplex: {
        type: "NO_DUPLEX"
      }
    }
  };

  var payload = {
    "printerid" : printerID,
    "title"     : docName,
    "content"   : DriveApp.getFileById(docID).getBlob(),
    "contentType": "application/pdf",
    "ticket"    : JSON.stringify(ticket)
  };

  var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/submit', {
    method: "POST",
    payload: payload,
    headers: {
      Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
    },
    "muteHttpExceptions": true
  });

  response = JSON.parse(response);

  if (response.success) {
    Logger.log("%s", response.message);
  } else {
    Logger.log("Error Code: %s %s", response.errorCode, response.message);
  }
}

These can be extended to print web pages, images or any file that is preset in your Google Drive. You’ll have to modify the “content-Type” based on the mimeType of the file. The valid values are:

"url" (for web pages)
"dataUrl" (for printing base64 encoded images)
"google.drive" (Google Drive files)
"google.kix" (Google Document)
"google.mail" (Gmail thread)
"google.presentation" (Google Presentations)
"google.spreadsheet" (Google Spreadsheets)

If you looking for a automated system to email Google Spreadsheets as PDF, Google Cloud Print maybe too complex a solution, try this alternative.

Categories
Code

Know Who Changed a File in Google Drive with Apps Script

Google Drive maintains a history of all edits made to a file and this information comes if you are trying to figure out who modified the files in your Google Drive. You can know the date and time when a file was modified, the name of the user who made the edit and their email address is available as well.

To get started, you need to enable the Advanced Google Drive API in the Google Services section of your Google Apps Script project. You can use the method to track revisions made to your Google Sheets, Presentations, Documents and other native Google Formats. The script can be further enhanced to send you email alerts as soon as a file is updated in Drive.

Also see: Get your Google Drive Activity Report

/* Credit: +Jean-Pierre Verhulst */

function listFileRevisions(fileID) {
    
  var editList = [],
      revisions = Drive.Revisions.list(fileID);
  
  if (revisions.items && revisions.items.length > 0) {
    for (var i=0; i < revisions.items.length; i++) {
      var revision = revisions.items[i];
      editList.push([revision.id, (new Date(revision.modifiedDate)).toLocaleString(),
        revision.lastModifyingUserName, revision.lastModifyingUser.emailAddress
      ]);
    }
    Logger.log(editList);
  } else {
    Logger.log('No file revisions found.');
  }

}
Categories
Code

Get EXIF Data and GPS Location of Images in Google Drive

When you upload your images to Google Photos, they also become available in Google Drive and you can these access these image files with Google Apps Scripts and the Google Drive API.

Here’s a little snippet that will show you how to get the GPS location data, capture date and EXIF information of any photograph in your Google Drive. You’ll need to enable the Google Drive service to access the file’s meta data. The same technique can used to get the size and duration of a video file that’s in your Drive.

function getFileMetaData(fileID) {
    
  var api = "https://www.googleapis.com/drive/v2/files/" + fileID;
  
  var params = {
    method:"get",
    contentType: "application/json",
    headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
    muteHttpExceptions:true,
  };
  
  var meta = JSON.parse(UrlFetchApp.fetch(api, params).getContentText());
  
  Logger.log(meta.title); // File name
  Logger.log(meta.imageMediaMetadata); // Photo EXIF data like Camera, Date taken, Focal Length, Lens, etc.
  Logger.log(meta.imageMediaMetadata.location); // Photo Location coordinates
  Logger.log(meta.videoMediaMetadata); // Video Size and Length.
}
Categories
Code

Search Files inside Sub-folders in Google Drive

Like the previous script for listing Google Drive files, this Google Script will find all files of any particular MIME type in your Google Drive.

Unlike the DriveApp.getFilesByType() method that will only search for files in the immediate folder, this Google Script will also search for files inside the sub-folders.


/* Adapted from: http://qiita.com/atsaki/items/60dbdfe5ab5133a5f875 */
function getDriveFiles(folder, path) {

    // If Drive folder is not specified, start from the root folder
    if (folder == null && path == null) {
        return getDriveFiles(DriveApp.getRootFolder(), "");
    }

    var files = [];
    path = path + "/" + folder.getName();

    // Specify the MimeType of files you wish to search
    var fileIt = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
    while ( fileIt.hasNext() ) {
        var f = fileIt.next();
        files.push({id: f.getId(), path: path + "/" + f.getName()});
    }

    // Get all the sub-folders and iterate
    var folderIt = folder.getFolders();
    while(folderIt.hasNext()) {
        fs = getDriveFiles(folderIt.next(), path);
        for (var i = 0; i < fs.length; i++) {
            files.push(fs[i]);
        }
    }
    
    return files;
}

Categories
Code

Make a Copy of Folders in Google Drive with Google Scripts

In Google Drive, there’s no easy way to clone a folder. You can make a copy of individual files but there’s no command for creating duplicate folders that are a mirror of another folder. Fortunately, there’s Google Script to the rescue. The only downside is that the script execution may time out if you are trying to copy a large folder with several sub-folders and files.

function start() {
  
  var sourceFolder = "source";
  var targetFolder = "target";
  
  var source = DriveApp.getFoldersByName(sourceFolder);
  var target = DriveApp.createFolder(targetFolder);

  if (source.hasNext()) {
    copyFolder(source.next(), target);
  }
  
}

function copyFolder(source, target) {

  var folders = source.getFolders();
  var files   = source.getFiles();
  
  while(files.hasNext()) {
    var file = files.next();
    file.makeCopy(file.getName(), target);
  }
  
  while(folders.hasNext()) {
    var subFolder = folders.next();
    var folderName = subFolder.getName();
    var targetFolder = target.createFolder(folderName);
    copyFolder(subFolder, targetFolder);
  }  
  
}
Categories
Code

Convert Google Documents and Spreadsheets with Apps Script

You can easily convert any Google Spreadsheet or Google Document in your Google Drive to other formats like PDF, XLS, etc with Google Apps Script and either email the converted file or save it back to Google Drive.

You can get the Email Google Spreadsheet add-on if you prefer the easier route that doesn’t require you to write any Google Apps Script code.


// Credit Stéphane Giron
// Save the Google Document as HTML

function exportAsHTML(documentId){
  var forDriveScope = DriveApp.getStorageUsed(); //needed to get Drive Scope requested
  var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+documentId+"&exportFormat=html";
  var param = {
    method      : "get",
    headers     : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
    muteHttpExceptions:true,
  };
  var html = UrlFetchApp.fetch(url,param).getContentText();
  var file = DriveApp.createFile(documentId + ".html", html);
  return file.getUrl();
}

// Credit: Eric Koleda
// Export Google Spreadsheet as Microsoft Excel format

function exportAsExcel(spreadsheetId) {
  var file = Drive.Files.get(spreadsheetId);
  var url = file.exportLinks['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
  var token = ScriptApp.getOAuthToken();
  var response = UrlFetchApp.fetch(url, {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  });
  return response.getBlob();
}

Categories
Code

Save Gmail Files to Google Drive

The Google Script will save file attachments from Gmail threads marked with a particular label to a specific folder in Google Drive. It takes the last email message in a thread and saves the first attachment to Drive. Credit: S. Dolidze

Also see: Save Gmail Attachments to Google Drive

function main() {
  
  var label = "Clients/New York/Design";
  var folder = "design-assets";
  
  folder = DriveApp.createFolder(folder);
  
  GmailApp
  .getUserLabelByName(label)
  .getThreads()
  .map(lastMessage)
  .map(extractAttachment)
  .forEach(saveFile(folder));

}

function lastMessage(thread) {
  return thread.getMessages().pop();
}

function extractAttachment(message) {
  var blob = message.getAttachments()[0].copyBlob();
  var filename = message.getFrom() + "." + extension(blob.getName());
  blob.setName(filename);
  return blob;
}

function extension(filename) { 
  return filename.split(".").pop();
}

function saveFile(folder) {
  return function(blob) {
    folder.createFile(blob);
    Logger.log("Saved file " + blob.getName());
  };
}
Categories
Code

Generate List of all Files in a Google Drive Folder

This is like running the `ls` Linux command for listing all the files and their details in a particular Google Drive folder. You an even make a tree of files.

Call the listFiles method with the Drive folder name and it will create a list of all files and appends them to a spreadsheet. The direct download links are particularly handy for downloads PDFs and other non Google Docs documents.

Updated to use DriveApp instead of the deprecated DocsList service.


/* Code written by @hubgit 
   https://gist.github.com/hubgit/3755293
   Updated since DocsList is deprecated 
*/

function listFilesInFolder(folderName) {
  
  var folder = DriveApp.getFoldersByName(folderName).next();
  var contents = folder.getFiles();
  
  var file, data, sheet = SpreadsheetApp.getActiveSheet();
  sheet.clear();
  
  sheet.appendRow(["Name", "Date", "Size", "URL", "Download", "Description", "Type"]);
  
  for (var i = 0; i < contents.length; i++) {
 
    file = contents[i];
    
    if (file.getFileType() == "SPREADSHEET") {
      continue;
    }
        
    data = [ 
      file.getName(),
      file.getDateCreated(),
      file.getSize(),
      file.getUrl(),
      "https://docs.google.com/uc?export=download&confirm=no_antivirus&id=" + file.getId(),
      file.getDescription(),
      file.getFileType().toString()
    ];
    
    sheet.appendRow(data);
  
  }
  
};

Categories
Code

Get the Full Path of a Google Drive Folder

With Apps Script, you can specify the full path of a Google Drive folder in your method using the \root\parent\child\grandchild notation. The script will return the destination folder matching your path name or if the path doesn’t exist, it will create the specified folders using the same structure starting with the Root folder.

This style is also handy when you are trying to create a file in a specific Drive folder but do not want the hassle of dealing with File or Folder IDs of the Drive App.

  
function go() {    
    var path = "//main//parent//child//grandchild”;
    var folder = getDriveFolder(path);    
    Logger.log(folder.getUrl());    
}

function getDriveFolder(path) {
  
  var name, folder, search, fullpath;
  
  // Remove extra slashes and trim the path
  fullpath = path.replace(/^\/*|\/*$/g, '').replace(/^\s*|\s*$/g, '').split("/");
  
  // Always start with the main Drive folder
  folder = DriveApp.getRootFolder();
  
  for (var subfolder in fullpath) {
    
    name = fullpath[subfolder];
    search = folder.getFoldersByName(name);
    
    // If folder does not exit, create it in the current level
    folder = search.hasNext() ? search.next() : folder.createFolder(name);
    
  }
  
  return folder;
  
}
Categories
Code

List all Google Drive Files and Folders

With Google Scripts you can generate a Google Drive Tree with all the files and folders (and sub-folders). You can either start with the root (main) folder or specify a folder name – this is helpful when you have tons of files in your Google Drive and retrieving the entire list can cause the script to time out.


/* Change the FOLDER NAME to generate tree for any specify folder */

function generateFolderTree() {
  
  try {
    
    // If you want a tree of any sub folder
    //var parent = DriveApp.getFoldersByName("FOLDER_NAME").next();
    
    // If you want to search from the top (root) folder
    var parentFolder = DriveApp.getRootFolder();
    
    getChildFolders(parentFolder);
    
  } catch (e) {
    
    Logger.log(e.toString());
    
  }
  
}


function getChildFolders(parent) {
  
  var childFolders = parent.getFolders();
  
  while (childFolders.hasNext()) {
    
    var childFolder = childFolders.next();
    
    Logger.log("Folder Name: " + childFolder.getName());
    Logger.log("Folder URL:  " + childFolder.getUrl());
    
    var files = childFolder.getFiles();
    
    while (files.hasNext()) {
      
      // Print list of files inside the folder
      Logger.log(files.next().getName());
      
    }
    
    // Recursive call for any sub-folders
    getChildFolders(childFolder);
    
  }
  
}
Categories
Code

Monitor Files in Google Drive with Apps Script

The Drive Activity Report tracks changes to the files and documents in your Google Drive and send the list in an email every midnight. It also logs the changes in a Google Sheet.

It internally uses the DriveApp.search() method to find these files that have the modifiedDate property greater than the 24 hour period.


function driveActivityReport() {
  
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var sheet = ss.getActiveSheet();
  
  // Get the spreadsheet time zone
  
  var timezone = ss.getSpreadsheetTimeZone();
  
  // Find files modified in the last 24 hours
  
  var today     = new Date();
  var oneDayAgo = new Date(today.getTime() - 1 * 24 * 60 * 60 * 1000);  
  var startTime = oneDayAgo.toISOString();
  
  // The magic search expression
  var search = '(trashed = true or trashed = false) and (modifiedDate > "' + startTime + '")';
  var files  = DriveApp.searchFiles(search);
  
  // Loop through all the files in the search results
  while( files.hasNext() ) {
    
    var file = files.next();
    
    var fileName    = file.getName();
    var fileURL     = file.getUrl();
    var dateCreated =  Utilities.formatDate(file.getDateCreated(), timezone, "yyyy-MM-dd HH:mm")
        
    sheet.appendRow([dateCreated, fileName, fileURL]);
    
  }

}

Categories
Code

MIME Types in Google Drive

You can find the MIME type of any file in your Google Drive using getMimeType() method as long as the MIME is support by Google Drive. Your script can then easily figure out the actual type (more user friendly) of the file or document using the following getFileType method. For instance, Google Spreadsheet for “application/vnd.google-apps.spreadsheet” and so on.


var mimeType = file.getMimeType();
var fileType = getFileType(mimeType);

function getFileType(mimeType) {
  
  var filetype = "";
  
  switch (mimeType) {
    case MimeType.GOOGLE_APPS_SCRIPT: filetype = 'Google Apps Script'; break;
    case MimeType.GOOGLE_DRAWINGS: filetype = 'Google Drawings'; break;
    case MimeType.GOOGLE_DOCS: filetype = 'Google Docs'; break;
    case MimeType.GOOGLE_FORMS: filetype = 'Google Forms'; break;
    case MimeType.GOOGLE_SHEETS: filetype = 'Google Sheets'; break;
    case MimeType.GOOGLE_SLIDES: filetype = 'Google Slides'; break;
    case MimeType.FOLDER: filetype = 'Google Drive folder'; break;
    case MimeType.BMP: filetype = 'BMP'; break;
    case MimeType.GIF: filetype = 'GIF'; break;
    case MimeType.JPEG: filetype = 'JPEG'; break;
    case MimeType.PNG: filetype = 'PNG'; break;
    case MimeType.SVG: filetype = 'SVG'; break;
    case MimeType.PDF: filetype = 'PDF'; break;
    case MimeType.CSS: filetype = 'CSS'; break;
    case MimeType.CSV: filetype = 'CSV'; break;
    case MimeType.HTML: filetype = 'HTML'; break;
    case MimeType.JAVASCRIPT: filetype = 'JavaScript'; break;
    case MimeType.PLAIN_TEXT: filetype = 'Plain Text'; break;
    case MimeType.RTF: filetype = 'Rich Text'; break;
    case MimeType.OPENDOCUMENT_GRAPHICS: filetype = 'OpenDocument Graphics'; break;
    case MimeType.OPENDOCUMENT_PRESENTATION: filetype = 'OpenDocument Presentation'; break;
    case MimeType.OPENDOCUMENT_SPREADSHEET: filetype = 'OpenDocument Spreadsheet'; break;
    case MimeType.OPENDOCUMENT_TEXT: filetype = 'OpenDocument Word'; break;
    case MimeType.MICROSOFT_EXCEL: filetype = 'Microsoft Excel'; break;
    case MimeType.MICROSOFT_EXCEL_LEGACY: filetype = 'Microsoft Excel'; break;
    case MimeType.MICROSOFT_POWERPOINT: filetype = 'Microsoft PowerPoint'; break;
    case MimeType.MICROSOFT_POWERPOINT_LEGACY: filetype = 'Microsoft PowerPoint'; break;
    case MimeType.MICROSOFT_WORD: filetype = 'Microsoft Word'; break;
    case MimeType.MICROSOFT_WORD_LEGACY: filetype = 'Microsoft Word'; break;
    case MimeType.ZIP: filetype = 'ZIP'; break;
    default: filetype = "Unknown";
  }
  
  return filetype;
  
}

Categories
Code

File Permissions and Sharing Settings in Google Drive

This Google Script prints the sharing access and permissions of all files in your Google Drive. This helps you determine who has access to your Google Drive files. It uses the DriveApp service to retrieve all the files in your Google Drive and emails the report to the email address of the authorized Google user.

/* 


  ======================================
  Who Can See Your Files in Google Drive 
  ======================================
  
  Written by Amit Agarwal on 01/11/2014 
  
  Tutorial :: http://labnol.org/?p=28237
  

*/


function ScanGoogleDrive() {
    
  var files = DriveApp.getFiles();  
  var timezone = Session.getScriptTimeZone();
  var email = Session.getActiveUser().getEmail();
  
  var file, date, access, url, permission;
  var privacy, view, viewers, edit, editors;
  
  var rows = [["File Name", "Who has access?", "Date Created"]];
  
  while ( files.hasNext() ) {
    
    file = files.next();
    
    try {
      
      access     = file.getSharingAccess();
      permission = file.getSharingPermission();
      viewers    = file.getViewers();      
      editors    = file.getEditors();
      
      view = [];
      edit = [];
      
      date =  Utilities.formatDate(file.getDateCreated(), timezone, "yyyy-MM-dd HH:mm")
      url = '' + file.getName() + '';
      
      for (var v=0; v") + "";
  
  for (var i=1; i") + "";
  }
  
  html += "
For help, refer to this online tutorial written by Amit Agarwal."; MailApp.sendEmail(email, "Google Drive - File Permissions Report", "", {htmlBody: html}); }
Categories
Code

Share Google Drive Files with Apps Script

I wrote a little Google Script that saves Gmail attachments to Drive and shares the saved files with users based on rules defined in the message body itself. Here’s a sample rule:

# view@example.com, v #
# comment2@example.com, comment@example.com, c#
# edit1@example.com, edit2@example.com, e #

In the above case, the file(s) would be shared with all these users but the sharing permissions would be different. The user view@example can only view (v) the document, the users edit@example have editing permissions while others have commenting permissions.

function ShareDriveFiles() {
  
  var threads = GmailApp.search("subject:#share");
  
  for (var t in threads) {
    
    var messages = threads[t].getMessages();
    
    for (var m in messages) {
      
      var attachments = messages[m].getAttachments();
      
      if (attachments.length) {
        
        var body = messages[m].getPlainBody().replace(/\s*/g, "").toLowerCase();
        
        for (var a in attachments) {
          
          var rules = body.match(/(#[^#]+,[e|v|c]#)/g);
          
          if (rules) {
            
            var file = DriveApp.createFile(attachments[a]);
            
            for (var r in rules) {    
          
              var line = rules[r].substr(1, rules[r].length-2).split(",");
              for (var s=0; s

		
Categories
Code

Set Sharing Permissions in Google Drive with Apps Script

You can easily change the sharing and access permissions of any shared file or folder in Google Drive with the help of Google Apps Script.

The following Google Script sets auto-expiration dates for shared links and makes the folder /file “Private” after the expiration date.

var EXPIRY_TIME  = "2014-05-01 23:42"; 

function autoExpire() {
  
  var id, asset, i, email, users;

  // The URL of the Google Drive file or folder 
  var URL = "https://drive.google.com/folderview?id=0B4fk8L6brI_ednJaa052";
  
  try {
    
    // Extract the File or Folder ID from the Drive URL
    var id = URL.match(/[-\w]{25,}/);
    
    if (id) {
      
      asset = DriveApp.getFileById(id) ? DriveApp.getFileById(id) : DriveApp.getFolderById(id);
      
      if (asset) {
        
        // Make the folder / file Private 
        asset.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.NONE);  
        asset.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.NONE); 
        
        // Remove all users who have edit permissions
        users = asset.getEditors();
        for (i in users) {
          email = users[i].getEmail();
          if (email != "") {
            asset.removeEditor(email);
          }
        }
        
        // Remove all users who have view permssions
        users = asset.getViewers();
        for (i in users) {
          email = users[i].getEmail();
          if (email != "") {
            asset.removeViewer(email);
          }
        }  
        
      }
    }
  
  } catch (e) {
    
    Logger.log(e.toString());
    
  }
}

function Start() {
  
  var triggers = ScriptApp.getProjectTriggers();
  
  for (var i in triggers) {
    
    ScriptApp.deleteTrigger(triggers[i]);
    
  }
  
  var time = EXPIRY_TIME;
  
  // Run the auto-expiry script at this date and time

  var expireAt = new Date(time.substr(0,4),
                          time.substr(5,2)-1,
                          time.substr(8,2),
                          time.substr(11,2),
                          time.substr(14,2));
  
  if ( !isNaN ( expireAt.getTime() ) ) {
    ScriptApp.newTrigger("autoExpire").timeBased().at(expireAt).create();
  }

}
Categories
Code

Download Files from the Internet to Google Drive

The Save Files app downloads any files from the Internet to your Dropbox or Google Drive. It uses the Filepicker API but this can also be done through Google Apps Script.

This Google Script takes the URL of a file and downloads it to your Google Drive. You need to specify the full URL of the file and also the destination folder on Google Drive where that file would be saved.


function downloadFile(fileURL,folder) {
  
  var fileName = "";
  var fileSize = 0;
  
  var response = UrlFetchApp.fetch(fileURL, {muteHttpExceptions: true});
  var rc = response.getResponseCode();
  
  if (rc == 200) {
    var fileBlob = response.getBlob()
    var folder = DocsList.getFolder(folder);
    if (folder != null) {
      var file = folder.createFile(fileBlob);
      fileName = file.getName();
      fileSize = file.getSize();
    }
  }
    
  var fileInfo = { "rc":rc, "fileName":fileName, "fileSize":fileSize };
  return fileInfo;
}

Categories
Code

Send Google Document as HTML via Gmail

The Google Script extracts the content of a Google Documents, converts the styles as inline CSS using the MailChimp API and send the document via Gmail as HTML Mail.


/* Credit: https://gist.github.com/erickoledadevrel/11143648 */
/**
 * Sends an email using the contents of a Google Document as the body.
 */
function sendDocument(documentId, recipient, subject) {
  var html = convertToHtml(documentId);
  html = inlineCss(html);
  GmailApp.sendEmail(recipient, subject, null, {
    htmlBody: html
  });
}
 
/**
 * Converts a file to HTML. The Advanced Drive service must be enabled to use
 * this function.
 */
function convertToHtml(fileId) {
  var file = Drive.Files.get(fileId);
  var htmlExportLink = file.exportLinks['text/html'];
  if (!htmlExportLink) {
    throw 'File cannot be converted to HTML.';
  }
  var oAuthToken = ScriptApp.getOAuthToken();
  var response = UrlFetchApp.fetch(htmlExportLink, {
    headers:{
      'Authorization': 'Bearer ' + oAuthToken
    },
    muteHttpExceptions: true
  });
  if (!response.getResponseCode() == 200) {
    throw 'Error converting to HTML: ' + response.getContentText();
  }
  return response.getContentText();
}
 
/**
 * Inlines CSS within an HTML file using the MailChimp API. To use the API you must
 * register for an account and then copy your API key into the script property
 * "mailchimp.apikey". See here for information on how to find your API key:
 * http://kb.mailchimp.com/article/where-can-i-find-my-api-key/.
 */
function inlineCss(html) {
  var apikey = CacheService.getPublicCache().get('mailchimp.apikey');
  if (!apikey) {
    apikey = PropertiesService.getScriptProperties().getProperty('mailchimp.apikey');
    CacheService.getPublicCache().put('mailchimp.apikey', apikey);
  }
  var datacenter = apikey.split('-')[1];
  var url = Utilities.formatString('https://%s.api.mailchimp.com/2.0/helper/inline-css', datacenter);
  var response = UrlFetchApp.fetch(url, {
    method: 'post',
    payload: {
      apikey: apikey,
      html: html,
      strip_css: true
    }
  });
  var output = JSON.parse(response.getContentText());
  if (!response.getResponseCode() == 200) {
    throw 'Error inlining CSS: ' + output['error'];
  }
  return output['html'];
}
Categories
Code

Add #Tags to your Google Drive Files

Google Drive offers folders (or collections) for organizing your files but doesn’t support labels or tags. A disadvantage with folders is that a file can only belong to a single folder while multiple #tags, as in Gmail, can be assigned to a single file.

There’s a workaround though. You can assign tags to a file in Google Drive by adding them to the description of a file. A Google forum user has written this Google Script that takes the folder name in which a file is found and assigns those names as tags to the file. It works for nested folders too.

/*
 setDescriptionToFolderNames
 Workaround to fake Tags in Google Drive.
 Writes all the folder names of a file into the file description, so that the file can be found by searching the folder names.
*/

function setDescriptionToFolderNames() {
  
  var file;
  var filename;
  var folders;
  var filedescription;
  
  var contents = DocsList.getAllFiles();
  // sort ascending. Oldest first, in case of timeout:
  contents.sort(function(a,b) {return a.getLastUpdated()-b.getLastUpdated()});
  
  // synchronize folder names of all files (only updates if folders have changed):
  for (var i = 0; i < contents.length; i++) {
    file = contents[i];
    try {
        filename = file.getName();
        //Logger.log("Checking: " +filename +" ("+file.getLastUpdated()+")");
        folders = file.getParents();
        
        // sort by folder name:
        folders.sort(function(a, b) 
                     { return a.getName().localeCompare(b.getName()); }
                    );
        filedescription = "";
        
        for (var f = 0; f < folders.length; f++) {
          filedescription = filedescription+folders[f].getName()+" ";
        }

        if (filedescription != contents[i].getDescription())
        { 
          file.setDescription(filedescription);
          Logger.log("Updated: " +filename);
        }
     } catch(e){ Logger.log("Error: " +filename+" "+e); }
   }
  
};
Categories
Code

Google Drive Hosting with Apps Script

The tutorial on hosting websites with Google Drive makes use of the HTMLService of Google Apps Script. The user uploads a zip file, the file is extracted using the Utilities.unzip method (make the sure the MIME type is set to application/zip) and saved in a folder.

The setSharing method is then used for making the Google Drive folder public and the ID of the folder is passed to the user. Here’s the full code:



/* Written by Amit Agarwal on August 9, 2013 */

function doGet() {
  var output = HtmlService.createHtmlOutputFromFile('labnol');
  output.setTitle('Publish Website on Google Drive');
  return output;  
}

function uploadWebsite(form) {
  
  try {
    
    var zip, files, name, folder, file, host, found=false;
    
    zip    = form.zipFile.setContentType("application/zip");
    files  = Utilities.unzip(zip);
    
    // Unique folder name based on the current date and time
    name   = Utilities.formatDate(new Date(), "GMT", "ddMMyyyyHHmmss");
    folder = DriveApp.createFolder("Website #" + name);    
    
    for (var i=0; iwebsite is now live on Google Drive. The URL is: ' + site;
    } else {
      // if the index.html file is not available, don't publish the website
      DriveApp.removeFolder(folder);
    }
    
    return "Sorry, we couldn't find an index.html in your zip file. Please try again.";
    
  } catch (e) {    
    return e.toString();    
  }
  
}