GAS-built telegram bot: catching replies to bot - google-apps-script

I wrote an bot on GAS to read from / write to a google sheet from telegram. I use the webhook method. I can address the bot with /read <args> and /write <args>. However, the less tech-savvy are not able to understand the principle of arguments...
So I want to make a conversational bot, like botfather. eg, if /read or /write are sent, then the bot ask in pm for the arguments, one by one.
The "reply in PM" part is easy, but I don't see how I can catch replies for arguments?
As far as I understand, the function doPost is called each time a command is sent to the bot which poses issues of interactivity, and requiring a slash-something command to run the script instead of a plain text reply (and as the GAS data is volatile, the ugly work-around of storing a variable to know the bot should do the 2nd action is impossible too).
Is it feasible with webhook method?
Should I switch to polling / getUpdates method? I'm guessing it could work that way, with a time-out to exit the script in case of no reply, but I'm also guessing the PM chat should be set to 'no privacy' mode. or maybe it is intrinsic to the bot?
Any help appreciated!

So, GAS does offer a not-so volatile storage: CacheService.getScriptCache() (see also https://developers.google.com/apps-script/reference/cache/cache)
The principle is simple: store the variable you want persistent in the cache (optionally, set a time out too - the default is 10min), and get the values when the script is called again. I found out that project that helped me understand how to use it: https://github.com/Milleus/tessara/blob/master/Code.gs
In a few words: the syntax is cache.put(key, value) to store the value, and value=cache.get(key) to fetch it back.
The beauty of it is that all required variables (if more than one) can be stored in an object, the key can be a unique identifier for the "user", and the value is the stringified object.
In my case, I was able to build a fully conversational telegram bot (exactly like BotFather, but for my usage). Using the id from the person sending messages to the bot as the key, the script can run in "parallel" for multiple users at once.

The doGet and doPost are the functions that get called when you follow a web app url. You can use them as an api if you use something like UrlFetchApp to access them or even an Http Request if you can handle the oauth.

Related

can i set up a google sheet to receive data from an external webhook/PUSH API

i'm keen to understand if i can use a google sheet / script to receive incoming data from an external (3rd party / non google) webhook.
the webhook requirements:
a defined / expected method from POST (my preferred), PUT, PATCH
an endpoint to post to which, if this is possible, i assume would be something like https://docs.google.com/spreadsheets/d/[sheet_id]/[service_name] or even https://script.google.com/d/[project_id]/[service_name] where ScriptApp can perform handling of the data
method of authentication; the current options available from the sending system are "none" or "oauth"
incoming content; the body is a simple { "id": integer }
oauth inputs include authentication_url, azure_subscription_key, app_key, app_secret, resource_id.
hopefully this is enough information to determine if this is possible. if not then please comment with questions and i'll do my best to answer them. thanks in advance :)
Short answer: Yes, for the most part.
Explanation -
...receive incoming data from an external (3rd party / non google) webhook.
Google Apps Script (GAS) provides a format called as Web Apps where, you write a script to handle incoming requests and "deploy" the Apps Script itself as a web app. In doing so, GAS provides you with it's own endpoint.
Adding this as a point of clarification where the endpoint/URL would not be that of a 3rd party, but that of GAS itself, which will need to be used in a 3rd party's application where they require you to provide an endpoint :)
You only have GET & POST requests (as of now) that can be handled by Apps Script's Web App and not the others that you've stated.
The non-dev, prod-ready link would look something like this - https://script.google.com/macros/s/Unique-Script-ID-Goes-Here/exec
The available auth/permission settings are described here.
The request parameters also describes the format of data that can be processed by the Web App.
Hope this helps but please feel free to ask for any clarifications too, as required.

How to use OAuth 2.0 with a Google Apps Script library, with a static redirect URL?

I can't figure out how to make a shared Google Apps Script library, that uses OAuth 2.0.
The problem is that the usercallback redirect URL changes, every time I use the library in a different script. However, that means I'd need to add a new app and whitelisted redirect URL to Asana for each spreadsheet I use the script in. I'm using https://github.com/googlesamples/apps-script-oauth2.
Is there a way to always authenticate with the same redirect URL, so that the library I make can be used from any script, without registering a new redirect URL in Asana?
I'm a Developer Advocate here at Asana. If I understand your question correctly, then yes, you'll have to handle the callback separately for each script. For security reasons, we validate that the OAuth app registration registers the same url as an integration actually requests when authenticating. If this weren't true, for instance, it'd be possible to create a malicious script that uses the client_id from a legitimate script but asks for the redirect to go to its own credential-grabbing endpoint. This is fixed if the app that got the client_id on app registration also specifies precisely which endpoint should be the legal endpoint to redirect to. That means each OAuth app needs to have its own unique and consistent redirect URL :(
I suppose you could possibly create a single "router" Google Apps script which would set the state parameter with some user/script pair when hitting Asana's oauth_authorize endpoint and forward the user credentials on to the script that exists behind the router script based on that user/script pair when the response comes back, but it's not super trivial.
One final option would be to use a Personal Access Token to access Asana's API. This one token can be used by an unlimited number of scripts for access. The downside is that this token "looks like you", that is, it takes action on behalf of not a third party user but you yourself - your scripts would be an automated version of the user whose Personal Access Token they use. This can be mitigated to some extent by creating a "bot account" to access our API and giving it access inside of Asana to the projects or teams you want to gather data on. The other downside to this approach is that every script that uses the personal access token will break if you ever revoke the one token, so if that ever happens by either intent or accident, you'll have to update the Personal Access Token information in every script that uses it.
Hopefully this helps you to evaluate the options and choose which one of these options works best for your script.

“Pushing” Gmail to GAS — using Gmail forwarding to trigger GAS script

Summary
Is it possible to use the Gmail forwarding feature to send (i.e., “push”) via HTTP (GET/POST) to my GAS script URL? (And perhaps include its contents as a parameter?)
Goal/Background
My goal is to immediately process my incoming Gmail instead of, say, using the GAS trigger feature to query and “pull” my Gmail on a periodic basis.
The former method is relatively immediate. Whereas, the latter method creates an expected delay equal to the mean interval time between (automatically triggered) queries to my inbox.
Possible Solutions
1. Gmail Data API
This documentation states Gmail lacks a data API.
2. Atom/RSS Feeds
Atom/RSS feeds still require an aggregator to pull the data from the server and, thus, do not accomplish my goal of a push-only solution to my GAS URL to, then, in turn, trigger my script via doGet() or doPost().
3. IMAP/POP
These solutions are designed for desktop/offline processing of emails and, therefore, do not meet my goals. I need a solution that lives on the web and automates my web-based email checking tasks.
4. High-frequency GAS Trigger
A, say, 60-second trigger interval in GAS does not work because there is a cost to such high-frequency triggers in GAS due to quota limitations. i.e., I don't want to use up that much quota space on this one task because I need it for other stuff.
5. 3rd Party Listeners
I would prefer something free if possible. Someone has suggested Zapier® — which does have a free version. Do these work? Are there others?
Conclusion
Are there any creative ideas out there? Perhaps to point me in a creative direction?
I would even settle for just a way to be immediately notified (programmatically) that I received a new email.
Not possible from Google Apps Script:
Google Apps Script currently available events:
https://developers.google.com/apps-script/understanding_events
Does Gmail have a Data API?
FAQ: https://developers.google.com/gdata/faq#GmailAtomFeed
Looks like IMAP is the only option, not sure if IMAP supports callback.
A trigger can kick off a script every 60 seconds. As you stated before, this puts your average notification at 30 seconds (let's not get started on possible flaws in statistical assumptions).
Another possibility for a more immediate action is to use a service like Zapier.com as a listener. It can listen for new emails in your gmail inbox, apply filters, and initiate a GET/POST to the URL for your Apps Script (make sure it is the newest version published).
I hope this helps. Curious why you need immediate handling of the messages ...

How do I insert/update data into offsite databases that don't have an API available?

I'm trying to figure out how to insert/update data into offsite databases that don't have an API available. Since they don't have an API, I thought of an approach I can take to insert/update data into their database.
They would first need to build a script and place it in an accessible location on their webserver that I can access via a URL. They would be required to supply the URL to me. I then can do a cURL POST request to that URL and pass a JSON array of the data that needs to be inserted. The script on their server would handle the parsing of the JSON array and the insert/update into the database.
I think this should work, but what security issues would I be opening them up to?
What you described is them creating an API. Just because the url invokes a script and isn't written in something like Java or PhP doesn't mean its not an api.
You need to make sure your url is secure so only authorized people can invoke it, and they would probably want to do data validation.
You should let them decide whether that is easier than standing up a more robust/non-script based solution

How to invoke the application Using Mysql Command

I am writing a trigger, in which i need to invoke the external application using the MySQL
Looking a your comment, the response is obvious.
Write a program in whichever language you dominate the best. That program needs to
Read all email addresses
Iterate on the list
Send a mail in every iteration
If you promise not to use it for sending spam, I can give you a basic PHP script to do that
I would suggest having the external application request the list of users, and then looping through the list and sending the email. There's no real reason to mix the two.