I am trying to implement an Alexa Skill with Multi Turn method and a Node.js back end.
alexaApp.intent("findFact", {
"dialog": {
type: "delegate"
},
},
function(request, response) {
console.log("In Fact intent");
var test = this.event.request.intent.slots.testtwo.value;
// console.log(request.dialogState);
console.log("test fact : " + test);
response.say(get_fact());
}
);
Iam not able to get the value within the testtwo slot.
The console displays 'Unhandled exception: Cannot read property 'request' of undefined.'
Any idea why ?
Thanks !
ANSWER IS :
var test = request.data.request.intent.slots.testtwo.value;
Related
I have my Spring-Boot service setup so I can send messages through websocket to my browser and it works.
//#MessageMapping
#RequestMapping(value = "/notify")
#SubscribeMapping("/notification")
#SendTo("/topic/notification")
public String sendNotification() throws Exception {
sendMessage();
return "Request to update Tanks has been sent!";
}
public void sendMessage() {
this.messagingTemplate.convertAndSend("/topic/notification", "IT WORKS");
}
Here's the console log from chrome:
<<< MESSAGE
destination:/topic/notification
content-type:text/plain;charset=UTF-8
subscription:sub-1519225601109-13
message-id:f2qodiqn-8
content-length:8
IT WORKS
I want to be able to receive a message from the service and update the state in react, so, that it refetches from the backend. This is what my client looks like:
var socket = new SockJS("http://localhost:6667/refresh");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('connected: ' + frame);
stompClient.subscribe('/topic/notification', function(notification){
console.log(notification.body);
//this.showNotification(JSON.parse(notification.body).content);
//this.showNotification(notification.body);
})
}, function(err) {
console.log('err', err);
});
And the fetch in componentDidMount()
fetch(`http://localhost:6666/front/objects`)
.then(result=>result.json())
.then(fuelTanks=>this.setState({fuelTanks}))
.catch(function(err) {
console.log('Could not fetch: ' + err.message);
}
)
I can't use this.showNotification(notification.body), hence I can't set the state to be able to refetch my objects. I tried making methods outside the class but then I can't use anything from the main class.
Is there a way to make react run componentDidMount again, or better, just access the fetch method in my class when I get a message from spring through the websocket?
Like this:
componentDidMount(){
var socket = new SockJS("http://192.168.1.139:8610/refresh");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('connected: ' + frame);
stompClient.subscribe('/topic/notification', function(notification){
refetchTanks(); // call fetch tanks -> can't use "this"
})
}, function(err) {
console.log('err', err);
});
Thanks!
I know, it is a bit old question, but since it pops every time when you search for stomp issue, i thought of answering it. The way to access this in callbacks is to bind callbacks with this first, then the whole of object can be accessed in the callback.
Example:
connectCallBack(){
this.setState({loading:false})
}
errorCallback=()=>{
}
componentDidMount() {
axios.post('http://localhost:8080/subscribe', null, { params: {
deviceId
}})
.then(response => response.status)
.catch(err => console.warn(err));
const socket = new SockJS('http://localhost:8080/test');
const stompClient = Stomp.over(socket);
//stompClient.connect();
stompClient.connect( {}, this.connectCallBack, this.errorCallback);
If see above code both callbacks can access this.
I tried everything to be able to use my class methods and the state in stompClient's .subscribe method. I was able to connect and reconnect if the service died, nevertheless it wasn't working.
I decided to use react-stomp, which worked. I could use a class method in onMessage=.... This is what my code looks like:
<SockJsClient
url = 'http://localhost:8610/refresh/'
topics={['/topic/notification']}
onConnect={console.log("Connection established!")}
onDisconnect={console.log("Disconnected!")}
onMessage={() => this.update()} <------ this method performs a new GET
request
debug= {true}
/>
I also had to send the message in a specific way on the server side, since I was getting a JSON error when sending a string.
this.messagingTemplate.send("/topic/notification", "{"text":"text"}");
<<< MESSAGE
destination:/topic/notification
content-type:text/plain;charset=UTF-8
subscription:sub-0
message-id:aaylfxl4-1
content-length:49
{
"text": "text"
}
It currently works, but I am curious if there are other, better solutions to this issue.
EDIT: a much better solution here! Use the code from the first post and create a variable before connect to be able to access this like this var self = this;, then just access is as self.update() after subscribe!
I am trying to send data to Google Analytics from a WPF application. I can't find any resource online which clearly defines how to do that. I know that there are numerous NuGet packages available, but I'm not sure which to use, nor how to implement them. I also know that there are some third-party "helper" libraries available (see Using Google Analytics from a .NET desktop application), which I'm not interested in. It also looks like most instructions online are showing how to "pull" data from GA, not how to push. Not looking for "maybe"'s or workarounds but what the normal straightforward way to do this is. This shouldn't be complicated. Just need a "Hello World".
Can you please point me in the right direction? Thanks,
This worked for me:
var request = (HttpWebRequest)WebRequest.Create("http://www.google-analytics.com/collect");
request.Method = "POST";
// the request body we want to send
var postData = new Dictionary<string, string>
{
{ "v", "1" }, //analytics protocol version
{ "tid", "UA-XXXXXXXX-X" }, //analytics tracking property id
{ "cid", "XXXX"}, //unique user identifier
{ "t", "event" }, //event type
{ "ec", category },
{ "ea", action },
};
var postDataString = postData
.Aggregate("", (data, next) => string.Format("{0}&{1}={2}", data, next.Key,
Uri.EscapeDataString(next.Value)))
.TrimEnd('&');
// set the Content-Length header to the correct value
request.ContentLength = Encoding.UTF8.GetByteCount(postDataString);
// write the request body to the request
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(postDataString);
}
var webResponse = (HttpWebResponse)request.GetResponse();
if (webResponse.StatusCode != HttpStatusCode.OK)
{
throw new Exception($"Google Analytics tracking did not return OK 200. Returned: {webResponse.StatusCode}");
}
I currently have a Rails 5 application acting as my back-end,we can call this the "Core." I also have another Angular 1.6.4 application acting as my front-end, which is serving up Angular client side,And integrate with backed-end application through angular-actionable we can call this the "Front". These are two completely separate applications with completely different domains.
Basically, I am trying to integrate Action Cable through the Core and have it talk to the Front. I'm using this service here for the Front: enter link description here. As far as the Core, that's just basic Action Cable set up.
I have a list of chat rooms on admin side.
Problem: I sent message from client side but it broadcast message to all the chat rooms in admin side.I try to give the specific path of chat room in stream but still it broadcast message to all chat rooms.
I want to broadcast the message to specific chat room
Core
chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from stream_name
end
def unsubscribed
stop_all_streams
end
def receive(data)
ActionCable.server.broadcast stream_name, data.fetch('message')
end
private
def stream_name
"chat_channel_#{chat_id}"
end
def chat_id
params.fetch('data').fetch('chat')
end
end
Fornt
chatCtrl.js
app.run(function (ActionCableConfig){
ActionCableConfig.debug = true;
ActionCableConfig.wsUri= "ws://localhost:3000/cable";
});
app.controller('chatCtrl', ['$scope', 'ActionCableChannel',
function($scope, ActionCableChannel) {
var consumer = new ActionCableChannel("ChatChannel", { chat: 'localhost:3000/#!/chat/1'});
var callback = function(message) {
$scope.myData.push(message);
};
consumer.subscribe(callback).then(function(){
$scope.sendToMyChannel = function(message){
consumer.send(message);
};
$scope.$on("$destroy", function(){
consumer.unsubscribe().then(function(){ $scope.sendToMyChannel = undefined; });
});
});
}
]);
this is the solution for my problem, very similar to yours, but I did not use cofeescript, just javascript.. so I attach also my code if you need it.. I just check that the attribute data-chat-room-id from the DOM is equal to the one I am passing with the message:
The message controller create the message then with ActionCable.server.broadcast calls with those parameters (message, user, chatroom_id, lastuser) my js code in messages.js
class MessagesController < ApplicationController
def create
message = Message.new(message_params)
message.user = current_user
chatroom = message.chatroom
if message.save
ActionCable.server.broadcast 'messages',
message: message.content,
user: message.user.name,
chatroom_id: message.chatroom_id,
lastuser: chatroom.messages.last(2)[0].user.name
head :ok
end
end
end
Inside app/assets/javascrips/channels/messages.js I do a check that data.chatroom_id (the element from the DOM) equals chat_room_id (the element sent from the controller, of the object message just saved)
App.messages = App.cable.subscriptions.create('MessagesChannel', {
received: function(data) {
messages = $('#chatroom_id');
chat_room_id = messages.data('chat-room-id');
if (data.chatroom_id == chat_room_id) {
$('#messages').append(this.renderMessage(data));
};
},
renderMessage: function(data) {
return "<br><p> <strong>" + data.user + ": </strong>" + data.message + "</p>";
}
});
This is the article that gave me this answer
Action Cable chat Ilya Bodrov-Krukowski
Ilya Bodrov-Krukowski on Github
Another problem to tackle here is providing our script with the room’s id. Let’s solve it with the help of HTML data- attribute:
views/chat_rooms/show.html.erb
<div id="messages" data-chat-room-id="<%= #chat_room.id %>">
<%= render #chat_room.messages %>
</div>
Having this in place, we can use room’s id in the script:
javascripts/channels/rooms.coffee
jQuery(document).on 'turbolinks:load', ->
messages = $('#messages')
if $('#messages').length > 0
App.global_chat = App.cable.subscriptions.create {
channel: "ChatRoomsChannel"
chat_room_id: messages.data('chat-room-id')
},
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
# Data received
send_message: (message, chat_room_id) ->
#perform 'send_message', message: message, chat_room_id: chat_room_id
I'm using Twilio's NodeJS module & API to send out MMS messages with images attached (from a remote URL), and I want to delete the Media instances that get created on Twilio servers as soon as I send out the messages.
My messages send out correctly, and in the callback, I'm trying to 1) list media instances for the current message, then 2) loop through those instances and delete. The problem is that the mediaList array that comes back from the API for a current message is always empty.
Here's my code:
twilio_client.messages.create({
body: "Thanks for taking a photo. Here it is!",
to: req.query.From,
from: TWILIO_SHORTCODE,
mediaUrl: photo_URL,
statusCallback: STATUS_CALLBACK_URL
}, function(error, message) {
if (!error) {
twilio_client.messages(message.sid).media.list(function(err, data) {
console.log(data);
// The correct object comes back as 'data' here per the API
// but the mediaList array is empty
}
console.log('Message sent via Twilio.');
res.status(200).send('');
} else {
console.log('Could not send message via Twilio: ');
console.log(error);
res.status(500).send('');
}
});
So, it turns out that trying to get the media list at the point I was trying to doesn't work because the media instances didn't exist yet.
I have a separate little app running at the statusCallback (I supply a URL via a constant in the code above, STATUS_CALLBACK_URL), that until now, just checked to see if a message I tried to MMS to a user wasn't handled properly by Twilio, and alerted the user to a problem via SMS. So, I added a check in that same app to see if the message was actually 'sent' to the user, and then checked for and deleted the media instance(s) associated with the message at that point, and it works fine. Here's my code:
// issue message to user if there's a problem with Twilio getting the photo
if (req.body.SmsStatus === 'undelivered' || req.body.SmsStatus === 'failed') {
twilio_client.messages.create({
body: "We're sorry, but we couldn't process your photo. Please try again.",
to: req.body.To,
from: TWILIO_SHORTCODE
}, function(error, message) {
if (!error) {
console.log('Processing error message sent via Twilio.');
res.send(200,'');
} else {
console.log('Could not send processing error message via Twilio: ' + error);
res.send(500);
}
});
}
// delete media instance from Twilio servers
if (req.body.SmsStatus === 'sent') {
twilio_client.messages(req.body.MessageSid).media.list(function(err, data) {
if (data.media_list.length > 0) {
data.media_list.forEach(function(mediaElement) {
twilio_client.media(mediaElement.sid).delete;
console.log("Twilio media instance deleted");
});
}
});
}
I am building a web application using Parse.com as my backend. I have run into a problem when trying to store the response from Facebook's user profile API in a Parse database.
FB.api('/me', function(response) {
// Print Response to Console
console.log(response);
// Create New Parse Object
var Facebook = Parse.Object.extend("Facebook");
var userFacebook = new Facebook();
for(var element in response) {
userFacebook.set(element, response[element]);
}
// Store Data on Parse
userFacebook.save(null, {
success: function(user) {
console.log("User Facebook data saved.");
},
error: function(user, error) {
console.log("Facebook data storage error: " + error.code + " (" + error.message + ")");
}
});
The API response prints correctly to the console, and I receive two error messages, one after the other:
Failed to load resource: the server responded with a status of 404
(Not Found) https://api.parse.com/1/classes/Facebook/myID
and
Facebook data storage error: 101 (object not found for update)
In my Parse account, a database titled "Facebook" is created. However, it only contains a header for each of the elements in the response object (e.g., first_name, gender, email, etc.). It does not have a new row with these values.
I am really stuck on this one -- any help would be appreciated!
Note that the response object is in the form:
{
"email":"email#example.com",
"first_name":"myFirstName",
"gender":"myGender",
"id":"myID",
"last_name":"myLastName",
"link":"https://www.facebook.com/app_scoped_user_id/myID/",
"locale":"en_US",
"name":"myFullName",
"timezone":-7,
"updated_time":"2014-03-12T04:57:39+0000",
"verified":true
}
The object in for each loop
for(var element in response) {
userFacebook.set(element, response[element]);
}
FB.api('/me', function(response) {
// Print Response to Console
console.log(response);
// Create New Parse Object
var Facebook = Parse.Object.extend("Facebook");
var userFacebook = new Facebook();
for(var element in response) {
userFacebook.set(element, response[element]);
}
// Store Data on Parse
userFacebook.save(null, {
success: function(user) {
console.log("User Facebook data saved.");
},
error: function(user, error) {
console.log("Facebook data storage error: " + error.code + " (" + error.message + ")");
}
});
The "id" column on a Parse.Object is protected and cannot be set via the API. In my case, Facebook's API response includes an "id" key, which is colliding with the Parse.Object "id" key.
If you are running into the same problem, you simply need to change the name of the "id" column. You can do this with the following code:
for(var element in response) {
if(element=="id") {
userFacebook.set("userID", response[element]);
} else {
userFacebook.set(element, response[element]);
}
}
Thanks to Hector Ramos at Parse for helping me solve the problem! And thanks to Wayne for getting me part of the way!