Hyperlink in content in Amazon Lex - amazon-web-services

I want to hyperlink a particular text in lambda function content. I tried doing this but didn't work.
if (intentName == "greetings") {
var message = {
'contentType': 'PlainText',
'content': 'click here'
}
responseMsg = close( sessionAttributes, 'Fulfilled', message );
}
I know we can hyperlink response card, but i want to hyperlink a particular text in content. Any idea how to do it or any alternative? i am using javascript.
Edit 1 : I am able to do it by Attachments through attachment :
function close(sessionAttributes,fulfillmentState,message){
return{
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message,
"responseCard": {
"contentType": "application/vnd.amazonaws.card.generic",
"genericAttachments": [
{
'title': 'Google',
'attachmentLinkUrl': 'https://www.google.com',
}
]
}
}
};
}

I was trying this out on HTML a few months ago, you can check out my question at LexResponse output does not understand HTML data
The answer that worked was a JS function that looks like this:
function showResponse(lexResponse) {
var conversationDiv = document.getElementById('conversation');
var responsePara = document.createElement("P");
responsePara.className = 'lexResponse';
if (lexResponse.message) {
var message = lexResponse.message.replace(/"/g, '\'');
responsePara.innerHTML = message;
responsePara.appendChild(document.createElement('br'));
}
conversationDiv.appendChild(responsePara);
conversationDiv.scrollTop = conversationDiv.scrollHeight;
}
Please note that this is only to RENDER the response in HTML.

I implemented this recently.
I wanted a message with custom display, but also wanted normal speech.
Sending text with tags in it will cause the Text to Speech engine to read out the tags as well.
So, for each message I sent to the user, I put the "speechText" into the message content in the Lex response.
I put the "displayText" with tags and what not, within sessionAttributes.
but I had to make sure not to stringify that displayText. I only stringify a value in sessionAttributes if it is not a simple string.
On the client side, I pulled the audio data from the lex response, and I displayed the text I pull from the sessionAttributes.
sry if this is confusing.

Related

How do I handle Request Body Error in Ktor

I am new to Ktor and I have a route with a request body which i am parsing with Kotlin Serialization.
I know that the request body is expected to conform to the request body data class but then, I tested by passing the wrong field in my test payload and it crashed the app.
I want to be able to handle such scenarios and respond to the client that such a field is not allowed. How do i go about that.
This is my sample data class:
#kotlinx.serialization.Serializable
data class UserLoginDetails(
var email: String = "",
var password: String = ""
)
This is the route:
post("/user/login") {
val userInfo = call.receive<UserLoginDetails>()
//my code here
}
The payload below works
{
"email": "test#email.com",
"password": "password"
}
But if use an alternative payload for instance:
{
"phone": "test#email.com",
"password": "password"
}
The app crashes with the crash message:
kotlinx.serialization.json.internal.JsonDecodingException: Unexpected
JSON token at offset 7: Encountered an unknown key 'emai'. Use
'ignoreUnknownKeys = true' in 'Json {}' builder to ignore unknown
keys.
You have two options in Ktor:
call.receive is the function which can throw an exception in this case, you can simply catch it:
try {
val userInfo = call.receive<UserLoginDetails>()
} catch (t: Throwable) {
// handle error
}
Catching exceptions globally using Status Pages:
install(StatusPages) {
exception<SerializationException> { cause ->
call.respond(/* */)
}
}
The error message says you can setup your Json with the config ignoreUnknownKeys = true where you are creating the Json object. Here's the doc link.
a tip: You might also want to check other configuration options so you can avoid setting empty string as default values.

Telegram bot sendMediaGroup() in Postman - JSON-serialized array?

I'm using Postman app to interact with a Telegram bot api. I've sent photos using the sendPhoto() method, like this:
https://api.telegram.org/botToken/sendPhoto?chat_id=00000000&photo=AgAC***rgehrehrhrn
But I don't understand the sendMediaGroup() method. Can someone post an example how to compose the https string to send two photos?
Thanks
You need to send a POST request at the url https://api.telegram.org/botToken/sendPhoto with a JSON body. You are using the url to specify all the parameters of the request but urls are only 2000 characters long. The body of a POST request, instead, has no limits in terms of size. The JSON body should look something like this:
{
"chat_id": 777000,
"media": [
{
"type": "photo",
"media": "https://example.com/first_photo_url.png",
"caption": "an optional description of the first photo",
"parse_mode": "optional (you can delete this parameter) the parse mode of the caption"
},
{
"type": "photo",
"media": "https://example.com/fsecond_photo_url.png",
"caption": "an optional description of the second photo",
"parse_mode": "optional (you can delete this parameter) the parse mode of the caption"
}
],
}
For more info see:
how to send JSON (raw) data with Postman
and
sendMediaGroup Telegram API's method.
You must send JSON as a string, or serialized JSON, to Telegram API. The format is as same as #GioIacca9's answer.
Note: only the caption in the first image will be showen.
Have a try this Python code.
def send_photos(api_key, chat_id, photo_paths):
params = {
'chat_id': chat_id,
'media': [],
}
for path in photo_paths:
params['media'].append({'type': 'photo', 'media': path})
params['media'] = json.dumps(params['media'])
url = f'https://api.telegram.org/bot{api_key}/sendMediaGroup'
return requests.post(url, data=params)
if __name__ == '__main__':
send_photos('your_key', '#yourchannel', ['http://your.image.one', 'http://your.image.two'])

Can I create an AWS Lex Bot that displays different responses based on user input?

I am trying to create a lex bot that lets users learn about different options. For example, it can tell a user about the three different products available. I can't seem to find documentation about how to do this without using a lambda function, and I can't figure out how to pass the user input from the bot itself into the lambda function in order to use a simple "if/then" and then return the appropriate message. It seems excessive to have to use an lambda function to just give a response based on input, but I am stuck. Thanks.
To shed a little more light on how a Lex bot works, the service enables you to define utterances ("if" conditions), that it will intelligently try to perform fuzzy-matching to determine whether a user has said something that fits one of the utterances you've defined. You can declare and modify these utterances within the AWS console, examples of this are available here.
The "then" part of this conditional application is where you get to define what happens after the user input matches a defined utterance (state), where some basic computation is handled, most easily in the form of a Lambda function.
For something simple like returning static text/info once a condition is met:
Return from your lambda_handler function a string with the proper result. A barebones pseudocodey Python implementation of this would look like the following:
# Here's an implementation where you have an intent of a user asking
# for more info about a particular object (info_type as defined in Lex console).
def lambda_handler(event, context):
info_name = event['info_type']
if info_name = 'business_hours':
return "Our business hours are 9am-5pm"
elif info_name = 'slogan':
return "We're customer obsessed"
else:
return "Sorry, we don't have info about this!"
Depending on how you want to set up your application, you can decide how you want to split up the logic between different utterances and if/then cases with prop data passed in. If you have more complex queries, question types, and computation involved, these will all determine what the optimal way to architect your Lex chat bot will be.
A Lex bot by itself is really only good enough for simple FAQ conversations where certain inputs have pre-defined responses. But you cannot set the responses based on the slot values Lex captures. You could have a very limited dynamic response where those slot values are simply placed inside a response (imagine a Mad Libs game), but that's about it.
As soon as you want to create a truly dynamic response based on the user input, then you will need to use a Lambda function to compare the Lex request and build an appropriate response based on the user input or slot values.
Documentation
Amazon Lex - Using Lambda Functions
Create a Lambda Function (example Order Flowers)
Set the Lambda Function as the Lex Intent's Code Hook
Once you have your Lambda function set up and Lex ready to pass the processed user input through as a Lex Request (also referred to as "Event"), then you will have to pay close attention to this document:
Lex Request and Response Format
The incoming request has a consistent format for delivering the currentIntent, the sessionAttributes, the slots, the inputTranscript (the full user input), and more. It might look like a lot to take in but once you parse it into its main components, then it's really quite easy to work with in order to build dynamic responses. Just make sure you are following the Lex Request and Response format precisely.
Example
Here is an example for the start of your Lambda Function (Node.js):
// The JSON body of the request is provided in 'event'.
// 'respondToLex' is the callback function used to return the Lex formatted JSON response
exports.handler = (event, context, respondToLex) => {
console.log( "REQUEST= "+JSON.stringify(event) ); //view logs in CloudWatch
// INCOMING VARIABLES FROM REQUEST EVENT
// -------------------------------------
var intentName = event.currentIntent.name;
var slots = event.currentIntent.slots
var sessionAttributes = event.sessionAttributes
var userInput = event.inputTranscript
// OUTGOING VARIABLES FOR RESPONSE
// -------------------------------
var responseMsg = "";
var responseType = "";
var slotToElicit = "";
var error = null;
var fulfillmentState = null;
// DETERMINE RESPONSE BASED ON INTENTS AND SLOT VALUES
// ---------------------------------------------------
if (intentName == "intentA") {
responseType = "Close";
responseMsg = "I am responding to intentA";
fulfillmentState = "fulfilled';
}
elseif (intentName == "intentB") {
if (slots["productChoice"] == null) {
responseMsg = "I can tell that productChoice slot is empty, so I should elicit for it here. Which product would you like? Hat or Shoes?";
responseType = "ElicitSlot";
slotToElicit = "productChoice";
}
else {
if (slots["productChoice"]=="hat") {
responseMsg = "I can tell you selected a hat, here is my dynamic response based on that slot selection.";
}
elseif (slots["productChoice"]=="shoes") {
responseMsg = "I can tell you selected shoes, here is my dynamic response based on that slot selection.";
}
}
}
else {
error = "Throw Error: Unknown Intent";
}
// CREATE RESPONSE BUILDER for each responseType (could turn into functions)
// -------------------------------------------------------------------------
if (responseType=="Close") {
var response = [
"sessionAttributes" = sessionAttributes,
"dialogAction" = [
"type" = responseType,
"fulfillmentState" = fulfillmentState,
"message" = [
"contentType" = "PlainText";
"content" = responseMsg,
]
]
];
}
elseif (responseType == "ElicitSlot) {
var response = [
"sessionAttributes" = sessionAttributes,
"dialogAction" = [
"type" = responseType,
"intentName" = intentName,
"slots" = slots
"slotToElicit" = slotToElicit,
"message" = [
"contentType" = "PlainText";
"content" = responseMsg,
]
]
];
}
responseJSON = JSON.stringify(response);
console.log("RESPONSE= "+ responseJSON); // view logs in CloudWatch
respondToLex(error, responseJSON);
}

Provide AWS Lex response in Hyperlink format

While creating a chatbot using AWS Lex, I would like to provide the response in hyperlink format. But I don't want to use Response card in this case. As per the AWS Lex docs, I knew that hyperlinks can't be given directly in responses. Am new to Lamda functions and tried with the following.
exports.handler = (event, context, callback) => {
callback(null, {
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "CustomPayload",
"content": "my link"
}
}
});
};
but still am getting the result in text format. Am even okay with any other approaches.
You can send URL's (no HTML tags) in the response as a normal message. But how that URL is displayed to the user depends on the channel you are using and their output formatting of that message.
I know that Facebook Messenger will automatically change a URL string to be a link. Most of the other channels probably do too. But the Lex Test Chat will not.
For testing this sort of thing, it is best to do it in the actual channel your Lex bot will use because a lot of formatting like this works in the actual channel but does not work in the Test Chat.

Send Json via $.load() of jQuery in a GET request to Django

Happy coding weekend to everyone!!!.
I'm stuck trying to send a JSON object via $.load() of jQuery, i want to send it with the GET method, this is the code that i have in my javascript code, I attached the Ajax request that receives the JSON Object for clarity:
function ajaxLoadClasses() {
$.ajax({
url: 'load_classes/',
type: 'GET',
dataType: 'json',
success: function(json) {
$.each(json, function(iterator,item) {
loadViaGet(item);
});
},
error: function(xhr, status) {
alert('Sorry, there was a problem!');
},
complete: function(xhr, status) {},
});
}
function loadViaGet(item) {
$div = $('div.myClass');
//Here is where I'm stuck, I'm not sure if this is the way to send the JSON obj
$div.load('thisAppURL/?json=' + encodeURIComponent(item), function() {
alert('Load was performed');
});
}
The "item" json obj received was made out of a Model of Django using
jsonToSendToAjax = serializers.serialize('json', obj)
And I don't think that I'm using the correct methods in my Django to deserialize the JSON object or to convert the JSON object into a Python object so I can handle it in my view and send it to a template:
def popUpForm(request):
jsonData = request.GET['json']
deser = serializers.deserialize('json', jsonData)
#This could be another way to convert the JSON object to a Python Object
#pythonObj = simplejson.loads(jsonData)
return render_to_response('class_pop_up_form.html', deser)
It will be very helpful if someone can help me with this!! I'm really struggling with it but I don't find the right way to do it.
EDIT 1 :
I want to send the JSON object via the GET with the $.load() function, not with the POST method,as I read in the jQuery api: http://api.jquery.com/load/ the $.load() method works as follow: .load( url, [data], [complete(responseText, textStatus, XMLHttpRequest)] )
The POST method is used if data is provided as an object; otherwise, GET is assumed.
EDIT 2:
Forget about sending the json object via the GET method, now I'm using the POST method, but now I don't figure out how to use that json object in my Django View.py, don't know if i need to deserialize it or not, the format of the json object that I'm using is the following:
{"pk": 1,
"model": "skedified.class",
"fields": {
"hr_three": null,
"group": 1,
"name": "Abastecimiento de agua",
"day_three": null,
"day_one": "1 , 3",
"hr_one": "10+/3",
"online_class": null,
"teacher_name": "Enrique C\\u00e1zares Rivera / ",
"day_two": null,
"class_key": "CV3009",
"hr_two": null }
}
This isn't how jQuery suggests you should send the data and it's probably not a good idea to do it this way either. Your url gets very ugly and long very quick if you add the json string to it like that.
Use the second argument for $.load; "data" (see http://api.jquery.com/load/) instead. So something like
$div.load('thisAppURL', {"json": encodeURIComponent(item)});
Also, if you want to trace the output, I'd sugest using the third argument, the callback function, and use console instead of alert. You can get the actual return from the server that way too. So you'd get something like:
$div.load(
'thisAppURL',
{"json": encodeURIComponent(item)},
function(response, status, xhr){
console.log(response);
}
);
the question was not clear to me but you can send json via load as the second argument
$div = $('div.myClass');
//Here is where I'm stuck, I'm not sure if this is the way to send the JSON obj
$div.load('thisAppURL/?json=' + encodeURIComponent(item),{"name":"john","age":"20"}, function() {
alert('Load was performed');
});
for converting javascript array to json see this answer Convert array to JSON
and for deserializing json in django Django Deserialization