Scrape part of web page html and test it against condition - javascript

This is part of the html code from "view page source" I want to scrape
<span>Loyalty cijena</span>
<strong>863,84 KN</strong>
This is my code to scrape part which is now "863" and start my function if that number is under 863. But now the function start no matter condition is set [0-862] or [0-864]. Where is my mistake?
function createBackup() {
var folder = getFolder(FOLDER_NAME);
var exportUrl = RESOURCE_URL;
var response = UrlFetchApp.fetch(exportUrl);
var htmlBody = response.getContentText();
var scraped = htmlBody.match(/Loyalty cijena<\/span>\s*<strong>(\d+),(\d+) KN<\/strong>/m)[1];
if(scraped.match(/[0-862]/)); {
createBackupFile(folder, FILE_NAME, fetchData());
}
}
Edit: This is full code
var RESOURCE_URL = 'https://www...',
BACKUP_FOLDER_ID = 'xxx',
FOLDER_NAME_FORMAT = 'yyyy-MM-dd',
FILE_NAME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss",
FILE_EXT = '.pdf',
now = new Date(),
FOLDER_NAME = Utilities.formatDate(now, 'CET', FOLDER_NAME_FORMAT),
FILE_NAME = Utilities.formatDate(now, 'CET', FILE_NAME_FORMAT) + FILE_EXT;
function createBackup() {
var folder = getFolder(FOLDER_NAME);
var exportUrl = RESOURCE_URL;
var response = UrlFetchApp.fetch(exportUrl);
var htmlBody = response.getContentText();
var scraped = htmlBody.match(/Loyalty cijena<\/span>\s*<strong>(\d+),(\d+) KN<\/strong>/m)[1];
console.log(scraped,parseInt(scraped) > 0 && parseInt(scraped) < 863); {
createBackupFile(folder, FILE_NAME, fetchData());
}
}
function getFolder(name) {
var backupFolder = getBackupFolder(),
folders = backupFolder.getFoldersByName(name);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = backupFolder.createFolder(name);
}
return folder;
}
function getBackupFolder() {
return DriveApp.getFolderById(BACKUP_FOLDER_ID);
}
function createBackupFile(folder, filename, data, overwrite) {
if (overwrite) {
var existingFiles = folder.getFilesByName(filename);
while (existingFiles.hasNext()) {
var file = existingFiles.next();
folder.removeFile(file);
}
}
}
function fetchData() {
var exportUrl = RESOURCE_URL;
var response = UrlFetchApp.fetch(exportUrl);
var htmlBody = response.getContentText();
var blob = Utilities.newBlob(htmlBody, 'text/html').getAs('application/pdf').setName(FILE_NAME);
return folder.createFile(blob);
}

The pattern [0-862] matches text that ends with 62 and where the first symbol is 0 to 8, so for example 562 but not 561. In your case you should compare the number represented by those characters, instead of matching against a regular expression.

Don't use regex to match a value:
var htmlBody = `<span>Loyalty cijena</span>
<strong>863,84 KN</strong>`
var scraped = htmlBody.match(/Loyalty cijena<\/span>\s*<strong>(\d+),(\d+) KN<\/strong>/m)[1];
console.log(scraped,
parseInt(scraped) > 0 && parseInt(scraped) <= 863); // false if you change to < 863

Related

Function B returns null when called from function A, but returns correct value when logged within function B

please refer to the code below:
function getGdriveLinks() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Test');
const fileNames = sheet.getRange('C2:C').getValues();
const mainFolder = DriveApp.getFolderById('Folder ID');
for (var i = 0; i < fileNames.filter(String).length; i++){
var fileName = fileNames[i][0].toString();
var fileLink = getGdriveLink(fileName,mainFolder);
Logger.log(fileLink);
}
}
function getGdriveLink(searchFileName,folder){
var mainFiles = folder.getFiles();
while (mainFiles.hasNext()){
var file = mainFiles.next();
if(file.getName().indexOf(searchFileName) != -1){
Logger.log(file.getUrl());
return file.getUrl();
}
}
var subFolders = folder.getFolders();
while (subFolders.hasNext()){
var subFolder = subFolders.next();
getGdriveLink(searchFileName,subFolder);
}
}
Basically, the aim is to get the filenames in C2:C of Test sheet, find each of these in the 'Folder ID', and then return their URL. The URL is returned correctly when I log it from getGdriveLink(searchFileName,folder) using Logger.log(file.getUrl()). However, it returns null via the Logger.log(fileLink) when the result goes back to getGdriveLinks() function. Is there anything I'm missing? We're using a corporate domain if that's something to consider. Hoping for your guidance. Thanks!
You could also do it this way and avoid recursion altogether
function getPathAllDrivesFromId(fileid) {
var ids = [{id:fileid,name:DriveApp.getFileById(fileid).getName()}];
let r;
do {
r = Drive.Files.get(fileid,{supportsAllDrives:true,supportsTeamDrives:true});
if(r.parents.length > 0) {
//Logger.log(JSON.stringify(r.parents[0]));
ids.push({id:r.parents[0].id,name:DriveApp.getFolderById(r.parents[0].id).getName()});
fileid = r.parents[0].id
}
}while (r.parents.length > 0);
if(ids[ids.length - 1].name == "Drive") {
ids[ids.length - 1].name = Drive.Drives.get(ids[ids.length - 1].id).name;
}
//Logger.log(JSON.stringify(ids));
let path = ids.map(obj => obj.name).flat().reverse().join(' / ')
//Logger.log(path);
return path;
}
function getGdriveLinks() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Test');
const osh = ss.getSheetByName("Results");
const ns = sh.getRange('C2:C' + sh.getLastRow()).getValues();
const folder = DriveApp.getFolderById('Folder ID');
const result = [["Filename", "Id", "Url", "path"]];
ns.forEach(n => {
let files = DriveApp.getFilesByName(n);
while (files.hasNext()) {
let file = files.next();
let path = getPathAllDrivesFromId(file.getId());
if (~path.indexOf(folder.getName())) {
result.push([file.getName(), file.getId(), file.getUrl(), path]);
}
}
})
osh.clearContents();
osh.getRange(1, 1, result.length, result[0].length).setValues(result);
}

Google script - Service error: Spreadsheets

As of a couple of weeks now, I'm getting a "Service error: Spreadsheets" error when running a script in Google Sheets. Before that, it was working fine.
It's supposed to export a PDF while deleting some of the empty rows.
I tried adding a 1000ms delay, but that didn't work.
Any help would be greatly appreciated. You can find the code below.
var sheetName = "PDF - B";
var sheetName2 = "Offertes";
var folderID = "XXX"; // Folder id to save in a folder.
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var sourceSheet2 = sourceSpreadsheet.getSheetByName(sheetName2);
var folder = DriveApp.getFolderById(folderID);
var invoiceName = sourceSheet.getRange("B57").getValue();
var invoiceDate = sourceSheet.getRange("H57").getValue();
var invoiceBusnr = sourceSheet.getRange("J1").getValue();
var invoiceDate_2 = Utilities.formatDate(invoiceDate, "CET", "yyyy-MM-dd")
var pdfName = "["+invoiceDate_2+"] "+invoiceName+" - Offerte "+invoiceBusnr+" Ventje";
var fact = sourceSheet.getRange("H60").getValue();
var value_f1 = sourceSheet.getRange("I53").getValue();
var value_f2 = sourceSheet.getRange("I54").getValue();
var buyerRow = sourceSheet.getRange("I61").getValue();
var buyerColumn = sourceSheet.getRange("J61").getValue();
var vColumn = sourceSheet.getRange("G61").getValue();
var f_cell = sourceSheet2.getRange(buyerRow,buyerColumn);
var f_version = sourceSheet2.getRange(buyerRow,vColumn);
if (fact=="F1") {
f_cell.setValue(value_f1);
f_version.setValue(2);
}
if (fact=="F2") {
f_cell.setValue(value_f2);
}
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder));
//repace cell values with text (to avoid broken references)
var destSheet = destSpreadsheet.getSheets()[0]
var destSheet = destSpreadsheet.getSheetByName(sheetName)
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
var imageSheet = destSpreadsheet.getSheetByName("Bus foto's");
var imageRow = destSheet.getRange("B1").getValue();
var sourceImage_1 = imageSheet.getRange(imageRow, 2, 1, 1);
var destImage_1 = destSheet.getRange(4, 2, 1, 1);
var sourceImage_2 = imageSheet.getRange(imageRow, 3, 1, 1);
var destImage_2 = destSheet.getRange(4, 7, 1, 1);
var sourceImage_3 = imageSheet.getRange(imageRow, 4, 1, 1);
var destImage_3 = destSheet.getRange(6, 2, 1, 1);
var sourceImage_4 = imageSheet.getRange(imageRow, 5, 1, 1);
var destImage_4 = destSheet.getRange(6, 7, 1, 1);
sourceImage_1.copyTo(destImage_1,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
sourceImage_2.copyTo(destImage_2,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
sourceImage_3.copyTo(destImage_3,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
sourceImage_4.copyTo(destImage_4,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (i % 10 == 0) { Utilities.sleep(3000); } // Pause the function for 3000 milliseconds after 10 iterations
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
//delete redundant rows
var soverig14 = destSheet.getRange("B50").getValue();
var soverig13 = destSheet.getRange("B49").getValue();
var soverig12 = destSheet.getRange("B48").getValue();
var soverig11 = destSheet.getRange("B47").getValue();
var soverig10 = destSheet.getRange("B46").getValue();
var soverig9 = destSheet.getRange("B45").getValue();
var soverig8 = destSheet.getRange("B44").getValue();
var soverig7 = destSheet.getRange("B43").getValue();
var soverig6 = destSheet.getRange("B42").getValue();
var soverig5 = destSheet.getRange("B41").getValue();
var soverig4 = destSheet.getRange("B40").getValue();
var soverig3 = destSheet.getRange("B39").getValue();
var soverig2 = destSheet.getRange("B38").getValue();
var soverig1 = destSheet.getRange("B37").getValue();
var soverig_t = destSheet.getRange("B36").getValue();
var soverig_m1 = destSheet.getRange("B35").getValue();
var sschuif = destSheet.getRange("B34").getValue();
var boverig3 = destSheet.getRange("B26").getValue();
var boverig2 = destSheet.getRange("B25").getValue();
var boverig1 = destSheet.getRange("B24").getValue();
var boverig0 = destSheet.getRange("B23").getValue();
var boverig_t = destSheet.getRange("B22").getValue();
var boverig_m1 = destSheet.getRange("B21").getValue();
var f1 = destSheet.getRange("B53").getValue();
var f2 = destSheet.getRange("B54").getValue();
var f3 = destSheet.getRange("B60").getValue();
var f4 = destSheet.getRange("B61").getValue();
if (f4=="") {
destSheet.deleteRow(61);
}
if (f3=="") {
destSheet.deleteRow(60);
}
if (f2=="") {
destSheet.deleteRow(54);
}
if (f1=="") {
destSheet.deleteRow(53);
}
if (soverig14=="") {
destSheet.deleteRow(50);
}
if (soverig13=="") {
destSheet.deleteRow(49);
}
if (soverig12=="") {
destSheet.deleteRow(48);
}
if (soverig11=="") {
destSheet.deleteRow(47);
}
if (soverig10=="") {
destSheet.deleteRow(46);
}
if (soverig9=="") {
destSheet.deleteRow(45);
}
if (soverig8=="") {
destSheet.deleteRow(44);
}
if (soverig7=="") {
destSheet.deleteRow(43);
}
if (soverig6=="") {
destSheet.deleteRow(42);
}
if (soverig5=="") {
destSheet.deleteRow(41);
}
if (soverig4=="") {
destSheet.deleteRow(40);
}
if (soverig3=="") {
destSheet.deleteRow(39);
}
if (soverig2=="") {
destSheet.deleteRow(38);
}
if (soverig1=="") {
destSheet.deleteRow(37);
}
if (soverig_t=="") {
destSheet.deleteRow(36);
}
if (soverig_m1=="") {
destSheet.deleteRow(35);
}
if (sschuif=="") {
destSheet.deleteRow(34);
}
if (boverig3=="") {
destSheet.deleteRow(26);
}
if (boverig2=="") {
destSheet.deleteRow(25);
}
if (boverig1=="") {
destSheet.deleteRow(24);
}
if (boverig0=="") {
destSheet.deleteRow(23);
}
if (boverig_t=="") {
destSheet.deleteRow(22);
}
if (boverig_m1=="") {
destSheet.deleteRow(21);
}
// export url
var url = 'https://docs.google.com/spreadsheets/d/'+destSpreadsheet.getId()+'/export?exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=A4' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to page width, false for actual size
+ '&scale=4' // 1 = Normal 100% -- 2 = Fit to width -- 3 = Fit to height -- 4 = Fit to Page
//+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
// + '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
//+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&horizontal_alignment=CENTER' // LEFT/CENTER/RIGHT
//+ '&vertical_alignment=MIDDLE' // TOP/MIDDLE/BOTTOM
// SET ALL MARGINS IN ORDER FOR IT TO WORK
+ '&top_margin=0.4' // set top margin
+ '&bottom_margin=0.4' // set bottom margin
+ '&left_margin=0.7' // set left margin
+ '&right_margin=0.7' // set right margin
+ '&gid='+destSheet.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
// request export url
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var theBlob = response.getBlob().setName(pdfName+'.pdf');
// delete pdf if already exists
var files = folder.getFilesByName(pdfName);
while (files.hasNext())
{
files.next().setTrashed(true);
}
// create pdf
var newFile = folder.createFile(theBlob);
// return true;
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
I have also noticed "Service error: Spreadsheets" when trying to create a pdf; this started occurring sometime between 7 April and 28 April.
I have narrowed it down to to a column in my spreadsheet which contains images using the =IMAGE() function. If these are copied using Range.setValues() the "Service error" occurs. This in itself seems to me to be a bug as it's not very informative about what's wrong. It's arguable whether the =IMAGE() should be copyable using setValues()
However, I've discovered it is possible to copy the image formula using Range.setFormulas(), and it's also possible to use Range.setValues() on an image created using menu>insert>image but setValues() does not work if the image is created from a script using SpreadsheetApp.newCellImage()
The last mentioned problem means there is no bypass for scripts to avoid "Service error: spreadsheets" for scripts without some fiddly recoding.
Here's a shared spreadsheet which illustrates the problem: https://docs.google.com/spreadsheets/d/1xJoOf0DJBRUTbaskjKsly3pAGNJ72sT_EV8Tn246Ufo/edit?usp=sharing
"Service error" is also reported on the google issuetracker
Based on the comment of #Tyler2P, I created a workaround, replacing the part from //repace cell values with text with the following code:
var destSheet = destSpreadsheet.getSheets()[0];
var destSheet = destSpreadsheet.getSheetByName(sheetName);
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourceRange1 = sourceSheet.getRange(1,1,3,sourceSheet.getMaxColumns());
var sourceRange2 = sourceSheet.getRange(7,1,(sourceSheet.getMaxRows()-7),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var sourcevalues1 = sourceRange1.getValues();
var sourcevalues2 = sourceRange2.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
var destRange1 = destSheet.getRange(1,1,3,sourceSheet.getMaxColumns());
var destRange2 = destSheet.getRange(7,1,(sourceSheet.getMaxRows()-7),sourceSheet.getMaxColumns());
destRange1.setValues(sourcevalues1);
destRange2.setValues(sourcevalues2);

How can I copy data from a google spreasheet using the file name, and paste it into another file?

I am trying to use a file name to get data from a Spreadsheet, and copy the data into a different target file. I have the following code, and it is failing at line 7. When I manually put in an ID in line 7 the code works. Could someone help? Thank you very much.
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
Logger.log(fileList.next().getId())
}
var fileID = Logger.getLog();
var ss = SpreadsheetApp.openById(fileID);//fails here
var source = ss.getSheetByName('sheet name');
var rangeSource = source.getDataRange();
var data = rangeSource.getValues();
var rowsInData = data.length;
var colsInData = data[0].length;
var sss = SpreadsheetApp.openById('1Hia3_zGk1qyPlVuPTQR5iOjExFaMEe3EQOMXBc2C6eI');
var logSheet = sss.getSheetByName("diamondbackprogress");
var rowsInLogSheet = logSheet.getMaxRows();
var colsInLogSheet = logSheet.getMaxColumns();
if (rowsInLogSheet < rowsInData) {
logSheet.insertRowsAfter(rowsInLogSheet, rowsInData - rowsInLogSheet);
} else if (rowsInLogSheet > rowsInData) {
logSheet.deleteRows(rowsInData, rowsInLogSheet - rowsInData);
}
if (colsInLogSheet < colsInData) {
logSheet.insertColumnsAfter(colsInLogSheet, colsInData - colsInLogSheet);
} else if (colsInLogSheet > colsInData) {
logSheet.deleteColumns(colsInData, colsInLogSheet - colsInData);
}
logSheet.getRange(1, 1, rowsInData, colsInData).setValues(data);
}
Logger.getLog() won't give you the id of the file, it will give a list of messages in the current log. See here for more details.
Replace this part:
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
Logger.log(fileList.next().getId())
}
var fileID = Logger.getLog();
with this:
function openFile() {
var fileList = DriveApp.getFilesByName('file name')
while (fileList.hasNext()) {
var fID = fileList.next().getId();
}
var fileID = fID;

How to set a time-driven (clock) trigger for a function that needs parameters sent to it?

I'm trying to have a function run with a time-driven (clock) trigger. My issue is, the function needs variables sent to it as parameters. Normally if I'm not using a trigger I'll just send it directly like this.
<script>
function runFunction(){
google.script.run.myFunction(x,y,z);
}
</script>
And on the server side, I'll call them easily.
function myFunction(x,y,z){
var a = x;
var b = y;
var c = z;
Logger.log(a+b+c);
}
But when I'm using a time-driven (clock) trigger to run the function how can I get x,y,z into the function.
I searched around and saw one method of creating scriptProperties out of the parameters in the trigger function like this.
EDITED This is the actual code.
Client side.
<script>
function sendCall() {
var testNumber = document.getElementById('numberCall').value;
var testGroup = document.getElementById('groupsCall').value;
var testtime = document.getElementById('scheduleCall').value;
var now = document.getElementsByName('sendTimeCall')[0].checked;
var number;
if(testNumber == ''){
number = null;
}else{
number = testNumber;
}
var group;
if(testGroup == ""){
group = null;
}else{
group = testGroup;
}
var time;
if(testtime == ''){
time = null;
}else{
time = testtime;
}
var file = document.getElementsByName('audio')[0].files[0];
var name = file.name;
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
google.script.run.withSuccessHandler(success2).triggerCall(group, number, content, time, now, name);
return false;
}
reader.readAsDataURL(file);
}
</script>
Server side - Trigger Function.
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperties({
'GROUP_CALL': group,
'AUDIO': content,
'NUMBER_CALL': number,
'FILE_NAME': name
});
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
// Set here the date you want to schedule the one-time trigger
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall")
.timeBased()
.after(time_af * 60 *60 * 1000)
.create();
}
return status;
}
Server side - Here is The function that actually does the work.
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var blob = scriptProperties.getProperty('AUDIO');
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
//upload file to drive
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx');
var blob = blob.split(",");
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name);
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
//the url with HTTP request to create a call and parameters
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {
"To": fullNumber[i],
"From" : "+177777777",
"Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>",
};
var options = {
"method" : "post",
"payload" : payload
};
options.headers = {
"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")
};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
The problem is when I run the above code without the file input it works, But when I run it as above the function doesn't work. I did some trouble shooting and I think it has to do with transferring the file as a Data URL via the properties method. Is there a limit to how long of a string the VALUE can be?
in a nut shell these are the 2 points of my question.
Any other ideas how to send parameters to a triggered function
How I could do it using PropertiesService.
I would like to propose the following modification.
Modification points:
I think that the reason of your issue might be due to the maximum data size for PropertiesService. In the current stage, it seems that "Properties total storage" is "500kB / property store". I thought that in this case, when you upload a file, the file size might be over than it.
In order to remove your issue, how about creating content as a temporal file and put the file ID to the PropertiesService?
When above points are reflected to your script, it becomes as follows.
Pattern 1:
In this pattern, content is saved as a temporal file and that is used in the function of makeCall().
triggerCall()
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
var tempFile = DriveApp.createFile("tempFile.txt", content, MimeType.PLAIN_TEXT); // Added
scriptProperties.setProperties({'GROUP_CALL': group,'AUDIO': tempFile.getId(),'NUMBER_CALL': number,'FILE_NAME': name}); // Modified
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall").timeBased().after(time_af * 60 *60 * 1000).create();
}
return status;
}
makeCall()
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var tempfileId = scriptProperties.getProperty('AUDIO'); // Modified
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx');
var tempFile = DriveApp.getFileById(tempfileId); // Added
var text = tempFile.getBlob().getDataAsString(); // Added
tempFile.setTrashed(true); // Added
var blob = text.split(","); // Modified
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name);
var file = folder.createFile(blob);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {"To": fullNumber[i],"From" : "+177777777","Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>"};
var options = {"method" : "post","payload" : payload};
options.headers = {"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
Pattern 2:
In this pattern, content is saved to a file as the decoded data and that is used in the function of makeCall().
triggerCall()
function triggerCall(group, number, content, time, now, name){
var scriptProperties = PropertiesService.getScriptProperties();
var folder = DriveApp.getFolderById('xxxxxxxxxxxxxxxxxxxxxx'); // Added
var blob = content.split(","); // Added
var blob = Utilities.newBlob(Utilities.base64Decode(blob[1]), 'audio/mpeg', name); // Added
var file = folder.createFile(blob); // Added
scriptProperties.setProperties({'GROUP_CALL': group,'AUDIO': file.getId(),'NUMBER_CALL': number,'FILE_NAME': name}); // Modified
var status;
if(now){
status = 'Call Sent';
}else{
status = 'Call Scheduled';
}
if(now){
return makeCall(status);
}else{
var rawdate = time;
var today_D = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var scheduled_D = new Date(rawdate);
var time_af = Math.abs(scheduled_D - today_D) / 36e5;
ScriptApp.newTrigger("makeCall").timeBased().after(time_af * 60 *60 * 1000).create();
}
return status;
}
makeCall()
function makeCall(status) {
var scriptProperties = PropertiesService.getScriptProperties();
var fileId = scriptProperties.getProperty('AUDIO'); // Modified
var number = scriptProperties.getProperty('NUMBER_CALL');
var group = scriptProperties.getProperty('GROUP_CALL');
var name = scriptProperties.getProperty('FILE_NAME');
var fullNumber;
if(group){
var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
var sheet = ss.getSheetByName(group)
var length = sheet.getLastRow();
var values = sheet.getRange(1, 1, length).getValues();
fullNumber = values.flat();
}else{
var num = number;
var prefix = '+1';
var removeDashes = num.replace(/-/g,"");
var format = prefix + removeDashes;
var comma = format.replace(/ /g, ' +1');
fullNumber = comma.split(' ')
}
var file = DriveApp.getFileById(fileId); // Modified
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var id = file.getId();
for (var i = 0; i < fullNumber.length; i++){
var callsUrl = "https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxx/Calls.json";
var payload = {"To": fullNumber[i],"From" : "+177777777","Twiml" : "<Response><Play>https://docs.google.com/uc?export=play&id=" + id + "</Play></Response>"};
var options = {"method" : "post","payload" : payload};
options.headers = {"Authorization" : "Basic " + Utilities.base64Encode("xxxxxxxxxxx:xxxxxxxx")};
UrlFetchApp.fetch(callsUrl, options);
}
scriptProperties.deleteProperty('AUDIO');
scriptProperties.deleteProperty('NUMBER_CALL');
scriptProperties.deleteProperty('GROUP_CALL');
scriptProperties.deleteProperty('FILE_NAME');
return status;
}
Note:
In this modified script, when a file is uploaded, content is saved as a temporal file and the file ID is put to the PropertiesService. When makeCall is run, content is retrieved by the file ID and convert to the blob and saved it as a file. And the temporal file is removed. By this, the limitation of PropertiesService can be cleared.
But, in the current stage, the maximum blob size of Google Apps Script is 50 MB (52,428,800 bytes). So when the uploaded file size is over 50 MB, an error occurs. In this case, the file is converted to the base64 data. So, the maximum size is the size of base64 data. Please be careful this.
Reference:
Current limitations

How to call a function in a function with javascript small explanation

I'm a beginner in java script a trying a little program that parse data from a text file. In order to create a filter on a particular date i have made a function to get the date from and to that the user have enter. And the date a have to compare if it is in the range is in the text file, this date also i got it. But now i don't want to re-write the function "getAllFilesFromFolder" found in the code below, this function must be executed in all case but if i click on the button filter by by date it must read on the files with the date in range given by the user. Can someone give me an explanation on how to do it. i have tried the code below.
function getdate(){
var dateStart = new Date($('#dateStart').val()).getTime();
var dateEnd = new Date($('#dateEnd').val()).getTime();
//if(!testDate){var testDate = new Date(2014, 05, 02).getTime();}
var testDate = new Date(2014, 05, 02).getTime();
if (dateStart <= testDate && testDate <= dateEnd) {
alert('IN');
//Here filter the files with the date
}else{
alert('OUT');
//Here no new to read and parse the file beacause it is out of range
}
}
//Parse folder and file to get the required files
function getAllFilesFromFolder(folder){
//Parsing the given folder the result which is return is kept in an array
var test = fse.readdirSync(folder);
//Going through the array
for(var n=0; test[n]; n++){
var stats = fs.lstatSync(folder+"\\"+test[n]);
if(stats && stats.isDirectory()){
getAllFilesFromFolder(folder+"\\"+test[n]);
var path = folder+"\\"+test[n]+"<br />";
}else{
var path = folder+"\\"+test[n];
//Regex on the file to be taken
var pattern = /^(PM)[0-9]{5}[_](xam)[_](pmbok5th)[_](pmp)[_](v92)(.txt)$/;
var parent = folder+"\\";
var file = test[n];
var load = pattern.test(file);
//Split on file to get the "id user"
identifiant = file.split('_');
//Test the regex on file name "PM*_xam_pmbok5th_pmp_v92.txt"
if(load == true){
var read = fse.readFileSync(path, 'utf8');
var suspendDate = read.lastIndexOf('xam/');
var wantedDate = read.slice(suspendDate);
info = wantedDate.split('/');
var suspendData = read.lastIndexOf('/DB');
var suspendData = wantedDate.lastIndexOf('/DB');
var wantedData = wantedDate.slice(suspendData);
var db_response = wantedData.split(".");
var all_response = db_response[0].split(":");
if(typeof(info[2]) != "undefined" && all_response != "undefined"){
var response = all_response[1].split("|");
//Parsing the array response to find the "id" here id of the question and the "ans" here answer of the question "R" or "W"
for(var p = 0; p < response.length; p++){
//Test if result exist we increment if not it is generate with the function initResp
if(typeof(response[p]) != "undefined"){
var id = response[p].slice(0,6);
var ans = response[p].slice(-1);
if (question[id]) {
question[id][ans] += 1;
} else {
var results = initResp(ans);
question[id] = results;
};
} else {
}
}
} else {
//$("#results1").append("<strong>La session est vide</strong><br>");
}
i++;
}
}
}
};
I found a solution to my problem. See the code below for more information
function rangeDate(testDate){
var dateStart = new Date($('#dateStart').val()).getTime();
var dateEnd = new Date($('#dateEnd').val()).getTime();
if (dateStart <= testDate && testDate <= dateEnd) {
date = true;
return date;
}else{
date = false;
return date;
}
}
function getAllFilesFromFolder(folder)/*, useDate*/{
//Parsing the given folder the result which is return is kept in an array
var test = fse.readdirSync(folder);
//Going through the array
for(var n=0; test[n]; n++){
var stats = fs.lstatSync(folder+"\\"+test[n]);
if(stats && stats.isDirectory()){
getAllFilesFromFolder(folder+"\\"+test[n]);
var path = folder+"\\"+test[n]+"<br />";
}else{
var path = folder+"\\"+test[n];
//Regex on the file to be taken
var pattern = /^(PM)[0-9]{5}[_](xam)[_](pmbok5th)[_](pmp)[_](v92)(.txt)$/;
var parent = folder+"\\";
var file = test[n];
var load = pattern.test(file);
//Split on file to get the "id user"
identifiant = file.split('_');
//Test the regex on file name "PM*_xam_pmbok5th_pmp_v92.txt"
if(load == true){
var read = fse.readFileSync(path, 'utf8');
var suspendDate = read.lastIndexOf('xam/');
var wantedDate = read.slice(suspendDate);
var info = wantedDate.split('/');
testDate = new Date(info[4]).getTime();
rangeDate(testDate);
if(date == true){
var suspendData = read.lastIndexOf('/DB');
var suspendData = wantedDate.lastIndexOf('/DB');
var wantedData = wantedDate.slice(suspendData);
var db_response = wantedData.split(".");
var all_response = db_response[0].split(":");
if(typeof(info[2]) != "undefined" && all_response != "undefined"){
var response = all_response[1].split("|");
//Parsing the array response to find the "id" here id of the question and the "ans" here answer of the question "R" or "W"
for(var p = 0; p < response.length; p++){
//Test if result exist we increment if not it is generate with the function initResp
if(typeof(response[p]) != "undefined"){
var id = response[p].slice(0,6);
var ans = response[p].slice(-1);
if (question[id]) {
question[id][ans] += 1;
} else {
var results = initResp(ans);
question[id] = results;
};
} else {
}
}
} else {
//$("#results1").append("<strong>La session est vide</strong><br>");
}
i++;
}else{
}
}
}
}
};

Categories