How to deploy Google Sheet as Web-app using Google API - google-apps-script

I have a little proble with Google Sheets API
I have a Google Sheet Document on my GDrive. And I can work with it using Google Sheets API and Google Drive API. So I can move it, update it or make copies.
My task is:
1. make a copy of this document (I can do this)
2. publish this copy as web app. So each copy has a doGet() functon inside so it can be published as a Web app. Manually it can be done like: Publish -> Deploy as web app.. But I can't find any API to do this.
Get an URL of published service
UPDATE
I read documentation projects.deployments.create And I maanged to create a new deployment (before that I should create a version) But my new deployemnt has no web access, no url etc. IF I check via projects.deployments.list it shows:
{
"deploymentId": "AKfycbxVfuoeIQmumgy_Efhw12NCcqE7vqosYoxbDiKj5CT4mL_GbtybXsh1ppMIX22wQX20",
"deploymentConfig": {
"scriptId": "1zfjbALVe0jGbZCtqjFR0RP2-O___hR7MtAlx3biuJGXKsrKh3y1W0hMT",
"versionNumber": 1,
"manifestFileName": "appsscript",
"description": "v1"
},
"updateTime": "2019-05-13T22:33:23.760Z"
}
And if I will do this manually via web interface it will looks like
{
"deploymentId": "AKfycbyn3smPKxJcZwsm9SzSTtzNCAcWJzf1OVs4WTslvHo",
"deploymentConfig": {
"scriptId": "1zfjbALVe0jGbZCtqjFR0RP2-O___hR7MtAlx3biuJGXKsrKh3y1W0hMT",
"manifestFileName": "appsscript"
},
"updateTime": "1970-01-01T00:00:00Z",
"entryPoints": [
{
"entryPointType": "WEB_APP",
"webApp": {
"url": "https://script.google.com/macros/s/AKfycbyn3smPKxJcZwsm9SzSTtzNCAcWJzf1OVs4WTslvHo/exec",
"entryPointConfig": {
"access": "ANYONE_ANONYMOUS",
"executeAs": "USER_DEPLOYING"
}
}
}
]
}

The Apps Script API needs to be used. You can use the REST API and make a UrlFetchApp.fetch(url) request. This is a two step process. First you must create a new Apps Script file, then you must update that new Apps Script file with new contents in the manifest file. The manifest file must have a property for webapp which is what designates the type of deployment.
The code will probably look something like the following:
function deployA_project() {
var id, OAuthToken,options,payload,rtrn,url;
id = ScriptApp.getScriptId();//Get the project ID of this script project
Logger.log('id: ' + id)
url = 'https://script.googleapis.com/v1/projects/' + id + '/deployments';//For REST
OAuthToken = ScriptApp.getOAuthToken();
payload = {
"versionNumber": number,
"manifestFileName": string,
"description": string
}
options = {
"method" : "POST",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + OAuthToken
},
"contentType": "application/json",
"payload": JSON.stringify(payload)
};
rtrn = UrlFetchApp.fetch(url,options);
Logger.log('rtrn: ' + rtrn)
}
See the documentation:
projects.deployments.create
How the apps script project is deployed is designated in the manifest file:
{
"timeZone": "America/New_York",
"dependencies": {
},
"webapp": {
"access": "MYSELF",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER"
}
The API doesn't provide a configuration setting for creating the type of deployment. So, turning the deployment into a Web App is done by updating the manifest file. This must be a two step process. First, you create the new project file, then you update it with a JSON object of file content. You can designate the file content of the manifest file named "appsscript.json"
The content must be JSON in the following format:
{
"scriptId": "scriptId",
"files": [{
"name": "appsscript",
"type": "JSON",
"source": "{\"timeZone\":\"America/New_York\", \"webapp\": {\"access\": \"MYSELF\",\"executeAs\": \"USER_DEPLOYING\"},\"exceptionLogging\":\"STACKDRIVER\"}",
"lastModifyUser": {
"name": "MyName",
"email": "example#gmail.com",
}
}]
}
You need to make another request to a different url, and the request must be a PUT request in order to make an update:
url = 'https://script.googleapis.com/v1/projects/' + id + '/deployments/' + {deploymentId}
var newContent = {
"scriptId": "scriptId",
"files": [{
"name": "appsscript",
"type": "JSON",
"source": "{\"timeZone\":\"America/New_York\", \"webapp\": {\"access\": \"MYSELF\",\"executeAs\": \"USER_DEPLOYING\"},\"exceptionLogging\":\"STACKDRIVER\"}",
"lastModifyUser": {
"name": "MyName",
"email": "example#gmail.com",
}
}]
}
var requestBody = {};
requestBody.files = newContent;
requestBody.deploymentConfig = {
"scriptId": string,
"versionNumber": number,
"manifestFileName": string,
"description": string
}
options = {
"method" : "PUT",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + OAuthToken
},
"contentType": "application/json",
"payload": JSON.stringify(requestBody)
};
rtrn = UrlFetchApp.fetch(url,options);
Logger.log('rtrn: ' + rtrn)

Related

Google drive api Files: get doesn't list full metadata

I tried using the example get method on the google drive api documentation, however what is returned is not the full metadata of the file, only this:
"kind": "drive#file",
"id": "1vbLiXALYOYoVev1KD_ajVBfh5_CgvGgP",
"name": "3.png",
"mimeType": "image/png",
"result": {
"kind": "drive#file",
"id": "1vbLiXALYOYoVev1KD_ajVBfh5_CgvGgP",
"name": "3.png",
"mimeType": "image/png"
}
}
What should appear is something with many more fields:
{
"kind": "drive#file",
"id": "1vbLiXALYOYoVev1KD_ajVBfh5_CgvGgP",
"etag": "\"MTU4Njg3NTU3MjUxOQ\"",
"selfLink": "",
"webContentLink": "",
"alternateLink": "",
"embedLink": "",
"iconLink": "",
"thumbnailLink": "",
"title": "3.png"
// ... and so on
I get the full response when I use the "try api" screen on the api docs, but not when calling it from javascript:
function printFile(fileId) {
appendPre(fileId)
var request = gapi.client.drive.files.get({
'fileId': fileId
});
request.execute(function(resp) {
console.log(JSON.stringify(resp, null, 2))
});
}
I used the https://www.googleapis.com/auth/drive.file scope, which is listed as a scope sufficient for the request to be completed. Help!
How about this modification?
At Drive API V3, when fields property is not used, a part of fields is returned. So in your case, for example, you can retrieve other parameters using fields: "*". When your script is modified, please modify as follows.
From:
var request = gapi.client.drive.files.get({
'fileId': fileId
});
To:
var request = gapi.client.drive.files.get({
'fileId': fileId,
'fields': "*" // Added
});
Reference:
Parameters of Files: get

Is it possible to unzip a file in 7zip file format using Google Apps Script?

I've been able to successfully unzip a regular zip file easily using Google Apps Script. However, a program I use outputs certain files zipped using 7zip. Is there a way to unzip a 7zip file in Google Apps script?
Thanks!
Google Apps Script does not support 7 zip out of the box. It only supports Gzip and Zip.
However with the time and knowledge necessary, you can get an open source extension written in javascript and re-write it to Apps Script, just be aware that if the extension has dependencies you will have to re-write the dependencies as well.
Maybe you can try converting to zip file with cloudconvert api first (free for up to 25 conversions per day)
https://cloudconvert.com/api/v2/jobs/builder
ENDPOINT
POST https://api.cloudconvert.com/v2/jobs
REQUEST BODY
{
"tasks": {
"import-1": {
"operation": "import/url",
"url": "https://notepad-plus-plus.org/repository/7.x/7.0/npp.7.bin.minimalist.x64.7z"
},
"task-1": {
"operation": "convert",
"input_format": "7z",
"output_format": "zip",
"engine": "archivetool",
"input": [
"import-1"
]
},
"export-1": {
"operation": "export/url",
"input": [
"task-1"
],
"inline": false,
"archive_multiple_files": false
}
}
}
Create new API key: https://cloudconvert.com/dashboard/api/v2/keys
Google AppScript:
function cloudConvert7ztoZip() {
// Make a POST request with a JSON payload.
var data = {
"tasks": {
"import-1": {
"operation": "import/url",
"url": "https://notepad-plus-plus.org/repository/7.x/7.0/npp.7.bin.minimalist.x64.7z"
},
"task-1": {
"operation": "convert",
"input_format": "7z",
"output_format": "zip",
"engine": "archivetool",
"input": [
"import-1"
]
},
"export-1": {
"operation": "export/url",
"input": [
"task-1"
],
"inline": true,
"archive_multiple_files": true
}
}
}
var headers = {
'Authorization': 'Bearer CLOUDCONVERT API KEY'
};
var options = {
'method' : 'post',
'contentType': 'application/json',
'headers': headers,
// Convert the JavaScript object to a JSON string.
'payload' : JSON.stringify(data)
};
var response = JSON.parse(UrlFetchApp.fetch('https://api.cloudconvert.com/v2/jobs', options));
var dataID = response.data.id;
var options2= = {
'method' : 'get',
'contentType': 'application/json',
'headers': headers,
};
// if the file is too big wait a few seconds
// Utilities.sleep(3000);
var urlStatus = 'https://api.cloudconvert.com/v2/jobs/'+dataID+'/wait'
var conversionStatus = JSON.parse(UrlFetchApp.fetch(urlStatus, options2));
Logger.log(conversionStatus.data.tasks[0].result.files);
}
Reference:
https://cloudconvert.com/api/v2
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
https://developers.google.com/apps-script/reference/utilities/utilities?hl=en#sleep(Integer)

"errorCode":"UNSPECIFIED_ERROR","message":"Non-static method requires a target."

I am trying to create an envelope using E-signature post API from AppScript. I am able to Authenticate and call other Get API's like Status of Envelope and List of all envelopes successfully. But for this Post API I am facing below error.
"errorCode":"UNSPECIFIED_ERROR",
"message":"Non-static method requires a target."
here is the object which I am passing
var createEnvelopeObj =
{
"documents": [
{
"documentBase64": "JVBERi0----------DI0NGItMThmMzAtNS41LjEzLVNOQVBTSE9UCnN0YXJ0eHJlZgoxOTY2MDcKJSVFT0YK",
"documentId": "1323457",
"fileExtension": ".pdf",
"name": "sampledoc"
}
],
"emailSubject": "Please sign below Document ref: G654sfd238",
"recipients": {
"signers": [
{
"clientUserId": "xxxx#gmail.com",
"email": "xxxx#dddd.com",
"name": "xxxx",
"recipientId": "124",
"routingOrder": "1"
}
]
},
"status": "sent"
};
Below is the API call with above object
function DocusignPost(createEnvelopeObj){
var options = {
headers: {Authorization: 'Bearer eyJ0eXAiOiJNVCIsImFsZyI6IlJTMjU2Iiwia2lkIjoiNjgxO___xxxxx_VKdnH4FHUtI80s5xtZ9tusnP1DmYw '
},
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(createEnvelopeObj),
'muteHttpExceptions': true};
try{
var response = UrlFetchApp.fetch("https://demo.docusign.net/restapi/v2.1/accounts/xxxxxxx/envelopes", options );
var postresponce = JSON.parse(response);
Logger.log("postresponce : " + JSON.stringify(postresponce));
return postresponce;}catch(exp){
Logger.log(exp); }}
I have referred both these 57258880, 35047127 but I am using latest Auth method and passing object as payload, but still facing an issue.
Request someone to look into this and shed some light on it. I got stuck here for a couple of days.
I don't see any error in your JSON. So the next step I recommend is to obtain the API trace from DocuSign to see exactly what is being received from DocuSign.
See https://support.docusign.com/en/guides/ndse-user-guide-api-request-logging
You should also carefully check how you're reading in the PDF file before base64 encoding it. PDF files are (almost always) binary, so you need to read them using a binary-clean method.

How to create a file in a specific team drive or folder?

I'm using the Google Drive API Explorer. I can't seem to get a file to get created in the drive that I want. It either creates a file in the root of my drive or gives me an error of "file not found".
I Have Used Following javaScript Code in my project, it worked for me. Not sure which language you are using.
function createFolder(parentid,folderName) {
var access_token = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token;
var request = gapi.client.request({
'path': '/drive/v2/files/',
'method': 'POST',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + access_token,
},
'body': {
"title": folderName,
"mimeType": "application/vnd.google-apps.folder",
"parents": [{
"kind": "drive#file",
"id": parentid
}]
}
});
request.execute(function (resp) {
console.error("createFolder", resp.error);
});
};
parentid is the id of the folder in which you want to create a folder(ex: 1eYTYMkptjn8K9Pu8_aGII-rF3-3Oymlo)
and folderName is the name of the new folder
If you want to create other than the folder just change the mimeType

How to automatically authenticate Google Drive through Docusign API

I am creating an app with Google apps script to send Docusign envelopes to customers when I receive a google form from them (with the responses going into a google sheet with an onFormSubmit trigger). I'm using the Docusign REST API envelopes method to create an envelope, and send directly to the customer.
Once a customer submits their form, my google apps script function will automatically create a pdf document and put it in a google drive folder. I'm using the Docusign Envelopes method with "remoteUrl" parameter (reference in the document section here: https://docs.docusign.com/esign/restapi/Envelopes/Envelopes/create/) to specifiy the google drive document ID (the pdf) from which Docusign will create the envelope from.
Obviously, these pdf files are in my google drive, and mine only, so there's no reason for me to login to my google account every day, and that's the issue I'm having. When I try to run the script without signing into google, the Docusign API throws this error message:
"errorCode": "EXTERNAL_DOC_SERVICE_ERROR", "message": "An error occurred in the external doc service. NotAuthenticated"
Is there a way I can possibly use refresh tokens with one of Google's APIs to stay logged in? In layman's terms, a method of "auto-authentication". It would have to somehow communicate with my script using the Docusign API.
Here is my current Google Apps Script:
function Docusign() {
var ss = SpreadsheetApp.openById('MYSPREADSHEETID');
var sheet = ss.getSheetByName("SHEET");
var quotesheet = ss.getSheetByName("SHEET2");
var Avals = sheet.getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
var basicinfo = sheet.getRange(Alast, 1, 1, 35).getValues()[0];
var quotelinks = quotesheet.getRange(Alast, 1, 1, 10).getValues()[0];
var name = (basicinfo[2]);
var email = (basicinfo[1]);
//This is where the full links of the pdfs are stored
var doc = (quotelinks[0]);
//"DIGITS" is six digits followed by a colon, it might be private so I put "DIGITS" instead
var sub = "DIGITS" + doc.substring(32,65);
Logger.log(sub);
var url = "https://demo.docusign.net/restApi/v2/accounts/MYACCOUNTID/envelopes";
var payload =
{
"documents": [
{
"documentId": "1",
"fileExtension": "pdf",
"name": "NAMEOFDOC",
"remoteUrl": sub
}
],
"emailSubject": "SUBJECT",
"recipients": {
"signers": [
{
"email": email,
"name": name,
"recipientId": "1",
"tabs": {
"signHereTabs": [
{
"documentId": "1",
"pageNumber": "1",
"tabLabel": "Signature",
"xPosition": "140",
"yPosition": "650"
}
],
"dateTabs": [
{
"documentId": "1",
"pageNumber": "1",
"tabLabel": "date",
"xPosition": "420",
"yPosition": "680"
}
]
}
}
]
},
"status": "sent"
};
var options =
{
"contentType": "application/json",
"method" : "post",
"headers":
{
"X-DocuSign-Authentication": "{\"Username\":\"MYUSERNAME\",\"Password\":\"MYPASSWORD\",\"IntegratorKey\":\"MYINTEGRATORKEY\"}",
},
"payload" : JSON.stringify(payload)
};
UrlFetchApp.fetch(url, options);
}
Any help would be greatly appreciated.
You can try one thing, go to DocuSign webApp and do OAUTH to Google Drive once (by adding document from G Drive at the time of sending an envelope), this way you are giving permission to DocuSign to fetch documents from Google Drive on your behalf.
Once you Google OAUTH is done, then you can use DocuSign API to fetch documents from Google drive using Remote URL. For instance, in below call "112805:0B1-EnSmMAIOmc3RhcnRlcl9maWx" is the id of the document in the Google Drive. So using DS API, I am able to fetch the document and add it to my envelope creation API call.
"documents": [
{
"remoteUrl":"112806:0B1-EnSmMAIOmc3RhcnRlcl9maWx",
"documentId": "1",
"name": "Getting started"
}
]