newState.speaking vs oldState.speaking doesn't seem to be working :(
I want to establish a timestamp both when user starts speaking and also stops speaking.
My startTimer function starts like this:
async function startTimer() {
if (queueActive) {
try {
const currentUser = queue[0];
await unmuteUser(currentUser);
userActive = true;
unmuteTimestamp = Date.now();
const listener = speakingListener(currentUser);
client.on('voiceStateUpdate', listener);
while (userActive) {
The while loop runs some continuous checks on the timestamps.
The speakingListener looks like this (outside of the startTimer function):
const speakingListener = (currentUser) => {
return (oldState, newState) => {
if (newState.member && String(newState.member.id) === String(currentUser.id)) {
if (newState.speaking && !oldState.speaking && !startedSpeakingTimestamp) {
console.log(${currentUser.user.tag} started speaking);
startedSpeakingTimestamp = Date.now();
} else if (!newState.speaking && oldState.speaking) {
console.log(${currentUser.user.tag} stopped speaking);
stoppedSpeakingTimestamp = Date.now();
}
}
};
};
The speakingListener doesn't seem to ever be activated - am I missing something? 😦
6 Replies
- What's your exact discord.js
npm list discord.js
and node node -v
version?
- Not a discord.js issue? Check out #other-js-ts.
- Consider reading #how-to-get-help to improve your question!
- Explain what exactly your issue is.
- Post the full error stack trace, not just the top part!
- Show your code!
- Issue solved? Press the button!You're using a blocking while loop, this is a pretty terrible idea
The timestamp approach is otherwise okay, I dont know why the loop is there
<VoiceState>.speaking
also doesn't exist
you'd need to establish a VoiceConnection
with joinVoiceChannel
from @discordjs/voice
and listen to the start
/end
event on <VoiceConnection>.receiver.speaking
there's other stuff under the while loop 😉 just didn't include it
interesting, thanks - will check it out
Yeah but its still a blocking while loop
perhaps this clarifies? my userSwitchInterval is just the 'check period' until the speakingListener changes some of the timestamps. 🙂
async function startTimer() {
if (queueActive) {
try {
const currentUser = queue[0];
await unmuteUser(currentUser);
userActive = true;
unmuteTimestamp = Date.now();
const listener = speakingListener(currentUser);
client.on('voiceStateUpdate', listener);
while (userActive) {
elapsedTime = Date.now() - unmuteTimestamp;
if (!startedSpeakingTimestamp && (elapsedTime >= startedSpeakingLimit)) {
// User didn't start speaking quickly enough
console.log(
${currentUser.user.tag} did not start speaking.
);
await muteUser(currentUser);
queue.push(queue.shift());
userActive = false;
} else if (elapsedTime >= speakTime) {
console.log(${currentUser.user.tag} reached maximum speak time.
);
await muteUser(currentUser);
queue.push(queue.shift());
userActive = false;
}
// Repeat after userSwitchInterval
await new Promise(resolve => setTimeout(resolve, userSwitchInterval));
}
// Reset timestamps
startedSpeakingTimestamp = null;
stoppedSpeakingTimestamp = null;
unmuteTimestamp = null;
// Unregister the event listener once the loop is done
client.off('voiceStateUpdate', listener);
// Run startTimer again for the next currentUser
await startTimer();
} catch (error) {
console.error('Error in user timer:', error);
}
}
}