Is there any way to change User-Agent of Apps script? - javascript

I am trying to change User-Agent. But It seems like I can't change it.
I implemented like this:
{
'User-Agent': "my spreadsheet"
}
the value above passes API function like this:
function API(m_headers, method, data){
var options = {
'headers': m_headers,
'muteHttpExceptions' : false,
'method' : method,
'payload' : data
};
var url = base_url+api;
try{
var response = UrlFetchApp.fetch(url, options)
}catch(e){
return url+"\n"+JSON.stringify(e);
}
}
And I get Attribute provided with invalid value in Google Apps Script error.
{"message":"Attribute provided with invalid value: headers","name":"Exception","fileName":"Code","lineNumber":42,"stack":"\tat Code:42 (API)\n"}
How can I solve this?

Nope. The number of supported consistent headers is strictly limited.

Related

Asana Events API always returning invalid sync token in Apps Script

I am trying to call the Asana Events API - https://developers.asana.com/reference/getevents
This endpoint uses a 'Sync' token to track when you last called it, each call returns a new sync token which can then be stored and used for the next call to only retrieve events since the last call.
If you do not provide a sync token the API will return an 'invalid token' response and give you a new token to get started with.
However, I cannot seem to get it beyond the initial 'invalid token' call, when I used the token in the following call it still returns 'invalid token'
This is using Google's Apps Script, which is basically just JavaScript with some built-in Google functions
Here is my code:
This function makes a call without the ‘sync’ parameter, uses muteHttpExceptions to get the full response text, and sets the sync token as a property in Apps Script (just a key/value pair)
var asanaBaseUrl = 'https://app.asana.com/api/1.0'
function getSyncToken() {
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events'
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
var newSyncToken = data.sync
userProps.setProperty('syncToken', newSyncToken)
}
This function uses the properties service to pull the sync token set in the previous call and makes a new call with the sync parameter
function asanaEventCall() {
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events'
var syncToken = userProps.getProperty('syncToken')
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'sync': syncToken,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
return data
}
The second function always returns the following
{sync=[SYNC TOKEN HERE], errors=[{message=Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.}]}
I’ve confirmed that the token is being set, retrieved, and sent correctly using the logs.
I’ve confirmed the flow above works by manually using the URL, like this:
Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events
Copy sync token
Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events?sync=[SYNC TOKEN]
Events show properly
I've looked for other answers but haven't found anything specific that helped, and I asked on the Asana forum but haven't got an answer in a few days.
I'm sure I'm missing something painfully obvious here but just can't see it!
From Go to https://app.asana.com/api/1.0/projects/[PROJECT GID]/events?sync=[SYNC TOKEN] of I’ve confirmed the flow above works by manually using the URL, like this:, in your script, it seems that it is required to add 'sync': syncToken, as the query parameter. So, how about modifying your asanaEventCall() as follows?
Modified script:
function asanaEventCall() {
var syncToken = userProps.getProperty('syncToken')
var url = asanaBaseUrl + '/projects/' + asanaProject + '/events' + '?sync=' + syncToken;
var headers = {
'Authorization': 'Bearer ' + asanaPAT
}
var options = {
'method': 'GET',
'headers': headers,
'muteHttpExceptions': true
}
var r = UrlFetchApp.fetch(url, options)
var data = JSON.parse(r.getContentText())
return data
}
Note:
In this modification, it supposes that your values of asanaProject, asanaPAT and syncToken are valid values. Please be careful about this.

How do I pass a variable inside a POST request URL in JavaScript?

I am trying to pass a variable that is derived from a database (and keeps changing) to a fetch URL. I don't want to hard code it in the URL. How do I go about it? Here is the snippet of the code.
};
var searchString = amount;
var payload = JSON.stringify(data);
var options = {
'method': 'POST',
'Content-Type': 'application/json',
'payload' : data,
};
var url = 'https://......./**amount**/budget_items?token';
var response = UrlFetchApp.fetch(url, options);
I want to pass the search string variable but I don't know-how. Any help?
If you want to include searchString in the url you can use string concatenation or string interpolation. Here is string concatenation:
var url = 'https://.../' + searchString + '/...';
And here is string interpolation:
var url = `https://.../${searchString}/...`;
If you're sending a GET request, you must include the query arguments in the URL. You don't have to hardcode anything - just add the query parameters in the fetch itself:
var response = UrlFetchApp.fetch(url + `?search=${searchString}`);
If you're trying to send a JSON object, you should instead use POST. You'll be able to preserve the URL as it is (as long as it's accepting POST requests). You'll be able to send JSON in the data option too.
To dynamically include searchString in the URL string you can use Matt's method, but you have some problem with your code. You are passing the wrong payload. Here is the modified code you can use it.
};
var searchString = amount;
var payload = JSON.stringify(data);
var options = {
'method': 'POST',
'Content-Type': 'application/json',
payload
};
var url = `https://......./${searchString}/budget_items?token`;
var response = UrlFetchApp.fetch(url, options);
To know more about Template literals
You may also use URL object (needs polyfills in IE)
const url = new URL('http://foo.bar/?search');
url.searchParams.set('search', searchString);

JavaScript API post and return using Google Sheets script?

I need some help with this. I can't figure out how to print the return from an api post sent from Google Sheets (including any error codes). Posting seems to work fine as the data shows up on RequestBin when I run the function in Sheets (although there are no quotes "" around the nonce output, which I don't understand either).
I need to be able to print the return in Google Sheets (this function runs in the Script Editor) and the data needs to overflow into adjacent cells, whatever the post request returns.
This is the functional code that I have so far:
function testPost() {
var nonce = new Date().getTime();
var data = {
'key':'QrHuXeXcbN',
'signature':'c4cc0d98be8e0860391799c2ca719da5ea6514f1538c4ec69ec1c19',
'nonce':nonce
};
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(data)
};
var response = UrlFetchApp.fetch('https://requestb.in/19bzt9a1', options);
}
I have tried a number of different ways to return the values but I can't figure it out.
Got it. Finally. Just needed this at the end... return response.getContentText()
function testPost() {
var nonce = new Date().getTime();
var data = {
'key':'QrHuXeXcbN',
'signature':'c4cc0d98be8e0860391799c2ca719da5ea6514f1538c4ec69ec1c19',
'nonce':nonce
};
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(data)
};
var response = UrlFetchApp.fetch('https://requestb.in/19bzt9a1', options);
return response.getContentText()
}

Connecting to Bitfinex API from Google Sheets

I'm trying to connect my google sheet to Bitfinex through the 'authenticated' section of the API so I can access my account information. Here is the API link.
I haven't been able to get the 'request' or 'crypto' libraries to work so I've been trying to use other available functions in google sheets, but am having trouble.
Following is the code snippet I'm using:
var completeURL = "https://api.bitfinex.com/v1/account_infos";
var nonce = Math.floor(new Date().getTime()/1000);
var body = {
'request' : completeURL,
'nonce' : nonce
};
var payload = JSON.stringify(body).toString('base64');
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384,
payload,
secret);
signature = signature.map(function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('');
var params = {
headers: {
'X-BFX-APIKEY': key,
'X-BFX-PAYLOAD': payload,
'X-BFX-SIGNATURE': signature
},
}
Logger.log(completeURL);
Logger.log(params);
var response = UrlFetchApp.fetch(completeURL, params);
var json = JSON.parse(response.getContentText());
I get the following error from the API:
Request failed for https://api.bitfinex.com/v1/account_infos returned code 400. Truncated server response: {"message":"Invalid json."} (use muteHttpExceptions option to examine full response). (line 209, file "Code")
And the following are the values from the Logger.log calls:
[17-09-24 16:22:28:170 AEST] https://api.bitfinex.com/v1/account_infos
[17-09-24 16:22:28:171 AEST] {headers={X-BFX-PAYLOAD={"request":"https://api.bitfinex.com/v1/account_infos","nonce":1506234148}, X-BFX-SIGNATURE=06d88a85098aefbf2b56af53721506863978f9350b1b18386c23f446254789dbbfc1eeb520bdfc7761b30f98ea0c21a2, X-BFX-APIKEY=ak6UoPiwaLjwt2UqDzZzZGjpb9P2opvdPCAIqLy0eVq}}
I'm stuck and not sure what else to try?
Can anyone spot what I'm doing wrong?
How about this modification? Since I have no secret, I couldn't debug this sample. So I don't know whether this modified sample works. I'm sorry.
Modification points :
secret is not defined.
When POST method is used, it requires to include method: "post" to UrlFetchApp.fetch().
When it reads Javascript sample of the document, signature has to be modified.
When it reads Javascript sample of the document, body: JSON.stringify(body) is included in the request parameters.
There is an error message of {"message":"Invalid json."}.
The script which was reflected above modifications is as follows.
Modified script :
var secret = "#####"; // Please input this.
var completeURL = "https://api.bitfinex.com/v1/account_infos";
var nonce = Math.floor(new Date().getTime()/1000);
var body = {
'request' : completeURL, // I don't know whether this is the correct value.
'nonce' : nonce
};
var payload = Utilities.base64Encode(Utilities.newBlob(JSON.stringify(body)).getDataAsString());
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384, payload, secret);
signature = signature.map(function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('');
var params = {
method: "post",
headers: {
'X-BFX-APIKEY': key,
'X-BFX-PAYLOAD': payload,
'X-BFX-SIGNATURE': signature
},
payload: JSON.stringify(body),
contentType: "application/json",
muteHttpExceptions: true
}
var response = UrlFetchApp.fetch(completeURL, params);
var json = JSON.parse(response.getContentText());
If this was not useful for you, I'm sorry.
I am not sure if I am understanding your code, but if I do, there is at least one oddity at first sight:
In computeHmacSignature(...), you are using the variable secret which has not been initialized or even declared anywhere.
That's how it works
var body = {
'request' : "/v1/balances",
'nonce' : nonce,
'options':{}
};

Accessing Highrise Data through API using GAS

As the title says, I am having issues accessing data in Highrise through their API using Google Script. I am new to google script, so some of the functions are not entirely clear to me. I understand that for the actual use of the API, I will be using UrlFetchApp.fetch(url) and that the url I will be using is foocompanyname.highrisehq.com/partofhighriseyouwishtoaccess.xml. From there I am lost however. The API documentation explains the process of authentication using curl (something I have never used before) and I cannot think of analogous functions in Google Script to accomplish this.
Here is the curl example they use to simply gain access
curl -u 605b32dd:X https://example.highrisehq.com/people/1.xml
And here is part of the function I am using that is trying to accomplish the same thing. The whole function is designed to obtain all of the notes from the companies visible to the user whose credentials are being used.
function obtainData(){
//enter subject-id of admin
// |
// V
var userid = "123456789"
var payload =
{
"action" : "/companies.xml"
};
var options =
{
"headers" : { "USER-AGENT" : "name#company.com",
"Authorization" : "Basic" + Utilities.base64Encode( "APIkey_from_Highrise_website" + ":" + "Dummy_password" )
},
"method" : "GET",
"payload" : payload,
muteHttpExceptions : true
};
var xmlCompanies = UrlFetchApp.fetch("https://foocompany.highrisehq.com/companies.xml", options).getContentText();
Logger.log(xmlCompanies);
However, when I run this I receive the error "[HTTP Basic: Access denied.
]" which I assume means that I have not passed on the credentials correctly. Could anyone perhaps tell me what I am doing wrong? After this step I am fairly confident about getting the data, it's the authorization that is getting me.
Try this, note the space after "Basic"
function obtainData(){
//enter subject-id of admin
// |
// V
var userid = "123456789"
var payload =
{
"action" : "/companies.xml"
};
var options =
{
"headers" : { "USER-AGENT" : "name#company.com",
"Authorization" : "Basic " + Utilities.base64Encode( "APIkey_from_Highrise_website" + ":" + "Dummy_password" )
},
"method" : "GET",
"payload" : payload,
muteHttpExceptions : true
};
var xmlCompanies = UrlFetchApp.fetch("https://foocompany.highrisehq.com/companies.xml", options).getContentText();
Logger.log(xmlCompanies);

Categories

Resources