Tomato6966 / lavalink-client

Easy, flexible and feature-rich lavalink@v4 Client. Both for Beginners and Proficients.
https://tomato6966.github.io/lavalink-client/
MIT License
62 stars 22 forks source link

Client connect in the Voice Channel but don't play the song #5

Closed NedcloarBR closed 1 year ago

NedcloarBR commented 1 year ago

I migrated my bot from your fork of Erela.js to this new package and I'm experiencing some problems When I use my play command to play the music the bot connects to the voice channel but does not start playing the music, but if I check if the player is paused or not it says no, and if I check if it is connected returns false

TestPlay Command

/* eslint-disable @typescript-eslint/no-unused-vars */
import NDBClient from "@/Core/NDBClient";
import MusicTools from "@/Modules/Music/Utils/Tools";
import { CommandOptions } from "@/Types";
import { BaseCommand } from "@/Utils/Structures";
import { Message, VoiceChannel } from "discord.js";

export default class TestCommand extends BaseCommand {
  constructor(client: NDBClient, ...args: string[]) {
    const options: CommandOptions = {
      name: "test",
      aliases: ["t"],
      description: "Command to test things",
      category: "🛠 Developer Tools",
      usage: "",
      disable: false,
      cooldown: 1000,
      permissions: {
        user: [],
        bot: []
      },
      minArgs: 0,
      guildOnly: false,
      ownerOnly: true,
      nsfw: false,
      ndcash: 0
    };
    super(client, options, args);
  }

  async run(client: NDBClient, message: Message, args: Array<string>) {
    const player =
      (await MusicTools.getPlayer(client, message.guildId)) ||
      (await MusicTools.createPlayer(
        client,
        message.member.voice.channel as VoiceChannel,
        message.channelId
      ));

    await player.connect();
    const res = await player.search(
      {
        query: "Star Walkin'",
        source: "spotify"
      },
      client.user
    );

    player.queue.add(res.tracks[0]);

    await player.play({
      paused: false,
      volume: 50
    });
    console.log(player);
  }
}

Lavalink Manager

import { LavalinkManager as Manager } from "lavalink-client";
import NDBClient from "./NDBClient";

import { Config } from "@/Config/Config";
import "@/Utils/Structures/BasePlayer";
export default class LavalinkManager extends Manager {
  constructor(private readonly client: NDBClient) {
    super({
      nodes: [
        {
          regions: ["us-east", "us-central", "us-south", "us-west", "brazil"],
          id: "localhost",
          host: process.env.LavalinkHOST,
          port: 2333,
          authorization: process.env.LavalinkPassword,
          retryAmount: 22,
          retryDelay: 5000
        }
      ],
      client: {
        id: Config.Client.ID
      },
      autoSkip: true,
      playerOptions: {
        applyVolumeAsFilter: false,
        clientBasedPositionUpdateInterval: 100,
        defaultSearchPlatform: "ytmsearch",
        volumeDecrementer: 0.75,
        useUnresolvedData: true,
        onDisconnect: {
          autoReconnect: true,
          destroyPlayer: false
        }
      },
      queueOptions: {
        maxPreviousTracks: 1
      },
      sendToShard(id, payload) {
        return client.ws.shards
          .get(client.guilds.cache.get(id)!.shardId)!
          .send(payload);
      }
    });

    client.on("raw", data => {
      switch (data.t) {
        case "VOICE_SERVER_UPDATE":
        case "VOICE_STATE_UPDATE":
          this.sendRawData(data.d);
          break;
      }
    });

    this.setMaxListeners(16);
  }

  public async load(): Promise<void> {
    this.init({ ...this.client.user!, shards: "auto" });
  }
}

Get/Create Player functions

public static async getPlayer(client: NDBClient, guildId: string) {
    return client.LavalinkManager.getPlayer(guildId);
  }

public static async createPlayer(
    client: NDBClient,
    voiceChannel: VoiceChannel,
    textChannelId: string
  ) {
    return client.LavalinkManager.createPlayer({
      guildId: voiceChannel.guildId,
      textChannelId: textChannelId,
      voiceChannelId: voiceChannel.id,
      selfDeaf: Config.Music.Client.selfDeaf,
      instaUpdateFiltersFix: false
    });
  }

console.log(player)

<ref *1> Player {
  guildId: '679066351456878633',
  voiceChannelId: '796380288200474624',
  textChannelId: '796380299977424947',
  playing: true,
  paused: false,
  repeatMode: 'off',
  ping: { lavalink: 0.01, ws: 0 },
  volume: 50,
  lavalinkVolume: 37.5,
  position: 0,
  lastPosition: 0,
  createdTimeStamp: undefined,
  connected: false,
  voice: { endpoint: null, sessionId: null, token: null },
  data: {},
  options: {
    guildId: '679066351456878633',
    textChannelId: '796380299977424947',
    voiceChannelId: '796380288200474624',
    selfDeaf: true,
    instaUpdateFiltersFix: false
  },
  filterManager: FilterManager {
    equalizerBands: [],
    filterUpdatedState: 0,
    filters: {
      volume: false,
      vaporwave: false,
      custom: false,
      nightcore: false,
      echo: false,
      reverb: false,
      rotation: false,
      karaoke: false,
      tremolo: false,
      vibrato: false,
      lowPass: false,
      audioOutput: 'stereo'
    },
    data: {
      lowPass: [Object],
      karaoke: [Object],
      timescale: [Object],
      echo: [Object],
      reverb: [Object],
      rotation: [Object],
      tremolo: [Object],
      vibrato: [Object],
      channelMix: [Object]
    },
    player: [Circular *1]
  },
  LavalinkManager: <ref *2> LavalinkManager {
    _events: [Object: null prototype] {
      trackStuck: [Function (anonymous)],
      trackStart: [Function (anonymous)],
      trackError: [Function (anonymous)],
      trackEnd: [Function (anonymous)],
      playerSocketClosed: [Function (anonymous)],
      queueEnd: [Function (anonymous)],
      playerMove: [Function (anonymous)],
      playerDisconnect: [Function (anonymous)],
      playerDestroy: [Function (anonymous)],
      playerCreate: [Function (anonymous)]
    },
    _eventsCount: 10,
    _maxListeners: 16,
    initiated: true,
    players: MiniMap(1) [Map] { '679066351456878633' => [Circular *1] },
    options: {
      nodes: [Array],
      client: [Object],
      autoSkip: true,
      playerOptions: [Object],
      queueOptions: [Object],
      sendToShard: [Function: sendToShard]
    },
    utils: ManagerUtils { LavalinkManager: [Circular *2] },
    nodeManager: NodeManager {
      _events: [Object: null prototype],
      _eventsCount: 6,
      _maxListeners: undefined,
      nodes: [MiniMap [Map]],
      LavalinkManager: [Circular *2],
      [Symbol(kCapture)]: false
    },
    client: NDBClient {
      _events: [Object: null prototype],
      _eventsCount: 27,
      _maxListeners: undefined,
      options: [Object],
      rest: [REST],
      ws: [WebSocketManager],
      actions: [ActionsManager],
      voice: [ClientVoiceManager],
      shard: null,
      users: UserManager {},
      guilds: GuildManager {},
      channels: ChannelManager {},
      sweepers: [Sweepers],
      presence: [ClientPresence],
      user: [ClientUser],
      application: [ClientApplication],
      readyTimestamp: 1692560887075,
      Collections: [Collections],
      Tools: [Tools],
      Translate: [Translate],
      LavalinkManager: [Circular *2],
      LoadHandlers: [LoadHandlers],
      logger: [Logger],
      [Symbol(kCapture)]: true
    },
    [Symbol(kCapture)]: false
  },
  node: LavalinkNode {
    options: {
      secure: false,
      retryAmount: 22,
      retryDelay: 5000,
      requestTimeout: 10000,
      regions: [Array],
      id: 'localhost',
      host: 'localhost',
      port: 2333,
      authorization: 'youshallnotpass'
    },
    calls: 4,
    stats: {
      frameStats: null,
      players: 0,
      playingPlayers: 0,
      uptime: 2074150,
      memory: [Object],
      cpu: [Object]
    },
    sessionId: '5duc5sgl7chubeuu',
    info: {
      version: [Object],
      buildTime: 1688407038731,
      git: [Object],
      jvm: '19.0.2',
      lavaplayer: '1.4.2',
      sourceManagers: [Array],
      filters: [Array],
      plugins: [Array]
    },
    NodeManager: NodeManager {
      _events: [Object: null prototype],
      _eventsCount: 6,
      _maxListeners: undefined,
      nodes: [MiniMap [Map]],
      LavalinkManager: [LavalinkManager],
      [Symbol(kCapture)]: false
    },
    reconnectTimeout: undefined,
    reconnectAttempts: 1,
    socket: WebSocket {
      _events: [Object: null prototype],
      _eventsCount: 4,
      _maxListeners: undefined,
      _binaryType: 'nodebuffer',
      _closeCode: 1006,
      _closeFrameReceived: false,
      _closeFrameSent: false,
      _closeMessage: <Buffer >,
      _closeTimer: null,
      _extensions: {},
      _paused: false,
      _protocol: '',
      _readyState: 1,
      _receiver: [Receiver],
      _sender: [Sender],
      _socket: [Socket],
      _bufferedAmount: 0,
      _isServer: false,
      _redirects: 0,
      _url: 'ws://localhost:2333/v4/websocket',
      _req: null,
      [Symbol(kCapture)]: false
    },
    rest: Pool {
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      [Symbol(kCapture)]: false,
      [Symbol(destroyed)]: false,
      [Symbol(onDestroyed)]: null,
      [Symbol(closed)]: false,
      [Symbol(onClosed)]: [],
      [Symbol(queue)]: [FixedQueue],
      [Symbol(clients)]: [Array],
      [Symbol(queued)]: 0,
      [Symbol(onDrain)]: [Function: onDrain],
      [Symbol(onConnect)]: [Function (anonymous)],
      [Symbol(onDisconnect)]: [Function (anonymous)],
      [Symbol(onConnectionError)]: [Function (anonymous)],
      [Symbol(stats)]: [PoolStats],
      [Symbol(dispatch interceptors)]: [],
      [Symbol(connections)]: null,
      [Symbol(url)]: [URL],
      [Symbol(options)]: [Object],
      [Symbol(factory)]: [Function: defaultFactory],
      [Symbol(Intercepted Dispatch)]: [Function: [dispatch]],
      [Symbol(needDrain)]: false
    },
    version: 'v4',
    decode: {
      singleTrack: [AsyncFunction: singleTrack],
      multipleTracks: [AsyncFunction: multipleTracks]
    },
    routePlannerApi: {
      getStatus: [AsyncFunction: getStatus],
      unmarkFailedAddress: [AsyncFunction: unmarkFailedAddress],
      unmarkAllFailedAddresses: [AsyncFunction: unmarkAllFailedAddresses]
    }
  },
  queue: Queue {
    tracks: [],
    previous: [],
    current: {
      encoded: 'QAAA+AMALlNUQVIgV0FMS0lOJyAoTGVhZ3VlIG9mIExlZ2VuZHMgV29ybGRzIEFudGhlbSkACUxpbCBOYXMgWAAAAAAAAzaPABYzOFQwdFBWWkhjUFp5aHRPY0NQN3BGAAEANWh0dHBzOi8vb3Blbi5zcG90aWZ5LmNvbS90cmFjay8zOFQwdFBWWkhjUFp5aHRPY0NQN3BGAQBAaHR0cHM6Ly9pLnNjZG4uY28vaW1hZ2UvYWI2NzYxNmQwMDAwYjI3MzA0Y2Q5YTE2NjRmYjQ1MzlhNTU2NDNmZQEADFVTU00xMjIwODgwOQAHc3BvdGlmeQAAAAAAAAAA',
      info: [Object],
      pluginInfo: {},
      requester: [ClientUser]
    },
    options: { maxPreviousTracks: 1 },
    guildId: '679066351456878633',
    QueueSaver: QueueSaver { _: [DefaultQueueStore], options: [Object] },
    managerUtils: ManagerUtils { LavalinkManager: undefined },
    queueChanges: null,
    utils: {
      save: [AsyncFunction: save],
      sync: [AsyncFunction: sync],
      destroy: [AsyncFunction: destroy],
      toJSON: [Function: toJSON],
      totalDuration: [Function: totalDuration]
    }
  },
  playerMessage: '1142907960515899463'
}
Tomato6966 commented 1 year ago

Hello.

First before I suggest you how to solve the problem, some improvement "advices"

client.on("raw", data => {
      switch (data.t) {
        case "VOICE_SERVER_UPDATE":
        case "VOICE_STATE_UPDATE":
          this.sendRawData(data.d);
          break;
      }
});

The raw event, doesn't just require the base raw message for voice changes, also all raw event datas for stuff like channeldelete recognition, therfore you don't have to handle that!

client.on("raw", data => this.sendRawData(data.d));

Next the "playerCreate" function, returns getPlayer if players.has(playerGuildId)

const player = MusicTools.createPlayer(
        client,
        message.member.voice.channel as VoiceChannel,
        message.channelId);

Aka you can just do this and it will be fine

I think something's wrong with the raw listener / shard sending data, as player.voice is all null..

Could you edit node_modules / src for debug logs so you can see if the "raw" data surpasses the following things:

Just go to lavalinkmanager -> sendRawData function, alocate this:

await player.node.updatePlayer({
  guildId: player.guildId,
  playerOptions: {
    voice: {
      token: update.token,
      endpoint: update.endpoint,
      sessionId: player.voice?.sessionId,
    }
  }
});

add a console.log infront, if you never see the console log, your raw event isn't working...

If that's not the problme, then sending data to shards might not work on your end, i don't know what discord client library you are using

Tomato6966 commented 1 year ago

It says "not paused" cause it prolly never said "starting to play" aka player.paused = false player.playing = false

the problem of searching working but no audio either comes from raw event wrong / shards sending not working

NedcloarBR commented 1 year ago

Good afternoon! Thanks for the reply. I changed the raw event and the sendRawData function and it continues without playing the audio in the call but when I use my nowPlaying command it shows the progress of the song so the audio is being sent but not playing in the call

I didn't understand the part of editing the node_modules allocating the code and logging to see if the raw event is working properly

Edit: even with the status of the song being played and having changes in the progressbar of my nowplaying the trackStart event does not fire

I'm using Discord.js v14.13.0, lavalink-client github source, typescript v5.1.6

Sorry for my bad english 😵‍💫

Tomato6966 commented 1 year ago

do

lavalink.nodeManager.on("raw", (node, payload) => console.log(payload));

or try to figure out the problem by adding:

new Manager({
...
debugOptions: { noAudio: true }
})

maybe it's because you didn't provide the proper: managerOptions#client.id

NedcloarBR commented 1 year ago

raw event returns when th bot is ready

{ op: 'ready', resumed: false, sessionId: 'nosidru2opc3n9yc' }
{
  op: 'stats',
  frameStats: null,
  players: 0,
  playingPlayers: 0,
  uptime: 299407,
  memory: {
    free: 47397584,
    used: 63751472,
    allocated: 111149056,
    reservable: 4183818240
  },
  cpu: { cores: 12, systemLoad: 0.09708139865441107, lavalinkLoad: 0 }
}

when I use an command that uses player.search

{
  op: 'playerUpdate',
  state: { time: 1692815747471, position: 0, connected: true, ping: 0 },
  guildId: '679066351456878633'
}

debug: noAudio Bot is starting

Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, manager is not initated yet (20+x)

when I use an command that uses player.search

Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, Sent updatePlayer for voice token session {
  voice: {
    token: '93fc83eb7b******',
    endpoint: 'buenos-aires4905.discord.media:443',
    sessionId: '94205ce9831c8b6ac011160**********'
  }
}

when bot is disconected and auto reconects to a VoiceChannel

Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data: {
  member: {
    user: {
      username: 'N-D-B',
      public_flags: 0,
      id: '708822043420000366',
      global_name: null,
      display_name: null,
      discriminator: '9904',
      bot: true,
      avatar_decoration_data: null,
      avatar: 'b594f185569555b706f32a0fcd5bef74'
    },
    roles: [ '796380206721794089', '748269739859509300' ],
    premium_since: null,
    pending: false,
    nick: '[&] N-D-B',
    mute: false,
    joined_at: '2020-08-26T19:56:48.233000+00:00',
    flags: 0,
    deaf: true,
    communication_disabled_until: null,
    avatar: null
  },
  user_id: '708822043420000366',
  suppress: false,
  session_id: '94205ce9831c8b6ac011160fdd1f90f8',
  self_video: false,
  self_mute: false,
  self_deaf: true,
  request_to_speak_timestamp: null,
  mute: false,
  guild_id: '679066351456878633',
  deaf: true,
  channel_id: '796380288200474624'
}
Lavalink-Client-Debug | NO-AUDIO [::] sendRawData function, No Lavalink Player found via key: 'guild_id' of update-data: {
  token: 'fbdab7002b******',
  guild_id: '679066351456878633',
  endpoint: 'buenos-aires4905.discord.media:443'
}
Tomato6966 commented 1 year ago

Still no audio returning? Do you init the manager?

Is the code of your bot open source, so i can reproduce it?

Do you have the voice intents provided

NedcloarBR commented 1 year ago

audio is still not being returned I started the manager at my bot's ready event yes my bot is open source The master branch does not have the current code using with the bot using lavalink-client. I'll create another branch with the current code All intents are active

Edit: Branch created

Tomato6966 commented 1 year ago

Since you are using discord.js, do the followings:

instead of doing this

sendToShard(id, payload) {
  return client.ws.shards
    .get(client.guilds.cache.get(id)!.shardId)!
    .send(payload);
},

do this:

sendToShard(id, payload) {
  return client.guilds.cache.get(id)?.shard?.send(payload);
},

make sure to use latest Lavalink.jar version, and latest lavasrc version.

I can't really test it hence your to make your project "working" in my windows environment i have to tweak so many things.. If you want, we can hop in a discord voice call. simply dm me: chrissy8283. I really wanna know why it's not working.

No audio beeing plaid really has only one of those reasons:

NedcloarBR commented 1 year ago

After a conversation on Discord testing some things in the bot and lib was found the bug that has already been fixed in version 1.1.10