socket.io, users in specified socket - node.js

I have a little problem with socket.io. I want to update users in specified room. I followed this tutorial and added a "userlist"( http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/ ) when you change room your nickname should disappear from the list and update user/users in the new one
Is it possible by doing something like this?
usernames = {};
var clients = io.sockets.usernames(socket.room);
Then call:
io.sockets.emit('updateusers', clients);

The idea is that rooms have own list of sockets when you enter or leave it it manages own list.
So what you want to do, is when user leaves the room - broadcast message to that room:
socket.broadcast.to('room1').emit('userRemove', 'data');
Sockets from that room should process this message on receive, in order to remove actual record from the list (it can be html list if this is web applciation), as on server it is not in the room anymore.
This is called synchronization.

Related

Threaded messaging on pubnub

We want to create threads for messages within a chat channel on Pubnub. For example, someone could respond to a specific message in a channel by 'creating a thread' and starting to chat. Is there a prescribed way to model this behavior? If so, can you please reference documentation?
This is the behavior you see in slack, for reference.
There's no ready-made solution documented for threaded messaging. However, building a hierarchical relationship between messages could be achieved by tagging them with metadata (using PN Objects and/or MessageActions) and then some coding on your end to maintain and handle their relationship.
You could use the time token of the thread's first message as the key, group messages based on it, and use the messages' own time tokens to generate the order for the UI.
https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#methods
Here's the high-level design for doing this:
A message is published to a channel with the name chat_11223344 (channel name uses chat_ as a prefix for all chat channels and a generated id - keeping it short here but you can use a uuid generator for this). That publish returns a publish timetoken, something like this: 16183330926487763.
Using PN Objects, your display name for the channel can be set along with a description.
In your chat UI, you allow a person to create a thread on that message. The message gets published to a channel named chat_11223344.16183330926487763 , using the publish timetoken of the top-level message as the "sub-channel" name.
So that you can easily identify top-level messages that are threaded, you would add a MessageAction to that message when the first "threaded" message is published. You may also want to add custom Channel Metadata (PN Objects, again) to add a "isThreaded":true key/value.
So with PubNub you can append meta data to either the message itself or PubNub has a section called meta (https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#methods).
An example payload could be:
{
"type":"message",
"payload":"What do people want for lunch? Pizza?",
"sender":"me",
"sent":1618336638,
"messageActive":true,
"channel":"main",
"messageID":"main.abc123"
}
where abc123 is a uuid that references that message.
When someone wants to thread a message you can append "threaded":true variable to the object.
{
...
"messageID":"main.abc123",
"threaded":true,
...
}
Now your UI knows that there is a breakout thread, using main.abc123.thread as the channelID for that specific thread.
Your app then subscribes to the new channel main.abc123.thread and you can use fetchMessages(); to get history messages as well as new real time messages.

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 make the bot initiate 1:1 conversation in a group with the user in Slack using Microsoft bot-framework?

I am using Microsoft bot-framework for Nodejs. I want my bot to start a private conversation within a group with a user. Currently, my bot carries on the conversation with any member responding.
For example,
Me: Hi #bot
Bot: Hi
Me: I need to order a pizza
Bot: What would you like on your pizza?
SomeTeamMember: Mushrooms and Onions
Bot: Ordering Pizza with Mushrooms and Onions.
As you can see, the conversation was hijacked by some other member, this is the issue I am facing, I want to avoid this from happening. I want the bot to only communicate with one member at a time and when the conversation ends with that user, it is open to communicate with anyone in the same manner as previous user. Any suggestion would be great!
You are using slack? Anyway, when you reach "Bot: What would you like on your pizza?", you should be in a completely new dialog where you can use each conversation member Id and store it to data bag (context.ConversationData) in order to have context.
When "SomeTeamMember" joins the conversation, you can check his or hers conversation member id to get the state for each member, and act accordingly.
Hope this helps :)
Alex
I think you could use the session object and access the message sender id i.e session.message.user.id. And maybe filter out messages coming from other users other than the one that said I need to order a pizza.
Also from the documentation I think you could use something like dialog triggered by an action, activated right after I need to order a pizza.
You could then check the user's id, and reroute to dialogs where the other users will be filtered out, except for the sender of I need to order a pizza...
If you try something like, or complexify:
bot.dialog('pizzarouting', function (session, args, next) {
})
// Once triggered, will start a new dialog as specified by
// the 'onSelectAction' option.
.triggerAction({
matches: /^Pizza$/i,
onSelectAction: (session, args, next) => {
// Add the help dialog to the top of the dialog stack
// (override the default behavior of replacing the stack)
session.send('What would you like on your pizza?')
console.log(session.message);
// Reroute to dialog that filter out the other people id
// session.beginDialog(args.action, args);
}
});
This gets activated only if a user sends 'Pizza' in chat.
You'll see that the session object holds the message object, which you could use for example to identify the user who sent I need to order a pizza and get his id for subsequent filtering.
I hope you or anyone who gets around this gets interesting ideas.

METEOR JS: Actions with multiple users

I have 2 chat rooms, in every room I have 5 users and input field , where every user can enter some number and submit it to validate on server, if number equal (for example) to 5 than users in this room win, and users in other room lose, so I have 5 users that win and 5 that lose.
So, what I want: when one of team win, than redirect users that wins to some WIN page, and at the same time redirect users that lose to LOSE page. And !THIS IMPORTANT! if some users for example was offline but his team won or lose , than when the next time user log in show LOSE or WIN page which depends on whether his team won or not.
So I see 3 problems for which I do not find a solution:
Redirect group of users (I use Iron Router)
Track when one of team win (track for all users that play game) (Blaze if unsuitable)
If some team wins and user was offline , hen the next time user log in show LOSE or WIN page
I know that a lot of questions and they are very extensive, but could not find the solution, help somebody !
It might be simpler to track this at the group level and then just have a template helper that tracks the group's win/loss status. You wouldn't even need a session variable and all participants would get the correct notification instantly or deferred. Ex:
HTML:
<template name="wrapper">
{{#if state.inProgress}}
{{> gameTemplate}}
{{else}}
{{#if state.won}}
{{> winnnerTemplate}}
{{else}}
{{> loserTemplate}}
{{/if}}
{{/if}}
</template>
JS:
Template.wrapper.helpers({
state: function(){
var myGroupId = Meteor.user().myGroupId;
var outcome = Groups.find({ _id: myGroupId }).outcome;
return { inProgress: ( outcome === 'in progress'), won: ( outcome === 'won' ) };
}
});
Here I'm returning an object from the helper instead of separate variables for inProgress and won to avoid searching Groups twice.
I've also modeled each user as belonging to one group with the groupId being a key in the user object. This obviously allows you to have any number of people in each group as well as any number of groups.
What I've left out is the server side logic that sets the outcome key in the Group documents. You'll have to set one group to won and the other to lost in the same server method.
You have a design problem.
and 2. If you want to track the "groups" (if they lose or win, redirect to win or lose) in your app, you have to create a group collection to manage the "states" of your game(I think your app is like a game).
with the group collection you can show the information to the members, i.e. if I'm in a group even if I was offline when I login in your app I will be able to see what is in my groups records.
Its a matter of design and know how manage the data and the events in meteor

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

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.

Resources