How to send Whatsapp message using MessageBird from Firebase cloud function? - google-cloud-functions

I have installed MessageBird Firebase Extension.
I want to send Whatsapp template(template has Button with website link) message from Firebase Cloud Functions.
To send a Whatsapp message, I need to create a document in Firebase 'messages' collection, so that MessageBird extension processes it.
What should be the format of Firebase document to send Whatsapp message? I have attached the Whatsapp template
I have tried creating Firebase document similar to this API request format - https://developers.messagebird.com/quickstarts/whatsapp/send-message-with-buttons/, but I got delivery error 'Error: api error(s): JSON is not a valid format (code: 21)'.
Thank you.

You are right, you need to put a document with content into Firestore message collection that is accepted by ConversationsAPI, and then the message should be sent and the document should be updated with delivery details (response from MessageBird Conversations API).
This is example of the document that you will need to put to be able to send WA template message:
db.collection('YOUR_DOCUMENT_COLLECTION').add({
channelId: 'YOUR_CHANNEL_ID',
type: 'hsm',
content: {
hsm: {
namespace: 'YOUR_WA_ACCOUNT_NAMESPACE_ID',
templateName: 'YOUR_WA_TEMPLATE_NAME',
params: [{ default: 'YOU_PARAM_VALUE' }],
language: { code: 'en_US', policy: 'deterministic' }
}
},
to: 'RECIPIENT_OF_THE_MESSAGE',
});
You can find more details about HSM object and what each field means here: https://developers.messagebird.com/api/conversations/#messagehsm-object
I hope that helps.

Related

Application/Json error when sending Gmail with Postman

I'm trying to send a Gmail with Postman but got this error:
These are my configured headers:
I have configured everything needed on Google Cloud engine (Oauth permissions, certifications...etc), read similar posts, and also tried testing from gmail API playground and everything was ok:
Any idea of what could be wrong?
Remove all custome headers , (Create a new request by following below steps)
Steps:
https://console.developers.google.com/ Goto url and create an API. (by clicking credentials>create credentials)
https://console.developers.google.com/apis/api/gmail.googleapis.com/overview Goto url, click credentials> create new 0auth0.2 ( select applicaiton type as Web application)
While creating 0auth0.2 scroll down and set Authorized redirect URIs as https://localhost
CLick the download as json and then save the auth
Open postman and set authorization as 0auth2.0 from authorization header:
Generate new token by filling the content as per the downloaded json ( open the json and fill postman as in json)
set scope and state as : https://mail.google.com/ ( full access ) see scope at : https://developers.google.com/gmail/api/auth/scopes
In postman Set url as :https://gmail.googleapis.com/gmail/v1/users/praveendvd0pravu%40gmail.com/messages/send?key={YOURAPI_KEY_That_was_generated}
goto https://www.base64encode.org/ , and paste below content and click encode. Copy the output.
From: youremail#gmail.com
To: tosomeemail#gmail.com
Subject: Hi
Hi this is
9): paste it as json body
{
"raw":"IEZyb206IHlvdXJlbWFpbEBnbWFpbC5jb20KIFRvOiB0b3NvbWVlbWFpbEBnbWFpbC5jb20KIFN1YmplY3Q6IEhpICAKICAgIApIaSB0aGlzIGlzIA=="
}
Send it :

Configure microsoft teams incoming webhook json payload

I am trying to set up an incoming webhook to a Microsoft teams channel using the incoming webhook connector.
The payload that I am trying to send from my platform looks like this and is form CleverTap (which is failing so I'm trying to debug it using postman). but I am getting the error Summary or Text is required.
{
"profiles": [
{
"email": "jack#gmail.com",
"identity": "foo",
"objectId": "-g55b74fb1030740e4a4931910a8abb862",
"profileData": {
"Last Score": 308,
"High Score": 308,
"Replayed": true
},
"name": "Jack"
}
]
}
What am I doing wrong?
will I need to change the JSON payload according to the adaptive card syntax for teams to accept the incoming webhook? If so, where can I add my custom payload in the adaptive card JSON body?
are there other authentication factors at the webhook endpoint (do I have to whitelist the ip address from where the POST message is being sent from)?
To send a message using incoming webhook, you must post a JSON payload to the webhook URL. This payload should be in the form of O365 Connector card. Payload of any other format is not acceptable in Teams. Here is an Example Connector card that you can post. You can now also send an Adaptive card using incoming webhook. Please check the docs here.

"Invalid argument" when sending GET to spaces.members.list

I'm trying to create a Google Hangouts Chat chatbot (in G Suite) using Apps Script. I want to get a list of everyone in the chatroom, but this isn't directly supported in Apps Scripts yet, so I'm using the rest API. The API call list seems straightforward:
The command is
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
I've created a service account for authorization and then used
var endpoint = 'https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxx"}/members'
var options = {
method: "GET",
contentType : "application/json" ,
muteHttpExceptions : true,
headers: {
"Authorization": "Bearer " + goa.getToken(),
}
};
var response = UrlFetchApp.fetch(endpoint, options)`
To which I get
Invalid argument: https://chat.googleapis.com/v1/{parent="spaces/pQkgxxxxxxxx"}/members
I've tried encoding the parent parameter, but the error persists. Any ideas?
Per official documentation on the page you linked, the expected format of the path parameter parent is of the form spaces/*. The example value given is spaces/AAAAMpdlehY
In other words, you are not expected to write the {parents= and } bits, even though the template URL
GET https://chat.googleapis.com/v1/{parent=spaces/*}/members
has them. This template url format is explained in-depth on the Google API HTTP annotation website.
In your example, the correct URI to GET is https://chat.googleapis.com/v1/spaces/pQkgxxxxxxx/members
You should also consider that it may take multiple calls to resolve all members of the space pQkgxxxxxxx, by checking for a nextPageToken in the response (and passing that as the URL parameter pageToken in the next call).
You should also consider that the MemberShip returned by this query may include members with various states of membership.

How do i allow a CORS requests in my google script?

I want to post my contact form to my google script that will send an e-mail to me. I use the following code:
var TO_ADDRESS = "example#gmail.com"; // where to send form data
function doPost(e) {
var callback = e.parameter.callback;
try {
Logger.log(e); // the Google Script version of console.log
MailApp.sendEmail(TO_ADDRESS, "Contact Form Submitted",
JSON.stringify(e.parameters));
// return json success results
return ContentService
.createTextOutput(callback+
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(callback+JSON.stringify({"result":"error",
"error": e}))
.setMimeType(ContentService.MimeType.JSON);
}
}
When i try to post to the google script url, i get the following error:
Access to XMLHttpRequest at
'https://script.google.com/macros/s/~~myscriptid~~/exec' from origin
'http://localhost:4200' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I have no clue how to add the CORS-filter to my google script.
I know the script is working i have tested it with this plugin:
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
Late answer, but totally working...
To pass data from appscripts to another website, just use mime type JAVASCRIPT on appscripts side, like so:
doGet(e){
return ContentService
.createTextOutput(e.parameter.callback + "(" + JSON.stringify(YOUR OBJECT DATA HERE)+ ")")
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
And on the front end access it as:
<script>
var url = "https://script.google.com/macros/s/AKfy*****ACeR/exec?callback=loadData";
// Make an AJAX call to Google Script
jQuery.ajax({
crossDomain: true,
url: url,
method: "GET",
dataType: "jsonp"
});
// log the returned data
function loadData(e) {
console.log(e);
}
</script>
This works without any CROB/ CROS headache
After a lot of hard work, the only solution which worked for me:
In Google Apps Script
function doPost(e) {
return ContentService.createTextOutput(JSON.stringify({status: "success", "data": "my-data"})).setMimeType(ContentService.MimeType.JSON);
}
In JavaScript
fetch(URL, {
redirect: "follow",
method: "POST",
body: JSON.stringify(DATA),
headers: {
"Content-Type": "text/plain;charset=utf-8",
},
})
Note the attribute redirect: "follow" that is very important;
Quick answer
You (frontend developer) can't fix cors error from remote server. Only the owner of the remote server (google app script server) could do it.
Workaround 1 (GET)
Use only GET method in app script. Get method will not throw CORS errors, no matter where you consume it from: csr, spa, frontend, react, angular, vue, jquery, pure javascript, etc
Workaround 2 (Backend)
If you are in the backend server (java, php, c#, node, ruby, curl, etc) not in the frontend (browser, react, angular, vue), you could consume any method published on google apps script.
CORS don't affect when the consumption is at the backend layer
So if only use get endpoints are not an option for you, you could use another server language (java, nodejs, php, etc) to consume the Post google app script, and return that information to your web
Explanation
Let's imagine this script with 02 methods deployed as web in google app script
function doGet(e) {
var response = {
"code": 200,
"message": "I'm the get"
};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
var response = {
"code": 200,
"message": "I'm the post"
};
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
and url like this after the deployment:
https://script.google.com/a/utec.edu.pe/macros/s/AKfy\*\*\*\*\*\*eo/exec
In the backend
You could consume the POST and GET methods without any problems with any language: java, nodejs, python, php, c#, go , etc and/or with any http client like postman, insomnia, soapui, curl, etc
In the frontend (js in the browser)
I was not able to consume the POST method. I tried with jsonp and other crazy attempts and the error was the same:
Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at
https://script.google.com/a/utec.edu.pe/macros/s/AKfy***A4B***eo/exec?foo=bar
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
So for any reason, the google server don't allow us to use POST operations from javascript side (2021)
In the frontend : GET Method
Only GET method worked for me. I will assume that google configuration at server layer has some CORS permission only for GET method.
The following ways worked for me, from a simple js to an advanced frameworks like react, vue or angular:
axios
const axios = require('axios');
axios.get('https://script.google.com/a/acme.org/macros/s/AKfy***A4B***eo/exec').then(resp => {
console.log(resp.data);
});
$.getJSON
$.getJSON('https://script.google.com/a/acme.org/macros/s/AKfy***A4B***eo/exec?foo=bar', function(result) {
console.log(result);
});
XMLHttpRequest
var xmlhttp = new XMLHttpRequest();
var theUrl = "https://script.google.com/a/acme.org/macros/s/AKfy***A4B***eo/exec?foo=bar";
xmlhttp.open("GET", theUrl);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send();
CORS : Cross-origin resource sharing
A lot of developers don't understand what is CORS. It is not easy to understand. Commonly the developer fix the error at the server layer and don't invest time (or don't let him) to understand what CORS is:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
https://portswigger.net/web-security/cors
https://youtu.be/4KHiSt0oLJ0
If you don't have time, check my definition, extreme summary bordering on wrong:
CORS is a protection offered by trusted browsers to avoid that a web acme.com can load in the background(ajax/js) an http resource from another domain like hacker-api.com/foo/bar
But if acme.com and hacker-api.com/foo/bar are developed by you and/or hacker-api.com/foo/bar is designed to be consumed by any web of the world, you could fix it at server layer
How to fix CORS errors?
Are very common and simple to control with a few lines in the server if the server belongs to us, but since we don't have control over the server(google), we can not do anything at this layer.
Here some samples of CORS configuration to allow consumption from webs is the backend server belongs to you:
java sample:
//only http://acme.com could consume my api
#CrossOrigin("http://acme.com")
#RequestMapping(method = RequestMethod.GET, "/{id}")
public Account retrieve(#PathVariable Long id)
nodejs sample:
//only http://localhost:8080 could consume my api
var corsOptions = {
origin: 'http://localhost:8080',
optionsSuccessStatus: 200 // For legacy browser support
}
app.use(cors(corsOptions));
//any web could consume my api
origin : "*"
I ran into the same issue while trying to create an application that logs data and retrieves log sections to/from a google sheet through Google Apps Script using Get and Post requests.
I did find a solution that may or may not be helpful to some people.
From the Google Docs:
There are two types of CORS requests: simple and preflighted. A simple
request can be initiated directly. A preflighted request must send a
preliminary, "preflight" request to the server to get permission
before the primary request can proceed. A request is preflighted if
any of the following circumstances are true:
It uses methods other than GET, HEAD or POST. It uses the POST method
with a Content-Type other than text/plain,
application/x-www-form-urlencoded, or multipart/form-data. It sets
custom headers. For example, X-PINGOTHER.
All I did was change the content type of my Get and Post requests
var request = new window.XMLHttpRequest();
request.open(opts.method, opts.url, true);
request.setRequestHeader("Content-Type", "text/plain");
And within the google script, parse to JSON to be used
function doPost(e) {
const d = JSON.parse(e);
...
As far as I understood you have application to be run on custom domain. And it should access script on google cloud.
The bad news: there are no way to skip CORS check on your application side(until request is simple that I believe is not your case).
You should specify Access-Control-Allow-Origin on Google Cloud side:
Cloud Storage allows you to set CORS configuration at the bucket level only. You can set the CORS configuration for a bucket using the gsutil command-line tool, the XML API, or the JSON API. For more information about setting CORS configuration on a bucket, see Configuring Cross-Origin Resource Sharing (CORS). For more information about CORS configuration elements, see Set Bucket CORS.
You can use either of the following XML API request URLs to obtain a response from Cloud Storage that contains the CORS headers:
storage.googleapis.com/[BUCKET_NAME]
[BUCKET_NAME].storage.googleapis.com
If this does not help for any reason you will need to get your own server working as a proxy:
your client application <-> your backend that returns Access-Control-Allow-Origin <-> google cloud
Well after several attempts, I was able to send the data through a web app form in angular 8.
The solution is simple, within "HttpClient.post" you can enter a third parameter to establish an HTTP connection header this for "https://script.google.com" may not be correct and will end with an http connection failed by CORS security.
Just don't add the HTTP connection header as the third parameter of HttpClient.post
const object = {
title: 'Prices',
phone: '999999999',
full_name: 'Jerson Antonio',
email: 'test#example.com',
message: 'Hello, .......'
};
return this.http.post(this.API_REST_FORM, JSON.stringify(object));
In App script always use New deployment to deploy the script.
Otherwise it will use old script and you will get CORS error
The CORS error is most probably caused by a fatal error in your Google Apps Web App script. In this case the Google error handling system displays a human-readable HTML page that does not contain CORS headers.
In my case I got the following error page:

How to GET Recent Status Updates on Facebook Page Using Facebook Graph Search API?

Similar to Getting Recent Page feeds? Facebook Graph API / FQL and Getting Facebook Status updates with JSon I would like to do a GET request using Facebook's Graph API, and insert that data into a page. Using the search API, I am able to retrieve information about the page like locale, description, and website, but there is no status update/post update included in the resulting JSON.
How can I retrieve the latest status updates/posts from a given page using Facebook's public Graph API?
It turns out it is possible to do this, but you need to generate an access token (for the page). To do this, you will need to have admin rights to the page in question. So for me, I had to request from that the page make me an admin (point them to the "Manage Admin Roles" dropdown on the page).
Next, you will need to generate an access token. Go here Facebook API Browser, and click on the "GET Access Token" button the right. Select the manage_pages role only.
The final URL should look something like this: https://graph.facebook.com/{page_id}/statuses?access_token=BAACEdE...
Here is the javascript function I used to test my URL (you could also just navigate there on your browser):
function populateFacebookUpdates() {
var pageID = "mycompanypage",
accessToken = "BAACEdE...";
var postsURL = "https://graph.facebook.com/" + pageID + "/statuses?access_token=" + accessToken;
$.ajax({
url: postsURL,
method: 'GET',
dataType: "jsonp",
success: function (data)
{
console.log("Successfully retrieved Facebook data");
console.dir(data);
},
error: function(status) {
console.log("Facebook data could not be retrieved. Failed with a status of " + status);
}
});
}
The data returned in JSON was what I wanted. Also, note that the retrieval would work on any browser/machine/IP (it does expire, however). I would just caution against putting the entire URL inside a client-side javascript file for obvious security reasons...
Status's is a connection and not a field as per the documentation. As far as I know only field information can be retrieved via the search API. If you want statuses you'll have to get the page Id from your search and then query for that pages statuses using the call below.
https://graph.facebook.com/{pageID}/statuses