I need my script to load the URL of a drive file to be added to a spreadsheet. For whatever reason 'File.getUrl()' returns null, but everything else seems to be working.
For example, 'File.getName()' works. So am I missing a permission or something?
Here is my code (abridged):
function loadURL(folderPath, name) {
var folder = loadFolder(folderPath);
// Find file
var files = folder.searchFiles('modifiedDate >= "' + getDate() + '" and title = "' + name + '"'),
file, found = 0;
for (; files.hasNext(); found++) {
file = files.next();
}
if (found == 1) {
/////////////////////////////////
// Here is 'getUrl'
/////////////////////////////////
var url = file.getUrl();
Logger.log("Loaded: " + url);
return url;
} else {
throw "Error loading file";
}
}
/**
* ** NOTE: THIS SEEMS TO BE WORKING FINE **
* Load a folder
* #param {string} url
* #return {Folder}
*/
function loadFolder(url) {
var folders = url.split('/'),
folder = DriveApp.getRootFolder();
Logger.log("Loading URL: " + url);
for (var key in folders) {
var fName = folders[key];
if (fName.length > 0) {
var fIt = folder.getFoldersByName(fName),
found = 0;
Logger.log(" -> " + fName);
for (; fIt.hasNext(); found++) {
folder = fIt.next();
}
if (found == 0) {
throw "Could not find the folder '" + fName + "'";
} else if (found > 1) {
throw "Found multiple matches to the folder '" + fName + "'";
}
}
}
return folder;
}
And the log if you're curious:
[14-02-26 19:56:15:980 EST] Loading URL: Work/PDF/
[14-02-26 19:56:15:981 EST] -> Work
[14-02-26 19:56:16:120 EST] -> PDF
[14-02-26 19:56:16:450 EST] Loaded: null
And if I change getUrl to getName it (kinda) works
[14-02-26 20:10:20:588 EST] Loading URL: Work/PDF/
[14-02-26 20:10:20:589 EST] -> Work
[14-02-26 20:10:20:727 EST] -> PDF
[14-02-26 20:10:21:058 EST] Loaded: Test
var url = DocsList.getFileById(fileId).getUrl();
Was recommended as a workaround by a poster on the issue thread that zig posted.
So, in your case, you'd use:
for (; files.hasNext(); found++) {
file = files.next();
}
if (found == 1) {
/////////////////////////////////
// Here is 'getUrl'
/////////////////////////////////
var fileId = file.getId();//new line added to getId of the file
//modified url line to reference doc by id
var url = DocsList.getFileById(fileId).getUrl();
Logger.log("Loaded: " + url);
return url;
} else {
throw "Error loading file";
}
I didn't get to test this right now because it's late and I'd have to build a the right structure to test it properly, but since you already have the structure change those two commented lines and let me know if that worked.
Using the id instead of the url works:
var url = "https://docs.google.com/document/d/" + file.getId() + "/";
Today started an issue with drive getUrl, google is aware of it and working on it.
Does work using docList or drive advanced services.
Related
So here's what I'm trying to do:
There's a website called Torah Anytime (https://www.torahanytime.com/) which publishes audio files (I guess you can call them podcasts, the website refers to them as shiurim, shiur being hebrew for song, or in this case, audio) on a daily basis. I would like to create a script that downloads the audio of specific speakers and then emails those files to me. The way I'm accomplishing this is with Google Apps Scripts. Torah Anytime allows you to follow specific speakers and to get email notifications when a speaker you're following puts out a new podcast. Here is the code that I have so far:
function main() {
var emails = getemails();
for (var i = 0; i < emails.length; i++) {
var email = emails[i].getMessages();
if (email[0].getFrom() == "TorahAnytime Following <following#torahanytime.com>"){
var title = getTitle(email);
var shiurID = getShiurID(email);
var downloadLink = "https://dl.torahanytime.com/audio/" + shiurID;
var shiur = downloadShiur(downloadLink);
shiur.setName(title);
var emailSent = emailShiur(shiur);
if (emailSent) {email[0].moveToTrash();
Logger.log("Email moved to Trash");}
}
}
}
function getemails() {
var label = GmailApp.getUserLabelByName("TA Speeches");
return label.getThreads();
}
function getTitle(email) {
body = email[0].getPlainBody();
var begIndex = body.indexOf("from") + 4;
var endIndex = body.indexOf("on ");
var title = body.substring(begIndex, endIndex).toLowerCase().replaceAll(" ", "-").replace(/(\r\n|\n|\r)/gm, "-");
begIndex = body.indexOf("called ") + 7;
endIndex = body.indexOf(" [");
title += "-" + body.substring(begIndex, endIndex).toLowerCase().replaceAll(" ", "-").replace(/(\r\n|\n|\r)/gm, "-") + ".mp3";
return title;
}
function getShiurID(email) {
body = email[0].getPlainBody();
var begIndex = body.indexOf("[") + 1;
var endIndex = body.indexOf("]");
var link = body.substring(begIndex, endIndex).replaceAll("?v", "?a");
console.log(link);
var mainLink = UrlFetchApp.fetch(link);
//here I somehow need to get the link being used to stream that particular audio file
}
function getIDName(email) {
body = email[0].getPlainBody();
var begIndex = body.indexOf("ID ") + 3;
var endIndex = body.indexOf(" and");
return body.substring(begIndex, endIndex);
}
function downloadShiur(downloadLink) {
var audio = UrlFetchApp.fetch(downloadLink);
return audio.getBlob().getAs('audio/mp3');
}
function emailShiur(shiur) {
const maxFileSize = 26214400;
if (shiur.getBytes().length <= maxFileSize) {
MailApp.sendEmail("[Email addressed removed]", "TA Shiur (File)", "Enjoy!", {
attachments: [shiur],
name: 'Automatic Emailer Script'
});
return true;
} else {
MailApp.sendEmail("[Email addressed removed]", "TA Shiur (File)", "Error, File too large to email", {
name: 'Automatic Emailer Script'
});
return false;
}
}
My issue is that the URL to download the file is not in the HTML, so I don't know how to get to it using GAS. If you use chrome's dev-tools, you can see the URL right there in the network tab Example of output I see that I want to get. Does anyone know of any way that I can get the information that I see in chrome's dev-tools network tab (the name's of the URLs being received) using GAS? Thank you!
how can I swap characters from the filename that is saved in GDrive? e.g. "/" to "-"
I am using this great script -> https://github.com/ahochsteger/gmail2gdrive/blob/master/Code.gs &
https://github.com/ahochsteger/gmail2gdrive/blob/master/Config.gs
It works really well.
But i would like to exchange letters for the attachment filename that is saved.
I use this script from https://github.com/ahochsteger/gmail2gdrive:
Code.gs
// Gmail2GDrive
// https://github.com/ahochsteger/gmail2gdrive
/**
* Returns the label with the given name or creates it if not existing.
*/
function getOrCreateLabel(labelName) {
var label = GmailApp.getUserLabelByName(labelName);
if (label == null) {
label = GmailApp.createLabel(labelName);
}
return label;
}
/**
* Recursive function to create and return a complete folder path.
*/
function getOrCreateSubFolder(baseFolder,folderArray) {
if (folderArray.length == 0) {
return baseFolder;
}
var nextFolderName = folderArray.shift();
var nextFolder = null;
var folders = baseFolder.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
if (folder.getName() == nextFolderName) {
nextFolder = folder;
break;
}
}
if (nextFolder == null) {
// Folder does not exist - create it.
nextFolder = baseFolder.createFolder(nextFolderName);
}
return getOrCreateSubFolder(nextFolder,folderArray);
}
/**
* Returns the GDrive folder with the given path.
*/
function getFolderByPath(path) {
var parts = path.split("/");
if (parts[0] == '') parts.shift(); // Did path start at root, '/'?
var folder = DriveApp.getRootFolder();
for (var i = 0; i < parts.length; i++) {
var result = folder.getFoldersByName(parts[i]);
if (result.hasNext()) {
folder = result.next();
} else {
throw new Error( "folder not found." );
}
}
return folder;
}
/**
* Returns the GDrive folder with the given name or creates it if not existing.
*/
function getOrCreateFolder(folderName) {
var folder;
try {
folder = getFolderByPath(folderName);
} catch(e) {
var folderArray = folderName.split("/");
folder = getOrCreateSubFolder(DriveApp.getRootFolder(), folderArray);
}
return folder;
}
/**
* Processes a message
*/
function processMessage(message, rule, config) {
Logger.log("INFO: Processing message: "+message.getSubject() + " (" + message.getId() + ")");
var messageDate = message.getDate();
var attachments = message.getAttachments();
for (var attIdx=0; attIdx<attachments.length; attIdx++) {
var attachment = attachments[attIdx];
Logger.log("INFO: Processing attachment: "+attachment.getName());
var match = true;
if (rule.filenameFromRegexp) {
var re = new RegExp(rule.filenameFromRegexp);
match = (attachment.getName()).match(re);
}
if (!match) {
Logger.log("INFO: Rejecting file '" + attachment.getName() + " not matching" + rule.filenameFromRegexp);
continue;
}
try {
var folder = getOrCreateFolder(Utilities.formatDate(messageDate, config.timezone, rule.folder));
var file = folder.createFile(attachment);
var filename = file.getName();
if (rule.filenameFrom && rule.filenameTo && rule.filenameFrom == file.getName()) {
filename = Utilities.formatDate(messageDate, config.timezone, rule.filenameTo.replace('%s',message.getSubject()));
Logger.log("INFO: Renaming matched file '" + file.getName() + "' -> '" + filename + "'");
file.setName(filename);
}
else if (rule.filenameTo) {
filename = Utilities.formatDate(messageDate, config.timezone, rule.filenameTo.replace('%s',message.getSubject()));
Logger.log("INFO: Renaming '" + file.getName() + "' -> '" + filename + "'");
file.setName(filename);
}
file.setDescription("Mail title: " + message.getSubject() + "\nMail date: " + message.getDate() + "\nMail link: https://mail.google.com/mail/u/0/#inbox/" + message.getId());
Utilities.sleep(config.sleepTime);
} catch (e) {
Logger.log(e);
}
}
}
/**
* Generate HTML code for one message of a thread.
*/
function processThreadToHtml(thread) {
Logger.log("INFO: Generating HTML code of thread '" + thread.getFirstMessageSubject() + "'");
var messages = thread.getMessages();
var html = "";
for (var msgIdx=0; msgIdx<messages.length; msgIdx++) {
var message = messages[msgIdx];
html += "From: " + message.getFrom() + "<br />\n";
html += "To: " + message.getTo() + "<br />\n";
html += "Date: " + message.getDate() + "<br />\n";
html += "Subject: " + message.getSubject() + "<br />\n";
html += "<hr />\n";
html += message.getBody() + "\n";
html += "<hr />\n";
}
return html;
}
/**
* Generate a PDF document for the whole thread using HTML from .
*/
function processThreadToPdf(thread, rule) {
Logger.log("INFO: Saving PDF copy of thread '" + thread.getFirstMessageSubject() + "'");
var folder = getOrCreateFolder(rule.folder);
var html = processThreadToHtml(thread);
var blob = Utilities.newBlob(html, 'text/html');
var pdf = folder.createFile(blob.getAs('application/pdf')).setName(thread.getFirstMessageSubject() + ".pdf");
return pdf;
}
/**
* Main function that processes Gmail attachments and stores them in Google Drive.
* Use this as trigger function for periodic execution.
*/
function Gmail2GDrive() {
if (!GmailApp) return; // Skip script execution if GMail is currently not available (yes this happens from time to time and triggers spam emails!)
var config = getGmail2GDriveConfig();
var label = getOrCreateLabel(config.processedLabel);
var end, start, runTime;
start = new Date(); // Start timer
Logger.log("INFO: Starting mail attachment processing.");
if (config.globalFilter===undefined) {
config.globalFilter = "has:attachment -in:trash -in:drafts -in:spam";
}
// Iterate over all rules:
for (var ruleIdx=0; ruleIdx<config.rules.length; ruleIdx++) {
var rule = config.rules[ruleIdx];
var gSearchExp = config.globalFilter + " " + rule.filter + " -label:" + config.processedLabel;
if (config.newerThan != "") {
gSearchExp += " newer_than:" + config.newerThan;
}
var doArchive = rule.archive == true;
var doPDF = rule.saveThreadPDF == true;
// Process all threads matching the search expression:
var threads = GmailApp.search(gSearchExp);
Logger.log("INFO: Processing rule: "+gSearchExp);
for (var threadIdx=0; threadIdx<threads.length; threadIdx++) {
var thread = threads[threadIdx];
end = new Date();
runTime = (end.getTime() - start.getTime())/1000;
Logger.log("INFO: Processing thread: "+thread.getFirstMessageSubject() + " (runtime: " + runTime + "s/" + config.maxRuntime + "s)");
if (runTime >= config.maxRuntime) {
Logger.log("WARNING: Self terminating script after " + runTime + "s");
return;
}
// Process all messages of a thread:
var messages = thread.getMessages();
for (var msgIdx=0; msgIdx<messages.length; msgIdx++) {
var message = messages[msgIdx];
processMessage(message, rule, config);
}
if (doPDF) { // Generate a PDF document of a thread:
processThreadToPdf(thread, rule);
}
// Mark a thread as processed:
thread.addLabel(label);
if (doArchive) { // Archive a thread if required
Logger.log("INFO: Archiving thread '" + thread.getFirstMessageSubject() + "' ...");
thread.moveToArchive();
}
}
}
end = new Date(); // Stop timer
runTime = (end.getTime() - start.getTime())/1000;
Logger.log("INFO: Finished mail attachment processing after " + runTime + "s");
}
and for Config.gs:
/**
* Configuration for Gmail2GDrive
* See https://github.com/ahochsteger/gmail2gdrive/blob/master/README.md for a config reference
*/
function getGmail2GDriveConfig() {
return {
// Global filter
"globalFilter": "-in:trash -in:drafts -in:spam",
// Gmail label for processed threads (will be created, if not existing):
"processedLabel": "to-gdrive/processed",
// Sleep time in milli seconds between processed messages:
"sleepTime": 100,
// Maximum script runtime in seconds (google scripts will be killed after 5 minutes):
"maxRuntime": 280,
// Only process message newer than (leave empty for no restriction; use d, m and y for day, month and year):
"newerThan": "1m",
// Timezone for date/time operations:
"timezone": "GMT",
// Processing rules:
"rules": [
{ // Store all attachments sent to my.name+scans#gmail.com to the folder "Scans"
"filter": "has:attachment to:my.name+scans#gmail.com",
"folder": "'Scans'-yyyy-MM-dd"
},
{ // Store all attachments from example1#example.com to the folder "Examples/example1"
"filter": "has:attachment from:example1#example.com",
"folder": "'Examples/example1'"
},
{ // Store all pdf attachments from example2#example.com to the folder "Examples/example2"
"filter": "has:attachment from:example2#example.com",
"folder": "'Examples/example2'",
"filenameFromRegexp": ".*\.pdf$"
},
{ // Store all attachments from example3a#example.com OR from:example3b#example.com
// to the folder "Examples/example3ab" while renaming all attachments to the pattern
// defined in 'filenameTo' and archive the thread.
"filter": "has:attachment (from:example3a#example.com OR from:example3b#example.com)",
"folder": "'Examples/example3ab'",
"filenameTo": "'file-'yyyy-MM-dd-'%s.txt'",
"archive": true
},
{
// Store threads marked with label "PDF" in the folder "PDF Emails" als PDF document.
"filter": "label:PDF",
"saveThreadPDF": true,
"folder": "PDF Emails"
},
{ // Store all attachments named "file.txt" from example4#example.com to the
// folder "Examples/example4" and rename the attachment to the pattern
// defined in 'filenameTo' and archive the thread.
"filter": "has:attachment from:example4#example.com",
"folder": "'Examples/example4'",
"filenameFrom": "file.txt",
"filenameTo": "'file-'yyyy-MM-dd-'%s.txt'"
}
]
};
}
I use this part to save the PDF attachments
{ // Store all pdf attachments from example2#example.com to the folder "Examples/example2"
"filter": "has:attachment from:example2#example.com",
"folder": "'Examples/example2'",
"filenameFromRegexp": ".*\.pdf$"
},
However, the character "/" is often used in the filename of the attachment. e.g. "Konto/postbox3226.pdf"
How can I replace this with e.g. "-" to "Konto-postbox3226.pdf"
Does that work with the replace command? If so, how do I have to use this?
many thanks for your help
Okay, I have taken a deeper look at the code and I found how to change the name of the file that it is stored in Google Drive.
In code.gs line 92:
try {
var folder = getOrCreateFolder(Utilities.formatDate(messageDate, config.timezone, rule.folder));
// NEW CODE
var new_filename = attachment.getName()
new_filename = new_filename.replace('/','-')
attachment.setName(new_filename)
var file = folder.createFile(attachment);
Reference
File.getName()
File.setName(name)
Folder.createFile(blob)
Let me know if that finally works
I am making a feature in my Java backend to create a Google Sheet.
Now in that backend, it already has a function to create Google Docs and it is working well. Following is the function to create a Google Doc.
public String createFileFromHtml(Project project, String html) throws DocumentGatewayException {
// Determine the google drive ID for the given areaId
String areaId =
Strings.isNullOrEmpty(project.getAreaId()) ? Constants.TEST_AREA : project.getAreaId();
String areaGoogleDriveId = null;
try {
if (areaIdToGoogleDriveIdMap.isEmpty() || !areaIdToGoogleDriveIdMap.containsKey(areaId)) {
String pageToken = null;
do {
String query = "'" + ERD_GOOGLE_DRIVE_ID + "' in parents";
query += " and mimeType = '" + FOLDER_MIME_TYPE + "'";
query += "and trashed = false";
FileList result =
drive
.files()
.list()
.setQ(query)
.setPageToken(pageToken)
.setFields("nextPageToken, files(id, name)")
.execute();
for (File file : result.getFiles()) {
areaIdToGoogleDriveIdMap.put(file.getName(), file.getId());
}
pageToken = result.getNextPageToken();
} while (pageToken != null);
}
} catch (IOException e) {
throw new DocumentGatewayException(e);
}
areaGoogleDriveId = areaIdToGoogleDriveIdMap.get(areaId);
Preconditions.checkArgument(
!Strings.isNullOrEmpty(areaGoogleDriveId), areaId + " needs to have a google drive folder");
// Generate metadata to be used to create the file using the google drive ID above.
File fileMetadata = new File();
fileMetadata.setName(project.getTitle());
fileMetadata.setMimeType("application/vnd.google-apps.document");
fileMetadata.setParents(Collections.singletonList(areaGoogleDriveId));
try {
// Create file.
File file =
drive
.files()
.create(
fileMetadata,
new ByteArrayContent("text/html", html.getBytes(StandardCharsets.UTF_8)))
.setFields("id")
.execute();
// Make all authors writers
if (!project.getAuthorIds().isEmpty()) {
for (String authorId : project.getAuthorIds()) {
processor.setWritter(project.getUuid(), file.getId(), authorId, 0);
}
// Set owner
String authorId = EmailUtils.AuthorNameToEmail(project.getAuthorIds().get(0));
processor.setOwner(project.getUuid(), file.getId(), authorId, 0);
}
// Set commenter
processor.setCommenter(project.getUuid(), file.getId(), 0);
return file.getId();
} catch (IOException e) {
logger.error(
"Error creating document", KeyValue.string("project_uuid", project.getUuid()), e);
throw new DocumentGatewayException(e);
}
}
I wanted to create a Google Sheet instead. So I tried changing application/vnd.google-apps.document to application/vnd.google-apps.spreadsheet. But after this change, it was still creating Google Doc instead of Google Sheet.
So anyones knows why? I just need to create a Google Sheet.
Google Drive API version: google-api-services-drive-v3-rev130-1.25.0
Thanks.
I need to create sub folders in google drive using google drive api added using nuget package in console application.
I can get the folder id of root folder. Can get children of rot folder, can also upload file in root folder. Only problem is creation of sub folders in folders.
for (int i = 1; i < array.Count(); i++)
{
var subfoldername = new Google.Apis.Drive.v2.Data.File { Title = array[i], MimeType = "application/vnd.google-apps.folder" };
ChildrenResource.ListRequest request = service.Children.List(rootfolderid);
ChildList children = request.Execute();
if (children.Items.Count > 0)
{
foreach (ChildReference c in children.Items)
{
Google.Apis.Drive.v2.Data.File file = service.Files.Get(c.Id).Execute();
if (file.MimeType == "application/vnd.google-apps.folder")
{
List<GoogleDriveFile> googledrive = new List<GoogleDriveFile>();
googledrive.Add(new GoogleDriveFile
{
OriginalFilename = file.OriginalFilename
});
}
}
}
else
{
// here need to add sub folder in folder, but this line adds folder at root
var result = service.Files.Insert(foldername).Execute();
}
Here is the way i do, when creating a sub folder in google drive it must need a parents. So before execute the string q, we need to search for the parent root id
string findRootId = "mimeType = 'application/vnd.google-apps.folder' and title ='" + RootFolder + "' and trashed = false";
IList<File> _RootId = GoogleDriveHelper.GetFiles(service, findRootId);
if (_RootId.Count == 0) {
_RootId.Add(GoogleDriveHelper.createDirectory(service, RootFolder, "", "root"));
Console.WriteLine("Root folder {0} was created.", RootFolder);
}
var id = _RootId[0].Id;
string Q = "mimeType = 'application/vnd.google-apps.folder' and '" + id + "' in parents and title ='" + GoogleDriveFolderName + "' and trashed = false";
You must add the property parents while creating a Folder.
parents[]
Collection of parent folders which contain this file.
Setting this field will put the file in all of the provided folders. On insert, if no folders are provided, the file will be placed in the default root folder.
Sample Code:
function createSubFolder() {
var body = new Object();
body.title = 'SubFolder';
body.parents = [{'id':'0B5xvxYkWPFpCUjJtZVZiMWNBQlE'}];
body.mimeType = "application/vnd.google-apps.folder";
console.log(body)
var request = gapi.client.request({
'path': '/drive/v2/files',
'method': 'POST',
'body': JSON.stringify(body)
});
request.execute(function(resp) { console.log(resp); });
}
I'm using Drive v2 in JavaScript
Hope this helps
Below is the code taken from Arun Nagarajan's Example: I am tried the same code to check.. But Its not installing properly. (I removed my redirect url, client id and secret in the below). Please tell me what wrong in the below code.
var AUTHORIZE_URL = 'https://accounts.google.com/o/oauth2/auth';
var TOKEN_URL = 'https://accounts.google.com/o/oauth2/token';
var REDIRECT_URL = 'exec';
var tokenPropertyName = 'GOOGLE_OAUTH_TOKEN';
var CLIENT_ID = '';
var CLIENT_SECRET = '';
function doGet(e) {
var HTMLToOutput;
if(e.parameters.state){
var state = JSON.parse(e.parameters.state);
if(state.action === 'çreate'){
var meetingURL = createMeetingNotes();
HTMLToOutput = '<html><h1>Meeting notes document created!</h1> <click here to open</html>';
}
else if (state.ids){
var doc = DocsList.getFileById(state.ids[0]);
var url = doc.getContentAsString();
HTMLToOutput = '"<html><a href="' +url+'"</a></html>"';
}
else {
zipAndSend(state.ecportIds.Session.getEffectUser().getEmail());
HTMLToOutput = '"<html><h1>Email sent. Check your Inbox.</h1></html>"';
}
}
else if(e.parameters.code){
getAndStoreAccessToken(e.parameters.code);
HTMLToOutput = '<html><h1>App is installed. You can close this window now or navigate to your </h1>Google Drive</html>';
}
else {
HTMLToOutput = '<html><h1>Install this App into your google drive </h1>Click here to start install</html>';
}
return HtmlService.createHtmlOutput(HTMLToOutput);
}
function getURLForAuthorization() {
return AUTHORIZE_URL + '?response_type=code&client_id=' + CLIENT_ID + '&redirect_uri=' + REDIRECT_URL + '&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.install+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email';
}
function getAndStoreAccessToken(code) {
var parameters = { method : 'post',
payload : 'client_id='+ CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&grant_type=authorization.code&redirect_uri=' + REDIRECT_URL};
var response = UrlFetchApp.fetch(TOKEN_URL.parameters).getContentText();
var tokenResponse = JSON.parse(response);
UserProperties.getProperty(tokenPropertyName, tokenResponse.access_token);
}
function getUrlFetchOptions() {
return {'contentType' : 'application/json',
'headers' : {'Authorization': 'Bearer ' + UserProperties.getProperty(tokenPropertyName),
'Accept' : 'application/json'}};
}
function IsTokenValid() {
return UserProperties.getProperty(tokenPropertyName);
}
The error showing is: Bad request:undefined
I think the error is inside the function called : getAndStoreAccessToken.
var parameters = { method : 'post',
payload : 'client_id='+ CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&grant_type=authorization.code&redirect_uri=' + REDIRECT_URL};
Please tell me the correct url format for payload.
The error seems in this line -
var response = UrlFetchApp.fetch(TOKEN_URL.parameters).getContentText();
I think you want TOKEN_URL , parameters (note the comma)
First, if you are trying to access Google Drive from within google apps script, what is the purpose of the authorization? Google drive is available w/o authorization. Are you trying to make your application utilize the gDrive of other users (or on behalf of other users)?
Second, instead of manually performing the authorization, which is very hard to troubleshoot, you can take advantage of Class OAuthConfig which simplifies the authorization/request process. The only disadvantage is that OAuthConfig currently uses OAuth1.0 (which is currently deprecated). Although it's particular use is Fusion Tables, and not drive, this library makes great use of OAuthConfig and .fetch and I have used it to model my own OAuth functions. My example below works great. The googleAuth() function sets up the authorization and then the rest of the application can make authorized requests using UrlFetchApp.fetch(url,options) while google does all the authorization stuff in the background.
function googleAuth(oAuthFields) {
var oAuthConfig = UrlFetchApp.addOAuthService(oAuthFields.service);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/"+
"OAuthGetRequestToken?scope=" + oAuthFields.scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey(oAuthFields.clientId);
oAuthConfig.setConsumerSecret(oAuthFields.clientSecret);
return {oAuthServiceName:oAuthFields.service, oAuthUseToken:"always"};
}
function fusionRequest(methodType, sql, oAuthFields, contentType) {
var fetchArgs = OAL.googleAuth(oAuthFields);
var fetchUrl = oAuthFields.queryUrl;
fetchArgs.method = methodType;
if( methodType == 'GET' ) {
fetchUrl += '?sql=' + sql;
fetchArgs.payload = null;
} else{
fetchArgs.payload = 'sql='+sql;
}
if(contentType != null) fetchArgs.contentType = contentType;
Logger.log(UrlFetchApp.getRequest(oAuthFields.queryUrl, fetchArgs));
var fetchResult = UrlFetchApp.fetch(oAuthFields.queryUrl, fetchArgs);
if( methodType == 'GET' ) return JSON.parse(fetchResult.getContentText());
else return fetchResult.getContentText();
}