How to use Smooch postbacks? - smooch

I can't seem to find any documentation on how to actually use the postabck feature. Does it call functions on the server? What does ti do with the pasees value?
%[Button label here](postback:PAYLOAD_HERE) // What is the payload?

The payload is actually whatever you want!
Postback buttons can be used as triggers to your webhook. When a user taps on your postback button, a payload will be sent to your webhook with the following data:
{
"trigger": "postback",
"postbacks":[{
...
"action": {
"_id": "571530ee4fae94c32b78b170",
"type": "postback",
"text": "Read more",
"payload": "YOUR_PAYLOAD_HERE" // <---- your payload!
}
}],
...
}
For complete payload see this reference: http://docs.smooch.io/rest/#webhooks-payload
On your side, you could have automated messages, event scheduling or anything you want.
A simple payload could be TELL_ME_JOKE and on your backend, you could fetch your database for a joke, then send a message through the Smooch API to reply back.
Another payload could be RESERVE_MONDAY. When the user taps that button, your webhook receives RESERVE_MONDAY. Then you could use that value to know what to do next (call into your application to reserve that time slot).
Here's a simple Node.js implementation:
const express = require('express');
const SmoochCore = require('smooch-core');
const smoochApi = new SmoochCore({
keyId: 'some-key',
secret: 'some-secret',
scope: 'app'
});
express.Router().post('/smooch/webhooks', (req, res) => {
const smoochPayload = req.body.postbacks[0].action.payload;
const userId = req.body.appUser._id;
if (smoochPayload === 'TELL_ME_JOKE') {
smoochApi.conversations.sendMessage(userId, {
text: 'A cow walks into a bar...',
role: 'appMaker'
});
} else if (smoochPayload === 'RESERVE_MONDAY') {
CalendarController.reserve(userId, 'monday');
}
res.end();
});
Using the payload also allows you to use different button labels, but keep the same payload (ie. different translations).
Note: it could be anything even JSON if you want!
I hope this can help you!

The payload is what you want your bot to return. I'm not sure if my way of describing it is the best since I'm new at this. Think of it this way - If you have a button labeled %[Yes](postback:YES), then when the user clicks on the button that says yes, it will be just like they typed the word "yes."

Related

How do you properly call a conditional based on the intent's displayName for dialogflow?

I am trying to do webhook fulfillment for my dialogflow agent. However there are four specific intents that should all have different JSON responses based on what specific intent is called. Right now I am creating a switch case based on the called intent's displayName. However that is not working. Should I be using a different parameter to check what intent is called other than displayName?
HERE IS MY CODE THAT ONLY OUTPUTS "test"
server.post("/get-bill-details", function(req, res) {
let intentName = req.body.queryResult.intent.displayName;
let ret = "test";
if(intentName == "1 - Bill"){
ret = "your billing amount is $120.";
}
return res.json({
fulfillmentText: ret,
source: "get-bill-details"
});
});
I would suggest you use client libraries as they will ease out the process of parsing the JSON and reduce your development time. You can use NodeJS or Python clients for Dialogflow. Also, if you need Google Assistant, you can also use following NodeJS library to build webhook. They all have documentation on how to build webhooks on cloud or by using Express and other frameworks.
Instead of matching with intent name give your intent an action name( try not to give any spaces e.g input.welcome ).
Then get the action parameter using
let action = req.body.queryResult.action;
switch(action) {
your logic..
}
Also as abhinav said you can use this library to ease your development time and better readability of your code that also help cross platform response for Cards, Image and Suggestions.
const { WebhookClient } = require('dialogflow-fulfillment');
server.post('/', function (request, response, next) {
const agent = new WebhookClient({ request, response });
const welcome = () => {
agent.add('Hello Welcome To My bot');
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
agent.handleRequest(intentMap);
}

Express res.status(200).json(...) only sending json message. How to retrieve status code?

After a successful creation of new item in my database I send:
res.status(201).json({message:"Successfully Registered"});
On my angular front end I am able to console.log(res) and receive:
{message: "Successfully Registered"}
1) How do I get the status code on the front end? res.status returns undefined. The only response I'm getting is the JSON.
2) What would be the best way to confirm successful desired api calls? For example, when I log in and credentials are correct, should I check for a 200 and then proceed? Or send a custom JSON message and check if the message for example says "Successful login" then proceed?
A little bit late, but another option is to include the status in the JSON object:
res.status(201).json({message: "Successfully Registered", status: 201})
Now you can check the status in the front end doing res.status and use this to proceed with another action.
1- You can do res.status(200).send("You message here");
2- I would say your best option when doing the login and authenticating credentials is to create a session as such
req.session.user = req.body.username //username is the name attribute of the textfield
and then redirect to any page you'd like/you can also set status to 200
res.status(200);
I'm not familiar with Angular, but looking at the docs:
See https://angular.io/api/http/Response
You'll need to do something like:
http
.request('example.com')
.subscribe(response => console.log(response.status));
Sure, checking for 200 is fine. Typically with a REST API (inferred from what you've shown), after a login you're given back a JWT along with 200 OK. And any subsequent API all with that JWT will also yield a 200 OK along with the response body which is usually JSON.
You should tell your angular http client that you want to get the response status. By default, angular deserialize the response body, but you can set request option.observe:'response' to do so.
postData(model: MyModel): Observable<HttpResponse<{status: string}>> {
return this.http.post<{status: string}>(
model, { observe: 'response' });
}
See https://angular.io/guide/http#reading-the-full-response for details.
PS: sending a { status: 'message' } is not very useful, you may return an { id } or even nothing.
res.status(200).json({
status: 'success',
results: tours.length,
data:{
tour:tours
}
});
Usually, Jsend is a good choice to response, and also by convention. Absolutely you can see the 'status' in response data and the actually data you want in the data.
according to the angular guide, we can add observe in the options of our request.
getforgetpassword(email: string): Observable<any> {
const url = this.gatewayUrl + `newPasswordFor/${email}`;
return this.http.get(url, {observe: "response"});
}
using observe type as response will give total response along with request status, which you can use in your logic of controller.

Angular 6 HTTPClient: Request fired once, receives 2 responses

I've refactored an old project (Angular 2) to Angular 6. All works well, besides a problem I have with api calls.
On the sign-in component, when I submit the form, fires a POST request with the data and the interceptor adds certain headers (for now only content-type).
Code on submitting the form:
this.authService.signIn(this.account)
.subscribe( res => {
console.log('RES -> ', res);
this.router.navigate([this.returnUrl]);
},
err => console.log(err));
AuthService methods:
signIn(account: Account) {
const req = new HttpRequest(HttpMethods.Post, AuthService.signInUrl,{account: account});
return this.makeRequest(req);
}
private makeRequest(req: HttpRequest<any>): Observable<any> {
this.progressBarService.availableProgress(true);
return this.http.request(req)
.finally( () => this.progressBarService.availableProgress(false));
}
The console.log I've added is fired twice for some reason: the first time is {type: 0}, and second time returns the data I needed.
I've removed everything from interceptor, leaved only next.handle(req) and it does the same.
Any idea why I receive 2 responses, the first being just {type: 0}?
That's because you using this.http.request(). I guess the first response is actually the response for the OPTIONS request.
If you still insist to use this.http.request(), for example if you using it to upload files, you might need to use rxJs takeLast(1) to get the response that you need.
Here's the reference.
https://angular.io/api/common/http/HttpClient#request

How to create microsoft/google translate button for each div separately?

How to create microsoft or google translate button for each div?
Each div has content in different language and I would like to add a translate button for each div and make it respond to only that div like the button in the following link.
http://www.bing.com/widget/translator
But when I use the code mentioned in the link above, it translates the whole webpage. I would like to translate each div separately by clicking on the respective translate button.
Can the same thing be done easily using google translate?
Any translator is fine with me. Kindly help. Thanks.
This how the users' post appear on my website.
I would like to have a translate button for each of the divs so that the users can translate each div into any language they want.
Each of my div has an id.
Below I'm explaining how to get started with Microsoft Translator API. The very same functionality can be implemented via Google Translate API however it was somehow easier for me with MS as they offer 2M characters/monthly translation for free whereas Google charges minimum of 1$ for testing.
Prerequisites:
Sign up for free subscription on Microsoft Translator. For that you will be asked to create new MS account or login with existing one.
Register your application on Azure Datamarket.
Registration example. Note: There are two important fields here Client ID and Client secret you will need them for access token requests.
Implementation:
First things first, every request to the API should include access token. Expiration time is 10 minutes so you will have to renew them before they expire. Ideally the process should be done on the back-end side to protect your Client secret and result (token + expiration time) send back to web application.
Node.js example:
var request = require("request");
var options = {
method: 'POST',
url: 'https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/',
form: {
// Client ID & Client secret values (see screenshot)
client_id: 'translator_3000',
client_secret: 'ZP8LzjZkKuFAb2qa05+3nNq+uOcqzWK7e3J6qCN1mtg=',
scope: 'http://api.microsofttranslator.com',
grant_type: 'client_credentials'
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Response contains few fields including access_token, use its value for further requests.
{
"token_type": "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0",
"access_token": "http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=translator_3000&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=1435405881&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HMACSHA256=st9LJ0F8CKSa6Ls59gQN0EqMWLFed5ftkJiOCVXE4ns%3d",
"expires_in": "600",
"scope": "http://api.microsofttranslator.com"
}
Now when we have access token it's time for translation request. Note: These are JSONP requests and access token is supplied using query string parameter appId in the format Bearer <token> (separated by space). Query string also includes text parameter - text of your post and to parameter - language code selected by user, list of all supported codes and language friendly names you can get from API as well.
Here is example:
var settings = {
"url": "https://api.microsofttranslator.com/v2/Ajax.svc/Translate",
"method": "GET",
"dataType": "jsonp",
"jsonp" : "oncomplete",
"data" : {
"text" : "Good Morning StackOverflow",
"to" : "uk",
"appId" : "Bearer http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=translator_3000&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&Audience=http%3a%2f%2fapi.microsofttranslator.com&ExpiresOn=1435405881&Issuer=https%3a%2f%2fdatamarket.accesscontrol.windows.net%2f&HMACSHA256=st9LJ0F8CKSa6Ls59gQN0EqMWLFed5ftkJiOCVXE4ns%3d"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Response is translated string to be replaced with post original text:
"Доброго ранку StackOverflow"
And lastly, all language codes:
http://api.microsofttranslator.com/V2/Ajax.svc/GetLanguagesForTranslate
and friendly names for selected codes:
http://api.microsofttranslator.com/V2/Ajax.svc/GetLanguageNames?locale=en&languageCodes=["en", "de", "es", "uk"]
Official documentation included.
Use the Class element <div class="micropost293"> shown below.
<div class="micropost293"><p>Тестирование</p>
<div class="micropost293_control" lang="en"></div>
<script>
function googleSectionalElementInit() {
new google.translate.SectionalElement({
sectionalNodeClassName: 'micropost293',
controlNodeClassName: 'micropost293_control',
background: '#f4fa58'
}, 'google_sectional_element');
}
</script>
</div>
//Place this Script at bottom of page.
<script src="//translate.google.com/translate_a/element.js?cb=googleSectionalElementInit&ug=section&hl=en"></script>

Run multiple functions based on a SINGLE form submission (method="post") using Node-express

I am looking to perform multiple actions upon receiving HTML(or EJS) form content using the POST method. I am using Node express, mongoose & mongoDB. Each of the below POST responses work individually but i am unsure how to proceed in updating multiple databases based on ONE SINGLE form submission.
// insert into passport db
app.post('/signup', passport.authenticate('local-signup',
{
successRedirect : '/index', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
//insert into my database here
[the content of in the second function is unimportant as that is working fine and has been stripped down for simplification.]
app.post('/signup', function( req, res )
{
new UserDB(
{
user_id : req.body.content,
first_name : req.body.fname,
}).save( function( err, mySite, count )
{
res.redirect( '/index' );
});
});
I have tried redirecting but the form content is not accessible after the redirect so only the first function stores the data (ie. only 1 database is filled).
How would i run both functions within
app.post('/signup',.....
{
...
});
?
Thanks in advance!
You can do this by making one function the callback of the other. This is easy because each function maintains the same Connect middleware signature, function(req, res, next), where req and res are the request and response objects created and manipulated by the application, and next is the next function to call at the end of the current function's execution.
According to the official documentation, passport.authenticate() is a normal piece of middleware. All you need to do is specify the middleware you want to be called next. Express queues middleware functions in the order in which you pass them into app.post. You can do something like this:
app.post('/signup', passport.authenticate('local-signup', {
failureRedirect : '/signup',
failureFlash : true
}),
function(req, res) {
new UserDB({
user_id : req.body.content,
first_name : req.body.fname,
}).save(function(err, mySite, count) {
res.redirect('/index');
});
});
Middleware is an extremely powerful feature of the Express framework and possibly the single most important one to master. This guide would be a great next step if you want to learn more.