#How to correctly make a VoiceState event using eventHandler

53 messages · Page 1 of 1 (latest)

shrewd scarab
#

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 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")
})

north oracleBOT
#
  • What's your exact discord.js npm list discord.js and node node -v version?
  • Not a discord.js issue? Check out #1081585952654360687.
  • 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!
shy gyro
#

well, do you have the GuildVoiceStates intent enabled?

muted thicket
shrewd scarab
shrewd scarab
muted thicket
shrewd scarab
muted thicket
shrewd scarab
shrewd scarab
muted thicket
#

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.

shrewd scarab
muted thicket
shrewd scarab
fast lily
# shrewd scarab Full project https://replit.com/@keymax32/Shiza

Your eventHandler assumes each event emits with just one parameter and then it calls each event file with client as first and the event parameter as second parameter. Which causes newState to always be undefined in voiceXP file. You should get an error from trying to access .member on undefined though

shrewd scarab
#

I don't understand, but only today he started giving an error. Before that, he was just silent and did not react

shrewd scarab
fast lily
icy pollenBOT
#

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.

shrewd scarab
#

I have the same value displayed in the console,

[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
muted thicket
#

You would have to check the differences and handle them.

shrewd scarab
# muted thicket They could be doing something else besides joining or leaving. Such as muting de...

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

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```
#

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})

muted thicket
#

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.

shrewd scarab
muted thicket
shrewd scarab
# muted thicket oldState.channel should be null if joining.

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
muted thicket
#

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.

icy pollenBOT
#

guide Creating Your Bot: Event handling - Individual event files
read more

muted thicket
shrewd scarab
shrewd scarab
# muted thicket Could be

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);

Inside eventFunction, you would handle the arguments as 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);
}```
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```
Depending on your specific scenario, one of these options might be more preferable. Choose the one that best fits your requirements and coding style.
shrewd scarab
#

sweetpiano_happy
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);
      }
    });

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);
      }
    });```
shy gyro
shrewd scarab
fast lily
#

And the first doesn’t work because you need (…arg) in the parameter list of the arrow function too

shrewd scarab
fast lily
shrewd scarab
fast lily
#

oh, TIL. didn't know about the arguments object in JS before... but tbh it would be easier to read if you included actual parameters with ...args in the function you pass as callback to .on()

#

sorry for doubting you, you were correct

icy pollenBOT
#

mdn The arguments object
arguments is an array-like object accessible inside functions that contains the values of the arguments passed to that function.