Just-Some-Bots / MusicBot

:musical_note: The original MusicBot for Discord (formerly SexualRhinoceros/MusicBot)
https://just-some-bots.github.io/MusicBot/
MIT License
3.13k stars 2.35k forks source link

[Feature] Differents autoplaylists per servers #921

Closed Zenrac closed 5 months ago

Zenrac commented 7 years ago

Hey again !

What about the fact to makes differents autoplaylist with differents songs per server ? And why not adding some command such as : !createplaylist, !addtoplaylist [song] !removetoplaylist [song] .....

And it can be even better if we could choose to enable/disable the autoplaylist on one server, or not.

Selkea commented 7 years ago

I wrote this function to add songs to the playlist some time ago, feel free to use it if you like.

async def cmd_pladd(self, player, song_url=None):
        """
        Usage:
            {command_prefix}pladd current song
            {command_prefix}pladd song_url

        Adds a song to the autoplaylist.
        """

        #No url provided
        if not song_url:
            #Check if there is something playing
            if not player._current_entry:
                raise exceptions.CommandError('There is nothing playing.', expire_in=20)

            #Get the url of the current entry
            else:
                song_url = player._current_entry.url
                title = player._current_entry.title

        else:
            #Get song info from url
            info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

            #Verify proper url
            if not info:
                raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

            else:
                title = info.get('title', '')

        #Verify that the song isn't already in our playlist
        for url in self.autoplaylist:
            if song_url == url:
                return Response("Song already present in autoplaylist.", delete_after=30)

        self.autoplaylist.append(song_url)
        write_file(self.config.auto_playlist_file, self.autoplaylist)
        self.autoplaylist = load_file(self.config.auto_playlist_file)
        return Response("Added %s to autoplaylist." % title, delete_after=30)
TomLongAshfords commented 7 years ago

@Selkea - that's awesome, thank you! Stolen :)

Zenrac commented 7 years ago

Nice, btw, there is the oposite command (remove) Any idea about how to create different playlist for different servers ?


async def cmd_plremove(self, player, song_url=None):
        """
        Usage:
            {command_prefix}plremove current song
            {command_prefix}plremove song_url

        Remove a song from the autoplaylist.
        """

        #No url provided
        if not song_url:
            #Check if there is something playing
            if not player._current_entry:
                raise exceptions.CommandError('There is nothing playing.', expire_in=20)

            #Get the url of the current entry
            else:
                song_url = player._current_entry.url
                title = player._current_entry.title

        else:
            #Get song info from url
            info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

            #Verify proper url
            if not info:
                raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

            else:
                title = info.get('title', '')

        #Verify that the song is in our playlist
        for url in self.autoplaylist:
            if song_url != url:
                return Response("Song not present in autoplaylist.", delete_after=30)

        self.autoplaylist.remove(song_url)
        write_file(self.config.auto_playlist_file, self.autoplaylist)
        self.autoplaylist = load_file(self.config.auto_playlist_file)
        return Response("Removed %s from the autoplaylist." % title, delete_after=30)
Selkea commented 7 years ago
#Verify that the song is in our playlist
        for url in self.autoplaylist:
            if song_url != url:
                return Response("Song not present in autoplaylist.", delete_after=30)

This check won't work unless the song you are trying to remove is the only one in your autoplaylist. It'll always return that the song isn't present even if it is, and you'll never reach the end of the function that actually removes it.

Instead I would do this:

#Verify that the song is in our playlist
        for url in self.autoplaylist:
            if song_url == url:
                self.autoplaylist.remove(song_url)
                write_file(self.config.auto_playlist_file, self.autoplaylist)
                self.autoplaylist = load_file(self.config.auto_playlist_file)
                return Response("Removed %s from the autoplaylist." % title, delete_after=30)

return Response("Song not present in autoplaylist.", delete_after=30)       
Selkea commented 7 years ago

After doing some research the best way I found to implement creating a new playlist was:

async def cmd_newpl(self, file_name=None):
        """
        Usage:
            {command_prefix}newpl file_name

        Creates a new autoplaylist.
        """

        #Verify file name was provided
        if not file_name:
            raise exceptions.CommandError('Please specify a file name for the new playlist.', expire_in=20)

        #Create a new file
        else:
            #Append the file extension and make everything lowercase (important for checking against already existing files)
            fileName = (file_name + ".txt").lower()

            #Get the filepath, and set it to the autoplaylist directory
            savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to make sure there isn't already a file with the same name
            for root, dirs, files in os.walk(savePath):
                if fileName in files:
                    raise exceptions.CommandError("%s already exists in %s." % (fileName, savePath), expire_in=20)

            write_file(savePath + fileName, "")
            return Response("Created new playlist called %s." % file_name)

However even if you create new playlists, you'll need to make modifications to the previous commands (pladd/plrem) to ensure they are writing to the proper files, as well as a new command to load the playlist you want.

Selkea commented 7 years ago

Wrote function to load playlists on demand.

async def cmd_loadpl(self, file_name=None):
        """
        Usage:
            {command_prefix}loadpl file_name

        Loads an existing autoplaylist.
        """

        #Verify file name was provided
        if not file_name:
            raise exceptions.CommandError('Please specify which playlist to load.', expire_in=20)

        #Create a new file
        else:
            #Append the file extension and make everything lowercase (important for checking against already existing files)
            fileName = (file_name + ".txt").lower()

            #Get the filepath, and set it to the autoplaylist directory
            savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to locate existing file
            for root, dirs, files in os.walk(savePath):
                if fileName in files:
                    self.autoplaylist = load_file(savePath + fileName)
                    return Response("Loaded the %s playlist." % fileName, delete_after=30)

                else:
                    raise exceptions.CommandError('Could not find %s, please ensure the spelling is correct and that the file exists.' % fileName, expire_in=20)

This requires that you modify the following lines in both pladd/plrem:

write_file(self.config.auto_playlist_file, self.autoplaylist)
self.autoplaylist = load_file(self.config.auto_playlist_file)

to

write_file(self.autoplaylist, self.autoplaylist)
self.autoplaylist = load_file(self.autoplaylist)

Note that self.autoplaylist will always be the config default (autoplaylist.txt) until you chose to load a different playlist, and will return to the default if the bot is restarted. Furthermore loading different playlist changes it for every server.

Zenrac commented 7 years ago

It's amazing ! But the problem is to load differents playlists on differents servers. I don't know how it can be possible . I tried to add a command to enable/disable the autoplaylist only on one server. It looks like the blacklist command. We have to create a file named "serverautoplaylist" for example and add a command like that:

unfortunately, in vain, I don't know how to do that... I don't have much knowledge. Maybe you have an idea ?

Selkea commented 7 years ago

The problem as it stands, is that bot keeps track of the autoplaylist, instead of the player. You won't be able to fix that by making a new function, you'd have to make modifications to the player and the bot so that the player keeps track of it's own playlist and that the bot references the proper playlist when an event occurs or a function is called.

Selkea commented 7 years ago

Here's what I did.

In player.py

In bot.py

__init__:

cmd_loadpl:

Note that same as before, the default autoplaylist for all servers will be the same. However, you will now be able to load different playlist independantly to different servers.

and as a free bonus, a command to list existing playlist you can choose from:

async def cmd_listpl(self):
        """
        Usage:
            {command_prefix}listpl

        Gives a list of existing autoplaylists.
        """

        #Get the filepath, and set it to the autoplaylist directory
        savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

        listOfPlaylists = []

        #Check to locate existing file
        for root, dirs, files in os.walk(savePath):
            for file in files:
                if file.endswith(".txt"):
                    listOfPlaylists.append(file[:-4])
                else:
                    pass

        #Remove settings files
        listOfPlaylists.remove("blacklist")
        listOfPlaylists.remove("whitelist")

        return Response("Playlists available: %s." % ", ".join(listOfPlaylists), delete_after=30)
Zenrac commented 7 years ago

Thanks! But i've added all ur changes, and i've the following issue : image

Selkea commented 7 years ago

@zenrac That may have been an issue with the replace all, I forgot that instance shouldn't change, just replace that particular line back to self.autoplaylist = load_file(self.config.auto_playlist_file) and you should be fine.

Selkea commented 7 years ago

Make sure yours looks similar to mine.

    async def cmd_loadpl(self, player, file_name=None):
        """
        Usage:
            {command_prefix}loadpl file_name

        Loads an existing autoplaylist.
        """

        #Verify file name was provided
        if file_name:
            #Append the file extension and make everything lowercase (important for checking against already existing files)
            fileName = (file_name + ".txt").lower()

            #Get the filepath, and set it to the autoplaylist directory
            savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to locate existing file
            for root, dirs, files in os.walk(savePath):
                if fileName in files:
                    player.autoplaylist = load_file(savePath + fileName)
                    player.autoplaylist_file = savePath + fileName
                    return Response("Loaded the %s playlist." % file_name, delete_after=30)

                else:
                    raise exceptions.CommandError('Could not find %s, please ensure the spelling is correct and that the file exists.' % file_name, expire_in=20)

        else:
            raise exceptions.CommandError('Please specify which playlist to load.', expire_in=20)
DevanFischer commented 7 years ago

made the changes in player.py, bot.py, and cmd_loadpl got the same error as @zenrac so i did the change you said . now i get this error image

UPDATE i fixed the problem listed above, i can create and load new playlists using the commands but i cant add or remove to the playlists using pladd or plremove

Selkea commented 7 years ago

@DevFischer could you show me what error it is you're getting, or show me what your pladd and/or plrem look like?

DevanFischer commented 7 years ago

@Selkea sure!

    async def cmd_pladd(self, player, song_url=None):
        """
        Usage:
            {command_prefix}pladd current song
            {command_prefix}pladd song_url

        Adds a song to the autoplaylist.
        """

        #No url provided
        if not song_url:
            #Check if there is something playing
            if not player._current_entry:
                raise exceptions.CommandError('There is nothing playing.', expire_in=20)

            #Get the url of the current entry
            else:
                song_url = player._current_entry.url
                title = player._current_entry.title

        else:
            #Get song info from url
            info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

            #Verify proper url
            if not info:
                raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

            else:
                title = info.get('title', '')

        #Verify that the song isn't already in our playlist
        for url in player.autoplaylist:
            if song_url == url:
                return Response("Song already present in autoplaylist.", delete_after=30)

        player.autoplaylist.append(song_url)
        write_file(player.autoplaylist, player.autoplaylist)
        player.autoplaylist = load_file(player.autoplaylist)
        return Response("Added %s to autoplaylist." % title, delete_after=30)

    async def cmd_plremove(self, player, song_url=None):
        """
        Usage:
            {command_prefix}plremove current song
            {command_prefix}plremove song_url

        Remove a song from the autoplaylist.
        """

        #No url provided
        if not song_url:
            #Check if there is something playing
            if not player._current_entry:
                raise exceptions.CommandError('There is nothing playing.', expire_in=20)

            #Get the url of the current entry
            else:
                song_url = player._current_entry.url
                title = player._current_entry.title

        else:
            #Get song info from url
            info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

            #Verify proper url
            if not info:
                raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

            else:
                title = info.get('title', '')

            #Verify that the song is in our playlist
        for url in player.autoplaylist:
            if song_url == url:
                player.autoplaylist.remove(song_url)
                write_file(player.autoplaylist, player.autoplaylist)
                player.autoplaylist = load_file(player.autoplaylist)
                return Response("Removed %s from the autoplaylist." % title, delete_after=30)

        return Response("Song not present in autoplaylist.", delete_after=30)

this is what happens when i try to pladd to a playlist i loaded with loadpl image

Selkea commented 7 years ago

I see what the issue is, replace both instances of these lines in pladd and plrem and you should be good to go :)

write_file(player.autoplaylist, player.autoplaylist)
player.autoplaylist = load_file(player.autoplaylist)

To

write_file(player.autoplaylist_file, player.autoplaylist)
player.autoplaylist = load_file(player.autoplaylist_file)
DevanFischer commented 7 years ago

ok so i made the changes im no longer getting the error in my cmd, thank you for that, but im getting this message in the discord chat image and the songs are not in the playlist and "autoplaylist" is not the playlist i have loaded. any ideas?

Selkea commented 7 years ago

@DevFischer The only way you could get that message is if the song is in your autoplaylist, otherwise you'd never enter that statement, so I would double check and make sure your checking the proper autoplaylist you're trying to add it to.

As for your second question, the message you receive is static, it does not change depending on which playlist is loaded. I left it that way because whatever playlist you load is still an autoplaylist, however if you want to make it more descriptive, you could change it to include which autoplaylist it is you're adding it to.

Zenrac commented 7 years ago

This is my update for the "loadpl" command: It allows to start a song if nothing is queued.

    async def cmd_loadpl(self, player, file_name=None):
        """
        Usage:
            {command_prefix}loadpl file_name

        Loads an existing autoplaylist.
        """

        #Verify file name was provided
        if file_name:
            #Append the file extension and make everything lowercase (important for checking against already existing files)
            fileName = (file_name + ".txt").lower()

            #Get the filepath, and set it to the autoplaylist directory
            savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to locate existing file
            for root, dirs, files in os.walk(savePath):
                if fileName in files:
                    player.autoplaylist = load_file(savePath + fileName)
                    player.autoplaylist_file = savePath + fileName
                    song_url = random.choice(player.autoplaylist)
                    if not player.playlist.entries and not player.current_entry and self.config.auto_playlist: #if nothing is queued, start a song
                        await player.playlist.add_entry(song_url, channel=None, author=None)
                    return Response("Loaded the %s playlist." % file_name, delete_after=30)

                else:
                    raise exceptions.CommandError('Could not find %s, please ensure the spelling is correct and that the file exists.' % file_name, expire_in=20)

        else:
            raise exceptions.CommandError('Please specify which playlist to load.', expire_in=20)
DevanFischer commented 7 years ago

@zenrac awesome thank you!

Zenrac commented 7 years ago

Now i've a problem with the "not info" check, i tried the following command and it work : !pladd hello But "hello" isn't an URL and it creates bugs in the playlist Any Idea to fix it ?

OFFRANKED commented 7 years ago

image getting this error

OFFRANKED commented 7 years ago

image

OFFRANKED commented 7 years ago

ooh it's working now but when I use loadpl it doesn't autoplay songs from it

Selkea commented 7 years ago

@OFFRANKED if the autoplaylist you load has nothing in it when the bot in looking for the next entry to play, it will deactivate the autoplaylist for safety purposes, assuming you've followed the instructions above. You can get around this by either switching to a new autoplaylist while there is a current entry playing and adding a song before it ends, or manually editing the text file and adding an url that way before loading it in.

@zenrac, @DevFischer , @DukeMcAwesome I've made a small adjustment to how I check for a valid url.

See below:

async def cmd_pladd(self, player, song_url=None):
        """
        Usage:
            {command_prefix}pladd current song
            {command_prefix}pladd song_url

        Adds a song to the autoplaylist.
        """

        #No url provided
        if not song_url:
            #Check if there is something playing and get the information
            if player._current_entry:
                song_url = player._current_entry.url
                title = player._current_entry.title

            else:
                raise exceptions.CommandError('There is nothing playing.', expire_in=20)

        else:
            #Get song info from url
            info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)
            title = info.get('title', '')

            #Verify proper url
            if not title:
                raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

        #Verify song isn't already in our playlist
        for url in player.autoplaylist:
            if song_url == url:
                return Response("Song already present in autoplaylist.", delete_after=30)

        player.autoplaylist.append(song_url)
        write_file(player.autoplaylist_file, player.autoplaylist)
        player.autoplaylist = load_file(player.autoplaylist_file)
        return Response("Added %s to autoplaylist." % title, delete_after=30)

I've also made a modification to ensure safer file creation in cmd_newpl

This requires that you add a new function in utils.py

def illegal_char(string, chars):
    illegal = re.compile(chars)
    if illegal.search(string):
        return True
    else:
        return False

And include it in bot.py

from musicbot.utils import load_file, write_file, sane_round_int, illegal_char

cmd_newpl

async def cmd_newpl(self, file_name=None):
        """
        Usage:
            {command_prefix}newpl file_name

        Creates a new autoplaylist.
        """

        #Verify file name was provided
        if file_name:
            #Verify no illegal characters
            if illegal_char(file_name, "[/\\:*?\"<>|]"):
                raise exceptions.CommandError('Please ensure there are no illegal characters in the filename.', expire_in=20)

            #Create new file
            else:
                #Append the file extension and make everything lowercase (important for checking against already existing files)
                fileName = (file_name + ".txt").lower()

                #Get the filepath, and set it to the autoplaylist directory
                savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to make sure there isn't already a file with the same name
                for root, dirs, files in os.walk(savePath):
                    for file in files:
                        if fileName in file:
                            raise exceptions.CommandError("%s already exists in %s." % (fileName, savePath), expire_in=20)

                write_file(savePath + fileName, "")
                return Response("Created new playlist called %s." % file_name, delete_after=30)

        #Inform user
        else:
            raise exceptions.CommandError('Please specify a file name for the new playlist.', expire_in=20)
OFFRANKED commented 7 years ago

thanks

Zenrac commented 7 years ago

It looks great! Thx

DevanFischer commented 7 years ago

awesome thank you, added code to files and working great!

Selkea commented 7 years ago

Made a slight modification to cmd_newpl to allow users to add an url to the new autoplaylist during file creation, to avoid having to work around the autoplaylist disabling itself, and improved the url verification to prevent runtime errors.

async def cmd_newpl(self, player, file_name=None, song_url=""):
        """
        Usage:
            {command_prefix}newpl file_name [song_url]

        Creates a new autoplaylist.
        """

        #Verify file name was provided
        if file_name:
            #Verify no illegal characters
            if illegal_char(file_name, "[/\\:*?\"<>|]"):
                raise exceptions.CommandError('Please ensure there are no illegal characters in the file name.', expire_in=20)

            #Create new file
            else:
                if song_url:
                    #Get song info from url
                    info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)
                    try:
                        title = info.get('title', '')

                    except (AttributeError, TypeError, ValueError):
                        raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

                    #Verify proper url
                    if not title:
                        raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)

                #Append the file extension and make everything lowercase (important for checking against already existing files)
                fileName = (file_name + ".txt").lower()

                #Get the filepath, and set it to the autoplaylist directory
                savePath = os.path.join(os.path.dirname(__file__), os.pardir) + "\config\\"

                #Check to make sure there isn't already a file with the same name
                for root, dirs, files in os.walk(savePath):
                    for file in files:
                        if fileName in file:
                            raise exceptions.CommandError("%s already exists in %s." % (fileName, savePath), expire_in=20)

                write_file(savePath + fileName, [song_url])
                return Response("Created new autoplaylist called %s." % file_name, delete_after=30)

        #Inform user
        else:
            raise exceptions.CommandError('Please specify a file name for the new playlist.', expire_in=20)

The following lines should also be added/replace the url verification in cmd_pladd in the same way it is used in cmd_newpl

info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)
                    try:
                        title = info.get('title', '')

                    except (AttributeError, TypeError, ValueError):
                        raise exceptions.CommandError('Invalid url. Please insure link is a valid YouTube, SoundCloud or BandCamp url.', expire_in=20)
rustymike commented 7 years ago

Sorry i'm a total noob at this programming stuff... anyway you can provide the files so i can just add to my folders? if not its cool.

TheDefendHand commented 7 years ago

hi guys

Great work you made here, but i got a little error report and i would be happy if someone could help me. 2017-06-25 04_34_31- free_for_all - discord

UPDATE: i'm also not sure, if i have done those stepts right: 2017-06-25 04_49_07- feature differents autoplaylists per servers issue 921 just-some-bots_mus 2017-06-25 04_49_18- feature differents autoplaylists per servers issue 921 just-some-bots_mus

thx for help and keep the great work up.

Selkea commented 7 years ago

It's an indentation error; if you copy/pasted the lines of code, make sure there are no 'tab' spaces.

TheDefendHand commented 7 years ago

thx Selkea

After your fix i got an new problem. when i use the pladd command, it wont add the song-url to my autoplaylist.txt or other playlists. 2017-06-25 14_30_06-bot py musicbot c__users_iason_onedrive_documents_musikbot_discord_meinfreun it worked, as long i dont make your modifications to the pladd/plremove commands. 2017-06-25 14_54_56- feature differents autoplaylists per servers issue 921 just-some-bots_mus that means, i can use the pladd/plremove only for the autoplaylist but i would be happy, if i could use more than just 1 playlist.

thx for help

Zenrac commented 7 years ago

because you have to replace every "self.autoplaylist" by "player.autoplaylist"

TheDefendHand commented 7 years ago

Hi guys

I really thank you for your help. I asked an friend of mine, but he also doesn't understands what to do. If it isnt asked to much, i would be happy if you could explain me what i have actually to do here: 2017-06-27 23_50_38- feature differents autoplaylists per servers issue 921 just-some-bots_mus Optional with screenshots. But even if you don't want to help me, i want to thank you both for your try :)

Selkea commented 7 years ago

Are you having issues with the whole thing, or certain areas?

TheDefendHand commented 7 years ago

well the first thing with "in player.py" isn't much of an problem. the same is for the first 2 "in bot.py" but for the other 3 lines, i have no idea what to do.

thx Selkea

Selkea commented 7 years ago

Don't worry if yours doesn't look exactly the same, I've made other modifications to my MusicBot that weren't mentioned in this thread.

First of all, the line we moved from \_init___ to _on_player_finishedplaying in bot.py is:

if not player.autoplaylist:
                print("Warning: Autoplaylist in %s is empty, disabling." % player.voice_client)
                self.config.auto_playlist = False

This is because we are now adding and removing songs from autoplaylists, as well as loading up new one's on the go. We can no longer only verify if the autoplaylist isn't valid when the MusicBot first initializes.

I put it at the top of the function like so:

async def on_player_finished_playing(self, player, **_):
        if not player.playlist.entries and not player.current_entry and self.config.auto_playlist:

            if not player.autoplaylist:
                print("Warning: Autoplaylist in %s is empty, disabling." % player.voice_client)
                self.config.auto_playlist = False

            while player.autoplaylist:
                song_url = player.autoplaylist[player.autoplaylist_index]
                info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

Secondly, we modified the _cmdloadpl function to accommodate switching autoplaylists in real time.

These were:

Adding an argument to the function:

cmd_loadpl(self, player, file_name=None):

Keeping track of the file location of the new autoplaylist we are using:

#Check to locate existing file
            for root, dirs, files in os.walk(savePath):
                if fileName in files:
                    player.autoplaylist_file = savePath + fileName
                    player.autoplaylist_index = 0
                    player.autoplaylist = load_file(player.autoplaylist_file)
                    return Response("Loaded the %s playlist." % file_name, delete_after=30)

                else:
                    raise exceptions.CommandError('Could not find %s, please ensure the spelling is correct and that the file exists.' % file_name, expire_in=20)
TheDefendHand commented 7 years ago

Well its working as i wanted.

THX Guys for your huge help :=)

Hydrophoby commented 7 years ago

Is there any way to make it so it calls out which playlist the song has been added/remove to instead of just saying "autoplaylist"?

Managed to get it to name the file, but I want it to remove the file path and .txt and just grab the playlist's name itself

Selkea commented 7 years ago

You could create another attribute in the player class and have it keep track of the file name of the current playlist for reference if you really wanted to

Hydrophoby commented 7 years ago

@Selkea Have you managed to make this work on the Review branch? Or havent tried? Been messing around with a test bot on Review branch and everything seems to work, except that when you load another playlist, it just doesnt play it. It'll load it just fine, no error at all, but when you skip song, it just keeps playing the default autoplaylist (even though it says that it loads the new playlist)

Example image: It says it's loaded the autoplaylist with 23 entries (my default playlist has 500), but it still plays songs from the 500song ones.

image

If I do pladd, plremove etc. It adds to the proper playlist, but still never plays the songs of that playlist.

Edit: Nevermind.. Found the issue, because I tried adding the Autoplaylist Improvement changes (Does not play the same song twice until the whole playlist has been played). For some reason that dont play well with your changes.

Selkea commented 7 years ago

I haven't tried putting it on the review branch. If it isn't working properly I would first check to make sure the modifications we made weren't overwritten or lost (to avoid conflicts) when you merged the two together.

Hydrophoby commented 7 years ago

Nah I got it working on the review branch, it's a conflict with #964 .

When I make those changes for "smarter" autoplaylist, it doesnt swap over to the loaded playlist for some reason. I guess I'll keep messing around on my test bot see if I can make it work with that smart playlist change.

Dunno if maybe you can give a hint.

Here's the change that was done

Under async def on_player_finishedplaying(self, player, **):

Change

        while player.autoplaylist:
            random.shuffle(player.autoplaylist)
            song_url = random.choice(player.autoplaylist)

to

        while player.autoplaylist:
            random.shuffle(self.song_list)
            if (len(self.song_list) == 0):
                print('All songs have been played. Restarting auto playlist...')
                self.song_list = self.autoplaylist[:]
            song_url = random.choice(self.song_list)
            self.song_list.remove(song_url)

Tried changing the "self" for "players" here and there, but nothing.

Edit: so far from testing, looks like it will play the whole autoplaylist before swapping to the newly loaded playlist.

Selkea commented 7 years ago

I made my own modification to the way it chose which song to play a while back to fix it repeating the same songs. I simply made it operate like a queue, which follows it's own index, and It's been working fine for me.

Hydrophoby commented 7 years ago

Would you be willing to share those changes? If not it's alright.

Selkea commented 7 years ago

I'll give you a starting point, but it's good for you to learn how to try and do this yourself.

This is what my on_player_finished_playing function looks like:

async def on_player_finished_playing(self, player, **_):
        if not player.playlist.entries and not player.current_entry and self.config.auto_playlist:

            if not player.autoplaylist:
                print("Warning: Autoplaylist in %s is empty, disabling." % player.voice_client)
                self.config.auto_playlist = False

            while player.autoplaylist:
                song_url = player.autoplaylist[player.autoplaylist_index]
                info = await self.downloader.safe_extract_info(player.playlist.loop, song_url, download=False, process=False)

                #Increment index
                player.autoplaylist_index += 1
                if (player.autoplaylist_index > len(player.autoplaylist)-1):
                    player.autoplaylist_index = 0

                if not info:
                    player.autoplaylist.remove(song_url)
                    self.safe_print("[Info] Removing unplayable song from autoplaylist: %s" % song_url)
                    write_file(player.autoplaylist_file, player.autoplaylist)

                    #Go back to last index
                    player.autoplaylist_index -= 1
                    if (player.autoplaylist_index < 0):
                        player.autoplaylist_index = 0

                    continue

                if info.get('entries', None):  # or .get('_type', '') == 'playlist'
                    pass  # Wooo playlist
                    # Blarg how do I want to do this

                # TODO: better checks here
                try:
                    await player.playlist.add_entry(song_url, channel=None, author=None, position=None)
                except exceptions.ExtractionError as e:
                    print("Error adding song from autoplaylist:", e)
                    continue

                break

            if not player.autoplaylist:
                print("[Warning] No playable songs in the autoplaylist, disabling.")
                self.config.auto_playlist = False

With this you should be able to figure out what small changes you need to make in other functions and files to ensure it works properly 👍

Hydrophoby commented 7 years ago

Thanks a bunch I'll have a go at it.

Selkea commented 7 years ago

If you're still struggling by tomorrow night, I'll help you some more. I'm off to bed so, goodnight and good luck!

Selkea commented 7 years ago

@Hydrophoby Have you figured it out?