Module cogs.recommender_cog
This file contains the recommender system for the bot. It will be used to poll the users for their preferences, and then recommend songs based on the preferences using the enhanced recommender system
Functions
async def setup(bot)
-
Function to setup the recommender cog
Classes
class Recommender (bot)
-
This class contains the commands to poll the user, then recommend songs based on the user's preferences
Expand source code
class Recommender(commands.Cog): """ This class contains the commands to poll the user, then recommend songs based on the user's preferences """ def __init__(self, bot): self.bot = bot self.message_id = None self.command_msg_id = None # Get the queue instance self.queue = Songs_Queue() self.emoji_list = [ "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟" ] def random_color(self): """ Function to get a random color for the embed message """ return discord.Colour.from_rgb(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) @commands.command(name="poll", help="Provides the user with a poll of 10 randoms songs from the dataset to choose from. Used in conjunction witht the !recommend command") async def poll(self, ctx): """ Function to poll the user for their preferences """ # Delete the previous poll message and command message if it exists if self.message_id and self.command_msg_id: try: message = await ctx.fetch_message(self.message_id) await message.delete() command_msg = await ctx.fetch_message(self.command_msg_id) await command_msg.delete() except Exception as e: print(e) # Get 10 random songs from the dataset, and store them in the class variable self.songs = utils.random_n(10).filter( ["track_name", "artist_name"]).reset_index(drop=True) # Create the poll message poll_message = "Please react to this message with your preferences:\n\n" for index, song in self.songs.iterrows(): # Get the emoji icon for the index emoji_icon = self.emoji_list[index] # Add the song to the poll message poll_message += f"{emoji_icon} **{song['track_name']} *by* {song['artist_name']}**\n" # Add instructions to the poll message poll_message += "\n*If you don't like any of the songs, you may run the command again to get new songs*\n" poll_message += "\n**Once you have chosen your songs, run the !recommend command to get your recommendations**" ads = [""] # Send the poll message embedded_message = discord.Embed( title="Song Poll", description=poll_message + ads[0], color=self.random_color()) message = await ctx.send(embed=embedded_message) # Add the reactions to the message for reaction in self.emoji_list[:len(self.emoji_list)]: await message.add_reaction(reaction) # Store the interaction self.message_id = message.id self.command_msg_id = ctx.message.id # await ctx.send("Choose a song(s) by reacting with the corresponding emoji, or if you don't like any of the songs, run the command again.") # await ctx.send("Once you have chosen your songs, run the !recommend command to get your recommendations") @commands.command(name="recommend", aliases=["get_songs"], help="Recommends songs based on the user's preferences. Must first call the !poll command") async def recommend(self, ctx): """ Function to recommend songs based on the user's preferences """ # Check if the user has run the poll command if not self.message_id: await ctx.send("Please run the !poll command first to choose your preferences.") return # Get the message message = await ctx.fetch_message(self.message_id) # Get the reactions reactions = message.reactions # Get the user's preferences preferences = [] for reaction in reactions: if reaction.count > 1: # if there is more than one reaction on a reaction, then the user has reacted to it, so add the corresponding song to the preferences index = self.emoji_list.index(reaction.emoji) preferences.append(self.songs.iloc[index]) # Send the user the chosen songs choose_message = "You have chosen the following songs:\n\n" if not preferences: choose_message = "You have not chosen any songs. Please react to the poll message with the corresponding emoji to choose a song." else: for song in preferences: choose_message += f"**{song['track_name']} *by* {song['artist_name']}**\n" # Clear the message reference self.message_id = None self.command_msg_id = None embedded_message = discord.Embed( title="Chosen Songs", description=choose_message, color=self.random_color()) await ctx.send(embed=embedded_message) # Get the user preferences as a list of tuples user_input = [(song["track_name"], song["artist_name"]) for song in preferences] # Get the recommendations recommendations = recommend(user_input) # Send the recommendations to the user recommend_message = "Here are some songs you may like based on your preferences:\n\n" for song, artist in recommendations: recommend_message += f"**{song} *by* {artist}**\n" embedded_message = discord.Embed( title="Recommendations", description=recommend_message, color=self.random_color()) await ctx.send(embed=embedded_message) # ask if the user wants to add the recommended songs to the queue add_message = "Would you like to add the recommended songs to the queue? React with the corresponding emoji to add the songs to the end of the queue, clear the queue and add the songs, or cancel the operation." add_message += f"\n\n{self.emoji_list[0]} **Add to the end of the queue**" add_message += f"\n{self.emoji_list[1]} **Clear the queue and add the songs**" add_message += f"\n{self.emoji_list[2]} **Cancel**" embedded_message = discord.Embed( title="Add Recommendations to Queue", description=add_message, color=self.random_color()) message = await ctx.send(embed=embedded_message) # Add the reactions to the message for reaction in self.emoji_list[:3]: await message.add_reaction(reaction) def check(reaction, user): return user == ctx.author and str(reaction.emoji) in self.emoji_list[:3] # wait for the user's response try: reaction, user = await ctx.bot.wait_for('reaction_add', timeout=60.0, check=check) if reaction.emoji == self.emoji_list[0]: # Add the songs to the end of the queue await ctx.send("Adding the songs to the end of the queue.") self.queue.add_to_queue(recommendations) await ctx.send(f"Songs added to the queue. Current queue: {self.queue.queue}\nStart playback with the !start command.") elif reaction.emoji == self.emoji_list[1]: # Clear the queue and add the songs await ctx.send("Clearing the queue and adding the songs.") self.queue.clear() self.queue.add_to_queue(recommendations) await ctx.send(f"Songs added to the queue. Current queue: {self.queue.queue}\nStart playback with the !start command.") elif reaction.emoji == self.emoji_list[2]: # Cancel the operation await ctx.send("Operation cancelled.") else: await ctx.send("Invalid reaction. Please run the command again.") except asyncio.TimeoutError: await ctx.send("You did not respond in time. Please run the command again.") return
Ancestors
- discord.ext.commands.cog.Cog
Class variables
var poll
var recommend
Methods
def random_color(self)
-
Function to get a random color for the embed message