With twilio: Mute a specific participant in a room - javascript

I made a lot of searches, and tried many things. Let's take the same scenario from this question.
Bob, Alice, and Jane are in a conference. I want Bob (the hoster of the room) to be able to mute Alice so sounds from Alice will not come through the room, but Alice still hear sounds from all other participants (Bob & Jane)
Imagine the scenario when you are in conference, and someone disturbs the Live. So I want the hoster to be able to mute or remove the audio track of that person.
So far, I can mute the audio tracks for the local participant with:
$(document).on("click",'.mute-audio',function(){
if(room){
let microEnabled = true;
microEnabled = !microEnabled;
room.localParticipant.audioTracks.forEach(function(audioTrack) {
audioTrack.enable(microEnabled);
});
}
});
We simply iterate through audioTracks of the local participant, and if I want to do so for a specific User, I just need to know his identity and I am good to go:
$(document).on("click",'.mute-user',function(){
var identity = $(this).data('identity'); // i.e the unique ID USER2323
if(room){
var user_to_mute;
room.participants.audioTracks.forEach(function(participant) {
audioTrack.enable(microEnabled);
user_to_mute = participant;
// We retrieve the target
return;
});
let m_Enabled = true;
m_Enabled = !m_Enabled;
if(user_to_mute){
user_to_mute.audioTracks.forEach(function(audioTrack) {
audioTrack.enable(m_Enabled);
// the error is here I think
return;
});
}
}
});
But it doesn't work, when I try I got this error from the browser
TypeError: audioTrack.enable is not a function

It looks like some copy paste errors to me, but not being familiar with the API, I'm making a few assumptions:
$(document).on("click",'.mute-user',function(){
var identity = $(this).data('identity'); // i.e the unique ID USER2323
if(room){
var user_to_mute;
// in the next line, we remove .audioTracks, since it looks like
// you want to iterate over participants, and removed audioTrack.enable
// since it's not defined yet
room.participants.forEach(function(participant) {
if (identity == participant.identity) {
// We retrieve the target
user_to_mute = participant;
return;
}
});
let m_Enabled = true;
m_Enabled = !m_Enabled;
if(user_to_mute){
user_to_mute.audioTracks.forEach(function(audioTrack) {
audioTrack.enable(m_Enabled);
return;
});
}
}
});

Related

TOO_MANY_CHARACTERS_OF_MENU_DESCRIPTION

I am trying to make a discord bot for a database or something similar. The point of the bot should be to store information. I want to store the number of podcasts I have listened to, how many hours they add up to, and what are they, all this sort of information. I thought a discord bot should do; I know of quite a few that store such information. I am really a beginner to this, and any information would help me out. one of the functions that this bot should have is a dropdown menu; I came across this problem where when I call the menu function, the bot crashes, and I get this type of error:
throw new Error(
^
Error: TOO_MANY_CHARACTERS_OF_MENU_DESCRIPTION: The maximum length of MessageMenuOption.description is 100 characters, received 54 instead.
This is my code of the dropdown menu:
client.on('message', async message =>{
if(!message.guild || message.author.bot) return;
if(message.content == prefix + 'menu'){
//first option
let = option1 = new MessageMenuOption()
.setLabel('Podcast')
.setValue('Podcast')
.setDescription('If you have listened to a podcast today, post it here!')
.setDefault()
//second option
let = option2 = new MessageMenuOption()
.setLabel('Tutorial')
.setValue('Tutorial')
.setDescription('If you have watched a tutorial today, post it here!')
.setDefault()
//third option
let = option3 = new MessageMenuOption()
.setLabel('Documentary/General_knowledge')
.setValue('Documentary/General_knowledge')
.setDescription('If you have watched a documentary today, post it here!')
.setDefault()
let selection = new MessageMenu()
.setID('Selection')
.setMaxValues(1)
.setMinValues(1)
.setPlaceholder('Select something!')
.addOption(option1)
.addOption(option2)
.addOption(option3)
let embed = new Discord.MessageEmbed()
.setColor('BLURPLE').setTitle('What have you learned today?')
let menuMsg = await message.channel.send(embed, selection)
function menu_selection(menu) {
switch(values[0]) {
case 'Podcast':
menu.reply.send("Nice!, hope this podcast was useful!")
break;
case 'Tutorial':
menu.reply.send("Nice!, hope this tutorial was useful!")
break;
case 'Documentary/General_knowledge':
menu.reply.send("Nice!, hope this video was useful!")
break;
}
}
client.on('clickMenu', (menu) => {
if(menu.message.id == menuMsg.id) {
if(menu.clicker.user.id == message.author.id) menu_selection(menu)
else menu.reply.send("Type ```.menu``` to get access to this menu!")
}
})
}
})

Discord.js - Getting users last activity?

I'm trying to find out if its possible to get the time/information of users last activity retrospectively using discord.js
Say I have something like
client.guilds.find('id', 'SERVER ID').fetchMembers().then(members => {
const role = members.roles.find('name', 'Newbies')
role.members.forEach(member => {
console.log(member.user.lastMessage) // null
})
})
Unless the member has posted, since the client is listening, the lastMessage is always null.
Is there a way to find the last activity? or a workaround, like a query to return all the users messages, which I can then take the most recent one from?
Effectively I want to know what date/time the user last posted so we can monitor non-contributing accounts.
Thanks
After looking thought the documentation I didn't find something neither so I came up with a manual search function.
Basically, it will scan every channels until finding a message from X user, or the end of the messages in the channel. It then compare the last messages of the users from every channels and print the last one.
It can be very long if the user hasn't write since a long time. Of course, you have to check lastMessage before trying this.
I would add a time limit maybe. Because if you have thousand of messages, the function will run eternally.
You can stop the function if the last message found is in the accepted time to not be kick/do whatever.
I made the search stop if the first message found in the pack of fetched messaged is older than the ban limit, however, if the first message is not older, remember that it means for the other, so we still need to check them (it can be avoided by checking the last message of the pack as well).
async function fetchMessageUser(chan, id, res) {
let option = {};
if (typeof res !== 'undefined'){
option = {before: res.id};
}
return await chan.fetchMessages(option)
.then(async msgs => {
if (msgs.size === 0){
return {continue: false, found: false};
};
if ((Date.now() - (msgs.first().createdTimestamp)) > 86400000 ) { // 1 day
return {continue: false, found: false};
}
let msgByAuthor = msgs.find(msg => {
return msg.author.id === id;
});
if (msgByAuthor === null){
return {continue: true, id: msgs.last().id};
} else {
return {continue: false, found: true, timestamp: msgByAuthor.createdTimestamp};
}
})
.catch(err => console.log('ERR>>', err));
}
client.on('message', async (msg) => {
let timestamp = [];
for (let [id, chan] of msg.guild.channels){
if (chan.type !== 'text'){ continue; }
let id = '587692527826763788'; // id of the user, here a non verified account
let res;
do {
res = await fetchMessageUser(chan, id, res);
} while(res.continue);
if (res.found) {
timestamp.push(res.timestamp);
}
}
console.log(timestamp);
let first = timestamp.sort((a,b) => (b-a))[0];
console.log(new Date(first));
});
A better variant would be to run it for an array of users, checking all 50 last messages from every channel, and associating each users with his most recent messages if he wrote one, and doing this until all the messages in all the channels are too old to avoid a kick/whatever. And then do something for all the users who don't have an associated messages.
I think what you need is one of Discord's built in features, namely: pruning. This feature will grab inactive members and lets you kick them. Luckily, discord.js has an API call for it and even lets you get the number of members first without actually kicking them by setting the dry parameter to true. The feature will also allow you to specify the amount of days a user has to be inactive.
Have a look at the docs: https://discord.js.org/#/docs/main/stable/class/Guild?scrollTo=pruneMembers
Hope that helps out!

Killing a "personalized" Interval

I've made this system so users can login to my website and play a game that requires some interval timing. When the user is done with playing I basically want to kill the interval. While everything seems to be running fine, there is something wrong with killing the interval.
Here is the problem Whenever a user is done playing the interval gets killed, not only for the user playing but for everyone. This might be because I'm assigning a variable to the interval and when a user is done playing a game I'm killing the interval, am I right that it then would kill the other intervals as well?
Here is some code I've written for this question,
var user; //this is a variable that has all info about the user. (its not usually empty)
var usersPlaying = [];
socket.on('game', function(game) {
if(game.type == "start"){
usersPlaying.push({
user_id: user.id
});
var game = setInterval(function(){
if(findUser(user.id) !== undefined){
console.log('Second passed!');
}else{
clearInterval(game); //stop the interval
}
}, 1000);
}else if(game.type == "stop"){
console.log("User has decided to quit playing the game!");
usersPlaying.splice(usersPlaying.findIndex(user => user === user.id), 1); //remove user from playing
}
});
There might be some mistakes in there since I rewritten and simplified the code otherwise it would be way to hard to help me out.
Anyways, how can I make it so it only clears the interval running for a certain specified person?
Thanks!
The setInterval call returns a unique id. You can use that id to clear that interval timer afterwards:
var uniqueId = setInterval(function () { /* ... */ }, 1000);
Later on ...
clearInterval(uniqueId);
will kill that specific timer.
I suggest storing the uniqueId for each user inside the usersPlaying array.
Store the interval for that specific socket inside its own scope :
var user; //this is a variable that has all info about the user. (its not usually empty)
var usersPlaying = [];
socket.on('game', function(game) {
if(game.type == "start"){
usersPlaying.push({
user_id: user.id
});
socket.game = setInterval(function(){
if(findUser(user.id) !== undefined){
console.log('Second passed!');
}else{
clearInterval(socket.game); //stop the interval
}
}, 1000);
}else if(game.type == "stop"){
console.log("User has decided to quit playing the game!");
usersPlaying.splice(usersPlaying.findIndex(user => user === user.id), 1); //remove user from playing
}
});
So you can also kill it when disconnections occur :
socket.on('disconnecting',function(){
if(socket.game){clearInterval(socket.game);}
});
EDIT :
var user; //this is a variable that has all info about the user. (its not usually empty)
better store all that inside the scope of the socket (each client socket object in the server will have its own "user" key instead of making use of ugly global variables
So store it like socket.user = {id:"foo"} and you can access the specific user object for that client performing the socket event request like if(findUser(socketuser.id) !== undefined){

Twitterbot use node and javascript continuously looping

It's my first time posting here so apologies in advance if it's not asked correctly.
I'm working on a project where I have a twitter bot that tweets every time a certain account tweets.
I can get it working when I set up a test account but when I do it with the real account (a popular one) my bot will just keep tweeting continuously.
I am basing my code on Daniel Shiffman's twitter bot tutorials on YouTube:
...OK as an edit I have discovered via another forum that the reason is that I am also incoporating any retweets/loves etc of the tweet that I want my bot to react to..as per Twitter API Documentation:
follow
A comma-separated list of user IDs, indicating the users whose Tweets should be delivered on the stream. Following protected users is not supported. For each user specified, the stream will contain:
Tweets created by the user.
Tweets which are retweeted by the user.
Replies to any Tweet created by the user.
Retweets of any Tweet created by the user.
Manual replies, created without pressing a reply button (e.g. “#twitterapi I agree”).
So what I now need to do is implement some logic so that my bot will only react to the actual tweet of the account I am following and not to any retweets/favourites etc of it..
I have included an if/else statement along with my original code below:
console. log('The streambot is starting');
var Twit = require('twit');
var config = require('./config');
var T = new Twit(config);
var stream = T.stream('statuses/filter', { follow: '(//TWITTERID OF ACCOUNT GOES HERE' });
stream.on('tweet',thisTweet);
/*
if ('statuses/filter' != userID){
console.log("error")
} else {
thisTweet;
} */
//this IF is to try and limit reaction of my bot only to the tweets of the account I am following
function thisTweet(){
var randomWords= "//a list of random words"
var splitrandom = randomWords.split(",");
//picks a random word from list
var oneWord = splitrandom [Math.floor(Math.random() * splitrandom .length)];
tweetIt(oneWord);
}
function tweetIt(txt){
var tweet = {
status : txt
}
T.post('statuses/update',tweet,tweeted);
}
function tweeted(err, data, response) {
if (err){
console.log("something went wrong!");
}else{
console.log("It Worked");
}
}
Any help would be great!
I got some help from twitter developers on this one:
This should do the trick:
// define the ID of the user we are interested in
var userID = 'some number';
// open a stream following events from that user ID
var stream = T.stream('statuses/filter', { follow: ( userID ) });
stream.on('tweet', function (tweet) {
// compare the user ID inside the Tweet object we passed in
// to check it matches
if (tweet.user.id == userID) {
console.log("this was sent by the user we want to track")
// now do something else
} else {
console.log(tweet.user.id + " - " + tweet.user.screen_name)
// so we can ignore it
}
});

Socket.IO disconnecting first user in room

I am having trouble with having the first user of the room I am trying to communicate to always leaving but this only happens when I check for its id.
socket.on('player moved', function(msg) {
var curr_room = msg.room_number;
var room_data = io.sockets.adapter.rooms[curr_room];
var temp_room = [];
console.log(room_data);
for (var id in room_data) {
temp_room.push(io.sockets.adapter.nsp.connected[id]);
}
var player1_id = temp_room[0].id;
var player2_id = temp_room[1].id;
console.log(player1_id);
console.log(player2_id);
console.log(msg.player_id);
if (player1_id && player2_id) {
if (player1_id === msg.player_id) {
temp_room[1].emit('update coords', "dude");
} else if ("ffff" === msg.player_id) {
console.log('tessting to see wheter i can be in')
temp_room[0].emit('update coords', "sweet");
}
}
So this works without any errors and when I console.log room data I see two sockets which is what I want, however if I change "ffff" to player2_id I get this weird error where for the first iteration of this function I get the two sockets but after that the first player disconnects and I'm left with
var player1_id = temp_room[0].id;
^
TypeError: Cannot read property 'id' of undefined
I have absolutely no idea why having this check would make the user disconnect and furthermore I have no idea why the user is disconnecting if the page remains open.
Anybody have any insights, it would be greatly appreciated!
Thanks!!

Categories