I'm trying to add two numbers using DialogFlow.
Question: Add 5 and 6
My Ans: Result is 5+6
but I'm getting the response this one.
Ans Logic: Result is $number + $number1
https://discuss.api.ai/t/start-conversation-with-user-programatically-from-the-server-side-api-ais-side-on-a-notification/1876/2
It’s an API for creating a Natural Language Understanding model for a
conversational interface. If you have custom business logic or
platform-specific message formatting requirements then
for that you will need to turn on fulfillment and in that part get the parameters that was recognised in action and parameters using queryResult.parameters.<nameofparam> and do your task like
let num1 = parseInt(queryResult.parameters.number);
let num2 = parseInt(queryResult.parameters.number1);
let responseText = {
"fulfillmentText": "",
"fulfillmentMessages": [],
"source": "example.com",
"payload": {},
"outputContexts": [],
"followupEventInput": {}
};
responseText.fulfillmentText = "" + num1 + num2;
res.status(200).send(JSON.stringify(responseText));
If you need to perform some operations, then you need to make use of fulfillment - webhook concept. I used Django framework to capture the request and sent back the response as jsonresponse.
Below is the piece of code:
#csrf_exempt
def webhook(request):
# build a request object
req = json.loads(request.body)
# get action from json (i.e) arithmetic operation that we need to perform
action = req.get('queryResult').get('action')
#get the numbers from the json
num = req.get('queryResult').get('parameters')
n1 = int(num.get('number'))
n2 = int(num.get('number1'))
if action == 'addition':
# return a fulfillment message
fulfillmentText = {'fulfillmentText': n1+n2}
return JsonResponse(fulfillmentText, safe=False)
If you are interested to know more, please spend sometime in reading my blog which has the complete piece of code along with steps of implementation.
Related
I am currently making REST API over gRPC. The generated REST API url doesnt look good, so I want to know how to resolve the issue.
ISSUE
Currently I have these Protobuf
message GetBookTitleListRequest {
repeated int32 book_ids = 1;
}
message GetBookTitleListResponse {
repeated string book_titles = 1;
}
rpc GetBookTitles(GetBookTitleListRequest) returns GetBookTitleListResponse {
option (google.api.http) = {
get: 'api/v1/books/titles'
};
}
I can specify the book ids in GetBookTitleListRequest and API returns the list of book titles.
The generated api looks like this if I want book titles with id (1, 2, 3) localhost:8000/api/v1/books/titles?book_ids=1&book_ids=2&book_ids=3.
However, I want it be like localhost:8000/api/v1/books/titles?book_ids=1,2,3.
Is it possible to do this?
So I'm writing a chatbot application which requires the intake of parameters and then uses these parameters in post requests sent via a payload.
I'm having problems with grabbing the context value from a context variable within swift and was wondering how I would go about grabbing the value of the context variable and executing an action based on the value of that said context.
An example of this would be the following dialog flow...
Me: Trigger this
Bot: Ok, give me param x
Me: x
Bot: Ok I have x param, will post job now
This is the kind of flow I want to happen in the background of my application under the hood but I'm not sure how to grab value x after my user has input it.
So, suppose that you are using the iOS SDK from Watson Developer Cloud.
In your Conversation, add in your node:
{
"context": {
"myVariable": "<? input.text ?>"
},
"output": {
"text": {
"values": [
"My context variable value is $myVariable."
],
"selection_policy": "sequential"
}, { "etc": "etc" }
Obs.: The input.text will capture all that user types, you need to use regex for extract exactly what you want, try to see my examples in this answer.
And, in the iOS SDK you can see this follow example:
func testMessage() {
let description1 = "Start a conversation."
let expectation1 = self.expectation(description: description1)
let response1 = ["Hi. It looks like a nice drive today. What would you like me to do?"]
let nodes1 = ["node_1_1467221909631"]
var context: Context?
conversation.message(workspaceID: workspaceID, failure: failWithError) {
response in
// verify input
XCTAssertNil(response.input?.text)
// verify context
XCTAssertNotNil(response.context.conversationID)
XCTAssertNotEqual(response.context.conversationID, "")
XCTAssertNotNil(response.context.system)
XCTAssertNotNil(response.context.system.additionalProperties)
XCTAssertFalse(response.context.system.additionalProperties.isEmpty)
// verify entities
XCTAssertTrue(response.entities.isEmpty)
// verify intents
XCTAssertTrue(response.intents.isEmpty)
// verify output
XCTAssertTrue(response.output.logMessages.isEmpty)
XCTAssertEqual(response.output.text, response1)
XCTAssertEqual(response.output.nodesVisited!, nodes1)
context = response.context
expectation1.fulfill()
}
So, you can access your context variable using:
context.myVariable
response.context.myVariable
See more about methods in Watson Conversation here.
iOS SDK from Watson Developer Cloud.
I have a minimal (example) REST end-point test/people.cfc:
component
restpath = "test/people/"
rest = true
{
remote void function create(
required string first_name restargsource = "Form",
required string last_name restargsource = "Form"
)
httpmethod = "POST"
restpath = ""
produces = "application/json"
{
// Simulate adding person to database.
ArrayAppend(
Application.people,
{ "first_name" = first_name, "last_name" = last_name }
);
// Simulate getting people from database.
var people = Application.people;
restSetResponse( {
"status" = 201,
"content" = SerializeJSON( people )
} );
}
}
As noted here and in the ColdFusion documentation:
Note: ColdFusion ignores the function's return value and uses the response set using the RestSetResponse() function.
So the void return type for the function appears to be correct for the REST function.
Now, I know I can call it from a CFM page using:
httpService = new http(method = "POST", url = "https://localhost/rest/test/people");
httpService.addParam( name = "first_name", type = "formfield", value = "Alice" );
httpService.addParam( name = "last_name", type = "formfield", value = "Adams" );
result = httpService.send().getPrefix();
However, I would like to call the function without making a HTTP request.
Firstly, the REST CFCs do not appear to be accessible from within the REST directory. This can be solved simply by creating a mapping in the ColdFusion admin panel to the root path of the REST service.
I can then do:
<cfscript>
Application.people = [];
people = new restmapping.test.People();
people.create( "Alice", "Adams" );
WriteDump( application.people );
</cfscript>
This calls the function directly and the output shows it has added the person. However, the response from the REST function has disappeared into the aether. Does anyone know if it is possible to retrieve the response's HTTP status code and content (as a minimum - preferably all the HTTP headers)?
Update - Integration Testing Scenario:
This is one use-case (of several) where calling the REST end-point via a HTTP request has knock-on effects that can be mitigated by invoking the end-point directly as a method of a component.
<cfscript>
// Create an instance of the REST end-point component without
// calling it via HTTP request.
endPoint = new restfiles.test.TestRESTEndPoint();
transaction {
try {
// Call a method on the end-point without making a HTTP request.
endPoint.addValueToDatabase( 1, 'abcd' );
assert( getRESTStatusCode(), 201 );
assert( getRESTResponseText(), '{"id":1,"value":"abcd"}' );
// Call another method on the end-point without making a HTTP request.
endPoint.updateValueInDatabase( 1, 'dcba' );
assert( getRESTStatusCode(), 200 );
assert( getRESTResponseText(), '{"id":1,"value":"dcba"}' );
// Call a third method on the end-point without making a HTTP request.
endPoint.deleteValueInDatabase( 1 );
assert( getRESTStatusCode(), 204 );
assert( getRESTResponseText(), '' );
}
catch ( any e )
{
WriteDump( e );
}
finally
{
transaction action="rollback";
}
}
</cfscript>
Calling each REST function via a HTTP request will commit the data to the database after each request - cleaning up between tests where the data has been committed can get very complicated and often results in needing to flashback the database to a previous state (resulting in integration tests being unable to be run in parallel with any other tests and periods of unavailability during flashbacks). Being able to call the REST end-points without making lots of atomic HTTP requests and instead bundle them into a single transaction which can be rolled back means the testing can be performed in a single user's session.
So, how can I get the HTTP status code and response text which have been set by RestSetResponse() when I create an instance of the REST component and invoke the function representing the REST path directly (without using a HTTP request)?
#MT0,
The solution will* involve a few steps:
Change remote void function create to remote struct function create
Add var result = {"status" = 201, "content" = SerializeJSON( people )}
Change your restSetResponse(..) call to restSetResponse(result)
Add return result;
* The solution will not currently work, b/c ColdFusion ticket CF-3546046 was not fixed completely. I've asked Adobe to re-open it and also filed CF-4198298 to get this issue fixed, just in case CF-3546046 isn't re-opened. Please see my most recent comment on CF-3546046, and feel free to vote for either ticket. Once either is fixed completely, then the above-listed changes to your code will allow it to set the correct HTTP response when called via REST and to return the function's return variable when invoked directly. Note: you could also specify a headers struct w/in the result struct in step 2, if you also want to return headers when the function is invoked directly.
Thanks!,
-Aaron Neff
I've setup a form using googledocs. I just want to have the actual data entered into the form emailed to me, as opposed to the generic response advising that the form has been completed.
I have no skill or experience with code etc, but was sure i could get this sorted. I've spent hours+hours and haven't had any luck.
My form is really basic.it has 5 fields. 4 of which are just text responses, and one multiple choice.
I found this tute online (http://www.labnol.org/internet/google-docs-email-form/20884/) which i think sums up what i'm trying to do, but have not been able to get it to work.
from this site i entered the following code:
function sendFormByEmail(e)
{
var email = "reports.mckeir#gmail.com";
var subject = "Google Docs Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers)
message += headers[i] + ' = '+ e.namedValues[headers[i]].toString() + "\n\n";
MailApp.sendEmail(email, subject, message);
}
To this, i get the following response: ->
Your script, Contact Us Form Mailer, has recently failed to finish successfully. A summary of the failure(s) is shown below. To configure the triggers for this script, or change your setting for receiving future failure notifications, click here.
The script is used by the document 100% Club.
Details:
Start Function Error Message Trigger End
12/3/12 11:06 PM sendFormByEmail TypeError: Cannot call method "toString" of undefined. (line 12) formSubmit 12/3/12 11:06 PM
Is anyone able to help shed some light on this for me? I'm guessing i'm not including some data neeeded, but i honestly have no clue.
Workaround http://www.labnol.org/internet/google-docs-email-form/20884/
You have to setup app script to forward the data as email.
I'll point to the comment above that solved it for me: https://stackoverflow.com/a/14576983/134335
I took that post a step further:
I removed the normal notification. The app script makes that generic text redundant and useless now
I modified the script to actually parse the results and build the response accordingly.
function sendFormByEmail(e)
{
var toEmail = "changeme";
var name = "";
var email = "";
// Optional but change the following variable
// to have a custom subject for Google Docs emails
var subject = "Google Docs Form Submitted";
var message = "";
// The variable e holds all the form values in an array.
// Loop through the array and append values to the body.
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
// Credit to Henrique Abreu for fixing the sort order
for(var i in headers) {
if (headers[i] = "Name") {
name = e.namedValues[headers[i]].toString();
}
if (headers[i] = "Email") {
email = e.namedValues[headers[i]].toString();
}
if (headers[i] = "Subject") {
subject = e.namedValues[headers[i]].toString();
}
if (headers[i] = "Message") {
message = e.namedValues[headers[i]].toString();
}
}
// See https://developers.google.com/apps-script/reference/mail/mail-app#sendEmail(String,String,String,Object)
var mailOptions = {
name: name,
replyTo: email,
};
// This is the MailApp service of Google Apps Script
// that sends the email. You can also use GmailApp here.
MailApp.sendEmail(toEmail, subject, message, mailOptions);
// Watch the following video for details
// http://youtu.be/z6klwUxRwQI
// By Amit Agarwal - www.labnol.org
}
The script utilized in the example is extremely generic but very resilient to change because the message is built as a key/value pair of the form fields submitted.
If you use my script you'll have to tweak the for loop if statements to match your fields verbatim. You'll also want to edit the toEmail variable.
Thanks again for the question and answers. I was about to ditch Google Forms as the generic response was never enough for what I was trying to do.
Lastly, in response to the actual problem above "toString of undefined" specifically means one of the form fields was submitted as blank. If I had to guess, I would say the author only used this for forms where all the fields were required or a quick undefined check would've been put in place.
Something like the following would work:
for(var i in headers) {
var formValue = e.namedValues[headers[i]];
var formValueText = "";
if (typeof(formValue) != "undefined") {
formValueText = formValue.toString();
}
message += headers[i] + ' = '+ formvalueText + "\n\n";
}
I haven't tested this precisely but it's a pretty standard way of making sure the object is defined before trying methods like toString() that clearly won't work.
This would also explain Jon Fila's answer. The script blindly assumes all of the header rows in the response are sent by the form. If any of the fields aren't required or the spreadsheet has fields that are no longer in the form, you'll get a lot of undefined objects.
The script could've been coded better but I won't fault the author as it was clearly meant to be a proof of concept only. The fact that they mention the replyTo correction but don't give any examples on implementing it made it perfectly clear.
If this is a Google Form, do you have any extra columns in your spreadsheet that are not on the form? If you delete those extra columns then it started working for me.
You don't need to use a script. Simply go to Tools >> Notification Rules on your Google Spreadsheet. There you can change the settings to receive an email with your desired information every time the document is changed.
I am building a REST API for my project. The API for getting a given user's INFO is:
api.com/users/[USER-ID]
I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?
If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.
RESTful attempt:
POST http://example.com/api/batchtask
[
{
method : "GET",
headers : [..],
url : "/users/id1"
},
{
method : "GET",
headers : [..],
url : "/users/id2"
}
]
Server will reply URI of newly created batchtask resource.
201 Created
Location: "http://example.com/api/batchtask/1254"
Now client can fetch batch response or task progress by polling
GET http://example.com/api/batchtask/1254
This is how others attempted to solve this issue:
Google Drive
Facebook
Microsoft
Subbu Allamaraju
I find another way of doing the same thing by using #PathParam. Here is the code sample.
#GET
#Path("data/xml/{Ids}")
#Produces("application/xml")
public Object getData(#PathParam("zrssIds") String Ids)
{
System.out.println("zrssIds = " + Ids);
//Here you need to use String tokenizer to make the array from the string.
}
Call the service by using following url.
http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76
where
http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
As much as I prefer this approach:-
api.com/users?id=id1,id2,id3,id4,id5
The correct way is
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
or
api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5
This is how rack does it. This is how php does it. This is how node does it as well...
There seems to be a few ways to achieve this. I'd like to offer how I solve it:
GET /users/<id>[,id,...]
It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.
I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).
I'm interested in comments in my hunt for the ideal solution to this form :)
You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON.
An example controller function would be:
public JsonpResult GetUsers(string userIds)
{
var values = JsonConvert.DeserializeObject<List<int>>(userIds);
var users = _userRepository.GetAllUsersByIds(userIds);
var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
var result = new { users = collection };
return this.Jsonp(result);
}
public IQueryable<User> GetAllUsersByIds(List<int> ids)
{
return _db.Users.Where(c=> ids.Contains(c.Id));
}
Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.
function GetUsers()
{
var link = '<%= ResolveUrl("~")%>users?callback=?';
var userIds = [];
$('#multiselect :selected').each(function (i, selected) {
userIds[i] = $(selected).val();
});
$.ajax({
url: link,
traditional: true,
data: { 'userIds': JSON.stringify(userIds) },
dataType: "jsonp",
jsonpCallback: "refreshUsers"
});
}