I'm making a music bot, and, im struggling with some parts. I don't know how to make the skip part or play the next song in the queue once the current one ends. Any help?
Here is all the code (all of it because just in case)
The queue part is near the bottom, the skip part is also near the bottom and playing the song is right below here.
import os
import re
import urllib.request
import youtube_dl
import shutil
import discord
from discord.ext import commands
from discord.utils import get
bot = commands.Bot(command_prefix='g.')
token = '<mytoken>'
#bot.command(pass_context=True)
async def play(ctx, *args: str):
search = '+'.join(args)
print(search)
if search == " ":
await ctx.send("Uso: g.play (Video)")
return
else:
html = urllib.request.urlopen("https://www.youtube.com/results?search_query=" + search)
video_ids = re.findall(r"watch\?v=(\S{11})", html.read().decode())
url = "https://www.youtube.com/watch?v=" + video_ids[0]
print(url)
def check_queue():
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is True:
DIR = os.path.abspath(os.path.realpath("Queue"))
length = len(os.listdir(DIR))
still_q = length - 1
try:
first_file = os.listdir(DIR)[0]
except:
print("No more queued song(s)\n")
queues.clear()
return
main_location = os.path.dirname(os.path.realpath(__file__))
song_path = os.path.abspath(os.path.realpath("Queue") + "\\" + first_file)
if length != 0:
print("Song done, playing next queued\n")
print(f"Songs still in queue: {still_q}")
song_there = os.path.isfile("song.mp3")
if song_there:
os.remove("song.mp3")
shutil.move(song_path, main_location)
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, 'song.mp3')
enfile = file
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.07
print(f"Playing {nname[0]}")
else:
queues.clear()
return
else:
queues.clear()
print("No songs were queued before the ending of the last song\n")
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
queues.clear()
print("Removed old song file")
except PermissionError:
print("Trying to delete song file, but it's being played.")
print("ERROR: Music Playing")
await ctx.send("Error: Ya estoy poniendo musica! Usa g.queue (cancion) para agregar una cancion a la lista.")
search = ' '.join(args)
channel = ctx.message.channel
return
Queue_infile = os.path.isdir("./Queue")
try:
Queue_folder = "./Queue"
if Queue_infile is True:
print("Removed old Queue Folder")
shutil.rmtree(Queue_folder)
except:
print("No old queue folder.")
print("Getting everytihng ready now.")
await ctx.send("Preparando cancion...")
voice = get(bot.voice_clients, guild=ctx.guild)
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
ydl.download([url])
for file in os.listdir("./"):
if file.endswith(".mp3"):
name = file
print(f"Renamed file: {file}\n")
os.rename(file, "song.mp3")
nfile = file
print(str(voice))
channel = ctx.message.author.voice.channel
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.3
nname = name.rsplit("-", 2)
print(f"Playing {nname[0]}")
await embed(ctx, url, nfile, video_ids[0])
queues = {}
#bot.command(pass_context=True)
async def queue(ctx, *searchs):
search = '+'.join(searchs)
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is False:
os.mkdir("Queue")
DIR = os.path.abspath(os.path.realpath("Queue"))
q_num = len(os.listdir(DIR))
q_num += 1
add_queue = True
while add_queue:
if q_num in queues:
q_num += 1
else:
add_queue = False
queues[q_num] = q_num
queue_path = os.path.abspath(os.path.realpath("Queue") + f"\song{q_num}.%(ext)s")
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'outtmpl': queue_path,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192'
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
html = urllib.request.urlopen("https://www.youtube.com/results?search_query=" + search)
video_ids = re.findall(r"watch\?v=(\S{11})", html.read().decode())
url = "https://www.youtube.com/watch?v=" + video_ids[0]
print(url)
ydl.download([url])
await ctx.send("Añadiendo cancion " + str(q_num) + " a la lista!")
print("Song added to the queue:" + str(q_num))
#bot.event
async def on_ready():
print(f"""Bot {bot.user} has connected to discord!""")
bot.run(token)```
You can get code for understanding its not the proper-one but it can help you.
Music Bot Code
You will get an idea how to code these commands.
Related
I'm making a discord bot. But I'm having spotify issue.
its says
"spotdl: error: unrecognized arguments: -s: (music link)"
I've installed pip youtubedl,spotdl, every pip I needed.
I'm making this bot for my discord server.
Please help me.
I've learned this from this Youtube link. In this tutorial, bot was working fine. But not mine. What should I do now?
import os
import shutil
from os import system
import discord
import youtube_dl
from discord.ext import commands
from discord.utils import get
TOKEN = 'TOKEN'
BOT_PREFIX = '.'
bot = commands.Bot(command_prefix=BOT_PREFIX)
#bot.event
async def on_ready():
print("Logged in as: " + bot.user.name + "\n")
#bot.command(pass_context=True, aliases=['j', 'joi'])
async def join(ctx):
global voice
channel = ctx.message.author.voice.channel
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_connected():
await voice.move_to(channel)
else:
voice = await channel.connect()
await voice.disconnect()
if voice and voice.is_connected():
await voice.move_to(channel)
else:
voice = await channel.connect()
print(f"The bot has connected to {channel}\n")
await ctx.send(f"Joined {channel}")
#bot.command(pass_context=True, aliases=['l', 'lea'])
async def leave(ctx):
channel = ctx.message.author.voice.channel
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_connected():
await voice.disconnect()
print(f"The bot has left {channel}")
await ctx.send(f"Left {channel}")
else:
print("Bot was told to leave voice channel, but was not in one")
await ctx.send("Don't think I am in a voice channel")
#bot.command(pass_context=True, aliases=['p', 'pla'])
async def play(ctx, url: str):
def check_queue():
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is True:
DIR = os.path.abspath(os.path.realpath("Queue"))
length = len(os.listdir(DIR))
still_q = length - 1
try:
first_file = os.listdir(DIR)[0]
except:
print("No more queued song(s)\n")
queues.clear()
return
main_location = os.path.dirname(os.path.realpath(__file__))
song_path = os.path.abspath(os.path.realpath("Queue") + "\\" + first_file)
if length != 0:
print("Song done, playing next queued\n")
print(f"Songs still in queue: {still_q}")
song_there = os.path.isfile("song.mp3")
if song_there:
os.remove("song.mp3")
shutil.move(song_path, main_location)
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, 'song.mp3')
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 100.00
else:
queues.clear()
return
else:
queues.clear()
print("No songs were queued before the ending of the last song\n")
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
queues.clear()
print("Removed old song file")
except PermissionError:
print("Trying to delete song file, but it's being played")
await ctx.send("ERROR: Music playing")
return
Queue_infile = os.path.isdir("./Queue")
try:
Queue_folder = "./Queue"
if Queue_infile is True:
print("Removed old Queue Folder")
shutil.rmtree(Queue_folder)
except:
print("No old Queue folder")
await ctx.send("Getting everything ready now")
voice = get(bot.voice_clients, guild=ctx.guild)
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
try:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
ydl.download([url])
except:
print("FALLBACK: youtube-dl does not support this URL, using Spotify (This is normal if Spotify URL)")
c_path = os.path.dirname(os.path.realpath(__file__))
system("spotdl -f " + '"' + c_path + '"' + " -s " + url)
for file in os.listdir("./"):
if file.endswith(".mp3"):
name = file
print(f"Renamed File: {file}\n")
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.07
nname = name.rsplit("-", 2)
await ctx.send(f"Playing: {nname[0]}")
print("playing\n")
#bot.command(pass_context=True, aliases=['pa', 'pau'])
async def pause(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_playing():
print("Music paused")
voice.pause()
await ctx.send("Music paused")
else:
print("Music not playing failed pause")
await ctx.send("Music not playing failed pause")
#bot.command(pass_context=True, aliases=['r', 'res'])
async def resume(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_paused():
print("Resumed music")
voice.resume()
await ctx.send("Resumed music")
else:
print("Music is not paused")
await ctx.send("Music is not paused")
#bot.command(pass_context=True, aliases=['s', 'sto'])
async def stop(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
queues.clear()
queue_infile = os.path.isdir("./Queue")
if queue_infile is True:
shutil.rmtree("./Queue")
if voice and voice.is_playing():
print("Music stopped")
voice.stop()
await ctx.send("Music stopped")
else:
print("No music playing failed to stop")
await ctx.send("No music playing failed to stop")
queues = {}
#bot.command(pass_context=True, aliases=['q', 'que'])
async def queue(ctx, url: str):
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is False:
os.mkdir("Queue")
DIR = os.path.abspath(os.path.realpath("Queue"))
q_num = len(os.listdir(DIR))
q_num += 1
add_queue = True
while add_queue:
if q_num in queues:
q_num += 1
else:
add_queue = False
queues[q_num] = q_num
queue_path = os.path.abspath(os.path.realpath("Queue") + f"\song{q_num}.%(ext)s")
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'outtmpl': queue_path,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
try:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
ydl.download([url])
except:
print("FALLBACK: youtube-dl does not support this URL, using Spotify (This is normal if Spotify URL)")
q_path = os.path.abspath(os.path.realpath("Queue"))
system(f"spotdl -ff song{q_num} -f " + '"' + q_path + '"' + " -s " + url)
await ctx.send("Adding song " + str(q_num) + " to the queue")
print("Song added to queue\n")
#bot.command(pass_context=True, aliases=['n', 'nex'])
async def next(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_playing():
print("Playing Next Song")
voice.stop()
await ctx.send("Next Song")
else:
print("No music playing")
await ctx.send("No music playing failed")
bot.run('TOKEN')
Hello Md Sadman Muhtasim Billah!
Well, it seems like the problem is actually in the URL you're submitting, as it don't recognize the '-s' argument, not the parameter itself.
So you should probably try the same URL he uses in the YouTube video you sent, to test it. Or try other links.
I couldn't find a flaw in the code, and it really is the same used in the YT tutorial.
Hope I helped. :)
Im trying to learn on how to make a music bot, the play command is alr fine but the youtube thumbnail pic doesnt show when the url is given in embed message. Idk whats the function to make the bot show the youtube video thumbnail into the embed message. Heres the code :
#client.command()
async def play(ctx, url : str):
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
except PermissionError:
await ctx.send("Wait for the current playing music to end or use %leave <:_Paimon6:827074349450133524>")
return
voiceChannel = discord.utils.get(ctx.guild.voice_channels, name='Private')
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
em6 = discord.Embed(title = "Downloading Music", description = f'{url}\n\nPlease wait for paimon to setup the music you provide.\nMusic provided by {ctx.author.mention} <:_Paimon6:827074349450133524>',color = ctx.author.color)
await ctx.send(embed = em6, delete_after = 2)
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"))
em1 = discord.Embed(title = "Now Listening", description = f'{url}\n\nPlease use %leave first to change music.\nMusic provided by {ctx.author.mention} <:_Paimon6:827074349450133524>',color = ctx.author.color)
await ctx.send(embed = em1)
Anyways, I think you're looking for the .set_image() method.
You can get a link to the thumbnail of a youtube video via
https://img.youtube.com/vi/<insert-youtube-video-id-here>/0.jpg
Like explained here.
Retrieve the id of the youtube video via
videoID = url.split("watch?v=")[1].split("&")[0]
And then you can set it as the embed image or thumbnail.
In your case it should look like this
#client.command()
async def play(ctx, url : str):
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
except PermissionError:
await ctx.send("Wait for the current playing music to end or use %leave <:_Paimon6:827074349450133524>")
return
voiceChannel = discord.utils.get(ctx.guild.voice_channels, name='Private')
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
em6 = discord.Embed(title = "Downloading Music", description = f'{url}\n\nPlease wait for paimon to setup the music you provide.\nMusic provided by {ctx.author.mention} <:_Paimon6:827074349450133524>',color = ctx.author.color)
await ctx.send(embed = em6, delete_after = 2)
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"))
em1 = discord.Embed(title = "Now Listening", description = f'{url}\n\nPlease use %leave first to change music.\nMusic provided by {ctx.author.mention} <:_Paimon6:827074349450133524>',color = ctx.author.color)
# get id
videoID = url.split("watch?v=")[1].split("&")[0]
em1.set_image(url = "https://img.youtube.com/vi/{videoID}/0.jpg".format(videoID = videoID))
await ctx.send(embed = em1)
If you find this image too big, you could also set it as a thumbnail via
embed.set_thumbnail(url)
I am trying to make a music bot for my server.
everything is working fine like the bot connecting to the channel but it is showing this error after joining the channel.
my code looks like this.
import discord
from discord.ext import commands
from random import choice
import youtube_dl
import asyncio
import urllib.parse, urllib.request, re
client = commands.Bot(command_prefix=commands.when_mentioned_or(">"), description='Relatively simple music bot example')
def colour():
l = [
1752220, 3066993, 3447003, 10181046, 15844367,
15105570, 15158332, 3426654, 1146986, 2067276,
2123412, 7419530, 12745742, 11027200, 10038562,
2899536, 16580705, 12320855
]
return choice(l)
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0'
}
ffmpeg_options = {'options': '-vn'}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=1):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
#classmethod
async def from_url(cls, url, *, loop=None, stream=True):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor( None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(
filename,
**ffmpeg_options,
before_options= '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5'),
data=data
)
async def join(ctx):
author = ctx.author.voice
if not author:
em = discord.Embed(
title = 'Opps! 😥',
description = 'You are not connected to any voice channel. \nTry again after connecting to a voice channel.',
colour = discord.Colour.red()
)
await ctx.send(embed=em)
return 1
else:
author = ctx.author.voice.channel
voiceClient = ctx.voice_client
if not voiceClient:
await author.connect()
else:
await ctx.send("**Already connected to :**" + author)
return 0
async def search(ctx, url=""):
if 'http://www.youtube.com' in url:
return url
else:
l = url.split(' ')
j = ''
for i in l:
j += i
j += '+'
url = j
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?search_query=' + url
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
std = 'http://www.youtube.com/watch?v='
url = str(std) + str(search_results[0])
return url
class Music(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command(aliases=["p"])
async def play(self, ctx, *, url=""):
w = await join(ctx)
if w == 1:
print("User not connected")
else:
if url == '':
embed = discord.Embed(
title = 'Opps! 😥',
description = "You didn't specified any song to play. \nPlease try again but this time specify a song name or url to play.",
colour = discord.Colour.orange()
)
await ctx.send(embed=embed)
else:
url = await search(ctx, url)
async with ctx.typing():
player = await YTDLSource.from_url(url, loop= ctx.bot.loop, stream=True) # before_options='-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5'
ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing: {}'.format(player.title))
client.add_cog(Music(client))
client.run(os.environ['token'])
I don't know what's the problem cause i coded this bot on repl.it and when i tried running it from it's shell everything is working fine but when i hosted this to heroku this error is coming.
Can anyone help.
Thanks for the help in advance 😊
ffmpeg has to exist as an executable binary file on the system you are trying to run your discord bot on. Including the ffmpeg-python library only links ffmpeg and python together, because it's only a binder between to two.
Make sure to download and install ffmpeg for your environment, then you can use ffmpeg-python library to do stuff in your bot's python code.
Installation does vary depending on what OS, so make sure you follow steps accordingly.
I'm developing a discord bot that can find spotify playlists and queue the tracks' youtube counterparts. I have a loop running that uses a list of tracknames to search for a video on youtube, it then grabs the top result and sends to an asynchronous function that plays it. However, whilst the bot is in this loop it does not accept other commands. Can I make this run concurrently with other commands? The following is all the code of my application
from bs4 import BeautifulSoup
import urllib.request
import os
import requests
import base64
import json
import time
import discord
import shutil
from discord.utils import get
from discord import FFmpegPCMAudio
import youtube_dl
import asyncio
from asgiref.sync import async_to_sync
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
bot = commands.Bot(command_prefix='s- ')
accessToken = ""
clientIDSECRET = os.getenv('SPOTIFY_ID')+':'+os.getenv('SPOTIFY_SECRET')
base64Auth = base64.b64encode(clientIDSECRET.encode("utf-8")).decode('ascii')
trackStrings = []
def pretty_print_POST(req):
print('{}\n{}\r\n{}\r\n\r\n{}'.format(
'-----------START-----------',
req.method + ' ' + req.url,
'\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
req.body,
))
#bot.event
async def on_ready():
payload={'grant_type':'client_credentials'}
headers = {'Authorization':f'Basic {base64Auth}'}
req = requests.Request('POST', "https://accounts.spotify.com/api/token", data = payload, headers = headers)
prep = req.prepare()
pretty_print_POST(prep)
s = requests.Session()
response = s.send(prep)
global accessToken
accessToken = json.loads(response.content)["access_token"]
print(accessToken)
#bot.command(pass_context=True, aliases=['sp'])
async def spotlist(ctx, userName, playlistName = "", shuffle=False, limit=100, offset=0):
print(limit)
if limit > 100 or limit < 0:
await ctx.send(f'Limit out of bounds! It needs to be between 0 and 100.')
return
playlistId = ""
headers = {'Authorization':f'Bearer {accessToken}'}
if playlistName == "id":
playlistId = userName #Username assumed to be a playlist id instead
else:
playlists = json.loads(requests.get(f'https://api.spotify.com/v1/users/{userName}/playlists', headers=headers).content)
for playlist in playlists["items"]:
if playlist["name"] == playlistName:
playlistId = playlist["id"]
nextURL = f'https://api.spotify.com/v1/playlists/{playlistId}/tracks?offset={offset}&limit={limit}'
while nextURL != None:
trackResponse = requests.get(nextURL, headers = headers)
tracks = json.loads(trackResponse.content)
if(tracks["total"] <= offset):
await ctx.send(f'Offset (third argument) is too large! Your playlist is {tracks["total"]} long.')
return
for track in tracks["items"]:
trackStrings.append(track["track"]["name"] + " " + track["track"]["artists"][0]["name"])
nextURL = tracks["next"]
if(limit != 100):
break
for trackString in trackStrings:
try:
await play(ctx, await SearchVid(trackString))
except:
print("couldn't find song")
#bot.command(pass_context=True, aliases=['j', 'joi'])
async def join(ctx):
channel = ctx.message.author.voice.channel
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_connected():
await voice.move_to(channel)
else:
voice = await channel.connect()
#bot.command(pass_context=True, aliases=['l', 'lea'])
async def leave(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_connected():
await voice.disconnect()
else:
await ctx.send("Don't think I am in a voice channel")
async def playSong(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
DIR = os.path.abspath(os.path.realpath("Queue"))
try:
first_file = os.listdir(DIR)[0]
except:
print("No more queued song(s)\n")
return
song_path = os.path.abspath(os.path.realpath("Queue") + "\\" + first_file)
async def func(x):
os.remove(song_path)
await playSong(ctx)
try:
voice.play(discord.FFmpegPCMAudio(song_path), after=async_to_sync(func))
await ctx.send(f"playing {first_file}")
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.07
except:
print("song already playing")
still_q = len(os.listdir(DIR))
print(f"Songs still in queue: {still_q}")
#bot.command(pass_context=True, aliases=['p', 'pla'])
async def play(ctx, url: str = ""):
await join(ctx)
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is True:
DIR = os.path.abspath(os.path.realpath("Queue"))
try:
_ = os.listdir(DIR)[0]
except:
print("No more queued song(s)\n")
await queue(ctx, url)
await playSong(ctx)
else:
await queue(ctx, url)
await playSong(ctx)
else:
return
#bot.command(pass_context=True, aliases=['s'])
async def skip(ctx):
await stop(ctx)
#bot.command(pass_context=True, aliases=['pa', 'pau'])
async def pause(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_playing():
print("Music paused")
voice.pause()
await ctx.send("Music paused")
else:
print("Music not playing failed pause")
await ctx.send("Music not playing failed pause")
#bot.command(pass_context=True, aliases=['r', 'res'])
async def resume(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_paused():
print("Resumed music")
voice.resume()
await ctx.send("Resumed music")
else:
print("Music is not paused")
await ctx.send("Music is not paused")
async def stop(ctx):
voice = get(bot.voice_clients, guild=ctx.guild)
if voice and voice.is_playing():
voice.stop()
else:
print("No music playing failed to stop")
async def SearchVid(textToSearch):
print(textToSearch)
query = urllib.parse.quote(textToSearch)
url = "https://www.youtube.com/results?search_query=" + query
response = urllib.request.urlopen(url)
html = response.read()
soup = BeautifulSoup(html, 'html.parser')
for vid in soup.findAll(attrs={'class':'yt-uix-tile-link'}):
if not vid['href'].startswith("https://googleads.g.doubleclick.net/"):
return 'https://www.youtube.com' + vid['href']
async def queue(ctx, url: str):
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is False:
os.mkdir("Queue")
DIR = os.path.abspath(os.path.realpath("Queue"))
q_num = len(os.listdir(DIR))
queue_path = os.path.abspath(os.path.realpath("Queue") + f"\\{q_num} %(title)s.%(ext)s")
print(queue_path)
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': queue_path,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
print(url)
ydl.download([url])
name = os.listdir(DIR)[-1]
await ctx.send("Adding song " + str(name) + " to the queue")
print("Song added to queue\n")
bot.run(TOKEN)
I would definitely suggest using the module threading. I do not currently have enough time to read your code and put it in, though I might edit this answer later.
Refer to:
https://docs.python.org/3/library/threading.html
Threading allows you to run multiple functions at once.
You're using blocking libraries. Discord.py is a asynchronous library and you need to use things that don't block your code. In Frequently Asked Questions you can see a example using requests library, that's blocking and you should use aiohttp to make asynchronous requests instead.
I am writing a bot for my discord server and I've put a play command to my bot. It works fine with URL's but I want the bot to work with searchs too. So instead of copying and pasting the URL I want to be able to write the keyword for it. This is the play command:
#client.command(pass_context=True, aliases=['p', 'pla'])
async def play(ctx, url: str):
def check_queue():
Queue_infile = os.path.isdir("./Queue")
if Queue_infile is True:
DIR = os.path.abspath(os.path.realpath("Queue"))
length = len(os.listdir(DIR))
still_q = length - 1
try:
first_file = os.listdir(DIR)[0]
except:
print("No more queued song(s)\n")
queues.clear()
return
main_location = os.path.dirname(os.path.realpath(__file__))
song_path = os.path.abspath(os.path.realpath("Queue") + "\\" + first_file)
if length != 0:
print("Song done, playing next queued\n")
print(f"Songs still in queue: {still_q}")
song_there = os.path.isfile("song.mp3")
if song_there:
os.remove("song.mp3")
shutil.move(song_path, main_location)
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, 'song.mp3')
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.07
else:
queues.clear()
return
else:
queues.clear()
print("No songs were queued before the ending of the last song\n")
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
queues.clear()
print("Removed old song file")
except PermissionError:
print("Trying to delete song file, but it's being played")
await ctx.send("ERROR: Music playing")
return
Queue_infile = os.path.isdir("./Queue")
try:
Queue_folder = "./Queue"
if Queue_infile is True:
print("Removed old Queue Folder")
shutil.rmtree(Queue_folder)
except:
print("No old Queue folder")
await ctx.send("Getting everything ready now")
voice = get(client.voice_clients, guild=ctx.guild)
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
try:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
print("Downloading audio now\n")
ydl.download([url])
except:
print("FALLBACK: youtube-dl does not support this URL, using Spotify (This is normal if Spotify URL)")
c_path = os.path.dirname(os.path.realpath(__file__))
system("spotdl -f " + '"' + c_path + '"' + " -s " + url)
for file in os.listdir("./"):
if file.endswith(".mp3"):
name = file
print(f"Renamed File: {file}\n")
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"), after=lambda e: check_queue())
voice.source = discord.PCMVolumeTransformer(voice.source)
voice.source.volume = 0.14
nname = name.rsplit("-", 2)
await ctx.send(f"Playing: {nname[0]}")
print("playing\n")
I know It looks a little complex, It's because It has a queue feature. I tried several solution I saw online, but they didn't help because of the differences between the code they gave and the code that I have. If there is any space mistakes, It's because I might have forgot to put spaces in stackoverflow.
In your youtube-dl options, set default_search. For example,
ydl_opts = {
'default_search': 'ytsearch',
# ... all other options
will search using the YouTube search if the input is not a URL. This works with any of the supported sites, for example 'default_search': 'https://instagram.com/explore/tags/' will search instagram tags by default.