using third party api on watson assistant - javascript

i'm using the open weather map api in order to get information on the current weather and then integrate it with watson assistant (i used this as a reference for the watson assistant code) before deploying on the terminal. here's my code:
var city = "Seattle";
weather.setCity(city);
function processResponse(err, response){
if(err){
console.log(err);
return;
}
var endConversation = false;
if(response.intents[0]){
if(response.intents[0].intent=="CurrentWeather"){
weather.getDescription(function(err, desc){
weather.getTemperature(function(err, temp){
console.log("It is " + desc + " today with a temperature of " + temp + " degrees Celsius.");
)};
)};
}
else if(response.intents[0].intent=="end_conversation"){
console.log(response.output.text);
endConversation = true;
}
}
if(!endConversation){
var newMessageFromUser = prompt(">> ");
service.message({
workspace_id: workspace_id,
input: {
text: newMessageFromUser
},
context: response.context
},processResponse);
}
}
it works, but then the response looks like this:
>> what is the weather today in seattle
>>
It is few clouds today with a temperature of 29 degrees Celsius.
>> bye
['See ya!']
whenever i use any third party apis, instead of responding right after i enter the trigger keywords, the terminal asks me to input another entry (in the scenario above, i entered nothing) before responding. however, when i try to enter keywords related to intents whose responses are just retrieved right away from the watson assistant (as is with end_conversation), the terminal responds right away.
Is there a way for me to force the terminal to only ask once?

There are different ways to get around entering something before the actual response.
Take a look at client-based dialog actions. The key is to use the skip_user_input flag and check it within your application. Basically, it would indicate to your application that you need to process some data. The app would it send back to Watson Assistant to respond. There is also the server-based dialog action. In that case Watson Assistant is invoking an IBM Cloud Functions action. A tutorial using that approach is here, interfacing with a Db2 database.
Another technique is what I call replaced markers. You would have Watson Assistant returns an answer with placeholders. Your app would replace those markers.
Third, you are using JavaScript with asynchronous processing. It seems that your empty prompt is processed while you fetch the weather data. The IF for the weather is independent of the empty prompt. Try fixing that.

following Michal Bida's advice, I tried implementing the third party API in cloud function and it worked. simply created a php function using the php implementation of the openweather map api and followed the steps on how to create an action in php through this tutorial. for the implementation, i followed this tutorial on how to implement actions in watson assistant. it now works even when directly invoked from the chat bot at the side of the watson assistant.
an example of a response it returns will be:
{"weather":"It is raining today in Seattle with a temperature of 15 degrees Celsius"}

Related

matrix-js-sdk setup and configuration

I am having some issues trying to connect to a matrix server using the matrix-js-sdk in a react app.
I have provided a simple code example below, and made sure that credentials are valid (login works) and that the environment variable containing the URL for the matrix client is set. I have signed into element in a browser and created two rooms for testing purposes, and was expecting these two rooms would be returned from matrixClient.getRooms(). However, this simply returns an empty array. With some further testing it seems like the asynchronous functions provided for fetching room, member and group ID's only, works as expected.
According to https://matrix.org/docs/guides/usage-of-the-matrix-js-sd these should be valid steps for setting up the matrix-js-sdk, however the sync is never executed either.
const matrixClient = sdk.createClient(
process.env.REACT_APP_MATRIX_CLIENT_URL!
);
await matrixClient.long("m.login.password", credentials);
matrixClient.once('sync', () => {
debugger; // Never hit
}
for (const room of matrixClient.getRooms()) {
debugger; // Never hit
}
I did manage to use the roomId's returned from await matrixClient.roomInitialSync(roomId, limit, callback), however this lead me to another issue where I can't figure out how to decrypt messages, as the events containing the messages sent in the room seems to be of type 'm.room.encrypted' instead of 'm.room.message'.
Does anyone have any good examples of working implementations for the matrix-js-sdk, or any other good resources for properly understanding how to put this all together? I need to be able to load rooms, persons, messages etc. and display these respectively in a ReactJS application.
It turns out I simply forgot to run startClient on the matrix client, resulting in it not fetching any data.

Sending a canned response with Gmail Apps Script

I'm writing an auto-replying tool for gmail using Google Apps Script (http://script.google.com).
In the docs, I don't find any function to send a Gmail canned response. Is there no such feature?
If not, how would you handle this? I thought about sending an email to myself in gmail:
To:example#gmail.com
From:example#gmail.com
Subject:This is a canned response ID1847
Hi
This is a test
adding the label mycannedresponse to it, and then loading in Apps Script this mail from code:
var threads = GmailApp.search("label:mycannedresponse ID1847");
if (threads.length != 1) {
// error: the canned response ID... is not unique
} else {
threads[0].getBody(...)
threads[0].getPlainBody(...)
}
Is there a more-documented way to do it?
Have you seen the sendEmail method for GAS? You can create a trigger to fire off this email.
// The code below will send an email with the current date and time.
var now = new Date();
GmailApp.sendEmail("mike#example.com", "current time", "The time is: " + now.toString());
https://developers.google.com/apps-script/reference/gmail/gmail-app#sendemailrecipient-subject-body

Send String to Node.js

I'm trying create a simple UI here on my iOS app to test a thing or two out but I'm having some issues here. My app is set up with a UITextField and UIButton. I'm trying to replace a string on my .js file which is saved on my virtual server. In my .js file I have below:
// Prepare a new notification
var notification = new apn.Notification();
// Display the following message (the actual notification text, supports emoji)
notification.alert = 'Hi James';
I basically would like to replace "Hi James" with whatever I typed in the UITextField in my Swift 3 project but not too sure where to start. This would be my first time sending data to .js file so anything would help. I'm thinking so far that it'd be something along the lines to below. Node.js would be similar to Javascript since it's cross platform.
func sendSomething(stringToSend : String) {
appController?.evaluateInJavaScriptContext({ (context) -> Void in
//Get a reference to the "myJSFunction" method that you've implemented in JavaScript
let myJSFunction = evaluation.objectForKeyedSubscript("myJSFunction")
//Call your JavaScript method with an array of arguments
myJSFunction.callWithArguments([stringToSend]) }, completion: { (evaluated) -> Void in
print("we have completed: \(evaluated)")
})
}
Found that on a relevant StackOverflow post so I feel like I'm getting close. Any assistant would be appreciated in advanced. Have a good one!
I recommend using the Node HTTP or ExpressJS server reading the POST fields and posting a document from your iOS app with the desired field
See
https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

Activate js when snowing in users location

So I have js that I want to only activate if it is snowing in the users area.
Here is a JSFiddle Here
<h1 onclick="snowStorm.toggleSnow();">
text
</h1>
<script src="https://web.archive.org/web/20161109225359/http://live.superedu.ml/snow.js"></script>
<script>
snowStorm.followMouse = false;
snowStorm.freezeOnBlur = true;
snowStorm.autoStart = false;
</script>
if you click test it activates snow.
how would I make this to activate the snow when it is snowing where the user is. thank you
First, you need to know if it's snowing or not at the user's location. So the very first thing you need to know is where they are. For this you use an IP geolocation service. Google it. One of them is https://freegeoip.net/
Next you need to ask a weather service about the weather.
Look into https://darksky.net/dev/docs/forecast
In order to ask something to a service like DarkSky API you will need to tell them the location you are interested in for the forecast, which is where you use the location coordinates you received from the geolocation service above.
You will then receive a response "object" from the DarkSky API, which will contain a bunch of information, amongst which the precipitation info as described below:
precipType optional
The type of precipitation occurring at the given time. If defined, this property will have one of the following values: "rain", "snow", or "sleet" (which refers to each of freezing rain, ice pellets, and “wintery mix”). (If precipIntensity is zero, then this property will not be defined.)
https://darksky.net/dev/docs/response
After which you can code something along the lines of
if (data.precipType === 'snow') { // do something }
Overall, it goes like this:
Send request to GeoIP (where is ip 8.8.8.8 ?)
Receive response from GeoIP (it's at lat:1.2345 lon:1.432)
Send request to DarkSky (what's the weather today at lat:1.2345 lon:1.432 ?)
Receive response from DarkSky (snow!)
… do stuff …
How
In order to succeed at this exercise, you will ned to familiarise a bit with basic asynchronous programming in JS, and how to send an AJAX request, and consume the response you receive.
In short you need to learn how to write code that is able to start function B only after function A is done (after an unknown amount of time, like when requesting over the net)
So things will look more like this:
1. Send request to GeoIP (where is ip 8.8.8.8 ?)
2. Receive response from GeoIP (it's at lat:1.2345 lon:1.432)
3. Send request to DarkSky (what's the weather today at lat:1.2345 lon:1.432 ?)
4. Receive response from DarkSky (snow!)
5. … do stuff …
Good keywords to search for this are jQuery AJAX, callbacks, and a tad more advanced, Promises. But start with the first two.
Good luck!

Speeding up an app that makes many Facebook API calls

I've got a simple app that fetches a user's complete feed from the Facebook API in order to tally the number of words he or she has written total on the site.
After he or she authenticates, the page makes a Graph call to /me/feed?limit100 and counts the number of responses and their dates. If there is a "next" cursor in the response, it then pings that next URL, which looks something like this:
https://graph.facebook.com/[UID]/feed?limit=100&until=1386553333
And so on, recursively, until we reach the time that the user joined Facebook. The function looks like this:
var words = 0;
var posts = function(callback, url) {
url = url || '/me/posts?limit=100';
FB.api(url, function(response) {
if (response.data) {
response.data.forEach(function(status) {
if (status.message) {
words += status.message.split(/ /g).length;
}
});
}
if (response.paging && response.paging.next) {
posts(callback, response.paging.next);
} else {
alert("You wrote " + words + " on Facebook!");
}
});
}
This works just fine for people who have posts a total of up to 4,000 statuses, but it really starts to crawl for power users with 10,000 lifetime updates or more. Each response from the API is only about 25Kb, but I cannot figure out what's straining the most.
After I've added the number of words in each status to my total word count, do I need to specifically destroy the response object so as not to overload memory?
Alternatively, is the recursion depth a problem? we're realistically talking about a total of 100 calls to the API for power users. I've experimented with upping the limit on each call to fetch larger chunks, but it doesn't seem to make a huge difference.
Thanks.
So, you're doing this with the JS SDK I guess, which mean this runs in the Browser... Did you try to run this in Chrome and then watch the network monitor to see about the response time etc.?
With 100 requests, this also means that the data object/JSON must be about the size of 2.5mb, which for some browsers/machines could be quite challenging I guess. Also, it must take quite a while to fetch the data from FB. What does the user see in the meantime?
Did you think of implementing this in the backend on the server side, and then just passing the results to the frontend?
For exmple use NodeJS together with SocketIO to do it on the server side and dynamically update the word count?

Categories

Resources