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

好久不见. 提交于 2021-01-28 20:23:22

问题


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&amp;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.

  1. Any other ideas how to send parameters to a triggered function
  2. How I could do it using PropertiesService.

回答1:


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&amp;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&amp;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


来源:https://stackoverflow.com/questions/63221917/how-to-set-a-time-driven-clock-trigger-for-a-function-that-needs-parameters-se

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!