Fetch JSON object from GAS WebApp from another development GAS WebApp? - google-apps-script

I have two different GAS projects Script1 and Script2.
Script1:
It is a development project with doPost() function. It uses the e.parameter or e.postData.contents to do something.
Script2:
It is a test script. It has also doPost() function. I want to transfer the doPost() e.parameter to Script1 by a post request. But the URLFetchApp success when I use the Current web app URL and ends in /exec. But I want to use the latest code and ends in /dev. Because of the Script1 is a development project and I can't update its version for a small change.
I tried this code. It not working
function myFunction() {
//var URL = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxx/exec";
var URL = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxx/dev";
var data = {
'message' : "This is working"
}
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(data)
};
var response = UrlFetchApp.fetch(URL, options);
}

I believe your goal as follows.
You want to access to Web Apps with the dev mode using Google Apps Script.
For this, How about this answer?
Modification points:
In order to access to the Web Apps with the dev mode, please use the access token. And in this sample, the scope of https://www.googleapis.com/auth/drive.readonly is used for the access token.
Modified script:
When your script is modified, please modify as follows.
function myFunction() {
//var URL = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxx/exec";
var URL = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxx/dev";
var data = {
'message' : "This is working"
}
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(data),
'headers': {'authorization': 'Bearer ' + ScriptApp.getOAuthToken()} // Added
};
var response = UrlFetchApp.fetch(URL, options);
}
// DriveApp.getFiles() // Added
Note:
The comment line of // DriveApp.getFiles() is used for automatically detecting the scope of https://www.googleapis.com/auth/drive.readonly by the script editor.
When the access token is used, even when Who has access to the app: is Only myself, the script works.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script

Related

Adding a doPost and doGet into google app script ("GAS") code

I am a total newbie when it comes to programming.
I have put a very simple switchbot script into google app script ("GAS") to make the switchbot bot do a press. While it can run when clicking on the "run" button in GAS, when sending a http post (i.e. via android's HTTP Shortcut app) to GAS, it connects but the action fails.
I do understand later that a doPost or doGet is required to run it when sending a post to the script from an external source, but after trying various methods with doPost and doGet, I still have no idea how to integrate it or where to put it into the code.
The code is below:
function main() {
var headers = {
"Authorization" : "SWITCHBOT_TOKEN_KEY",
"Content-type" : "application/json; charset=utf-8"
};
var data = {
"command" : "press",
"parameter" : "default",
"commandType": "command"
};
var options = {
'method' : 'post',
"headers" : headers,
muteHttpExceptions : true,
"payload" : JSON.stringify(data)
};
var deviceid = "INSERT_SWITCHBOT_DEVICEID";
var url1 = https://api.switch-bot.com/v1.0/devices/${deviceid}/commands;
var response = UrlFetchApp.fetch( url1, options );
var json = JSON.parse( response.getContentText() );
console.log( json )
}
Any assistance or lesson on how to do / understand this would be great!
Tried checking and looking at various codes with dePost and doGet and integrating it into the code but all seems not work.
While it connects to GAS via the deployed web app link, I am not able to get the actual script running. It simply logs it as failed in the GAS.

Google Sheets activity sending to GA4 with App Script

I have been trying to change my script that used to send to the old UA Google Analytics using the IMAGE() but with the new GA4 you have to send a POST. I tried to use the onOpen(e) with some of the code below but nothing seems to work even though I am not getting any errors. Does anyone know if it is possible to make a call [POST] with this information:
function onOpen(e) {
// Make a POST request with a JSON payload.
var data = {
"client_id": Utilities.getUuid(),
"user_id": "webuser",
"events": ["name", "cve_database"]
};
var options = {
'method' : 'post',
'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
'payload' : JSON.stringify(data)
};
var response = UrlFetchApp.fetch('https://www.google-analytics.com/mp/collect?api_secret=<ID-Here>&measurement_id=<GA4 Acc>', options);
Logger.log(response)
}
I tried to get it to update the Google Analytics information so that I can keep track of the users who view the page.

doPost not running for other users in google appscript

I have deployed my appscript as a form addon and as a web app both.
Everything seems to be working fine in the container form. But now I'm facing this issue where doPost function is not running as I have to run the function as other user. I tried this code from this answer, but this is also giving same authorization error.
function merry2script() {
var url = 'https://script.google.com/macros/s/AKfycbzM97wKyc0en6UrqXnVZuR9KLCf-UZAEpzfzZogbYApD9KChnnM/exec';
var payload = {payloadToSend : 'string to send'};
var method = 'post'
var headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}
var response = UrlFetchApp.fetch(url, {method : method, payload: payload, headers: headers}).getContentText();
Logger.log(response);
return;
}
Is this the correct way to post to appscript with oauth token?
If not how can I send a post request ?
I deployed the web app with these settings
I'm getting this error
I've been stuck for 3 days any help is appreciated
Thank you
UPDATED QUESTION:
APPSCRIPT DOPOST
function doPost(e) {
var data = JSON.stringify(e);
var jsonData = JSON.parse(data);
let query = jsonData.queryString;
let params = query.split("&");
let destinationId = params[0].split("=")[1];
// code is breaking here saying "you don't have access to the document"
let ss = SpreadsheetApp.openById(destinationId);
let sheetName = ss.getActiveSheet().getSheetName();
let dataSheet = ss.getSheetByName(sheetName);
var uniqueIdCol = dataSheet.getRange("A1:A").getValues();
let rowToUpdate;
// code to update row...
}
BACKEND CODE
// call appscript to update status sheet
const data = {
comment
};
let scriptId = process.env.DEPLOYMENT_SCRIPT_ID;
const config = {
method: "post",
url: `https://script.google.com/macros/s/${scriptId}/exec?destinationId=${destinationId}&uniqueId=${uniqueId}&status=${status}`,
data,
headers: {
Authorization: `Bearer ${respondent.form.oAuthToken}`,
},
};
await axios(config);
These are the scopes which I requested to user
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/forms.currentonly",
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/script.send_mail",
"https://www.googleapis.com/auth/forms",
"https://www.googleapis.com/auth/script.scriptapp",
"https://www.googleapis.com/auth/drive"
UPDATED QUESTION 2
I had made a script which can write to google sheet with some extra data which I send from my node backend.
So my script has doPost function which is invoked from backend. I send destinationId of the sheet to know in which sheet to write as in the code above.
I have deployed the webapp as Execute as: Me and Who has access to the app: Anyone.
I'm able to run the doPost function but not able to write to sheet.
Hope my question is clear
So after struggling for 4 days I was able to send email and write to spreadsheet with users OAuth token by directly interacting with Sheets API and Gmail API instead of doing it through ScriptApp doPost method

ScriptApp.getOAuthToken not getting the right permissions for drive through url fetch app?

Trying to explore this with a very simple script but I'm getting an insufficient permissions error:
function mini(){
var gdriveId = "1hp8ncIG4Ww7FH8wi7HjJzzzzzzz";
var options = {
method: "GET",
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
},
}
var url = "https://www.googleapis.com/drive/v2/files/"+gdriveId+"/children";
var response = JSON.parse(UrlFetchApp.fetch( url, options).getContentText());
}
I tried enabling the v2 drive api in the advanced google services dropdown but that didn't work.
I believe your situation and goal as follows.
From gdriveId in your script, I thought that you want to retrieve the folder list in the root folder of gdriveId using the method of "Children: list" in Drive API v2.
You have already enabled Drive API at Advanced Google Services.
For this, how about this answer?
Modification points:
When your script is put to new GAS project and Drive API is enabled at Advanced Google Services, the scopes of the project is only https://www.googleapis.com/auth/script.external_request. The required scope can be automatically detected by the script editor. But, even when Drive API is only enabled, it seems that no scopes are added. I think that the reason of your issue is this.
Under above situation, if you want to retrieve the access token including the required scopes, in order to make the script editor automatically detect the scope of https://www.googleapis.com/auth/drive.readonly, for example, please put // DriveApp.getFiles() to the script as a comment line.
In this case, when you use the methods for other scopes in your script, those scopes can be automatically detected and added by the script editor.
Modified script 1:
When your script is modified, it becomes as follows.
function mini(){
var gdriveId = "1hp8ncIG4Ww7FH8wi7HjJzzzzzzz";
var options = {
method: "GET",
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
},
}
var url = "https://www.googleapis.com/drive/v2/files/"+gdriveId+"/children";
var response = JSON.parse(UrlFetchApp.fetch( url, options).getContentText());
}
// DriveApp.getFiles() // <--- Added this comment line. By this, the scope of https://www.googleapis.com/auth/drive.readonly is added.
Modified script 2:
When the method of Advanced Google service is used, the scope of https://www.googleapis.com/auth/drive is automatically added. By this, the following script works.
function test() {
var gdriveId = "1hp8ncIG4Ww7FH8wi7HjJzzzzzzz";
var res = Drive.Children.list(gdriveId);
console.log(res)
}
Other pattern:
From June 1, 2020, the files and folders in the shared Drive can be retrieved by Drive service. So you can also use the following script.
function myFunction() {
const getFolderList = (id, folders = []) => {
const f = DriveApp.getFolderById(id);
const fols = f.getFolders();
let temp = [];
while (fols.hasNext()) {
const fol = fols.next();
temp.push({name: fol.getName(), id: fol.getId(), parent: f.getName()});
}
if (temp.length > 0) {
folders.push(temp);
temp.forEach((e) => getFolderList(e.id, folders));
}
return folders.flat();
};
var gdriveId = "###"; // Please set the Drive ID.
const res = getFolderList(gdriveId);
console.log(res);
}
References:
Advanced Google services
Children: list of Drive API v2
Authorization Scopes
If you want to give permission to write with ScriptApp.getOAuthToken(), just add the following code in a commented out form and authorize it at runtime. If you don't do this, you'll only be able to download and browse.
//DriveApp.addFile("test");
Reference URL:https://00m.in/UeeOB

Sheets & Appscripts Hubspot POST Request with Authentication Token Problem

I've created a GAS app to provide better pipeline reporting from our Hubspot instance. So far the app works and I have successfully created a Sales Pipeline that shows up in Google sheets. I am trying to add a capability that requires a POST method to query Hubspot's CRM V3. I got it to work in Postman but cannot replicate it in GAS.
The error I get is "Authentication credentials not found." The headers print to the log so I assume they are being generated properly. My guess is that my access Token and payload are not being passed properly to the API during the request. Any help on the matter would be much appreciated.
function getConversions() {
// Prepare authentication to Hubspot
var service = getService();
var headers = {headers: {'Authorization': 'Bearer ' + service.getAccessToken()}};
Logger.log(headers);
var raw = JSON.stringify({"filterGroups":[{"filters":[{"propertyName":"hs_analytics_last_visit_timestamp","operator":"GT","value":"1561514165666"}]}],"limit":100,"after":0});
var options = {
'method' : 'post',
headers: headers,
'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
body : raw,
redirect: 'follow',
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch('https://api.hubapi.com/crm/v3/objects/contacts/search?', options);
var result = JSON.parse(response.getContentText());
Logger.log(result);
};
How about this modification?
Modification points:
When I checked the official document of Search of HubSpot API, I found the curl sample. When this sample is converted to Google Apps Script, I noticed several modification points in your script.
UrlFetchApp.fetch has no properties of body and redirect.
About followRedirects, the official document says as follows.
If false the fetch doesn't automatically follow HTTP redirects; it returns the original HTTP response. The default is true.
In your URL, https://api.hubapi.com/crm/v3/objects/contacts/search? is used. If you don't use the API key, how about modifying to https://api.hubapi.com/crm/v3/objects/contacts/search?
When above modification is reflected to your script, it becomes as follows.
Modified script:
Please modify as follows.
From:
var options = {
'method' : 'post',
headers: headers,
'contentType': 'application/json',
// Convert the JavaScript object to a JSON string.
body : raw,
redirect: 'follow',
"muteHttpExceptions": true
};
To:
var options = {
method : 'post',
headers: headers,
contentType: 'application/json',
payload : raw,
muteHttpExceptions: true
};
Note:
Above modification is required for your script. But I'm worry about the error of Authentication credentials not found.. In this modification, it supposes that your access token of service.getAccessToken() can be used for this request. When I saw the official document, the API key can be also used. If the access token cannot be used, how about using the API key? It's like below.
https://api.hubapi.com/crm/v3/objects/contacts/search?hapikey=YOUR_HUBSPOT_API_KEY
References:
Search of HubSpot API
fetch(url, params)
function getConversions() {
// Prepare authentication to Hubspot
var service = getService();
var headers = {headers: {'Authorization': 'Bearer ' + service.getAccessToken()}};
var url = 'https://api.hubapi.com/crm/v3/objects/contacts/search'
//Logger.log(headers);
var raw = {"filterGroups":[{"filters":[{"propertyName":"hs_analytics_last_visit_timestamp","operator":"GT","value":"1561514165666"}]}],"limit":100,"after":0};
var options = {
method : 'post',
contentType: "application/json",
// Convert the JavaScript object to a JSON string.
payload : JSON.stringify(raw),
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch('https://api.hubapi.com/crm/v3/objects/contacts/search?hapikey=myapikey',options);
var result = JSON.parse(response.getContentText());
Logger.log(response)
Logger.log(result);
};