I'm trying to figure out how to send request to URL, so that it populates in Google Sheets. At this moment the log throws error "Order not found". It's my first time writing script for that request. So far I have:
function myFunction() {
var data = {
"date":"2021-07-01",
"reference":"REFERENCE",
"products":[
{
"id":"31565598851174",
"quantity":15
},
{
"id":"31424655589478",
"quantity":10
}
]
}
var options = {
'method' : 'post',
'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
'payload' : JSON.stringify(data)
};
var url = "https://stockists.rerootedorganic.co.uk/api/order/?key=example"
var response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
I think that the problem might be with the syntax in query. Any help to identify what I'm doing wrong would be amazing, thank you.
Errors:
Execution log
11:45:18 AM Notice Execution started
11:45:19 AM Info
{"error":{"message":"Order not found"}}
11:45:19 AM Info null
11:45:20 AM Info
{"error":{"message":"Order not found"}}
11:45:20 AM Info {error={message=Order not found}}
11:45:19 AM Notice Execution completed
Adapt this code
function myFunction() {
var url = 'https://stockists.rerootedorganic.co.uk/api/order/?key=example&date='
var when = '2021-07-01' // string format
var data = JSON.parse(UrlFetchApp.fetch(url+when).getContentText())
Logger.log(data.order.reference)
for (var i=0;i<data.order.products.length;i++){
Logger.log(data.order.products[i].id + ' qty: ' + data.order.products[i].quantity)
}
}
to populate the sheet
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('** Menu **')
.addItem('request','myFunction')
.addToUi();
}
function myFunction() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var d = Utilities.formatDate(sh.getRange('B3').getValue(), "GMT+2", "yyyy-MM-dd")
var url = sh.getRange('B1').getValue() + '?key=' + sh.getRange('B2').getValue() + '&date=' + d
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
for (var i=0;i<data.order.products.length;i++){
sh.appendRow([data.order.reference,data.order.products[i].id,data.order.products[i].quantity])
}
}
Related
I have a google app script that allows me to retrieve data via a public API and a fetch. So far so good. I initialized a table in order to push the data into it, then I call a function that will send the data to a column of my google sheets table. My first function fills the array with a "while" loop, when the length of the array reaches 12, my "pushDatasToSheet" function launches but I have an error, the console tells me that my data range is at 1 and therefore does not correspond not in range of my selected cells. What is funny is that my table does indeed indicate a length of 12 when executing my function sending data to the table and when I modify the range of my cells by putting only one , the console shows me 12 for my data range. I can't find where my mistake is coming from. thank you in advance for your help.
Here an image of the console error:
error code in app script console
And my code:
const signsList = ["aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn", "aquarius", "pisces"];
var SHEET_NAME = "horoscope";
const options = {
'method': 'post',
};
var rowDescription = [];
// Get horoscopes from API
function doPost(e) {
signsList.forEach(sign => {
while (rowDescription.length < 12) {
var url = 'https://aztro.sameerkumar.website/?sign=' + sign + '&day=today';
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.parse(json);
rowDescription.push(data.description);
}
pushDatasToSheet();
})
}
function pushDatasToSheet() {
Logger.log(rowDescription.length);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
var descriptionColumn = sheet.getRange('B2:B13');
descriptionColumn.setValues([rowDescription]);
};
Problem solved 😅
In case another person with the same problem happen, the array have to be a 2D array. And i have changed my while loop for a if statement.
Here the correction snippet:
const signsList = ["aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpio", "sagittarius", "capricorn", "aquarius", "pisces"];
var SHEET_NAME = "horoscope";
const options = {
'method': 'post',
};
var rowDescription = [];
// Get horoscopes from API
function doPost(e) {
if (rowDescription.length < 12) {
signsList.forEach(sign => {
var url = 'https://aztro.sameerkumar.website/?sign=' + sign + '&day=today';
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.parse(json);
rowDescription.push([data.description]);
})
}
pushDatasToSheet();
}
function pushDatasToSheet() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
sheet.getRange('B2:B13').setValues(rowDescription);
};
I'm writing a script that takes google sheet data and uploads my mailchimp subscriber data, where the edited cell values are sent over as updated merge tags. The original code came from here. I've got the script running successfully, accept for this one error:
"Invalid Resource","status":400,"detail":"Blank email address"
I understand the error according to the documentation in the mailchimp api documentation, but I'm not sure why it's not recognizing the subscriber data from the script:
var emHash = md5(em.toLowerCase()); //this is pulled from my md5 function
var payload = JSON.stringify({
"status_if_new": "subscribed",
"email_address": em,
"merge_fields": {
"LEAD": lead,
//rest of vars following same syntax
}
});
var options = {
"headers" : headers,
"payload": payload,
"method" : "put",
"muteHttpExceptions" : true
};
var response = UrlFetchApp.fetch('https://us15.api.mailchimp.com/3.0' + '/lists/' + 'xxxxxxx' + '/members/' + emHash,options);
Logger.log(response);
}
Last is the function triggered by editing so that changed values get sent over via the function above
function onEdit(e) {
var activeSheet = e.source.getActiveSheet();
var range = e.range;
var rowedited = range.getRowIndex();
if (activeSheet.getName() !== "ATTENDANCE"){
return;
Logger.log("Oops :(");
}
else {
var values = sheet.getRange(rowedited, 1, 1, 13).getValues()[0];
var em = values[2];
var lead = values[1];
//remaining vars omitted for brevity
sendToMailChimp_(em,lead...[etc.]);
}
Any thoughts?
I figured it out - I pulled an amateur move and had the columns attributed to the wrong array element.... So yes, I started at 1 and not 0
facepalm
It is now working!
I'm attempting to query items out of the Todoist API from Google Apps Script, mimicking a curl POST.
I originally tried to make OAuth2 work, but tokens were not persistent, and I instead opted for the API's method of using individual API tokens to exchange for a valid token.
Using App Script's UrlFetchApp class, I'm attempting to construct at POST request for Todoist's API to retrieve task items, and my getTodoistToken() function is indeed retrieving a valid token response, but the POST command is issuing the following 403:
"error_tag":"AUTH_CSRF_ERROR","error_code":0,"http_code":403,"error_extra":{"access_type":"web_session"},"error":"AUTH_CSRF_ERROR"}
Can anyone recommend a solution? Thanks so much, code below:
function getTodoistToken() {
var url = "https://todoist.com/api/access_tokens/migrate_personal_token";
var data = {
"client_id": "[my unique client_id]",
"client_secret": "[my unique client_secret]",
"personal_token":"[my API token from Todoist dashboard]",
"scope": "data:read"
};
var payload = JSON.stringify(data);
var headers = {
"Content-Type":"application/json",
};
var options = {
"method":"POST",
"contentType" : "application/json",
"headers": headers,
"payload" : payload
};
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.parse(json);
return(data.access_token);
}
function getTodoistTasks(){
var apiURL = "https://todoist.com/API/v7/sync";
var data = {
"token" : getTodoistToken(),
"sync_token" : '*',
"resource_types" : '["items"]'
};
var payload = JSON.stringify(data);
Logger.log(payload);
var headers = {
"Content-Type":"application/json",
};
var options = {
"method":"POST",
"contentType" : "application/json",
"headers": headers,
"payload" : payload,
"muteHttpExceptions" : true
};
var response = UrlFetchApp.fetch(apiURL, options);
Logger.log(response.getContentText());
}
I have figured out the answer. The Todoist API documentation is bit ambiguous, seeming written around POST requests, but to download (sync) a full list of tasks, a simple URL-encoded GET request, as constructed below, did the trick:
function getTodoistTasks(){
var apiURL = "https://todoist.com/API/v7/sync";
var queryString = "?token=" + getTodoistTokenRev() + "&sync_token=%27*%27&resource_types=[%22items%22]";
//Get params
var fetchParameters = {};
fetchParameters.method = 'get';
fetchParameters.contentType = 'x-www-form-urlencoded';
fetchParameters.muteHttpExceptions = true;
//make request and return
var response = UrlFetchApp.fetch(apiURL + queryString, fetchParameters);
var syncData = JSON.parse(response.getContentText());
return(syncData);
}
And if anyone is looking for an example of creating an item (a task in this case), as I was, here's the code for that (note you need to specify a date_string and due_date for it to appear in the web UI):
var API_URL = "https://todoist.com/API/v7/sync"
var BASE_QUERY = "?token=" + TOKEN
function addTask() {
// var taskName = SpreadsheetApp.getUi().prompt('What the task\'s name?')
var taskName = 'Test 1652'
var commands = encodeURI(JSON.stringify([{
"type": "item_add",
"temp_id": uuidv4(),
"uuid": uuidv4(),
"args": {
"content": taskName,
"date_string": "today",
"due_date_utc": "2017-12-2T18:00",
}
}]))
var queryString = BASE_QUERY + '&commands=' + commands
var options = {
method: 'post',
contentType: 'x-www-form-urlencoded',
muteHttpExceptions: true}
var response = UrlFetchApp.fetch(API_URL + queryString, options)
if (response.getResponseCode() !== 200) {
var content = response.getContentText()
throw new Error('URL fetch failed: ' + content)
}
var syncData = JSON.parse(response.getContentText())
return syncData
// Private Functions
// -----------------
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
} // addTask()
I'm trying to get a Google script (on a Google Sheet) to retrieve data from Float API. The endpoint and key are fine (tested and all works as expected on Postman) but it keeps returning 401.
Below is my code:
var API_KEY = "{ENTER YOUR KEY HERE}";
var ENDPOINT_PROJECTS = "https://api.float.com/api/v1/projects";
function getProjects() {
var headers = {
"Authorization" : "Bearer " + API_KEY,
};
var requestData = {
"method" : "GET",
"headers": headers,
"muteHttpExceptions": false
};
// Get the data
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS);
var responseCode = fetchResponse.getResponseCode();
if (responseCode == "200") {
var result = JSON.parse(fetchResponse.getContentText());
} else {
ui.alert("Error when attempting to fetch the list of spaces.");
}
}
Okay looked like I completely missed a small yet very important part...even though I created an object to hold the method and headers I was not passing this into the actual fetch!!! (This is what happens when you attempt to do a quick script at the end of the day)
So instead of this
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS);
we have this:
var fetchResponse = UrlFetchApp.fetch(ENDPOINT_PROJECTS, requestData);
I'm using Github Gists for a web playground I'm making as a side project. I load two json files into the editor. 1 handles all the libraries (jquery, bootstrap, etc:) and another for the users settings (fontsize, version, etc:)
So anyway I have this JSON named settings
var settings = gistdata.data.files["settings.json"].content
var jsonSets = JSON.parse(settings)
I parse and attempted to grab an object from the JSON and set it as a value of a input textbox.
Now console.log(jsonSets.siteTitle) works perfectly fine
but when I try to change the input dynamically...
$("[data-action=sitetitle]").val(jsonSets.siteTitle).trigger("change")
The problem is it's not actually applying the value!
The only way I've been able to successfully apply the value is...
setTimeout(function() {
$("[data-action=sitetitle]").val(jsonSets.siteTitle).trigger("change")
}, 5000)
Which is ridiculously slow.
Does anyone know why it's not applying the value?
in addition.
How can I solve this problem?
var hash = window.location.hash.substring(1)
if (window.location.hash) {
function loadgist(gistid) {
$.ajax({
url: "https://api.github.com/gists/" + gistid,
type: "GET",
dataType: "jsonp"
}).success(function(gistdata) {
var libraries = gistdata.data.files["libraries.json"].content
var settings = gistdata.data.files["settings.json"].content
var jsonLibs = JSON.parse(libraries)
var jsonSets = JSON.parse(settings)
// Return libraries from json
$.each(jsonLibs, function(name, value) {
$(".ldd-submenu #" + name).prop("checked", value)
})
// Return font settings from json
var siteTitle = jsonSets.siteTitle
var WeaveVersion = jsonSets.version
var editorFontSize = jsonSets.editorFontSize
var WeaveDesc = jsonSets.description
var WeaveAuthor = jsonSets.author
$("[data-action=sitetitle]").val(siteTitle).trigger("change")
$("[data-value=version]").val(WeaveVersion).trigger("change")
$("[data-editor=fontSize]").val(editorFontSize).trigger("change")
$("[data-action=sitedesc]").val(WeaveDesc).trigger("change")
$("[data-action=siteauthor]").val(WeaveAuthor).trigger("change")
}).error(function(e) {
// ajax error
console.warn("Error: Could not load weave!", e)
})
}
loadgist(hash)
} else {
// No hash found
}
My problem was actually related to localStorage.
I cleared it localStorage.clear(); ran the ajax function after and it solved the problem.
var hash = window.location.hash.substring(1)
if (window.location.hash) {
localStorage.clear()
function loadgist(gistid) {
$.ajax({
url: "https://api.github.com/gists/" + gistid,
type: "GET",
dataType: "jsonp",
jsonp: "callback"
}).success(function(gistdata) {
var htmlVal = gistdata.data.files["index.html"].content
var cssVal = gistdata.data.files["index.css"].content
var jsVal = gistdata.data.files["index.js"].content
var mdVal = gistdata.data.files["README.md"].content
var settings = gistdata.data.files["settings.json"].content
var libraries = gistdata.data.files["libraries.json"].content
var jsonSets = JSON.parse(settings)
var jsonLibs = JSON.parse(libraries)
// Return font settings from json
var siteTitle = jsonSets.siteTitle
var WeaveVersion = jsonSets.version
var editorFontSize = jsonSets.editorFontSize
var WeaveDesc = jsonSets.description
var WeaveAuthor = jsonSets.author
$("[data-action=sitetitle]").val(siteTitle)
$("[data-value=version]").val(WeaveVersion)
$("[data-editor=fontSize]").val(editorFontSize)
$("[data-action=sitedesc]").val(WeaveDesc)
$("[data-action=siteauthor]").val(WeaveAuthor)
storeValues()
// Return settings from the json
$(".metaboxes input.heading").trigger("keyup")
// Return libraries from json
$.each(jsonLibs, function(name, value) {
$(".ldd-submenu #" + name).prop("checked", value).trigger("keyup")
})
// Set checked libraries into preview
$("#jquery").trigger("keyup")
// Return the editor's values
mdEditor.setValue(mdVal)
htmlEditor.setValue(htmlVal)
cssEditor.setValue(cssVal)
jsEditor.setValue(jsVal)
}).error(function(e) {
// ajax error
console.warn("Error: Could not load weave!", e)
})
}
loadgist(hash)
} else {
// No hash found
}