Need recommendations for pattern for now.js object sharing in group - node.js

I have an application where I want to use node.js and now.js to share the state of an object within a nowjs "group" across any number of clients.
As an example of what I'm trying to do, let's say that within the multiroom chat example that comes with now.js, there could be any number of rooms, with the ID chosen by the user. If the user knows the ID, they can enter (or be the first to "create") that room. There is a "history" object that is maintained for each room once it is created and communication starts happening. The history object contains a property or two, and an array of comment objects, each with a user property, a comment property, and a datetime property. When a new user connects, they should immediately have access to the history.
Is there a way to store a group-scoped object variable on the server to sync with? Am I thinking about this in the wrong way? Am I crazy or a little slow?

OK...I got it.
I have a new function createHistory(groupid) on the server side, which returns a new history object if it doesn't already exist when the user enters the room(group). This would occur if this user just created the room.
This history object employs add, remove and list methods. Since I need to get at the list from the client, it's important that I use a callback like the following:
api.get = (callback) ->
callback(_history)
I assign the result:
everyone.getGroup(this.now.groupid).now.history = createHistory(this.now.groupid)
Now I can add history at the server:
api.add = (time,user,text) ->
_history.items.push {time:time, user:user,text:text}
And get to it from my client:
now.history.get (history) ->
for item in history
#do something...
The only drawback is once the room is empty, the history evaporates...I think. Although I suppose you could check for the last disconnect and persist it somewhere if you wanted.

Related

Can't get voiceStateUpdate when user disconnect from server

I have a function of automatized channels,
All changes are triggered with voiceStateUpdate event.
All work very good but when a user disconnect from server, voiceStateUpdate is not called...
So how can i know if user leave with disconnection from server ?
UPDATE :
I finally got it in voiceStateUpdate, I just dont check if newMember or oldMember, I make my channels update directly by Client and not by the user.
There is currently no voiceStateUpdate event emitted when a Member disconnects from a voicechannel by leaving the Guild. This is a limitation with Discord itself, not the library.
I'd suggest using the guildMemberRemove event, which emits a GuildMember object. You can use that Object to loop through all the voicechannels in the Guild and check which one the Member disconnected from when leaving.
You can save users who are in the voice channel and then checking if the user who left the guild is in the list.
Upon testing, voiceStatusUpdate does not fire when a user has exit. This seems to be an issue with Discord itself. The guildMemberRemove event does fire, though. So to work around this, you must create an array that holds the user's ID, and if a member leaves, check if they were in a voice channel. If you want to monitor multiple channels, you can put all of the channels in an object with the channel ID as a key, and the array of participants (using their IDs, to preserve memory) as the value.
Depending on what method you choose, the resulting object might look like this.
{
"channel1ID": ["member1ID", "member2ID"],
"channel2ID": ["member3ID", "member4ID"]
}
Now when a member disconnects, simply remove their name from the array of the voice channel they were in. When a member leaves, check every array for their ID. Using this, you'll also be able to get the ID of the channel the member was originally part of.

How to get data from other intent? (pass data for intents to other intents)

I'm making a actions on google project that will use basic functionality of remembering what the user says and using it for another intent.
So for example, this is what the conversation might look like:
1 User: Hello
2 Bot: Hey! What's your name?
3 User: Joel
4 Bot: Your name is Joel, is that correct?
5 User: Yes that is correct
6 Bot: Awesome, it's great to meet you Joel.
I know how to get the information initially, but I am having trouble with getting the information (the name 'Joel') passed to another intent that is used purely for confirmation.
Here is what I have:
app.intent('greeting', (conv, params) => {
const context = conv.contexts.set('context'); // working good
conv.ask(`I got ${params.name}, is that right?`);
});
app.intent('greeting_1', (conv,params) => {
const context1 = conv.contexts.get('context'); //not working
conv.ask(`Awesome, it's great to meet yoy ${params.name}`);
});
If this helps, specifically the error I'm getting reads:
TypeError: Cannot read property 'userDecision' of undefined
How do I get this to work? I have a feeling I have to save the data in userStorage but I've only really had to do that is very basic cases so I'm not to familiar with that.
Thanks for the help!
First of all, hi!
Your initial thought of storing the data in UserStorage might be correct depending on your use case. Let me elaborate:
Two Ways of Saving Data with Actions On Google Node.JS Client Library
Storing Data In A Conversation
You can use conv.data.name = 'Joel' to save the data between the turns of a conversation. But this data won't be available the next time user comes back.
Storing Data Permanently (As Long As The User Allows It)
This is where userStorage comes into play. You can use conv.user.storage.name = 'Joel' to remember the user's name every time they come back. Keep in mind that this type of permanent storage may require consent from the user depending on where they live.
Legal note: Obtaining consent prior to accessing userStorage. Some
countries have regulations that require developers to obtain consent
from the user before they can access, or save certain information
(e.g. personal information) in the userStorage. If you operate in one
of these countries and you want to access, or save such information in
userStorage, you must use the Confirmation helper to ask consent to
the user and obtain the consent before you can start storing such
information in userStorage.
You also need to explain the data you're saving in your Privacy Policy.
As for you specific use case, storing data that won't change (i.e. name) in userStorage is a much better method. Since if you only save it for one conversation, you'll need to ask for permission again the next time.
These should cover your basic needs of saving data on the platform. However, if you do need a more complex state management solution, you may want to check Dialogflow Contexts.
EDIT: I overlooked that you were already using contexts. But the answer still stands, you don't need to use contexts if all you want to do is to save data during a conversation.
But I think the reason you're having a problem is that you're not setting or getting the context parameters correctly. Take a look at the examples here and here:
The context.set() method gets three parameters; name, lifespan and parameters. You're only passing the name of the context in your code.
And, using only contexts.get() method isn't enough to read parameters of a context. You need to read them like this:
app.intent('Tell Greeting', conv => {
const context1 = conv.contexts.get('context1')
const { color, num } = context1.parameters
})
But, I repeat my original point. You shouldn't make things so complicated for yourself if you don't really need to. Try using conv.data and conv.user.storage if possible.

How can we know ID of the document on client side

I have recently learned tutorial about restful APIs.In that, my instructor suggested me that if we want to delete any document we should pass id in the parameter of the request. But now I am confused How do we handle this implementation on the client side.I mean how can even the programmer on the front side could be aware of that particular document ID. Does he need to go to the database each time?
Common practice for accessing a record in db is to use its unique identifier, to get or update or delete the record.
On the client side (if you mean user interface) when user wants to delete a document, he/she must see the document somewhere in the interface. Suppose a page with a table containing a list of all (for instance) books in the db. On each row, you have book title and author's name and the id of the book document in the db.
So you can use that id to call the delete rest API.
In a nutshell, when you want to delete something you must have got it from db to simply see it, so the id is at your hand.
When you want to delete a some doc from the database you need to get all documents to the front end to see what do we need to do to this data right ?
Imagine any database GUI that u have worked with..
let's say phpmyadmin when using mysqli
in that case you have php mydamin's GUI so that u can clearly see what are the tables and how things persist in the database. you need to see that in order for you to make decision
. Like that you will need to bring at least a portion of that data to the front end for user to see it and choose what portion of data the user want's to make changes or delete.
so when we have a set of data in the front end like a list, if a user select one item from that list the id or the name of that item can be send to the server side and make the task if the user wishes to do
that's why you need an Id or a identification field of that particular data..

Is it possible to gather multiple values with Twilio IVR?

I have a view function that needs to gather multiple pieces of information in one call (it's a quick outbound call - the user answers and is to be immediately prompted for these data points), based on data pulled from a DB. What I'd like the view function to do is something like the following:
group_id = <get group id>
params = data_element_select_params.DataElementSelectParams(group_id=group_id)
data_elements = worker.select(params) # function I wrote which returns a list of objects, in this case objects called DataElements
vr = VoiceResponse()
say_msg = 'Enter {element}, then press star.'
for element in data_elements:
say_message = say_msg.format(element=element.name)
<Gather input with say_message and save it>
Can this be achieved without routing to the same URL over and over? I have not seen any other solution, and I'd rather not continually redirect to the same URL as we'll have to pull the list of elements from the DB again for each element.
Apologies if anything is unclear - please point it out and I'll clarify as quickly as I can.
Twilio developer evangelist here.
You can only use one <Gather> per TwiML document, so no, you can't ask multiple questions and take multiple inputs within the one webhook.
You will need to route to a URL that receives the input from each <Gather> and then asks the next question.
To avoid pulling all the elements from the DB every time, you could investigate saving the elements to the HTTP session and pulling them back out of there. Twilio is a well behaved HTTP client, so you can use things like cookies to store information about the current call/conversation.

Related objects in activity feed

I'm building an activity feed application, where a user can like/comments on each activity feed. I went through GetStream.io documentation and looks like I'll have to send the activity with object ids.
{
id:"ef696c12-69ab-11e4-8080-80003644b625",
actor:"User:1",
object:"Comment:12",
started_at:"2014-11-11T15:06:16+01:00",
target:"Feed:100",
time:"2014-11-11T14:06:30.494",
verb:"add"
}
User:1 and Feed:12 are the objects in my application database? Does it mean that, while retrieving activities, I'll have to hit my database to retrieve the complete feeds?
Say the Feed:12 had few likes and comments earlier from other users. How do I get the complete set of likes/comments on user timeline feed?
What if I want to customize the view, say I want to show all users (image, name, the profile like etc) along with comment with timestamp similar to FB? Do I need to send these attributes as additional parameters for each feed?
Thanks,
Yes, when you fetch a feed from Stream and we give you back these references like user:1 or comment:12, we expect that you'd "enrich" those details from your database.
Typically what our users do is track the name of the model (eg, user) and the user_id (eg, 1). When you get the feed and put it into a hash map, you'll iterate over the activities, pull out all of the actor attributes, and do a single lookup like select * from user where id in (1,3,5,6,9,12) so that you're only hitting your database one time for all user objects or all comment objects or whatever. Then, replace those activities in your hash map so now you'd have actor: <object for User 9> and any other attributes you'd need for your UI presentment.
Then do the same for other references you pass in the activity, and so on.
Things we DON'T recommend are putting in string references for things that could change on your side. For example, if you had actor: "user:ian" instead of my user_id, if I ever change my username later then things probably wouldn't work properly on your side.

Resources