Skip to content

Instantly share code, notes, and snippets.

@CapyTheBeara
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CapyTheBeara/9539722 to your computer and use it in GitHub Desktop.
Save CapyTheBeara/9539722 to your computer and use it in GitHub Desktop.
An Ember object to send Google Drive API requests
// Created this object to facilitate an Ember Data Adapter
// Usage:
g = Gapi.create();
// create a file with just meta data (no content)
g.insert({ title: 'first' });
// create a file with content
g.insert({ title: 'second', content: 'second content'});
// search for a file
g.findQuery({ q: "title contains 'fir'" });
g.findQuery({ q: "fullText contains 'content'" });
// find all and get file ids
var ids;
g.findAll().then(function(res) { ids = res.items.getEach('id'); });
// update a file's meta data
g.update(ids[0], { title: 'third' });
// get a file an then its content
var url;
g.fetch(ids[0]).then(function(res){ url = res.downloadUrl; });
g.getFileContent(url).then(function(res) { console.log(res); });
// update a file's content
g.update(ids[0], { content: 'new content here'} );
g.getFileContent(url).then(function(res) { console.log(res); });
// destroy a file
ids.forEach(function(id) { g.destroy(id); });
////////////////////////////////////////
var gapiScriptUrl = 'https://apis.google.com/js/client.js?onload=gapiReady',
scopes = 'https://www.googleapis.com/auth/drive.appdata',
apiKey = 'YOUR_KEY',
clientId = 'YOUR_CLIENT_ID',
Promise = Em.RSVP.Promise;
function log() {
if (!window.config.DEBUG) { return; }
console.log.apply(console, Array.prototype.slice.call(arguments, 0));
}
function handleResponse(resolve, reject) {
return function(res) {
if (res.error) {
log(res);
Em.run(null, reject, res);
} else {
log(res);
Em.run(null, resolve, res);
}
};
}
var boundary = '-------314159265358979323846';
var delimiter = "\r\n--" + boundary + "\r\n";
var close_delim = "\r\n--" + boundary + "--";
function createRequestBody(fileResource, content) {
return delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(fileResource) +
delimiter +
'Content-Type: ' + fileResource.mimeType + '\r\n\r\n' +
content +
close_delim;
}
var driveUploadPath = '/upload/drive/v2/files';
// allows adding content to a file (either insert or update)
function clientRequest(opts) {
var fileResource = opts.fileResource,
content = fileResource.content,
path = opts.id ? driveUploadPath + '/' + opts.id : driveUploadPath;
if (!fileResource.mimeType) {
fileResource.mimeType = 'text/plain';
}
if (!content) {
return opts.simpleRequest();
} else {
delete fileResource.content;
}
log('==sending client request== ', opts);
return new Promise(function(resolve, reject) {
gapi.client.request({
path: path,
method: opts.method,
params: { uploadType: 'multipart' },
headers: {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
body: createRequestBody(fileResource, content)
}).execute(handleResponse(resolve, reject));
});
}
function ajax(url, method, token) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
type: method,
headers: {
'Authorization': 'Bearer ' + token
},
success: function(res) {
Em.run(null, resolve, res);
},
error: function(jqXHR, status, error) {
Em.run(null, reject, error);
}
});
});
}
var Gapi = Em.Object.extend(Em.PromiseProxyMixin, {
promise: null,
authorized: null,
reqMethod: null,
reqArgs: null,
requestedAt: null,
accessToken: null,
gapiReady: false,
driveReady: false,
init: function() {
this._super();
if (!window.gapi) {
window.gapiReady = this.setGapiReady.bind(this);
$.getScript(gapiScriptUrl);
} else {
this.set('gapiReady', true);
}
},
setGapiReady: function() {
this.set('gapiReady', true);
},
gapiReadyChanged: function() {
if (!this.get('gapiReady')) { return; }
gapi.client.setApiKey(apiKey);
gapi.client.load('drive', 'v2', function(res) {
this.set('driveReady', true);
}.bind(this));
Em.run.next(this, function() { this.authorize(true); });
}.observes('gapiReady').on('init'),
authorize: function(immediate) {
gapi.auth.authorize({
client_id: clientId,
scope: scopes,
immediate: immediate
}, this.handleAuthResult.bind(this));
},
handleAuthResult: function(authResult) {
if (authResult && !authResult.error) {
this.set('authorized', true);
this.set('accessToken', gapi.auth.getToken().access_token);
} else {
this.set('authorized', false);
}
},
fetch: function(id) {
return this.request('get', { fileId: id });
},
findQuery: function(query) {
return this.request('list', query);
},
findAll: function() {
return this.request('list');
},
// creates new file w/ metadata or file w/ metadata and content
insert: function(fileResource) {
if (!fileResource.parents) {
fileResource.parents = [{ id: 'appdata' }];
}
return clientRequest({
fileResource: fileResource,
method: 'POST',
simpleRequest: function() {
return this.request('_insert', { resource: fileResource });
}.bind(this)
});
},
// only updates file metadata
patch: function(id, fileResource) {
return this.request('patch', {
fileId: id,
resource: fileResource
});
},
// updates file metadata or content
update: function(id, fileResource) {
return clientRequest({
id: id,
fileResource: fileResource,
method: 'PUT',
simpleRequest: function() {
return this.patch(id, fileResource);
}.bind(this)
});
},
// This sends a POST request which sends back a response.
// Ember Data throws an error because of this.
// destroy: function(id) {
// return this.request('delete', { fileId: id });
// },
destroy: function(id) {
var url = 'https://www.googleapis.com/drive/v2/files/' + id;
return ajax(url, 'DELETE', this.get('accessToken'));
},
request: function() {
var args = Array.prototype.slice.call(arguments, 0);
this.setProperties({
reqMethod: args[0],
reqArgs: args.slice(1),
requestedAt: new Date().getTime()
});
return this;
},
sendRequest: function() {
var method = this.get('reqMethod'),
args = this.get('reqArgs');
if (!this.get('driveReady') || !method) { return; }
log('==sending request== ', method, args);
if (method === 'insert') {
return this.insert.apply(this, args);
}
if (method === '_insert') {
method = 'insert';
}
var promise = new Promise(function(resolve, reject) {
gapi.client.drive
.files[method].apply(null, args)
.execute(handleResponse(resolve, reject));
});
this.set('promise', promise);
}.observes('driveReady', 'requestedAt'),
getFileContent: function(downloadUrl) {
var token = this.get('accessToken');
return ajax(downloadUrl, 'GET', token);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment