I’m working on a Twitch bot using tmi.js and running into a problem with my winner selection logic. When I try to pick a random winner from my participants array, sometimes I get undefined as the result instead of an actual username.
I think the issue might be related to how arrays work with zero indexing, but I’m not entirely sure. Here’s my current code:
setTimeout(() => {
client.action(TwitchChannel, `"${selectedWinner} emerges victorious from the chaos! Better luck next time everyone else."`);
}, 3000);
How can I make sure there’s always a valid winner selected and never get undefined in the chat message?
Your problem is timing - you’re picking a winner every time someone sends a message, but the participants array might be empty then. Move the winner selection out of the message handler and only run it when you actually want to pick someone. Right now you’re basically choosing a new ‘winner’ whenever anyone types in chat, which is why you get undefined when the array’s empty. Keep storing participants in the message handler like you’re doing, but create a separate function for picking the winner. Check if there are any participants first, then do the random selection. I made this exact mistake on my first bot and wasted way too much time before realizing I was trying to pick winners before anyone entered.
yeah, ur picking a winner in the msg event which happens a lot. that’s y you get undefined when no one has entered yet. just add if(playerList.length === 0) return; before picking the index, or move the selection logic to when you wanna announce winners.
Your code has a bigger problem than just timing issues. You’re declaring selectedWinner inside the message event listener, but then trying to use it in a setTimeout that’s probably outside that scope. So selectedWinner might not even exist when the timeout runs. Plus, you’re selecting a winner for every single message, which is wasteful and creates race conditions. I’d restructure this with a dedicated !draw command that handles both picking and announcing the winner in one go. Also heads up - using an object for participants automatically prevents duplicates, which is probably what you want, but just make sure that’s intentional.
The issue arises because you’re trying to select a winner within the message event. This can lead to instances where no one has entered yet, causing Object.values(participants) to return an empty array. Consequently, Math.floor(Math.random() * 0) results in undefined. To resolve this, consider moving the winner selection logic outside of the message handler. Implement a distinct command, such as !pickwinner, or utilize a timer that executes only when you intend to conclude the contest. Also, ensure to check that the participants array isn’t empty before attempting to select a winner. I’ve faced similar challenges when I began using tmi.js, frequently encountering undefined winners until I understood the timing issue.