1
  1. Project_1 is a container-bound script. A container is a readable spreadsheet (Template).

Code_1:

function doPost(e) {
  return HtmlService.createHtmlOutput(JSON.stringify(e));
}

The user makes a copy of the Template, deploys the script (Project_1) as a webapp with permissions: "Execute as: Me, Who has access: Anyone". The user is the owner of Project_1.

  1. Project_2 is a script deployed as an add-on. The user from point 1 is not the owner of Project_2.

Code_2:

function sendPost() {
  var sheetURL = SpreadsheetApp.getActiveSpreadsheet().getUrl();

  var webAppUrl = "https://script.google.com/macros/s/###/exec"; // 7: Part_1 - WebApp: Tester

  // var auth = ScriptApp.getOAuthToken();
  // var header = { 'Authorization': 'Bearer ' + auth };
  var payload = { scriptName: 'updateData', sheetURL: 'sheetURL' };
  var options = {
    method: 'post',
    // headers: header,
    muteHttpExceptions: true,
    payload: payload
  };

  var resp = UrlFetchApp.fetch(webAppUrl, options);
  var respTxt = resp.getContentText();
  console.log('resp: ' + respTxt);
}

function doPost(ev) {
  var respWebapp = func(ev);
}

The user installs an add-on (Project_2).

  1. The flow in the direction of addon -> webapp is fine: when sendPost() starts, it sends a request to the webapp and receives a response with the necessary data_1 in response.

The flow in the direction of "someone on the web" -> webapp also flows well: when requesting a webapp_url receives the transferred data_2.

  1. I am trying to transfer data_2 to an addon. I read a lot about scripts.run, but it seems that this option is not applicable in such a situation. There is also nowhere to add an eventListener.

  2. I would not want to deploy webapp from my account, so as not to spend my quota for simultaneous executions (<= 30). Also I would not like to do a sidebar, etc. in the spreadsheet and try to screw eventListener to html. I assume that with this approach, the listener (if it is possible to add it there at all) will be active only when ui is active (the spreadsheet is open and the sidebar is active). Data can come at any time of the day and must be immediately transferred to the addon.

Added: I feel like I'm stumped. Therefore I reaches out to the community in the hope that someone would suggest a workaround or a new strategy for this initial data. By initial data I mean provide the opportunity for more than 30 users to exchange messages in both directions Spreadsheet <--> External service (for example, Telegram) and at the same time not fall under the limit of 30 simultaneous script executions.

Added_2: I'm going to assign a bounty, so I'm transferring here from the comments what is missing in the post and updating the question itself.

I rejected the option with immediate entry into the sheet, because this will cause constant calls to the spreadsheet and slow down the performance of the system as a whole.

I am aware of the existence of Google cloud functions and Google compute engine, but would like to stay within the free quotas.

QUESTION: How to transfer data from webapp to addon and execute func () or which workaround to use to achieve the goals?

Boris Baublys
  • 952
  • 10
  • 22
  • What is the purpose of you do post in the addon? – Cooper Oct 31 '21 at 20:18
  • *I would not want to deploy webapp from my account* So deploy to execute as "user accessing" – TheMaster Oct 31 '21 at 20:32
  • @Cooper I plan to process these messages and enter them into the spreadsheet. – Boris Baublys Oct 31 '21 at 20:55
  • @TheMaster Do you mean "Who has access: Anyone with Google account"? The fact is that the sender of the request may not be a person with a Google account, but a service. – Boris Baublys Oct 31 '21 at 21:00
  • I don't get how you would avoid simultaneous executions(hereafter, se), when webapp#1 is set to Execute as "me", then wouldn't se limit of 30 apply to webapp#1 first? – TheMaster Oct 31 '21 at 21:03
  • 1
    @TheMaster "The user ... deploys the script (Project_1) as a webapp with permissions:" Execute as: Me, Who has access: Anyone "". The user will spend not mine but his quota. – Boris Baublys Oct 31 '21 at 21:10
  • @TheMaster [Add-on & Web Apps: Limitations and Who Has Access - Only Me vs Anyone With a Google Account](https://stackoverflow.com/questions/69686615/add-on-web-apps-limitations-and-who-has-access-only-me-vs-anyone-with-a-goo) – Boris Baublys Oct 31 '21 at 21:14
  • I have edited points 1 and 2 for clarity. Added about webapp and addon owners. – Boris Baublys Oct 31 '21 at 21:56
  • 1
    Google Apps Script Workspace Editor haven't incoming/outgoing end-points to get data from external code, so you will have to rethink your solution. – Rubén Oct 31 '21 at 22:21
  • @Rubén Yes I also feel like I'm stumped. Therefore I reached out to the community in the hope that someone would suggest a workaround or a new strategy for this initial data. By initial data I mean provide the opportunity for more than 30 users to exchange messages in both directions Spreadsheet <--> External service (for example, Telegram) and at the same time not fall under the limit of 30 simultaneous script executions. – Boris Baublys Oct 31 '21 at 22:33
  • 2
    Please update the question accordingly. P.S. One possibility among many is to use a spreadsheet as a database to be used as data store by "Code_1" and "Code_2". – Rubén Oct 31 '21 at 22:48
  • Is the Project 2 add-on added to the container of project1? – Cooper Oct 31 '21 at 22:49
  • @Cooper No, Project_2 is a standalone script. – Boris Baublys Nov 01 '21 at 01:06
  • 1
    You could look into external resources like firebase or a database. Then you could poll from webapp#2. Of course if you're willing to live with se of 30, you could always deploy webapp#2 from your addon. Alternatively, `with a Google account, but a service.` Maybe make the service run as the user? – TheMaster Nov 01 '21 at 06:52
  • @TheMaster "Then you could poll from webapp # 2" Sorry, didn't quite get it. is webapp #1? "Maybe make the service run as the user?" I'm not sure, but it seems unlikely. When I do "Me and Everyone" access, everything is OK. If "User and Google acc" - not. – Boris Baublys Nov 01 '21 at 12:43
  • @BorisBaublys 1. About polling, webapp#1 posts to a Google sheet or a external database. Webapp#2, the one deployed from addon, then polls, repeatedly fetches data from a external database, every hour or so. 2. `If "User and Google acc" - not.` Why can't you deploy webapp#1 as user accessing? – TheMaster Nov 01 '21 at 13:30
  • @TheMaster "every hour or so" Look at point 5, please: "Data can come at any time of the day and must be **immediately** transferred to the addon" – Boris Baublys Nov 01 '21 at 14:54
  • @TheMaster "Why can't you deploy webapp#1 as user accessing?" We discussed this [here](https://stackoverflow.com/questions/69686615/add-on-web-apps-limitations-and-who-has-access-only-me-vs-anyone-with-a-goo), please see. "When I choose the permission: "Execut as: User accessing the webapp" I get an alternative: "Who has access: Only myself" or "Who has access: Anyone with Google account", i.e. webapp will be unavailable to services in both cases. – Boris Baublys Nov 01 '21 at 15:07
  • Ok, but do you really expect more than 30 users to ping you **at the same time**? Also, even if that happens, Wouldn't the webapp just fail and wouldn't the bot re-ping after some time? Anyway, I'm out of ideas currently. – TheMaster Nov 01 '21 at 15:47
  • @TheMaster I'm not sure, but I would like to provide protection against this. I think that if such a situation arises, users will not be able to use the bot. It seems to me that this is the normal approach, but perhaps I am wrong. I would be grateful if you would correct me. – Boris Baublys Nov 01 '21 at 16:49
  • If you want realtime "push", you're limited to 30 simultaneous executions, no matter what you try (as long as requests are anonymous). If you want "pull", you can try polling other databases, you can even poll every second, but you'll be limited to a quota of 90min/day. If you want to provide "professional" bot services, I don't think "free" apps script hosting is the way to go. – TheMaster Nov 01 '21 at 18:39
  • @TheMaster "If you want to provide" professional "bot services". To a certain degree. Imagine there are 50 students in the classroom. They send the Start command to the Telegram bot and begin to pass the test. And they immediately fall under the SE limitations <= 30. You may ask: "Why Telegram, when there are Google Forms and so on?" And the teacher will answer: "This is something new, it will add variety." This is just an example. – Boris Baublys Nov 01 '21 at 20:20
  • 1
    It's highly unlikely for 50 users to send a command at exactly the same time. As long as your webapp is fast and executes under 30s or so, I don't think this will be a problem with 50 users. If you're worried, look into professional servers/domains- like Google cloud functions, Google compute engine. – TheMaster Nov 01 '21 at 20:29
  • 1
    Yes, thanks, I have been researching this topic since I came across the post [Can a Google Apps Script Web App be scalable?](https://stackoverflow.com/questions/54909117/can-a-google-apps-script-web-app-be-scalable) and @TheAddonDepot's answer. – Boris Baublys Nov 01 '21 at 21:29
  • 1
    Hi there @BorisBaublys! If you goal is to let users edit a Sheet and then run a script thought it to communicate to third parties (i.e. Telegram), you could do it very easily with [triggers](https://developers.google.com/apps-script/guides/triggers/installable) and Apps Script. Would that be a valid solution for you? – Jacques-Guzel Heron Nov 08 '21 at 07:56
  • The use of triggers was one option that had to be dropped. Suppose that webapp writes data coming from an external service to Properties or to a sheet. Then the addon must somehow catch the moment of changing this data. A timed trigger has a minimum firing frequency of 1 minute. Thus, the minimum time between the bot's question and the user's answer to this question will be at least 1 minute, which is unacceptable. – Boris Baublys Nov 08 '21 at 15:53

3 Answers3

1

I understand that the solutions proposed in the comments, by others and myself, can't work in your scenario because it can't stand an average delay of 30 seconds. In that case I strongly advise you to set up a Cloud project that can be used as an instant server, as opposed to triggers/apps/etc.

Jacques-Guzel Heron
  • 2,480
  • 1
  • 7
  • 16
  • It looks like it. First, the palisade of quotas and limitations will not allow using a trigger that will request external data once every 1-2 seconds. Secondly, the connection with the addon is one-way. It is not possible to transfer data inside. If only it was possible to send the flag to the addon that new data has arrived. Then it was possible to request data from an external source from within the addon. – Boris Baublys Nov 17 '21 at 00:09
  • There was a hope that the collective intelligence would suggest something, but it did not come true. Therefore, only cloud-based functions remain. But as I wrote in the post, I would like to stay within the free quotas. And the point is not that this is a paid service. The point is, I don't understand anything about it. And there are no good manuals. – Boris Baublys Nov 17 '21 at 00:13
1

Here is a list of your requirements:

  • Trigger add-on code to run from some external request, not using the add-on user interface or time based trigger.
  • Code runs from the user's account, using their quota
  • Run the add-on code regardless of whether the user is using the add-on or not. For example, their Google Sheet is closed, and the user may even be signed out.

I only know of one way to do that, and it's with a Sheet's add-on by triggering the "On Change" event by setting a value in a Sheet cell using the Sheets API. The Sheets API must use a special option to set the value "As the User."

The special setting is:

valueInputOption=USER_ENTERED

That option will trigger the "On Change" event even if the Sheet is closed. Obviously the script making the request needs authorization from the user to set a value in a cell of the Sheet. If the script sending the request is outside of the user's account then you'd need to use OAuth. The add-on would need to install an "On Change" trigger for the Sheet and the function that the trigger is bound to would need to determine whether the change was from the special cell designated for this special functionality.

If the request to set a value in the users Sheet is from outside of that users Google account, then the user of the Sheet would need to somehow authorize the OAuth credentials for the Sheets API to make a change to the Sheet.

Depending upon the programming language being used with the Google Sheets API, there may be a Sheets API Library specifically for that language. You can also use the Sheets REST API.

There is an example here on StackOverflow of using the Sheets REST API from Apps Script, but if the external request is from some code that isn't Apps Script, it won't be exactly the same.

Alan Wells
  • 30,746
  • 15
  • 104
  • 152
  • Thanks Alan, this is a very good option. More precisely, he is the only one today. Perhaps in the future it will be possible to pass data or at least a tag to the add-in without tricks. I checked it works in an container-bound script which combines web app code and add-on code. To check exactly as in the title of the post, I can not. Unfortunately [Installable triggers aren't supported when testing](https://developers.google.com/apps-script/add-ons/how-tos/testing-editor-addons#testing_details). I hope when the add-in passes the test, the effectiveness of the method will be confirmed. – Boris Baublys Apr 27 '22 at 00:22
  • Do I understand correctly that the addon user does not need to enable the Sheet API if it is specified in the addon manifest? "dependencies": {"enabledAdvancedServices": [{"userSymbol": "Sheets", "serviceId": "sheets", "version":"v4"}]} – Boris Baublys Apr 27 '22 at 14:01
  • I never use the testing feature in the Apps Script code editor for the add-on, partly because of the problem with testing triggers. I do all development for an add-on in a bound script to the document (Form, Sheet, Doc) and then transfer all the code from the bound file to a stand alone file. – Alan Wells Apr 27 '22 at 18:10
  • 1
    Concerning the Sheets API. You need to associate the stand alone Apps Script file with a Google Cloud Project. That must be done in order to publish the add-on, but also to enable API's. So, you need to do more than just set the dependency in the manifest file. The user who installs the add-on doesn't need to enable any API. Google doesn't explain how that works, but because YOU enabled the API in YOUR GCP project, it somehow works for the user. – Alan Wells Apr 27 '22 at 18:17
  • The container-bound script has been tested, everything is OK there. However when the script is divided into 2 parts - add-on and webapp - there is a problem. To publish the addon, I need "A YouTube video showing how you plan to use the Google user data you get from scopes". How to show data usage on video if installed onChange() doesn't work? And its NOTwork is regulated by the [documentation](https://developers.google.com/apps-script/add-ons/how-tos/testing-editor-addons#testing_details). – Boris Baublys Apr 27 '22 at 20:58
  • 1
    I've had serious problems creating the YouTube video for the add-on review. I was able to overcome those problems, but it's not easy. When I recorded the video, I did some of the recording from my "dev" version which uses the bound Apps Script file, and then recorded another part of the video from a different Google account. How the people at Google test the add-on, I'm not sure. They should have a way of testing it that can install the triggers. When the YouTube video shows the authorization dialog box, you need to be using the Apps Script file from which the real add-on will be published. – Alan Wells Apr 28 '22 at 01:03
  • 1
    The reason you need to use the Apps Script file from which the add-on will be published for the authorization dialog, is that there is an ID number in the address bar at the top, that the reviewers must verify is coming from your account. I'm guessing that this requirement is for legal purposes so that Google can cover themselves legally. But other than showing that ID number in the authorization dialog, the rest of the video content could come from another Apps Script file. Plus I didn't want to show the email address of my development account in the video, so I used a different account. – Alan Wells Apr 28 '22 at 01:12
  • During the "Test as addon" when trying to set onMyChange() from the custom menu, I get the same exception as a [year ago](https://stackoverflow.com/questions/34820967/onedite-not-working-in-add-on#comment116720669_34822268). In my opinion "an action" is too vague. Is the reason for the exception in an attempt to install and test the install trigger or in something else? There is no clarity. – Boris Baublys Apr 29 '22 at 09:56
  • 1
    If the error was caused by something other than the restriction of "Test as addon" not allowing installation of triggers, it would have stated something else. So, by the logic of excluding what is not probable, I believe the error is caused by that restriction. I never use the "Test as add-on" feature from the code editor. Without triggers, the add-on is useless, and we need to test the triggers. If your add-on has a lot of code, then copying the "dev" version code over to your "production" version could be a lot of work. So I have a special program to do that. – Alan Wells Apr 29 '22 at 13:57
  • I wonder what kind of program it is. Can you please share it? Maybe that can help me. – Boris Baublys Apr 29 '22 at 17:46
  • I created an Apps Script Web App that uses the Apps Script API to copy the bound "dev" Apps Script file to the stand alone "production" Apps Script file. I was going to publish it to the public, but it's a lot of work. Some people use the Chrome extension [GitHub Assistant](https://chrome.google.com/webstore/detail/google-apps-script-github/lfjcgcmkmjjlieihflfhjopckgpelofo?hl=en) – Alan Wells Apr 30 '22 at 13:59
  • Happy news! The add-on is published, works great. Thanks for your valuable help, Alan. I accepted your answer. It is a pity that you did not see my post when I announced the bounty. – Boris Baublys May 04 '22 at 20:40
0

In "Code_1" and "Code_2" use a shared data store. In other words, instead of directly passing the data from "Code_1" to "Code_2", make that Code_1 write to the datastore and "Code_2" read from it.

One possibility among many is to use a spreadsheet as a database. In this case you might use on change triggers to do some action when the spreadsheet is changed by one of the "Code_1" scripts and/or use time-driven triggers to do some action with certain frequency or at certain datetime.

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • Yes, now Project_1 and Project_2 share PropertyService. But I fear that there will be a limitation for the addon (Project_2) "Properties read / write 50,000 / day". And I couldn't think of how to get Project_2 to respond to a property change. That's why I wrote about EventListener and scripts.run. It didn't occur to me to use onChange, because I thought it only fires when changed by the user and not by the script. – Boris Baublys Nov 01 '21 at 02:27
  • In the first version of the project, the scripts Project_1 and Project_2 is combined. When testing, it in many parts of the code, outputs were installed into a custom logger with a record on a sheet. At the same time, some users noted lags between sending a message to the bot and its response message up to 10 seconds. After I removed all logging the delays do not exceed 1 second. Therefore, I rejected the option with immediate entry into the sheet, because this will cause constant accesses to the spreadsheet and slow down the performance of the system as a whole. – Boris Baublys Nov 01 '21 at 02:30
  • Similar concerns arise with the use of a timing trigger. Perhaps I can put a minimum delay (1 second? I didn't see the minimum number anywhere) between trigger firing. I have never used a trigger with such a timing. Therefore I do not know how correctly the project as a whole will work with such a trigger. And how will Google servers feel if thousands of scripts are hammered into them every second =) In addition, there is a high probability of running into the "Triggers total runtime 90 min / day" limit. – Boris Baublys Nov 01 '21 at 02:31
  • Google Apps Script projects can't share "PropertiesService". Anyway, it looks that you have you multiple follow-up questions. Choose one, and post it as a new question. – Rubén Nov 01 '21 at 02:42
  • I am constantly struggling with the language barrier, it is difficult for me to accurately express my thoughts. Please advise what to highlight in a new question. – Boris Baublys Nov 01 '21 at 02:49
  • 2
    Maybe you should go several steps back and think about what lead to make a solution that require the users to publish a web-app instead of asking them to use the same web app. – Rubén Nov 01 '21 at 03:42
  • "require the users to publish a web-app instead of asking them" If I understand correctly, you mean to force users to deploy a webapp? Sorry, what does it do? – Boris Baublys Nov 01 '21 at 12:51
  • Yes, IMHO you have to think about what leads you to create a spreadsheet template and ask users to deploy a web-app from it. Apparently your solution is based on a misunderstanding about how Google Apps Script web-app deployment works and the alternatives to handle their limitations (your previous [question](https://stackoverflow.com/q/69686615/1595451) needs more focus and is unclear) – Rubén Nov 01 '21 at 17:25
  • "what leads you to create a spreadsheet template" This is for the convenience of users. So they can flexibly change the structure. It is less convenient via prompts or sidebar. || "users to deploy a web-app from it" So we get out of the limitations of 30 simultaneous executions. || "your previous question ... is unclear" Thanks, I will try to improve the previous question so that someone can answer it. Would you like to comment on my previous post indicating what needs to be fixed? – Boris Baublys Nov 01 '21 at 20:44
  • 1
    Besides what was already said by Tanaike and Master I think that the last statement does a big jump by mentioning add-on as all the previos question development was only about web-app. May suggestion is to center on understanding how a the web-app deployment options works. – Rubén Nov 01 '21 at 21:21