Reputation: 5518
So I'm working on a bot for Slack that mentions a random user every week. I get to a point where the bot does exactly that, but I'm not sure how to avoid duplicates. As you can see in the screenshot below, duplicate names are being shown:
Here is my code:
// Handle events related to the websocket connection to Slack
controller.on('rtm_open', function (bot) {
console.log('** The RTM api just connected!');
// Get all users
bot.api.users.list({}, function(err, list){
// If list and members exist
if (list && list.members) {
list.members = list.members.filter(function(member) {
return (member.real_name != undefined && member.real_name != "" && member.real_name != null && member.real_name != "slackbot");
});
// console.log(list.members);
var previousRandomNumber = -1;
// Every X amount of milliseconds
var interval = setInterval(function() {
var members = list.members;
// Generating random number from 0 to how many members exist (exclusive) in the member list
var randomNumber = Math.floor(Math.random() * members.length);
console.log('1) previous: ' + previousRandomNumber + ' randomNumber ' + randomNumber);
if (previousRandomNumber == randomNumber) {
randomNumber = Math.floor(Math.random() * members.length);
}
console.log('2) previous: ' + previousRandomNumber + ' randomNumber ' + randomNumber);
previousRandomNumber = randomNumber;
// Get random name
var randomName = members[randomNumber].name;
//console.log(randomName);
// If random name is null or undefined, reshuffle.
if (randomName == null || randomName == "" || randomName == undefined) {
console.log('user has been deleted');
// clearInterval(interval);
} else {
console.log('actual person - ' + randomName);
// Configuring webhook and sending message to channel
bot.configureIncomingWebhook({url: 'https://hooks.slack.com/services/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'});
bot.sendWebhook({
text: '@' + randomName + ", you've been selected for #snapshot! ",
channel: '#test',
},function(err,res) {
// handle error
});
}
}, 3000); // 604800000 ms = 1 week
console.log("message");
}
})
});
Does anyone know how I could somehow splice the names that have already been mentioned from the array?
Upvotes: 2
Views: 871
Reputation: 11050
First, I agree with Erik that you need to explicitly ensure that you do not select the same member twice. This can be done by storing members you already selected (or still need to select) in a database. We don't have enough details to help you with how to do that.
What I want to add, however, is that the best way to select random members without repetition is not by randomly selecting a user and making sure you did not select that member before. That can take a long time. You can remove a member from the array, but there is another way.
Shuffle (in the right way!) the array of members and then simply loop over them in order. You can shuffle again when all members have been selected. Here is an example using ES6 syntax and a generator, because this seems an ideal use case for it. If the browser support (no IE, other major browsers are fine) is not a problem, you can use this by passing in your list.members
to uniqueRandomIterate
and use iterator.next().value
in your interval.
function shuffle(a) {
for (let i = a.length; i; i--) {
let j = Math.floor(Math.random() * i);
[a[i - 1], a[j]] = [a[j], a[i - 1]];
}
}
function* uniqueRandomIterate(array) {
var ind = 0;
while (true) {
shuffle(array);
for (let i = 0; i < members.length; ++i) {
yield array[i];
}
console.log('got everyone, starting over');
}
}
var members = ['a', 'b', 'c', 'd', 'e', 'f'],
iterator = uniqueRandomIterate(members);
for (let i = 0; i < 3 * members.length; ++i) {
console.log(iterator.next().value);
}
.as-console-wrapper {
max-height: 100% !important;
}
Upvotes: 3
Reputation: 32837
To avoid duplicated you will need to store the IDs of users that were already mentioned and remove those from your copy of the userlist each time you run it (e.g. once a week). Until all users have been mentioned, then you have to reset.
There are many ways how you can store the IDs. e.g. you can put them into a database or you can safe them into a JSON file stored on the server.
Upvotes: 4