-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from rahulgautam21/dev
Merging dev to main
- Loading branch information
Showing
8 changed files
with
280 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
pytest==7.1.2 | ||
pandas | ||
discord.py==2.0.1 | ||
pandas==1.4.2 | ||
python-dotenv==0.21.0 | ||
setuptools==63.2.0 | ||
youtube_dl==2021.12.17 | ||
youtube_search_python==1.6.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from multiprocessing.util import debug | ||
import discord | ||
import os | ||
from get_all import * | ||
import re | ||
from dotenv import load_dotenv | ||
from discord.ext import commands | ||
from utils import searchSong | ||
from songs_queue import Songs_Queue | ||
from songs_cog import Songs | ||
|
||
|
||
load_dotenv('../.env') | ||
TOKEN = os.getenv('DISCORD_TOKEN') | ||
# This can be obtained using ctx.message.author.voice.channel | ||
VOICE_CHANNEL_ID = 1017135653789646851 | ||
intents = discord.Intents.all() | ||
intents.members = True | ||
client = commands.Bot(command_prefix='/', intents=intents) | ||
|
||
|
||
@client.event | ||
async def on_ready(): | ||
# for guild in client.guilds: | ||
# print(guild.name) | ||
# print( | ||
# f'{client.user} is connected to the following guild:\n' | ||
# f'{guild.name}(id: {guild.id})' | ||
# ) | ||
voice_channel = client.get_channel(VOICE_CHANNEL_ID) | ||
if client.user not in voice_channel.members: | ||
await voice_channel.connect() | ||
await client.load_extension("songs_cog") | ||
|
||
|
||
@client.event | ||
async def on_message(message): | ||
if message.author == client.user: | ||
return | ||
options = set() | ||
|
||
if message.channel.name == 'general': | ||
user_message = str(message.content) | ||
await client.process_commands(message) | ||
|
||
client.run(TOKEN) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,43 @@ | ||
import pandas as pd | ||
import random | ||
|
||
|
||
#add pagination support | ||
def get_all_songs(self): | ||
def filtered_songs(): | ||
all_songs = pd.read_csv("../data/songs.csv") | ||
print(' Data has (rows, columns):', all_songs.shape) | ||
|
||
all_songs = all_songs.filter(["title", "artist", "year"]) | ||
print(all_songs.head(10)) | ||
all_songs = all_songs.filter(["title", "artist", "year", "top genre"]) | ||
return all_songs | ||
|
||
def get_all_songs(): | ||
all_songs = pd.read_csv("../data/songs.csv") | ||
return all_songs | ||
|
||
def recommend(input_songs): | ||
# removing all songs with count = 1 | ||
songs = get_all_songs() | ||
songs = songs.groupby('top genre').filter(lambda x : len(x)>0) | ||
# creating dictionary of song titles and genre | ||
playlist = dict(zip(songs['title'], songs['top genre'])) | ||
# creating dictionary to count the frequency of each genre | ||
freq = {} | ||
for item in songs['top genre']: | ||
if (item in freq): | ||
freq[item] += 1 | ||
else: | ||
freq[item] = 1 | ||
# create list of all songs from the input genre | ||
selected_list = [] | ||
output = [] | ||
for input in input_songs: | ||
if input in playlist.keys(): | ||
for key, value in playlist.items(): | ||
if playlist[input] == value: | ||
selected_list.append(key) | ||
selected_list.remove(input) | ||
if (len(selected_list) >= 10): | ||
output = random.sample(selected_list, 10) | ||
else: | ||
extra_songs = 10 - len(selected_list) | ||
song_names = songs['title'].to_list() | ||
song_names_filtered = [x for x in song_names if x not in selected_list] | ||
selected_list.extend(random.sample(song_names_filtered, extra_songs)) | ||
output = selected_list.copy() | ||
return output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
from multiprocessing.util import debug | ||
import discord | ||
from numpy import empty_like | ||
from get_all import * | ||
from dotenv import load_dotenv | ||
from discord.ext import commands | ||
from utils import searchSong, random_ten | ||
from songs_queue import Songs_Queue | ||
import youtube_dl | ||
|
||
FFMPEG_OPTIONS = { | ||
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'} | ||
YDL_OPTIONS = {'format': 'bestaudio/best', 'noplaylist': 'True'} | ||
|
||
|
||
class Songs(commands.Cog): | ||
|
||
def __init__(self, bot): | ||
self.bot = bot | ||
|
||
@commands.command(name='resume', help='Resumes the song') | ||
async def resume(self, ctx): | ||
voice_client = ctx.message.guild.voice_client | ||
if voice_client.is_paused(): | ||
await voice_client.resume() | ||
else: | ||
await ctx.send("The bot was not playing anything before this. Use play command") | ||
|
||
@commands.command(name='play_custom', help='To play custom song') | ||
async def play_custom(self, ctx): | ||
user_message = str(ctx.message.content) | ||
song_name = user_message.split(' ', 1)[1] | ||
await self.play_song(song_name, ctx) | ||
|
||
@commands.command(name='stop', help='Stops the song') | ||
async def stop(self, ctx): | ||
voice_client = ctx.message.guild.voice_client | ||
if voice_client.is_playing(): | ||
voice_client.stop() | ||
else: | ||
await ctx.send("The bot is not playing anything at the moment.") | ||
|
||
async def play_song(self, song_name, ctx): | ||
# First stop whatever the bot is playing | ||
await self.stop(ctx) | ||
try: | ||
server = ctx.message.guild | ||
voice_channel = server.voice_client | ||
url = searchSong(song_name) | ||
async with ctx.typing(): | ||
with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: | ||
info = ydl.extract_info(url, download=False) | ||
I_URL = info['formats'][0]['url'] | ||
source = await discord.FFmpegOpusAudio.from_probe(I_URL, **FFMPEG_OPTIONS) | ||
voice_channel.play(source) | ||
voice_channel.is_playing() | ||
await ctx.send('**Now playing:** {}'.format(song_name)) | ||
except Exception as e: | ||
await ctx.send("The bot is not connected to a voice channel.") | ||
|
||
async def handle_empty_queue(self, ctx): | ||
try: | ||
songs_queue | ||
except NameError: | ||
await ctx.send("No recommendations present. First generate recommendations using /poll") | ||
return True | ||
if songs_queue.get_len() == 0: | ||
await ctx.send("No recommendations present. First generate recommendations using /poll") | ||
return True | ||
return False | ||
|
||
|
||
@commands.command(name='next_song', help='To play next song in queue') | ||
async def next_song(self, ctx): | ||
empty_queue = await self.handle_empty_queue(ctx) | ||
if not empty_queue: | ||
await self.play_song(songs_queue.next_song(), ctx) | ||
|
||
@commands.command(name='prev_song', help='To play prev song in queue') | ||
async def play(self, ctx): | ||
empty_queue = await self.handle_empty_queue(ctx) | ||
if not empty_queue: | ||
await self.play_song(songs_queue.prev_song(), ctx) | ||
|
||
|
||
@commands.command(name='pause', help='This command pauses the song') | ||
async def pause(self, ctx): | ||
voice_client = ctx.message.guild.voice_client | ||
if voice_client.is_playing(): | ||
await voice_client.pause() | ||
else: | ||
await ctx.send("The bot is not playing anything at the moment.") | ||
|
||
@commands.command(name='poll', help='Poll for recommendation') | ||
async def poll(self, ctx): | ||
reactions = ['👍', '👎'] | ||
selected_songs = [] | ||
count = 0 | ||
bot_message = "Select song preferences by reaction '👍' or '👎' to the choices. \nSelect 3 songs" | ||
await ctx.send(bot_message) | ||
ten_random_songs = random_ten() | ||
for ele in zip(ten_random_songs["title"], ten_random_songs["artist"]): | ||
bot_message = str(ele[0]) + " By " + str(ele[1]) | ||
description = [] | ||
poll_embed = discord.Embed( | ||
title=bot_message, color=0x31FF00, description=''.join(description)) | ||
react_message = await ctx.send(embed=poll_embed) | ||
for reaction in reactions[:len(reactions)]: | ||
await react_message.add_reaction(reaction) | ||
res, user = await self.bot.wait_for('reaction_add') | ||
if (res.emoji == u'👍'): | ||
selected_songs.append(str(ele[0])) | ||
count += 1 | ||
if (count == 3): | ||
bot_message = "Selected songs are : " + \ | ||
' , '.join(selected_songs) | ||
await ctx.send(bot_message) | ||
break | ||
global songs_queue | ||
recommended_songs = recommend(selected_songs) | ||
songs_queue = Songs_Queue(recommended_songs) | ||
await self.play_song(songs_queue.next_song(), ctx) | ||
|
||
@commands.command(name='queue', help='Show active queue of recommendations') | ||
async def queue(self, ctx): | ||
empty_queue = await self.handle_empty_queue(ctx) | ||
if not empty_queue: | ||
queue,index = songs_queue.return_queue() | ||
await ctx.send("Queue of recommendations: ") | ||
for i in range(len(queue)): | ||
if i == index: | ||
await ctx.send("*" + queue[i]) | ||
else: | ||
await ctx.send(queue[i]) | ||
|
||
|
||
async def setup(client): | ||
await client.add_cog(Songs(client)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# This queue will store all the recommendation of the songs | ||
|
||
class Songs_Queue(): | ||
def __init__(self, song_names): | ||
self.queue = song_names | ||
self.index = 0 | ||
self.current_index = 0 | ||
|
||
def next_song(self): | ||
print(self.queue) | ||
if (self.index == len(self.queue)): | ||
self.index = 0 | ||
val = self.index | ||
self.current_index = val | ||
self.index += 1 | ||
return self.queue[val] | ||
|
||
def prev_song(self): | ||
self.index -= 1 | ||
if (self.index <= 0): | ||
self.index = len(self.queue) - 1 | ||
val = self.index | ||
self.current_index = val | ||
return self.queue[val] | ||
|
||
def get_len(self): | ||
return len(self.queue) | ||
|
||
def return_queue(self): | ||
return (self.queue, self.current_index) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from youtubesearchpython import VideosSearch | ||
|
||
from get_all import filtered_songs | ||
|
||
|
||
def searchSong(name_song): | ||
print(name_song) | ||
videosSearch = VideosSearch(name_song, limit=1) | ||
result = videosSearch.result() | ||
link = result['result'][0]['link'] | ||
return link | ||
|
||
|
||
all_songs = filtered_songs()[["title", "artist", "top genre"]] | ||
|
||
|
||
def random_ten(): | ||
ten_random_songs = (all_songs.sample( | ||
frac=1).groupby('top genre').head(1)).sample(10) | ||
return ten_random_songs |