Tomato6966 / lavalink-client

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

How to stop the player without destroying? #15

Closed zoli456 closed 9 months ago

zoli456 commented 10 months ago

I am moving away your erela.js. but I cant a way to stop the player without destroying it.

zoli456 commented 10 months ago

This library really need a Stop() function.

Tomato6966 commented 10 months ago

player.stop() previously was calling lavalink stop function aka skipping the track

You can call player.skip() for that. If u run out of tracks u cant skip. Therefore only player.destroy() is the case. If u keep the player active on lavalink without actually using it thats a bunch of memory leak.

However if you really want that, ig ill create a command called player.stopPlaying(true) It will stop playing and clear the queue. If false than only stop playing and play next track or so idk yet.

Idk when ill be able to do that, so please be patient

You can do a work around with seek. Or destroy without disconnecting if thats your goal

zoli456 commented 10 months ago

My quick fix was copying over the old stop() function and adding a try{}catch(){} around player.queue.previous.unshift(track); in queueEnd function and emptying the player.queue .

new_player.stop = async function () {
      const now = performance.now();
      await this.node.updatePlayer({
        guildId: this.guildId,
        playerOptions: { encodedTrack: null },
      });
      this.ping = Math.round((performance.now() - now) / 10) / 100;
      return true;
    };
zoli456 commented 10 months ago

There is an another thing. It would be good to have build-in support for the sponsor blocker plugin (https://github.com/topi314/Sponsorblock-Plugin).

    async setsponsorblocker(segments = ["sponsor", "selfpromo"]){
        await fetch(`http://${this.node.options.host}:${this.node.options.port}/${this.node.options.version}/sessions/${this.node.sessionId}/players/${this.guild}/sponsorblock/categories`, {
            method: 'PUT',
            body: JSON.stringify(segments),
            headers: {Authorization: this.node.options.password, 'Content-Type': 'application/json'}
        });
    }

And need 2 new events

 else if (payload.type === "SegmentsLoaded") {
            this.manager.emit("SegmentsLoaded", this, payload);
        }
        else if (payload.type === "SegmentSkipped") {
            this.manager.emit("SegmentSkipped", this, payload);
        }
Tomato6966 commented 10 months ago

My quick fix was copying over the old stop() function and adding a try{}catch(){} around player.queue.previous.unshift(track); in queueEnd function and emptying the player.queue .

new_player.stop = async function () {
      const now = performance.now();
      await this.node.updatePlayer({
        guildId: this.guildId,
        playerOptions: { encodedTrack: null },
      });
      this.ping = Math.round((performance.now() - now) / 10) / 100;
      return true;
    };

the current player.skip() is the same as the old player.stop() except it tracks if it should check for tracks in the queue.. I will do: player.skip(checkForTracksInQueue?:boolean = true, skipTo?: number) and if you put false it won't check and it will behave as in Erela.js. I will also put player.stopPlaying still.

Tomato6966 commented 10 months ago

There is an another thing. It would be good to have build-in support for the sponsor blocker plugin (https://github.com/topi314/Sponsorblock-Plugin).

    async setsponsorblocker(segments = ["sponsor", "selfpromo"]){
        await fetch(`http://${this.node.options.host}:${this.node.options.port}/${this.node.options.version}/sessions/${this.node.sessionId}/players/${this.guild}/sponsorblock/categories`, {
            method: 'PUT',
            body: JSON.stringify(segments),
            headers: {Authorization: this.node.options.password, 'Content-Type': 'application/json'}
        });
    }

And need 2 new events

 else if (payload.type === "SegmentsLoaded") {
            this.manager.emit("SegmentsLoaded", this, payload);
        }
        else if (payload.type === "SegmentSkipped") {
            this.manager.emit("SegmentSkipped", this, payload);
        }

Thanks for that, I will take a look

zoli456 commented 10 months ago

I am struggling to fix a problem in my bot. If a track trigger the trackError event and queue hasn't got more tracks left it send the queueEnd event twice. If it has remaning tracks it not continue playing the queue with autoSkip enabled .

I use long Google TTS requests to trigger the error.

Tomato6966 commented 10 months ago

This library really need a Stop() function.

Implemented with version 1.2.0: player.stopPlaying() -> it will clear queue, and execute "stop" function for lavalink, to stop playing without destroying the player. Also added to skip the "throwError" Property, so you can do:

player.skip(0, false) or shortcut: player.skip(false) which still skips, but if no tracks in queue it will not throw an error, instead execute "stop" and don't destroy the player..

Note: If the player isn't playing something and you execute player.skip(0, false) it will try to play the next song, which ofc. isn't possible and that will throw an error (via events)

For the trackError double execution of queueEnd, i'll take a look later today and if i can reproduce it, i will throw out a patch for that.

Tomato6966 commented 10 months ago

I am struggling to fix a problem in my bot. If a track trigger the trackError event and queue hasn't got more tracks left it send the queueEnd event twice. If it has remaning tracks it not continue playing the queue with autoSkip enabled .

I use long Google TTS requests to trigger the error.

I can't figure out that problem / replicate it. Can you declare what Event fires first and what next etc. etc. I also can't test it using Google TTS Plugin since i Don't have a google tts api key. You may text me on discord for that (chrissy8283)

zoli456 commented 10 months ago

I used the DuncteBot lavalink plugin. It doesnt need api key. You only need to enable the source and set the language and send request with speak. If you send a few hundred character long text it will trigger the error. I sent a friend request on Discord.

Tomato6966 commented 10 months ago

Well what you said was google tts, and google tts needs api key, duncte bot doesn't use google tts :) Anyways. it's not officially supported for lavalink v4. but i'll see if i can reproduce it with it What version are you running on?

zoli456 commented 10 months ago

I am using PRE_1.5.0_25

zoli456 commented 9 months ago

setSponsorBlock() cause Content-Type 'application/octet-stream' is not supported error.

Tomato6966 commented 9 months ago

Author

Should be fixed with version 1.2.2

Tomato6966 commented 9 months ago

It should be fixed with v1.2.4 that the queueEnd get's executed twice on trackError / trackStuck. it's because after trackError trackEnd get's executed with the reason loadFailed.

I am using PRE_1.5.0_25