I am trying to run a google apps script, in a document, that sends an email with an attached google spreadsheet as an .xlsx file automatically, running every few hours.
Below is the solution that works if I use a manual OAuth2 code coming from the google OAuth2 playground :
function downloadXLS() {
var AUTH_TOKEN = "xxxx";
var auth = "AuthSub token=\"" + AUTH_TOKEN + "\"";
var file = Drive.Files.get('xxxx');
var response = UrlFetchApp.fetch('https://docs.google.com/spreadsheets/d/xxx/export?format=xlsx',{headers: {Authorization: auth}});
var doc = response.getBlob();
app = DriveApp.createFile(doc).setName(file.title + '.xls')
MailApp.sendEmail("xxx#xxx.com", "oh man", " Body", { attachments: app })
}
To try to auto-generate the authorization token I followed exactly all the steps here:
https://github.com/googlesamples/apps-script-oauth2
Changing on the script :
.setClientId('...')
.setClientSecret('...')
I also put in the URI the the Project Id inside the https://script.google.com/macros/d/myprojectkey/usercallback of the google developer console
But when i run the function makeRequest() it tells me : "Access not granted or expired"
So i wonder which step i missed.
Do you have any clue on what is going on ?
Help is much appreciated,
Thanks
You need to do step 2: Direct the user to the authorization URL
When the sidebar loads you will click the link and the Oauth dialog will open. After you allow access you can use the getAccessToken() method.
EDIT:
For your specific case you do not need a separate OAuth flow. You can use Apps Script to get the token you need to do that export. As you are already requesting access to drive your token will work for the export call.
function downloadXLS() {
var file = Drive.Files.get('xxxx');
var response = UrlFetchApp.fetch('https://docs.google.com/spreadsheets/d/xxx/export?format=xlsx',{headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}});
var doc = response.getBlob();
app = DriveApp.createFile(doc).setName(file.title + '.xls')
MailApp.sendEmail("xxx#xxx.com", "oh man", " Body", { attachments: app })
}
Related
I have a Google Maps Engine project where a datasource can be updated via Google Forms/Google Apps Script. I know that there is a way to configure OAuth in GAS (https://developers.google.com/apps-script/reference/url-fetch/o-auth-config) but I can't figure out how to make it work after spending hours reading through the GAS and GME documentation. I have been able to get around it using the OAuth Playground to obtain an access token, but I need to manually refresh each hour. I know the answer is probably simple, but I am new to OAuth and I can't find a simple guide out there to help me.
How can I get my Google Apps Script to play nicely with Google Maps Engine through OAuth?
I have included how I currently access GME below:
/* This function is called when a new provider is added through the "Medical Providers" form
It sends an HTTP request to Google Maps Engine to add the new provider to the map */
function addNewtoTable(row){
var aPIKey = "MY_API_KEY";
var bearer = "ACCESS_TOKEN_FROM_OAUTH_PLAYGROUND";
var projectID = "MY_PROJECT_ID";
var tableID = "MY_TABLE_ID";
//tutorial here https://developers.google.com/maps-engine/documentation/tutorial
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Providers");
var address = sheet.getRange(row,2).getValue();
var response = Maps.newGeocoder().geocode(address);
for (var j = 0; j < response.results.length; j++) {
var result = response.results[j];
//Logger.log('%s: %s, %s', result.formatted_address, result.geometry.location.lat,
// result.geometry.location.lng);
};
var lat = result.geometry.location.lat;
var long = result.geometry.location.lng;
var name= '"'+sheet.getRange(row,1).getValue()+'"';
var phone= '"'+sheet.getRange(row,4).getValue().toString()+'"';
var email= '"'+sheet.getRange(row,3).getValue()+'"';
var inbounds= '"'+sheet.getRange(row,5).getValue().toString()+'"';
var outbounds = '"'+sheet.getRange(row,6).getValue().toString()+'"';
var lastIn = '" '+sheet.getRange(row,7).getValue().toString()+' "';
var lastOut = '" '+sheet.getRange(row,8).getValue().toString()+' "';
var gxid = '"'+sheet.getRange(row,9).getValue().toString()+'"';
//HTTP request goes here
var payload = '{features:[{type: "Feature",geometry:{type: "Point",coordinates: ['+long+','+lat+']},properties: {gx_id: '+gxid+',name: '+name+',phone:'+phone+',email:'+email+',inbound:'+inbounds+',outbound:'+outbounds+',last_inbound:'+lastIn+',last_outbound:'+lastOut+'}}]}';
Logger.log(payload);
var headers = {"Authorization": "Bearer ACCESS_TOKEN_FROM_OAUTH_PLAYGROUND", "Content-type": "application/json"};
var options ={"method" : "post","headers" : headers, "payload" : payload, "muteHttpExceptions" : true};
var httpresponse = UrlFetchApp.fetch("https://www.googleapis.com/mapsengine/v1/tables/MY_TABLE_ID/features/batchInsert",options);
Logger.log(httpresponse);
if (httpresponse!=""){
MailApp.sendEmail('MY_EMAIL', 'HTTP Request Failed to Send', httpresponse);
};
};
It's certainly possible. The App Script docs have a tutorial explaining how to connect to a remote service using OAuth that uses the Twitter API as an example. This example also shows an OAuth-authorized call being executed.
The main difference in the tutorial for Maps Engine is the first step, where you don't set up with Twitter, you set up in the Developers Console.
You want to create a new OAuth client ID, under APIs & Auth -> Credentials. It's a web application.
Instead of setting the "Callback URL" in Twitter, you'll set the "Authorized Redirect URI" in the console, when creating the client ID. Set the authorized origins to docs.google.com too, just in case.
You'll get your "Consumer Key" and "Consumer Secret" through console.developers.google.com too, they correspond to the Client ID and Client Secret that are referred to in this GME doc.
In addition to the set up, these pointers may help you.
The UrlFetchApp.addOauthService("twitter") calls can use any string as an identifier, there's nothing special about the phrase "twitter", but it needs to match oAuthServiceName
The URLs you need look like they should be these (grabbed from here):
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope); Scope is explained here.
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
A little too late for my purposes, but I found that Google themselves made a library for GAS that enables OAuth 2.0. Why this is not included within GAS is beyond me. This also looks to be pretty recent, with some updates as of 5 days ago.
I am trying to call Twitter's REST API from Google Apps Script.
The code I am using is copied one to one from here:
https://developers.google.com/apps-script/guides/services/external
and specifically:
function test() {
var consumerKey = 'XXXX'; // Copied from my twitter app setting.
var consumerSecret = 'XXXXX'; // Copied from my twitter app setting.
var oauthConfig = UrlFetchApp.addOAuthService('twitter');
oauthConfig.setAccessTokenUrl('http://api.twitter.com/oauth/access_token');
oauthConfig.setRequestTokenUrl('http://api.twitter.com/oauth/request_token');
oauthConfig.setAuthorizationUrl('http://api.twitter.com/oauth/authorize');
oauthConfig.setConsumerKey(consumerKey);
oauthConfig.setConsumerSecret(consumerSecret);
var options = {
'oAuthServiceName' : 'twitter',
'oAuthUseToken' : 'always'
};
var url = 'https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=hello';
var response = UrlFetchApp.fetch(url, options);
var tweets = JSON.parse(response.getContentText());
Logger.log(tweets)
}
Nevertheless, I get Oauth ERROR every time I run it.
My settings in the twitter app allows for "Read and Write"
Any suggestions
Just go to your twitter application and set the callback url as
https://script.google.com
This is now best handled through the following open source Google Apps Script library:
https://github.com/googlesamples/apps-script-oauth1
The example in the documentation is twitter itself (because it's probably the only remaining user of oauth v1 out there...)
Cheers, M
I'm trying to build a Google Apps Script that integrates with Trello, the idea being to use it to push information from spreadsheets and forms into the Trello API and create cards on a pending list on a certain board.
I found another question that pointed me in the right direction, and added in OAuth based on the GAS OAuth Documentation. The problem is I can't post the the board. I run the script, the OAuth prompt fires, and the script completes with no errors. I can also GET data from the private board, so I assume the authorization is working properly.
So, what am I doing wrong that prevents my script from POSTing to Trello?
Here's the code I'm working with:
var trelloKey = [Trello API key];
var trelloSecret = [Trello API key secret];
var trelloList = [the id of the list we're posting to];
var oauthConfig = UrlFetchApp.addOAuthService('trello');
oauthConfig.setAccessTokenUrl('https://trello.com/1/OAuthGetAccessToken');
oauthConfig.setRequestTokenUrl('https://trello.com/1/OAuthGetRequestToken');
oauthConfig.setAuthorizationUrl('https://trello.com/1/OAuthAuthorizeToken');
oauthConfig.setConsumerKey(trelloKey);
oauthConfig.setConsumerSecret(trelloSecret);
function createTrelloCard() {
//POST [/1/cards], Required permissions: write
var payload = {'name': 'apiUploadedCard',
'desc': 'description',
'pos': 'top',
'due': '',
'idList': trelloList};
var url = 'https://api.trello.com/1/cards'
var options = {'method' : 'post',
'payload' : payload,
'oAuthServiceName' : 'trello',
'oAuthUseToken' : 'always'};
UrlFetchApp.fetch(url, options);
}
You just need set fetch options contentType to application/json. I just resolved the same problem by this.
Try adding the scope=read,write in your authorization url.
from:
oauthConfig.setAuthorizationUrl('https://trello.com/1/OAuthAuthorizeToken');
to:
oauthConfig.setAuthorizationUrl("https://trello.com/1/OAuthAuthorizeToken?scope=read,write");
Hello,
I'm trying to acess, perform a post, into Tumblr with Oauth api provided by Tumblr) http://tumblr.com/api). I'm using Google Script and I've tryied too many solutions but anyone worked. To implement i've basaed myself into this(https://developers.google.com/apps-script/articles/twitter_tutorial) Google script twitter tutorial, once on Tumblr API web page they say that twitter api is almost the same that tumblr.
Contextualizing,
I've already set the Oauth class methods with data below and substituted consumer and secret keys with values got from the api i've created.
var oauthConfig = UrlFetchApp.addOAuthService("tumblr");
oauthConfig.setAccessTokenUrl(
"http://www.tumblr.com/oauth/access_token");
oauthConfig.setRequestTokenUrl(
"http://www.tumblr.com/oauth/request_token");
oauthConfig.setAuthorizationUrl(
"http://www.tumblr.com/oauth/authorize");
oauthConfig.setConsumerKey(<i>consumerkey</i>);
oauthConfig.setConsumerSecret(<i>consumerSecret</i>);
Error,
The code below isnt working as it should be.
var requestData = {
"method": "POST",
"oAuthServiceName": "tumbler",
"oAuthUseToken": "always"
};
var result = UrlFetchApp.fetch(
"https://api.tumblr.com/v2/blog/{blog}.tumblr.com/post?type=text&body=word",
requestData);
The Script to Twitter is almost the same and it works. Im able to perform tweets.
var result = UrlFetchApp.fetch(
"https://api.twitter.com/1/statuses/update.json?status=" + tweet,
requestData);
Response From Server
Request failed for returned code 400. Server response: {"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Post cannot be empty."]}}
Possible Solutions
A possible solution can work using this information(got from tumblr.com/api):
OAuth
The API supports the OAuth 1.0a Protocol, accepting parameters via the Authorization header, with the HMAC-SHA1 signature method only. There's probably already an OAuth client library for your platform.
My question is, what am I doing wrong?(my post inst empty, i have 2 params). Had anyone had the same problem? Someone has suggestions?
Thank You.
I don't know anything about the tumblr api, but your http post is empty (the oAuth parameters aren't in the post body, they're advanced options), the body of the post needs to go in the "payload" parameter. See the section "Advanced parameters" in the docs. Or, as you aren't using the post can't you use a get request instead? Remove the method: POST parameter (GET is the default).
Thank You very much Daniel. It worked now!!
Everybody that want use Tumblr + Google Script API + oAuth can use de code below to perform posts.
I created I Google Spreadsheet and then a script there. Before to be able to post I neded to create and app into tumblr.com/api and get secret and consumer keys. Also I've deployed the Google script as an web app(ensure that the version is the last one(the final code)) before to create a new version. After that you go tu publish > deploy as web app !
That twitter tutorial I put on my first question is the only path you need to conclude your job.
function authorize() {
var oauthConfig = UrlFetchApp.addOAuthService("tumblr");
oauthConfig.setAccessTokenUrl(
"http://www.tumblr.com/oauth/access_token");
oauthConfig.setRequestTokenUrl(
"http://www.tumblr.com/oauth/request_token");
oauthConfig.setAuthorizationUrl(
"http://www.tumblr.com/oauth/authorize");
oauthConfig.setConsumerKey(getConsumerKey());
oauthConfig.setConsumerSecret(getConsumerSecret());
var requestData = {
"oAuthServiceName": "tumblr",
"oAuthUseToken": "always"
};
var result = UrlFetchApp.fetch(
"http://api.tumblr.com/v2/blog/{your_blog}.tumblr.com/posts/queue",
requestData);
}
function doGet(e) {
var tweet = e.parameter.tumblr;
var app = UiApp.createApplication().setTitle("Approved");
var panel = app.createFlowPanel();
authorize();
var encodedTweet = encodeURIComponent(tweet);
var payload =
{
"body" : encodedTweet,
"type" : "text"
};
var requestData = {
"method" : "POST",
"oAuthServiceName": "tumblr",
"oAuthUseToken": "always",
"payload" : payload
};
try {
var result = UrlFetchApp.fetch(
"https://api.tumblr.com/v2/blog/{your_blog}.tumblr.com/post",
requestData);
panel.add(app.createLabel().setText("You have approved: \"" + tweet + "\""));
} catch (e) {
Logger.log(e);
panel.add(app.createLabel().setText(e));
}
app.add(panel);
return app;
}
I get this error: Unexpected exception upon serializing continuation (not much help)
It is caused by the FetchUrlApp.fetch(); call. I akm using Google Apps Script for Sites, not Google Spreadsheets. The code works in the original instance but as soon as I copy and paste the code into a new project I get the above error message. I am accessing Google Docs APIs. I have read on other forums that I need authorization but I have been unable to gain the right authorization for the code to work. No prompt ever pops up when I run a copy of the code for the first time.
Code exert:
var oauthConfig = UrlFetchApp.addOAuthService("docs");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://docs.google.com/feeds/");
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey(_consumerKey_);
oauthConfig.setConsumerSecret(_consumerSecret_);
var requestData3 = {
"method": "GET",
"headers": {"GData-Version": "3.0"},
"oAuthServiceName": "docs",
"oAuthUseToken": "always",
};
var url = "https://docs.google.com/feeds/" + userName + "/private/full/-/mine";
var result = UrlFetchApp.fetch(url, requestData3); //error occurs, any thoughts?
Thank you in advance,
James Krimm
You have to set both consumerKey and consumerSecret to "anonymous" in order to trigger the 3-legged OAuth process:
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
Replace your two lines with these and the authorization popup dialog will show up, allowing the user to grant access to its documents.
What I would suggest is to write a special function that does nothing else than call the Oauth process and call it from the script editor once.
As an example, here is the one I have used recently to make the authorize popup appear :
function authorize(){
// function to call from the script editor to authorize googleOauth
var id=mailtemplatedoc
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/documents/Export? exportFormat=html&format=html&id='+id,
googleOAuth_('docs',url)).getContentText();
}
EDIT : And the missing part I had forgotten :
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}