"Invalid argument" when sending GET to spaces.members.list - google-apps-script

I'm trying to create a Google Hangouts Chat chatbot (in G Suite) using Apps Script. I want to get a list of everyone in the chatroom, but this isn't directly supported in Apps Scripts yet, so I'm using the rest API. The API call list seems straightforward:
The command is
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
I've created a service account for authorization and then used
var endpoint = 'https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxx"}/members'
var options = {
method: "GET",
contentType : "application/json" ,
muteHttpExceptions : true,
headers: {
"Authorization": "Bearer " + goa.getToken(),
}
};
var response = UrlFetchApp.fetch(endpoint, options)`
To which I get
Invalid argument: https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxxx"}/members
I've tried encoding the parent parameter, but the error persists. Any ideas?

Per official documentation on the page you linked, the expected format of the path parameter parent is of the form spaces/*. The example value given is spaces/AAAAMpdlehY
In other words, you are not expected to write the {parents= and } bits, even though the template URL
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
has them. This template url format is explained in-depth on the Google API HTTP annotation website.
In your example, the correct URI to GET is https://chat.googleapis.com/v1/spaces/pQkgxxxxxxx/members
You should also consider that it may take multiple calls to resolve all members of the space pQkgxxxxxxx, by checking for a nextPageToken in the response (and passing that as the URL parameter pageToken in the next call).
You should also consider that the MemberShip returned by this query may include members with various states of membership.

Related

weird file listing response differences between v2 and v3

I am using the google-drive-sdk with our company-made device. We upload pictures made by our device to google drive. After that I try to list the files with a GET request to https://www.googleapis.com/drive/v2/files to get thumbnailLink and webContentLink. Everything is working fine except that when I switch to v3 I don't get the response I should. The documentation says I should get a metadata response like https://developers.google.com/drive/v3/reference/files
but I only get: id, kind, name and mimeType. What am I doing wrong?
As stated in Migrate to Google Drive API v3 documentation, there are changes on how fields were returned.
Full resources are no longer returned by default. You need to use the fields query parameter to request specific fields to be returned. If left unspecified only a subset of commonly used fields are returned.
You can see examples on Github. This SO question might also help.
In v3 they made all the queries parametric. So you can query passing some parameter like
var request = gapi.client.drive.files.list({
'pageSize': 10,
'fields': 'files,kind,nextPageToken'
});
This block of code will return you all the information of every file just like v2.
If you are sending a get request then for fetching all the information you can try GET https://www.googleapis.com/drive/v3/files?fields=files%2Ckind%2CnextPageToken&key={YOUR_API_KEY}
Suppose you need ownsers and permissions only then set
var request = gapi.client.drive.files.list({
'pageSize': 10,
'fields':'files(owners,permissions),kind,nextPageToken'
});
For GET request use GET https://www.googleapis.com/drive/v3/files?fields=files(owners%2Cpermissions)%2Ckind%2CnextPageToken&key={YOUR_API_KEY}
for reference you can use Google Developers Documentation for fetching File list

Angular JSONP request

I'm trying to get a jsonp response from an api call api.brewerydb.com. However, it's not wrapping the json with a function on its call back. Here is my code:
app.factory('beer', ['$http',function($http){
var url = "http://api.brewerydb.com/v2/beers?key=MYKEY&application/json&name=oberon&callback=JSON_CALLBACK";
$http.jsonp(url)
.success(function(data){
return data;
});
}]);
It is returning json data, however I get a syntax error at a file whose name is the url I passed and it contains the json data.
I discovered that the api does not support jsonp which is why this isn't working out for me
Your url may be incorrect: '../application/json..' is for an optional HTTP_ACCEPT header per their api docs here: breweryDB , so remove it from the var url string if its not needed.
Per their docs, the default return type is JSON, so no need to pass an extra parameter if its not needed.
Try this instead (for the endpoint /Beers) per their endpoint doc :
var url = "http://api.brewerydb.com/v2/beers?key=MYKEY&name=oberon&callback=JSON_CALLBACK";
Go get them beers!
EDIT: code is here: http://jsfiddle.net/r47y3mq3/1/ copy/paste to your local dev environment and use Safari. Using Chrome results in an Access-Control-Allow-Origin header concern as discussed here: access-control
I was having some similar issues. You have name=oberon which is a brewery, but you are searching for beers in your url.
If you tried:
var url = "http://api.brewerydb.com/v2/breweries?key=MYKEY&application/json&name=oberon&callback=JSON_CALLBACK";
...you'd get an array of all the beers in the Oberon brewery.

How to GET Recent Status Updates on Facebook Page Using Facebook Graph Search API?

Similar to Getting Recent Page feeds? Facebook Graph API / FQL and Getting Facebook Status updates with JSon I would like to do a GET request using Facebook's Graph API, and insert that data into a page. Using the search API, I am able to retrieve information about the page like locale, description, and website, but there is no status update/post update included in the resulting JSON.
How can I retrieve the latest status updates/posts from a given page using Facebook's public Graph API?
It turns out it is possible to do this, but you need to generate an access token (for the page). To do this, you will need to have admin rights to the page in question. So for me, I had to request from that the page make me an admin (point them to the "Manage Admin Roles" dropdown on the page).
Next, you will need to generate an access token. Go here Facebook API Browser, and click on the "GET Access Token" button the right. Select the manage_pages role only.
The final URL should look something like this: https://graph.facebook.com/{page_id}/statuses?access_token=BAACEdE...
Here is the javascript function I used to test my URL (you could also just navigate there on your browser):
function populateFacebookUpdates() {
var pageID = "mycompanypage",
accessToken = "BAACEdE...";
var postsURL = "https://graph.facebook.com/" + pageID + "/statuses?access_token=" + accessToken;
$.ajax({
url: postsURL,
method: 'GET',
dataType: "jsonp",
success: function (data)
{
console.log("Successfully retrieved Facebook data");
console.dir(data);
},
error: function(status) {
console.log("Facebook data could not be retrieved. Failed with a status of " + status);
}
});
}
The data returned in JSON was what I wanted. Also, note that the retrieval would work on any browser/machine/IP (it does expire, however). I would just caution against putting the entire URL inside a client-side javascript file for obvious security reasons...
Status's is a connection and not a field as per the documentation. As far as I know only field information can be retrieved via the search API. If you want statuses you'll have to get the page Id from your search and then query for that pages statuses using the call below.
https://graph.facebook.com/{pageID}/statuses

UrlFetchApp.fetch Link Length Limit

I'm having some trouble with the UrlFetchApp class, fetch() method. I've singled out the issue, and it seems to be the fact that the actual link I'm fetching is just too long
When I eliminate some needed data(resulting in ~1900 characters), it send the fetch request fine
The length limit is somewhere between 2040 and 2060 characters, as that is where it stops working and I receive a "Bad request" error. I'm assuming it's 2048, as that seems to have been the industry standard some time ago.
I'm needing to fetch data from a link that's upwards of 3400 characters! Is this just too long? 2048 characters might have been understandable a while back, but in this day in age it's a limit that is going to be met quite often
My question is this: Is there a way around this? I'm assuming Google set the limit, is there some way to request this limit be raised?
Thank you!
The restriction is on the size (2kB) and not on the length of the url.
On March 30, 2018, Google deprecated the URL Shortener service that was used in the accepted answer.
I wrote a script to use the Firebase Dynamic Links Short Links API service.
The docs are here if you want to cook your own.
You can try UrlShortener to shorten the URL and then use UrlFetchApp with the shortened URL
I used the POST method with payload data instead, showed here:
Google Apps Script POST request UrlFetchApp
The classic code is:
// Make a POST request with form data.
var resumeBlob = Utilities.newBlob('Hire me!', 'text/plain', 'resume.txt');
var formData = {
'name': 'Bob Smith',
'email': 'bob#example.com',
'resume': resumeBlob
};
// Because payload is a JavaScript object, it is interpreted as
// as form data. (No need to specify contentType; it automatically
// defaults to either 'application/x-www-form-urlencoded'
// or 'multipart/form-data')
var options = {
'method' : 'post',
'payload' : formData
};
UrlFetchApp.fetch('https://httpbin.org/post', options);

How can I access auth-only Twitter API methods from a web application

I have a web application for iPhone, which will ultimately run within a PhoneGap application - but for now I'm running it in Safari.
The application needs to access tweets from Twitter friends, including private tweets. So I've implemented OAuth using the Scribe library. I successfully bounce users to Twitter, have them authenticate, then bounce back.
At this point the web app has oAuth credentials (key and token) which it persists locally. From here on I'd like it to user the Twitter statuses/user_timeline.json method to grab tweets for a particular user. I have the application using JSONP requests to do this with unprotected tweets successfully; when it accesses the timeline of a private Twitter feed, an HTTP basic authentication dialog appears in the app.
I believe that I need to provide the OAuth credentials to Twitter, so that my web application can identify and authenticate itself. Twitter recommends doing so through the addition of an HTTP Authorization header, but as I'm using JSONP for the request I don't think this is an option for me. Am I right in assuming this?
My options therefore appear to either be putting the oAuth credentials as query-string parameters (which Twitter recommends against, but documentation suggests still supports); or proxying all the Tweets through an intermediate server. I'd rather avoid the latter.
I access the Twitter API using URLs of the form
http://api.twitter.com/1/statuses/user_timeline.json?user_id=29191439&oauth_nonce=XXXXXXXXXXX&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323042&oauth_consumer_key=XXXXXXXXXX&oauth_signature=XXXXXXXXXX&oauth_version=1.0
When user_id is a public user, this works fine. When user_id is a private user, I get that HTTP Basic Auth dialog. Any idea what I'm doing wrong? I'm hoping it's something embarrassingly simple like "forgetting an important parameter"...
The oAuth stanza needs to be exact, as per http://dev.twitter.com/pages/auth#auth-request - I ended up building an Authorization: header that I could first check with curl.
I built it using the really helpful interactive request checker at http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
Here's a friends API request for a protected user:
curl -v -H 'Authorization: OAuth realm="https://api.twitter.com/1/friends/ids.json", oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_token="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXX", oauth_timestamp="1300728665", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="XXXXXXXXXXXXXXXX%3D"' https://api.twitter.com/1/friends/ids.json?user_id=254723679
It's worth re-iterating that as you've tried to do, instead of setting the Authorization header via e.g. jquery's beforeSend function, that for cross-domain JSONP requests (which can't add HTTP headers) you can make oAuth requests by putting all the relevant key/value pairs in the GET request. This should hopefully help out various other questioners, e.g
Set Headers with jQuery.ajax and JSONP?
Modify HTTP Headers for a JSONP request
Using only JQuery to update Twitter (OAuth)
Your request looks like it has a couple of problems; it's missing the user's oauth_token plus the oauth_signature doesn't look like it has been base64 encoded (because it's missing a hex encoded = or ==, %3 or %3D%3D respectively).
Here's my GET equivalent using oAuth encoded querystring params, which you can use in a cross-domain JSONP call:
https://api.twitter.com/1/friends/ids.json?user_id=254723679&realm=https://api.twitter.com/1/friends/ids.json&oauth_consumer_key=XXXXXXXXXXXXXXXX&oauth_token=XXXXXXXXXXXXXXXX&oauth_nonce=XXXXXXXXXXXXXXXX&oauth_timestamp=1300728665&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=XXXXXXXXXXXXXXXX%3D
I was struggling with similar problem of making JSONP requests from Jquery, the above answer helped just to add what I did to achieve my solution.
I am doing server to server oauth and then I send oauth token, secret, consumer key and secret (this is temporary solution by the time we put a proxy to protect consumer secret). You can replace this to token acquiring code at client.
Oauth.js and Sha1.js download link!
Once signature is generated.
Now there are 2 problems:
JSONP header cannot be edited
Signed arguments which needs to be sent as part of oauth have problem with callback=? (a regular way of using JSONP).
As above answer says 1 cannot be done.
Also, callback=? won't work as the parameter list has to be signed and while sending the request to remote server Jquery replace callback=? to some name like callback=Jquery1232453234. So a named handler has to be used.
function my_twitter_resp_handler(data){
console.log(JSON.stringify(data));
}
and getJSON did not work with named function handler, so I used
var accessor = {
consumerSecret: XXXXXXXXXXXXXXXXXXXXXX,
tokenSecret : XXXXXXXXXXXXXXXXXXXXXX
};
var message = { action: "https://api.twitter.com/1/statuses/home_timeline.json",
method: "GET",
parameters: []
};
message.parameters.push(['realm', "https://api.twitter.com/1/statuses/home_timeline.json"]);
message.parameters.push(['oauth_version', '1.0']);
message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);
message.parameters.push(['oauth_consumer_key', XXXXXXXXXXXXXXXX]);
message.parameters.push(['oauth_token', XXXXXXXXXXXXXXX]);
message.parameters.push(['callback', 'my_twitter_resp_handler']);
OAuth.completeRequest(message, accessor);
var parameterMap = OAuth.getParameterMap(message.parameters);
Create url with base url and key value pairs from parameterMap
jQuery.ajax({
url: url,
dataType: "jsonp",
type: "GET",
});