I am terribly confused on how one is to write a javascript client (non-gadget) to a private Google Spreadsheet using supported APIs? I have no difficulties getting an OAuth2 Drive API client going, but then there is no spreadsheet support!
https://developers.google.com/apis-explorer
This issue crudely asks for the spreadsheet API to appear on that page:
http://code.google.com/p/google-api-javascript-client/issues/detail?id=37
I am probably missing something obvious, so thank you for your kindness to help me...
Update:
Wow, this is kicking my behind! So, I am going down the path of attempting to take the access_token from the Oauth2 workflow and then set the gdata API Authorization header like so:
service = new google.gdata.client.GoogleService('testapp');
service.setHeaders({'Authorization': 'Bearer '+ access_token});
Unfortunately, chrome console shows that this header is not actually getting sent to google when I do something like
service.getFeed(url, cb, eb);
Uffff!
In order to get information from Google Spreadsheets, just send a GET request to the relevant link with the access token attached. The urlLocation is found by going to Google Drive and copying the long string of digits and letters in the url after the word "key=".
Also I used jQuery in this example.
Code:
var urlLocation = ''; //Put the Spreadsheet location here
var url = 'https://spreadsheets.google.com/feeds/list/' + urlLocation + '/od6/private/full?access_token=' + token;
$.get(url, function(data) {
console.log(data);
});
In order to get a JSON representation, use this instead:
var urlLocation = ''; //Same as above
var url = 'https://spreadsheets.google.com/feeds/list/' + urlLocation + '/od6/private/full?alt=json-in-script&access_token=' + token + '&callback=?';
$.getJSON(url, function(data) {
console.log(data);
});
Related
I am thinking of creating a google slides to Figma exporter using Google App Script. Starting out I would first like to route the shapes created in from google Slides to figma. How would I go about setting up my file? And I don't know how to set up the Oauth api communication between Google and Figma or if it's even possible.
I believe that I can start with:
References
Figma reference
https://github.com/figma/plugin-samples/blob/master/react/src/code.ts
google app script reference
https://github.com/gsuitedevs/apps-script-samples/blob/master/slides/style/style.gs#L30
Get Figma Shape
var file=projectid.key()
var=figma rectangle= file()
await figma.loadFontAsync({ family: "Roboto", style: "Regular" })
name;
var figmaShape = {
figma.ui.onmessage = msg => {
if (msg.type === 'create-rectangles') {
const nodes = []
for (let i = 0; i < msg.count; i++) {
const rect = figma.createRectangle()
rect.x = i * 150
rect.fills = [{type: 'SOLID', color: {r: 1, g: 0.5, b: 0}}]
figma.currentPage.appendChild(rect)
nodes.push(rect)
}
figma.currentPage.selection = nodes
figma.viewport.scrollAndZoomIntoView(nodes)
}
figma.closePlugin()
}
};
Get Google Docs File Shape
var powerpointfile = driveApp.getFileById = ("### Slide file ID ###")
function powerPointShape = () {
var slide = SlidesApp.getActivePresentation().getSlides()[0];
var shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 100, 200, 300,
getObjectId.element(SHAPE);
};
Create new Figma file#
file.getSlides.shape = (powerPointShape, ) => {
this.powerPointShape.getRigh()=this.figmaShape(rect.x);
this.powerPointShape.getleft()=this.figmaShape(rect.y);
}
But from there would I also want to get the file id from google app script to a Figma File?
and after looking at: https://github.com/alyssaxuu/figma-to-google-slides/blob/master/Chrome%20Extension/background.js I wonder if I would have to create a chrome extension or a google Slides plugin.
How about this answer?
Issue and workaround:
Unfortunately, it seems that the shapes of Google Slides cannot be put to the page of Figma file. Because it seems that there are no methods of API for putting the shapes. But it was found that that the pages of Figma file can be retrieved as the image using Figma API.
In this answer, I would like to propose the sample script that the pages of Figma file can be put to the Google Slides as the image using Figma API with the access token. So you can directly use Figma API with Google Apps Script.
Usage:
1. Retrieve access token
You can see the method for retrieving the access token at here. Although there is also OAuth2 for retrieving the access token, in your situation, I thought that the method for directly generating the access token on the site might be suitable. So in this answer, the generated access token on the site is used. Please retrieve the access token as follows.
Generate a personal access token
Login to your Figma account.
Head to the Account Settings from the top-left menu inside Figma.
Find the Personal Access Tokens section.
Click Create new token.
A token will be generated. This will be your only chance to copy the token, so make sure you keep a copy of this in a secure place.
The access token is like #####-########-####-####-####-############. At Google Apps Script, the authorization is done by headers: {"X-Figma-Token": accessToken}.
2. Retrieve file key
In order to retrieve the Figma file using Figma API, the file key is required. You can retrieve the file key from the URL of the file.
The URL of the file is like https://www.figma.com/file/###/sampleFilename. In this case, ### is the file key.
3. Run script
The sample script is as follows. Before you run the script, please set the variables of accessToken and fileKey.
function myFunction() {
var accessToken = "###"; // Please set your access token.
var fileKey = "###"; // Please set the file key.
var baseUrl = "https://api.figma.com/v1";
var params = {
method: "get",
headers: {"X-Figma-Token": accessToken},
muteHttpExceptions: true,
};
var fileInfo = JSON.parse(UrlFetchApp.fetch(baseUrl + "/files/" + fileKey, params));
var children = JSON.parse(UrlFetchApp.fetch(baseUrl + "/images/" + fileKey + "?format=jpg&scale=3&ids=" + fileInfo.document.children.map(function(c) {return c.id}).join(","), params));
if (!children.err) {
var s = SlidesApp.create("sampleSlide");
var slide = s.getSlides()[0];
var keys = Object.keys(children.images);
keys.forEach(function(c, i) {
slide.insertImage(children.images[c]);
if (i != keys.length - 1) slide = s.insertSlide(i + 1);
})
} else {
throw new Error(children);
}
}
When myFunction() is run, at first, the file information is retrieved with the file key fileKey. Then, all pages are retrieved from the retrieved file information, and the retrieved pages are put to each slide of new Google Slides.
I think that the action of this script is similar to the script which is shown at the bottom of your question.
Note:
This is a sample script. So please modify it for your actual situation.
References:
Figma API
Class UrlFetchApp
Class SlidesApp
If I misunderstood your question and this was not the direction you want, I apologize.
I'm trying to get a direct download URL for a file using Google's Picker API so that I can choose a file and pass this URL to server side code to download and store a copy of the item on the server.
I'm able to authorize through the picker API and get info of a picked file including the file name and preview URL (which is confusingly referred to as simply "A URL to this item" in the JSON response docs: https://developers.google.com/picker/docs/results)
I noticed that there is a post about using the Drive API to get a direct download URL here: Get google drive file download URL
However when I do this in my picker callback function (based on the docs here: https://developers.google.com/picker/docs/)
I get an error of:
"Project [number here] is not found and cannot be used for API calls. If it is recently created, enable Drive API by visiting https://console.developers.google.com/apis/api/drive.googleapis.com/overview?project=[project number here] then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
I have the API enabled in my developer console and the URL added to the JS allowed origins.
The documentation is very confusing and there seems to be 3 versions of the REST API to use with Drive which is based on an gapi.auth2 object whereas the picker api uses gapi.auth object.
I'm not sure if I need to authenticate again using the Google Drive API before performing the GET request. This all seems very messy and I believe there must be an easier approach for what is a simple request!
My picker callback function:
pickerCallback: function(data) {
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
var fileName = doc[google.picker.Document.NAME];
var url = doc[google.picker.Document.URL];
var docId = doc[google.picker.Document.ID];
var request = null;
gapi.client.load('drive', 'v2', function() {
request = gapi.client.drive.files.get({
'fileId': docId
});
request.execute(function(resp){
console.log(resp);
});
});
//Write upload details to page
//Populate hidden field
}
Developer console screen - The first app is the picker API the second is for the Drive API:
You may want to try the simple callback implementation shown in this documentation. Notice that url was initialized before the if statement:
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
Also, in authorizing, set the AppId value and choose the user account with the app's current OAuth 2.0 token. Note that the AppId set and the client ID used for authorizing access to a user's files must be contained in the same app. Then, after successfully obtaining the fileId, you can then send request using files.get. By default, this responds with a Files resource in the response body which includes downloadUrl.
For additional insights, see this related SO post.
Hi I am buliding my first web app using javascript and fetching data using API from www.openweathermap.org/
I have used the API key as mentioned in the documentation still it is giving an error of unauthorization. Can there be any other reason for this error while calling a function or so . Thank you in advance.
var APPID = "my_secret_key";
var temp;
var loc;
var icon;
var wind;
var humidity;
var direction;
function updateByZip(zip){
var url = "http://api.openweathermap.org/data/2.5/weather?" +
"zip = " + zip +
"&APPID =" + APPID ;
sendRequest(url);
}
function sendRequest(url){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
var data = JSON.parse(xmlhttp.responseText) ;
var weather = {};
weather.wind = data.wind.speed;
weather.direction = data.wind.deg;
weather.loc = data.name;
weather.temp = data.main.temp;
weather.icon = data.weather[0].id;
weather.humidity=data.main.humidity;
update(weather);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
It's the spaces near the equal signs in your URL. It's likely urlencoding the space and sending your parameter as APPID%20 which is not being recognized as valid.
var url = "http://api.openweathermap.org/data/2.5/weather?" +
"zip=" + zip +
"&APPID=" + APPID;
for future users, as i was having 401 error but solved it differently.
Error:
Invalid API key. Please see http://openweathermap.org/faq#error401 for more info
API calls responds with 401 error:
You can get the error 401 in the following cases:
You did not specify your API key in API request.
Your API key is not activated yet. Within the next couple of hours, it will be activated and ready to use.
You are using wrong API key in API request. Please, check your right API key in personal account.
You have free subscription and try to get access to our paid services (for example, 16 days/daily forecast API, any historical weather data, Weather maps 2.0, etc). Please, check your tariff in your [personal account]([price and condition]).
here are some steps to find problem.
1) Check if API key is activated
some API services provide key information in dashboard whether its activated, expired etc. openWeatherMap don't.
to verify whether your key is working 'MAKE API CALL FROM BROWSER'
api.openweathermap.org/data/2.5/weather?q=peshawar&appid=API_key
replace API_key with your own key, if you get data successfully then your key is activated otherwise wait for few hours to get key activated.
2) Check .env for typos & syntax
.env is file which is used to hide credentials such as API_KEY in server side code.
make sure your .env file variables are using correct syntax which is
NAME=VALUE
API_KEY=djgkv43439d90bkckcs
no semicolon, quotes etc
3) Check request URL
check request url where API call will be made , make sure
It doesn't have spaces, braces etc
correct according to URL encoding
correct according to API documentation
4) Debug using dotenv:
to know if you dotenv package is parsing API key correctly use the following code
const result = dotenv.config()
if (result.error) {
throw result.error
}
console.log(result.parsed)
this code checks if .env file variables are being parsed, it will print API_KEY value if its been parsed otherwise will print error which occur while parsing.
Hopefully it helps :)
Others suggestion
5) Check location of .env file
look for location of .env file in your directory, moving it to root directory might help (suggested in comments)
For those who followed the previous answers and are still facing the 401 issue: it seems it is now required to access the the API via HTTPS --- at least that's the case for me. Some older guides and tutorials might continue to use http:// in their code, so you'll have to change it to https://.
As far as I know, there is no mention of this in OpenWeather's official docs, and they don't include the protocol in their examples too.
I have a client that wants to pull the latest video in a specific Vimeo Portfolio. I can pull in the latest video on the entire account using JS like so:
http://codepen.io/buschschwick/pen/pgrmvg
var vimeoUserName = 'yellowboxfilms';
// Tell Vimeo what function to call
var videoCallback = 'latestVideo';
var oEmbedCallback = 'embedVideo';
// Set up the URLs
var videosUrl = 'http://vimeo.com/api/v2/' + vimeoUserName + '/videos.json?callback=' + videoCallback;
var oEmbedUrl = 'http://vimeo.com/api/oembed.json';
// This function puts the video on the page
function embedVideo(video) {
videoEmbedCode = video.html;
document.getElementById('embed').innerHTML = unescape(video.html);
}
// This function uses oEmbed to get the last clip
function latestVideo(videos) {
var videoUrl = videos[0].url;
// Get the oEmbed stuff
loadScript(oEmbedUrl + '?url=' + encodeURIComponent(videoUrl) + '&callback=' + oEmbedCallback);
}
// This function loads the data from Vimeo
function loadScript(url) {
var js = document.createElement('script');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', url);
document.getElementsByTagName('head').item(0).appendChild(js);
}
// Call our init function when the page loads
window.onload = function() {
loadScript(videosUrl);
};
But I want to pull a latest in a portfolio. I found the API Call, but I get an authorization error.
http://codepen.io/buschschwick/pen/jWLoWb
var latestVideo = function() {
var vimeoAPI = 'https://api.vimeo.com/users/414104/portfolios';
$.getJSON(vimeoAPI).done(function(data) {
console.log(data);
})
};
latestVideo();
I think it might need an oAuth token or something like that, but trying to find out how to pass that got me no where and I feel the Vimeo API Docs aren't helping either. Any help or guidance would be much appreciated. Thanks!
Here are Vimeo's authentication docs: https://developer.vimeo.com/api/authentication
You can generate a single token on your app page, or you can generate the token on a server.
Vimeo's token generation does not yet support client side authorization, so know that if you share the token in the client, anyone can take that token and make API calls.
You can reduce the risk by requesting read-only scopes, but that token will still have access to private data.
When you enter an importrange function manually into a spreadsheet you receive a pop up and must 'allow access'.
However, I'm trying to find a way to do this via a script because I'm creating many spreadsheets, each with a query-importrange function (I 'own' the spreadsheet which has data to import). There's too many for me to manually 'allow access' via the pop up and update the function to include the query function.
Hence, I'm looking for a function call in apps script that can perform the same action that the pop up did. Code segment example below.
Does anyone know of a function that can 'allow access'?
Stefan
// create new spreadsheet file
...
var ss = createSpreadsheet(fileName);
var spreadsheet = SpreadsheetApp.open(ss);
var sheet = spreadsheet.getSheetByName("Sheet1");
// Add student as Viewer
spreadsheet.addViewer(studentEmail);
// Add ImportRange function
var sheet = spreadsheet.getSheets()[0];
var cell = sheet.getRange("A1");
var filter = "select * where Col3='" + studentEmail + "'";
var qry = '=QUERY(importRange("' + fileKey + '","14-15S2!A1:AE");"' + filter + '";1)';
cell.setValue(qry);
// I need a function to 'allow access' here, so the function can be allowed access. Otherwise, it throws an error.
...
#Franzi suggested using undocumented approach which works and does not require making a donor/source spreadsheet public. Here's how you can do it from Google App Script:
function addImportrangePermission() {
// id of the spreadsheet to add permission to import
const ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
// donor or source spreadsheet id, you should get it somewhere
const donorId = '1GrELZHlEKu_QbBVqv...';
// adding permission by fetching this url
const url = `https://docs.google.com/spreadsheets/d/${ssId}/externaldata/addimportrangepermissions?donorDocId=${donorId}`;
const token = ScriptApp.getOAuthToken();
const params = {
method: 'post',
headers: {
Authorization: 'Bearer ' + token,
},
muteHttpExceptions: true
};
UrlFetchApp.fetch(url, params);
}
Usually there is no need, but in some rare cases you might want to add the required oauthScopes in appscript.json manifest:
...,
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/script.external_request"
],
...
I had a problem similar to this and found the answer was to alter the permissions of the spreadhseet file from which you are importing data (the "filekey" in your example").
This is the google app script that made "Allow Access" go away for me:
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW)
I'm doing it automatically using the gspread python library by calling the addimportrangepermissions endpoint.
sheet.client.request(
'post',
f'https://docs.google.com/spreadsheets/d/{sheet.spreadsheet.id}/externaldata/addimportrangepermissions',
params={'donorDocId': external_sheet.spreadsheet.id}
)
I know it's not via the apps script, but it could provide you some hints on how to do it there.
Note: I didn't find any doc about this, so I though this could help anyone trying to do the same in any platform (app script, python, etc.).
This code is based on the answer by #kishkin:
/**
* #param {string} fileId - id of the spreadsheet to add permission to import
* #param {string} donorId - donor or source spreadsheet id, you should get it somewhere
*/
function addImportrangePermission_(fileId, donorId) {
// adding permission by fetching this url
var url = 'https://docs.google.com/spreadsheets/d/' +
fileId +
'/externaldata/addimportrangepermissions?donorDocId=' +
donorId;
var token = ScriptApp.getOAuthToken();
var params = {
method: 'post',
headers: {
Authorization: 'Bearer ' + token,
},
muteHttpExceptions: true
};
UrlFetchApp.fetch(url, params);
}
It is compatible with the ES5 engine and easily used as a function outside.
All I did was share the 'source' sheets - the sheets from which ImportRange grabs its data - with the people in my organsation who are using the gsheet template. I edited the template by clicking the authorise access button and all sheets that I have made from the template since have worked.
The ImportRange function works without me having to re-authorise access within each new sheet created from the template. I hope it works for others in my organisation.