425 lines
12 KiB
JavaScript
425 lines
12 KiB
JavaScript
/**
|
|
* Utils contains useful functions for working with drive
|
|
* you must provide run DriveUtils.setService(yourdriveapp) before using
|
|
* @namespace
|
|
*/
|
|
var DriveUtils = (function (ns) {
|
|
|
|
|
|
var ENUMS = {
|
|
MIMES: {
|
|
SOURCE:"application/vnd.google-apps.script+json",
|
|
SCRIPT:"application/vnd.google-apps.script",
|
|
FOLDER:"application/vnd.google-apps.folder",
|
|
AUDIO:"application/vnd.google-apps.audio",
|
|
DOCUMENT:"application/vnd.google-apps.document",
|
|
DRAWING:"application/vnd.google-apps.drawing",
|
|
FILE:"application/vnd.google-apps.file",
|
|
FORM:"application/vnd.google-apps.form",
|
|
PHOTO:"application/vnd.google-apps.photo",
|
|
PRESENTATION:"application/vnd.google-apps.presentation",
|
|
SITES:"application/vnd.google-apps.sites",
|
|
FUSIONTABLE:"application/vnd.google-apps.fusiontable",
|
|
SPREADSHEET:"application/vnd.google-apps.spreadsheet",
|
|
UNKNOWN:"application/vnd.google-apps.unknown",
|
|
VIDEO:"application/vnd.google-apps.video",
|
|
gadget:"application/xml",
|
|
xml:"text/xml",
|
|
json:"application/json"
|
|
}
|
|
};
|
|
|
|
ns.getShortMime = function (mimeType) {
|
|
var f = Object.keys(ENUMS.MIMES).filter(function(k) {
|
|
return ENUMS.MIMES[k] === mimeType;
|
|
});
|
|
return f.length ? f[0].toLowerCase() : mimeType.toLowerCase();
|
|
};
|
|
// for handling advanced services
|
|
ns.ads = (function (ads) {
|
|
|
|
/**
|
|
* get files by name
|
|
* @param {string} parentId the parentId
|
|
* @param {string} name the name
|
|
* @param {string} optMime the mime type
|
|
* @param {string} optFields the fields to return
|
|
*/
|
|
ads.getFilesByName = function (parentId, name , optMime, optFields) {
|
|
return ads.getChildItems (parentId, optMime , optFields || "items/id" , "title='" + name + "'" + " and mimeType!='" + ENUMS.MIMES.FOLDER + "'" );
|
|
};
|
|
|
|
ads.getFoldersByName = function (parentId, name , optFields) {
|
|
return ads.getChildFolders (parentId, optFields || "items/id" , "title='" + name + "'");
|
|
};
|
|
|
|
ads.getChildFiles = function (parentId, optMime, optFields , optExtraQueries) {
|
|
return ads.getChildItems (parentId, optMime , optFields || "items/id" , "mimeType!='" + ENUMS.MIMES.FOLDER + "'" );
|
|
};
|
|
|
|
/**
|
|
* get child folders
|
|
* @param {string} parentId the id of the parent
|
|
* @param {string} optFields the fields to return
|
|
* @param {Array.string} optExtraQueries
|
|
*/
|
|
ads.getChildFolders = function (parentId, optFields, optExtraQueries) {
|
|
return ads.getChildItems(parentId , ENUMS.MIMES.FOLDER , optFields || "items/id", optExtraQueries) ;
|
|
};
|
|
/**
|
|
* get child items
|
|
* @param {string} parentId the id of the parent
|
|
* @param {ENUM.MIMES} optMime the mime type
|
|
* @param {string} optFields the fields to return
|
|
* @param {Array.string} optExtraQueries
|
|
*/
|
|
ads.getChildItems = function (parentId,mime,optFields,optExtraQueries) {
|
|
|
|
// add the folder filter
|
|
var q= mime ? ["mimeType='" + mime + "'"] : [];
|
|
|
|
// dont include anything deleted
|
|
q.push("trashed=false");
|
|
|
|
//plus any extra queries
|
|
if(optExtraQueries) {
|
|
var e = Array.isArray(optExtraQueries) ? optExtraQueries : [optExtraQueries];
|
|
Array.prototype.push.apply (q,e);
|
|
}
|
|
|
|
var options= {};
|
|
if (optFields) {
|
|
options.fields = optFields;
|
|
}
|
|
if(options.fields && options.fields.indexOf("nextPageToken") === -1) options.fields = (options.fields ? options.fields + "," : "") + "nextPageToken";
|
|
|
|
options.q = q.join(" and ");
|
|
|
|
var items =[] , pageToken;
|
|
|
|
do {
|
|
|
|
var result = Utils.expBackoff(function() {
|
|
return ns.service.Children.list(parentId,options);
|
|
|
|
},{ logAttempts:false});
|
|
|
|
|
|
pageToken = result.nextPageToken;
|
|
Array.prototype.push.apply(items , result.items);
|
|
options.pageToken = pageToken;
|
|
|
|
|
|
} while (pageToken);
|
|
|
|
return items;
|
|
|
|
};
|
|
|
|
/**
|
|
* return a folder id from a path like /abc/def/ghi
|
|
* @param {string} path the path
|
|
* @param {boolean} [create=false] create it
|
|
* @return {object} {id:'xxxx'} or null
|
|
*/
|
|
ads.getFolderFromPath = function (path) {
|
|
|
|
return (path || "/").split("/").reduce ( function(prev,current) {
|
|
if (prev && current) {
|
|
// this gets the folder with the name of the current fragment
|
|
var fldrs = ads.getFoldersByName(prev.id,current);
|
|
return fldrs.length ? fldrs[0] : null;
|
|
}
|
|
else {
|
|
return current ? null : prev;
|
|
}
|
|
},ns.rootFolder);
|
|
};
|
|
return ads;
|
|
})({});
|
|
|
|
/**
|
|
* to keep this namespace dependency free
|
|
* this must be run to set the driveappservice before it can be used
|
|
* @param {driveapp} dap the driveapp
|
|
* @return {DriveUtils} self
|
|
*/
|
|
ns.setService = function (dap) {
|
|
ns.service = dap;
|
|
if (ns.isDriveApp()) {
|
|
ns.rootFolder = Utils.expBackoff ( function () {
|
|
return ns.service.getRootFolder();
|
|
});
|
|
ns.rootFolderId = ns.rootFolder.getId();
|
|
}
|
|
else {
|
|
ns.rootFolder = ns.getFolderById ('root');
|
|
ns.rootFolderId = ns.rootFolder.id;
|
|
}
|
|
return ns;
|
|
};
|
|
|
|
/**
|
|
* whether we are using driveapp
|
|
* @return {bool} whether we are using driveapp
|
|
*/
|
|
ns.isDriveApp = function () {
|
|
ns.checkService();
|
|
return typeof ns.service.continueFolderIterator === 'function';
|
|
};
|
|
|
|
ns.checkService = function () {
|
|
if(!ns.service) {
|
|
throw 'please do a DriveUtils.setService (yourdriveapp) to inialie namespace';
|
|
}
|
|
};
|
|
|
|
ns.getFolders = function (parent) {
|
|
if (ns.isDriveApp()) {
|
|
return parent.getFolders();
|
|
}
|
|
else {
|
|
return ns.ads.getChildFolders (parent.id);
|
|
}
|
|
};
|
|
|
|
ns.getFiles = function (parent,mime) {
|
|
|
|
if (ns.isDriveApp()) {
|
|
|
|
return mime ? ns.service.getFilesByType (mime) : parent.getFiles();
|
|
}
|
|
else {
|
|
|
|
return ns.ads.getChildFiles (parent.id, mime);
|
|
}
|
|
};
|
|
|
|
ns.getFileById = function (id) {
|
|
try {
|
|
return Utils.expBackoff ( function () {
|
|
|
|
if (!ns.isDriveApp()) {
|
|
return ns.service.Files.get(id,{fields:"id,title"});
|
|
}
|
|
else {
|
|
return ns.service.getFileById(id);
|
|
}
|
|
},{logAttempts:false});
|
|
}
|
|
catch (err) {
|
|
return null;
|
|
}
|
|
|
|
}
|
|
ns.getFolderById = function (path) {
|
|
|
|
try {
|
|
return Utils.expBackoff ( function () {
|
|
if (!ns.isDriveApp()) {
|
|
return ns.service.Files.get(path,{fields:"id,title"});
|
|
}
|
|
else {
|
|
return ns.service.getFolderById (path);
|
|
}
|
|
},{logAttempts:false});
|
|
}
|
|
catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
/**
|
|
* get all the files as an array from a folder path
|
|
* @param {string} path the path to the start folder
|
|
* @param {string} [mime] the mime type
|
|
* @param {boolean} [recurse=false] whether to recurse
|
|
* @return {[files]} an array of files
|
|
*/
|
|
ns.getPileOfFiles = function ( path , mime , recurse ) {
|
|
|
|
var pile, startFolder;
|
|
|
|
// first check if the path is an id or a path
|
|
startFolder = ns.getFolderById (path) || ns.getFolderFromPath (path) ;
|
|
|
|
if (!startFolder) {
|
|
throw 'folder path/id ' + path + ' not found';
|
|
}
|
|
|
|
// if opened successfully, then get all the files
|
|
if (startFolder) {
|
|
pile = (recurse ? recurseFolders ( startFolder,mime ) : pileFiles (startFolder,mime));
|
|
}
|
|
return pile;
|
|
|
|
/**
|
|
* get all the files in this and child folders
|
|
* @param {folder} folder where to start
|
|
* @param {string} [mime] the mime type
|
|
* @param {[files]} [pile] the growing pike of files
|
|
* @return {[files]} the growing pike of files
|
|
*/
|
|
function recurseFolders (folder, mime, pile) {
|
|
|
|
|
|
// get the folders from the next level
|
|
var it = ns.getFolders(folder);
|
|
if (ns.isDriveApp () ) {
|
|
while (it.hasNext()) {
|
|
pile = recurseFolders (it.next() , mime , pile);
|
|
}
|
|
}
|
|
else {
|
|
it.forEach(function(d) {
|
|
pile = recurseFolders (d , mime , pile)
|
|
});
|
|
}
|
|
|
|
// collect from this folder
|
|
return pileFiles(folder, mime, pile);
|
|
|
|
}
|
|
|
|
/**
|
|
* get all the files in this folder
|
|
* @param {folder} folder where to start
|
|
* @param {string} [mime] the mime type
|
|
* @param {[files]} [pile] the growing pike of files
|
|
* @return {[files]} the growing pike of files
|
|
*/
|
|
function pileFiles (folder, mime , pile) {
|
|
|
|
var pile = pile || [];
|
|
Array.prototype.push.apply (pile, getFiles(folder,mime));
|
|
return pile;
|
|
}
|
|
|
|
/**
|
|
* get all the files in a gven folder
|
|
* @param {folder} folder where to start
|
|
* @param {string} [mime] the mime type
|
|
* @return {[files]} the files
|
|
*/
|
|
function getFiles (folder,mime) {
|
|
var files= [];
|
|
var it = ns.getFiles (folder , mime) ;
|
|
folderPath = ns.getPathFromFolder (folder);
|
|
|
|
if (ns.isDriveApp()) {
|
|
while (it.hasNext()) {
|
|
var file = it.next();
|
|
var fileName = file.getName();
|
|
files.push({
|
|
file:file,
|
|
folder:folder,
|
|
path:folderPath + fileName,
|
|
fileName:fileName,
|
|
id:file.getId()
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
|
|
it.forEach(function(d) {
|
|
|
|
// need to get the file name
|
|
var fileName = ns.getFileById(d.id).title;
|
|
files.push({
|
|
file:d,
|
|
folder:folder,
|
|
path:folderPath + fileName,
|
|
fileName:fileName,
|
|
id:d.id
|
|
});
|
|
})
|
|
}
|
|
return files;
|
|
}
|
|
|
|
|
|
};
|
|
/**
|
|
* get the files from a path like /abc/def/hgh/filename
|
|
* @param {string} path the path
|
|
* @return {FileIterator} a fileiterator
|
|
*/
|
|
ns.getFilesFromPath = function (path) {
|
|
|
|
// get the filename and the path seperately
|
|
var s = path.split("/");
|
|
if (!s.length) {
|
|
return null;
|
|
}
|
|
var filename = s[s.length-1];
|
|
|
|
// the folder
|
|
var folder = ns.getFolderFromPath (
|
|
"/" + (s.length > 1 ? s.slice(0,s.length-1).join("/") : "")
|
|
);
|
|
|
|
if (ns.isDriveApp() ) {
|
|
return Utils.expBackoff ( function () {
|
|
return folder.getFilesByName (filename);
|
|
});
|
|
}
|
|
else {
|
|
return ns.ads.getFilesByName (folder.id , filename);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* get a folder from a path like /abc/def/hgh
|
|
* @param {string} path the path
|
|
* @return {Folder} a folder
|
|
*/
|
|
ns.getFolderFromPath = function (path) {
|
|
|
|
// the drivapp way
|
|
if (ns.isDriveApp()) {
|
|
return (path || "/").split("/").reduce (
|
|
function(prev,current) {
|
|
if (prev && current) {
|
|
var fldrs = Utils.expBackoff ( function () {
|
|
return prev.getFoldersByName(current);
|
|
});
|
|
return fldrs.hasNext() ? fldrs.next() : null;
|
|
}
|
|
else {
|
|
return current ? null : prev;
|
|
}
|
|
},ns.rootFolder);
|
|
}
|
|
|
|
|
|
// the advanced service way
|
|
else {
|
|
return ns.ads.getFolderFromPath (path);
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* get a path like /abc/def/hgh from a folder
|
|
* @param {Folder} folder the folder
|
|
* @return {string} a path
|
|
*/
|
|
ns.getPathFromFolder = function ( folder ,optPath) {
|
|
|
|
ns.checkService();
|
|
if (!folder) return '';
|
|
var path = optPath || '/';
|
|
|
|
// we're done if we hit the root folder
|
|
return folder.getId() === ns.rootFolderId ? path : ns.getPathFromFolder (
|
|
folder.getParents().next() , '/' + folder.getName() + path
|
|
);
|
|
|
|
};
|
|
|
|
|
|
return ns;
|
|
}) (DriveUtils || {});
|
|
|
|
|