yu1612
yu1612

Reputation: 5

discord.py outputting from a list at random without duplicates, then restarts when list is empty

I've been wanting to develop a bot for my server.

I'm trying to make a command "+audio" that returns a link to a song out of a list of 15 links; however, I want it to be able to "shuffle" through the list without duplicates until the list is emptied, then it should reshuffle the entire list again.

Here's what I have so far:

import discord
import urllib.parse, urllib.request, re
from discord.ext import commands
from discord.ext.commands import Bot
import asyncio
import random

# this is the list of all the audios, i'm using x here as a substitute 
all_audios = [x, x, x, etc.]

@client.command()
async def audio(ctx):
        audios = random.choice(all_audios)
        await ctx.send(audios)

client.run('token')

Upvotes: 0

Views: 199

Answers (2)

toto le harico
toto le harico

Reputation: 26

You can use the random.chice(myList) which shuffles the list. Then to extract the elements one by one you can use myList.pop() which removes the last element of the list and returns the last element (thus using the list as a stack).

You can do:

all_audios = [x, x, x, etc.] 
shuffled_songs = []

@client.command()
async def audio(ctx):
        if shuffled_songs == []:
            shuffled_songs = all_audios[:]
            random.shuffle(shuffled_songs)
            # the list of songs is copied and shuffled

        await ctx.send(shuffled_songs.pop())
        # the last element of the list is played and removed from the list

client.run('token')

Upvotes: 0

PotentialStyx
PotentialStyx

Reputation: 442

The problem here is you are using one list, and the songs stay there after being played, so what you could do is make a copy of the list, then grab random songs from that list and remove each song after being chosen. That way every song will only be played once. To deal with when the list is empty, you can just check if the new copy has 0 elements with either len(not_played) == 0 or no_played == []

Here is an example implementation of that:

all_audios = [x, x, x, etc.] # replace with list of songs
not_played = all_audios[:]

@client.command()
async def audio(ctx):
        if len(not_played) == 0:
            not_played = all_audios[:]
        
        audios = random.choice(not_played)
        not_played.remove(audios)
        await ctx.send(audios)

client.run('token')

Explaination:

  1. code first makes a copy with all_audios[:].

  2. when the command is called it checks if the list is empty, if it is the list is refilled with all the songs.

  3. it finds a random song, then removes it from the list copy.

  4. it sends that song choice into the channel the command was used.

*This will keep the same list across all guilds / clients

Upvotes: 1

Related Questions