Can't get voiceStateUpdate when user disconnect from server - node.js

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.

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.

Have a bot mention all users in a Discord voice channel

Does anyone know of a way to return all users within a Discord voice channel for the purpose of having a bot mention them all in a text message? I do not mean the #everyone mention.
For example, if players A, B, and C were all in the same voice channel, and one of them typed .vote (my bot's trigger command), the bot would create a new vote which mentions players A, B, and C. The vote closes once all mentioned players have reacted to the vote.
I'm pretty new to making discord bots... I have looked through the Discord Developer Portal SDK, but did not find anything on this subject.
After some work looking in the manual, I found something you can use.
There is a class named VoiceChannel, this one has a snowflake with all members in it. Every member in that snowflake is an instance of GuildMember.
So, if I'm not wrong, you can use this code:
VoiceChannel.members.forEach(function(guildMember, guildMemberId) {
console.log(guildMemberId, guildMember.user.username);
Channel.send("<#" + guildMemberId + ">");
})
Please note that you can't just copy paste the code and expect it to work. You need to change both VoiceChannel and Channel to the proper objects.
Read this as reference:
https://discord.js.org/#/docs/main/stable/class/VoiceChannel

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.

socket.io, users in specified socket

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.

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