How to correctly make a VoiceState event using eventHandler

I created the voiceXP.js event, which was supposed to grant experience every minute while in the Voice Chat. However, for some reason, the added console.log statements are not working, and XP is not being awarded. It's as if the "VoiceState" event is not triggering at all voiceXP.js:
const { VoiceState } = require('discord.js');
const calculateLevelXp = require('../../utils/calculateLevelXp');
const Level = require('../../models/Level');
const cooldowns = new Set();
console.log(`WORK`);

function getRandomXp(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
*
* @param {VoiceState} oldState
* @param {VoiceState} newState
*/
module.exports = async (oldState, newState) => {
console.log(`WORK`);
if (!newState.member || newState.member.user.bot || cooldowns.has(newState.member.user.id)) return;

const xpToGive = getRandomXp(10, 25); // Adjust the XP range as needed

const query = {
userId: newState.member.user.id,
guildId: newState.guild.id,
};

try {
const level = await Level.findOne(query);

if (level) {
level.xp += xpToGive;
console.log(`WORK CLAIM`);
if (level.xp > calculateLevelXp(level.level)) {
level.xp = 0;
level.level += 1;

newState.guild.systemChannel.send(`${newState.member} you have leveled up to **level ${level.level}**.`);
}

await level.save().catch((e) => {
console.log(`Error saving updated level ${e}`);
return;
});

cooldowns.add(newState.member.user.id);
setTimeout(() => {
cooldowns.delete(newState.member.user.id);
}, 60000);
} else {
const newLevel = new Level({
userId: newState.member.user.id,
guildId: newState.guild.id,
xp: xpToGive,
});

await newLevel.save();

cooldowns.add(newState.member.user.id);
setTimeout(() => {
cooldowns.delete(newState.member.user.id);
}, 60000);
}
} catch (error) {
console.log(`Error giving xp: ${error}`);
}
console.log(`WORK OUT`);
};
const { VoiceState } = require('discord.js');
const calculateLevelXp = require('../../utils/calculateLevelXp');
const Level = require('../../models/Level');
const cooldowns = new Set();
console.log(`WORK`);

function getRandomXp(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
*
* @param {VoiceState} oldState
* @param {VoiceState} newState
*/
module.exports = async (oldState, newState) => {
console.log(`WORK`);
if (!newState.member || newState.member.user.bot || cooldowns.has(newState.member.user.id)) return;

const xpToGive = getRandomXp(10, 25); // Adjust the XP range as needed

const query = {
userId: newState.member.user.id,
guildId: newState.guild.id,
};

try {
const level = await Level.findOne(query);

if (level) {
level.xp += xpToGive;
console.log(`WORK CLAIM`);
if (level.xp > calculateLevelXp(level.level)) {
level.xp = 0;
level.level += 1;

newState.guild.systemChannel.send(`${newState.member} you have leveled up to **level ${level.level}**.`);
}

await level.save().catch((e) => {
console.log(`Error saving updated level ${e}`);
return;
});

cooldowns.add(newState.member.user.id);
setTimeout(() => {
cooldowns.delete(newState.member.user.id);
}, 60000);
} else {
const newLevel = new Level({
userId: newState.member.user.id,
guildId: newState.guild.id,
xp: xpToGive,
});

await newLevel.save();

cooldowns.add(newState.member.user.id);
setTimeout(() => {
cooldowns.delete(newState.member.user.id);
}, 60000);
}
} catch (error) {
console.log(`Error giving xp: ${error}`);
}
console.log(`WORK OUT`);
};
If you add
client.on('voiceStateUpdate', (oldState, newState) => {
// console.log(oldState, newState)
console.log("Test")
})
client.on('voiceStateUpdate', (oldState, newState) => {
// console.log(oldState, newState)
console.log("Test")
})
it to index.js, it produces messages normally
No description
39 Replies
d.js toolkit
d.js toolkit15mo ago
- 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!
chewie
chewie15mo ago
well, do you have the GuildVoiceStates intent enabled?
SpecialSauce
SpecialSauce15mo ago
How are you importing and executing the exported function from voiceXP?
Keymax
KeymaxOP15mo ago
Keymax
KeymaxOP15mo ago
Of course, because if I'm directly from index.js I'm trying to trigger everything goes fine
SpecialSauce
SpecialSauce15mo ago
I’m confused at how you’re expecting the voiceXP function to execute. Are you importing it like it’s an event?
Keymax
KeymaxOP15mo ago
Yep
Keymax
KeymaxOP15mo ago
Here is my other MessageCreate event, it works fine
SpecialSauce
SpecialSauce15mo ago
What folder is the voiceXP.js in?
Keymax
KeymaxOP15mo ago
No description
Keymax
KeymaxOP15mo ago
keymax32
replit
Shiza
Run Node.js (Beta) code live in your browser. Write and run code in 50+ languages online with Replit, a powerful IDE, compiler, & interpreter.
SpecialSauce
SpecialSauce15mo ago
I’m not sure if that event file is being imported. It looks like it should log 'work' to the console but isn’t. Id log eventName, eventFiles in your event handler outside the listener.
Keymax
KeymaxOP15mo ago
Just "giveUserXp.js" is working fine
SpecialSauce
SpecialSauce15mo ago
Is voiceXP being imported?
Keymax
KeymaxOP15mo ago
I'm not sure, but at least the first WORK output, which is declared at the very beginning of the code, works.
console.log(`WORK`);
console.log(`WORK`);
But the rest are gone
Keymax
KeymaxOP15mo ago
I don't understand, but only today he started giving an error. Before that, he was just silent and did not react
No description
Keymax
KeymaxOP15mo ago
Thanks for the help, I really added to EventHandler.js 1 more argument for events and everything started to work stably. Thanks a lot ❤️
await eventFunction(client, arg, arg);
await eventFunction(client, arg, arg);
d.js docs
d.js docs15mo ago
mdn Spread syntax (...) The spread (...) syntax allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected. In an object literal, the spread syntax enumerates the properties of an object and adds the key-value pairs to the object being created.
Keymax
KeymaxOP15mo ago
💗
Keymax
KeymaxOP15mo ago
I have the same value displayed in the console,
[JOIN] <#883322478036938792> and <#883322478036938792>
[JOIN] null and null
[JOIN] <#883322478036938792> and <#883322478036938792>
[JOIN] null and null
do I not understand something? I want to check the current state of the user and compare it, but it gives the same thing. How do I understand what is happening to a person right now
SpecialSauce
SpecialSauce15mo ago
They could be doing something else besides joining or leaving. Such as muting deafening or other actions that modify voiceState. You would have to check the differences and handle them.
Keymax
KeymaxOP15mo ago
Yes, I understand, but even if I output these values in the console, they are still always the same: Mute and unmute:
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: false New Channel ID: false
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: true New Channel ID: true
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: false New Channel ID: false
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: true New Channel ID: true
Deaf and undeaf
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: false New Channel ID: false
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: true New Channel ID: true
[Mute] Old Channel ID: true New Channel ID: true
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: false New Channel ID: false
[Mute] Old Channel ID: false New Channel ID: false
[JOIN] Old Channel ID: 883322478036938792 New Channel ID: 883322478036938792
[Deaf] Old Channel ID: true New Channel ID: true
[Mute] Old Channel ID: true New Channel ID: true
I specified the variables correctly:
console.log(`[JOIN] Old Channel ID: ${oldState.channelId} New Channel ID: ${newState.channelId}`)
console.log(`[Deaf] Old Channel ID: ${oldState.selfDeaf} New Channel ID: ${newState.selfDeaf}`)
console.log(`[Mute] Old Channel ID: ${oldState.selfMute} New Channel ID: ${newState.selfMute}`)
console.log(`[JOIN] Old Channel ID: ${oldState.channelId} New Channel ID: ${newState.channelId}`)
console.log(`[Deaf] Old Channel ID: ${oldState.selfDeaf} New Channel ID: ${newState.selfDeaf}`)
console.log(`[Mute] Old Channel ID: ${oldState.selfMute} New Channel ID: ${newState.selfMute}`)
SpecialSauce
SpecialSauce15mo ago
Something is changing to fire the event. Those are only two examples of state changes. You could try to compare the entries of both old and new state objects and filter the ones that don’t match if you really want to see what changed.
Keymax
KeymaxOP15mo ago
I just thought if I join a voice chat, then:
oldState.channel = null and newState.channel = 12313213
oldState.channel = null and newState.channel = 12313213
But for some reason these values are always the same
SpecialSauce
SpecialSauce15mo ago
oldState.channel should be null if joining.
Keymax
KeymaxOP15mo ago
Okay, I figured it out, because I tried to import this event as a separate file. However, if I prescribe directly from index.js works everything out fine
[INDEX] Old Channel ID: null New Channel ID: 883322478036938792
[VOICEXP.js] Old Channel ID: null New Channel ID: null
[INDEX] Old Channel ID: null New Channel ID: 883322478036938792
[VOICEXP.js] Old Channel ID: null New Channel ID: null
SpecialSauce
SpecialSauce15mo ago
You still have a parameter issue when you call the execute() function in your handler. You pass the same object as the second and third argument. So oldMember and newMember are the same object I would review the event handler portion of the guide and see how the args are passed to the event listeners with separate files.
d.js docs
d.js docs15mo ago
guide Creating Your Bot: Event handling - Individual event files read more
SpecialSauce
SpecialSauce15mo ago
This was an attempt to resolve that issue.
Keymax
KeymaxOP15mo ago
I didn't really understand, do I need to declare in this way?
eventFunction(client, ...arg);
eventFunction(client, ...arg);
SpecialSauce
SpecialSauce15mo ago
Could be
Keymax
KeymaxOP15mo ago
Use arrays in both cases. You can pass single arguments as an array with one element. This ensures consistency but might require additional handling inside the function.
// Single argument
const arg1 = [singleValue];
await eventFunction(client, ...arg1);

// Multiple arguments
const arg2 = [value1, value2, value3];
await eventFunction(client, ...arg2);
// Single argument
const arg1 = [singleValue];
await eventFunction(client, ...arg1);

// Multiple arguments
const arg2 = [value1, value2, value3];
await eventFunction(client, ...arg2);
Inside eventFunction, you would handle the arguments as an array:
function eventFunction(client, ...args) {
// args is an array
}
function eventFunction(client, ...args) {
// args is an array
}
Check the type of arg before calling. If arg is an array, you can use the spread syntax; otherwise, pass it as is.
if (Array.isArray(arg)) {
await eventFunction(client, ...arg);
} else {
await eventFunction(client, arg);
}
if (Array.isArray(arg)) {
await eventFunction(client, ...arg);
} else {
await eventFunction(client, arg);
}
Modify the structure of eventFunction to always accept an array. This way, you won't have to worry about the number of arguments you're passing.
async function eventFunction(client, args) {
// args is always an array
}

// When calling
await eventFunction(client, [singleArg]); // One argument
await eventFunction(client, [arg1, arg2, arg3]); // Multiple arguments
async function eventFunction(client, args) {
// args is always an array
}

// When calling
await eventFunction(client, [singleArg]); // One argument
await eventFunction(client, [arg1, arg2, arg3]); // Multiple arguments
Depending on your specific scenario, one of these options might be more preferable. Choose the one that best fits your requirements and coding style. <a:sweetpiano_happy:1051864341835698276> I finally understood the incorrectly described import of events, old
client.on(eventName, async (arg) => {
for (const eventFile of eventFiles) {
const eventFunction = require(eventFile);
await eventFunction(client, ...arg);
}
});
client.on(eventName, async (arg) => {
for (const eventFile of eventFiles) {
const eventFunction = require(eventFile);
await eventFunction(client, ...arg);
}
});
that's how it should be new
client.on(eventName, async function() {
for (const eventFile of eventFiles) {
const eventFunction = require(eventFile);
await eventFunction(client, ...arguments);
}
});
client.on(eventName, async function() {
for (const eventFile of eventFiles) {
const eventFunction = require(eventFile);
await eventFunction(client, ...arguments);
}
});
chewie
chewie15mo ago
Those are the same, just that one uses arrow functions instead
Keymax
KeymaxOP15mo ago
I don't know, but the first option didn't work for me
Keymax
KeymaxOP15mo ago
Why, everything works fine and works fine. It conveys oldState and newState well
No description
Keymax
KeymaxOP15mo ago
keymax32
replit
Shiza
Run Node.js (Beta) code live in your browser. Write and run code in 50+ languages online with Replit, a powerful IDE, compiler, & interpreter.
d.js docs
d.js docs15mo ago
mdn The arguments object arguments is an array-like object accessible inside functions that contains the values of the arguments passed to that function.
Want results from more Discord servers?
Add your server