So I'm trying to make a music bot which just joins,plays,stops and resume music. However my bot can join and leave a voice channel fine, however when i do my /play command it get stuck on [youtube] oCveByMXd_0: Downloading webpage
(this is output in vscode) and then does nothing after. I put some print statement (which you can see in the code below and it prints 1 and 2 but NOT 3). Anyone had this issue?
MUSIC BOT FILE
import discord
from discord.ext import commands
import youtube_dl
class music(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command()
async def join(self, ctx):
if(ctx.author.voice is None):
await ctx.reply("*You're not in a voice channel.*")
voiceChannel = ctx.author.voice.channel
if(ctx.voice_client is None): # if bot is not in voice channel
await voiceChannel.connect()
else: # bot is in voice channel move it to new one
await ctx.voice_client.move_to(voiceChannel)
@commands.command()
async def leave(self, ctx):
await ctx.voice_client.disconnect()
@commands.command()
async def play(self,ctx, url:str = None):
if(url == None):
await ctx.reply("*Check your arguments!*\n```/play VIDEO_URL```")
else:
ctx.voice_client.stop() # stop current song
# FFMPEG handle streaming in discord, and has some standard options we need to include
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
YTDL_OPTIONS = {"format":"bestaudio"}
vc = ctx.voice_client
# Create stream to play audio and then stream directly into vc
with youtube_dl.YoutubeDL(YTDL_OPTIONS) as ydl:
info = ydl.extract_info(url, download=False)
print("1")
url2 = info["formats"][0]["url"]
print("2")
source = await discord.FFmpegOpusAudio.from_probe(url2,FFMPEG_OPTIONS)
print("3")
vc.play(source) # play the audio
await ctx.send(f"*Playing {info['title']} -* 🎵")
@commands.command()
async def pause(self, ctx):
await ctx.voice_client.pause()
await ctx.reply("*Paused -* ⏸️")
@commands.command()
async def resume(self, ctx):
await ctx.voice_client.resume()
await ctx.reply("*Resuming -* ▶️")
def setup(bot):
bot.add_cog(music(bot))
MAIN FILE
from discord.ext import commands
from dotenv import load_dotenv
from lxml import html
import youtube_dl
import requests
import random
import discord
import requests
import os
import music
# Load .env file
load_dotenv()
COGS = [music]
PREFIX = "/"
bot = commands.Bot(command_prefix=PREFIX, intents=discord.Intents.all())
for x in range(len(COGS)):
COGS[x].setup(bot)
# EVENTS #
@bot.event
async def on_ready():
await bot.get_channel(888736019590053898).send(f"We back online! All thanks to *sploosh* :D")
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.CommandNotFound):
replies = ["Err is that even a command?", "Can you type bro?", "Yeah... thats not a command buddy.", "Sorry forgot you can't spell"]
await ctx.send(random.choice(replies))
@bot.event
async def on_message(message):
if str(message.channel) == "images-videos" and message.content != "":
await message.delete()
await bot.process_commands(message)
# COMMANDS #
@bot.command()
async def hello(ctx):
# Get a random fact
url = 'http://randomfactgenerator.net/'
page = requests.get(url)
tree = html.fromstring(page.content)
hr = str(tree.xpath('/html/body/div/div[4]/div[2]/text()'))
await ctx.reply("**Hello Bozo!**\n" + "*Random Fact : *" + hr[:-9]+"]")
@bot.command()
async def randomNum(ctx, start:int = None, end:int = None):
if(start == None or end == None):
await ctx.reply("*Check your arguments!*\n```/randomNum START_NUMBER END_NUMBER```")
else:
randNum = random.randint(start, end)
await ctx.reply(f"*{randNum}*")
@bot.command()
@commands.is_owner()
async def kick(ctx, member:discord.Member = None, *, reason="You smell bozo."):
if(member == None):
await ctx.reply("*Check your arguments!*\n```/kick @MEMBER REASON(optional)```")
elif ctx.author.id in (member.id, bot.user.id):
await ctx.reply("*You cant kick yourself/me you silly.*")
else:
await member.kick(reason=reason)
@bot.command()
@commands.is_owner()
async def ban(ctx, member:discord.Member = None, *, reason="Bye Bye! :D."):
if(member == None):
await ctx.reply("*Check your arguments!*\n```/kick @MEMBER REASON(optional)```")
elif ctx.author.id in (member.id, bot.user.id):
await ctx.reply("*You cant ban yourself/me you silly.*")
else:
await member.ban(reason=reason)
@bot.command()
@commands.is_owner()
async def close_bot(ctx):
replies = ["Well bye!", "Guess I go now?", "Please let me stay..."]
await ctx.send(random.choice(replies))
await bot.close()
if __name__ == "__main__":
bot.run(os.getenv("BOT_TOKEN"))
This is how my play music command is setup, and i know for sure it works and it seems like it should work for you too.
@commands.command()
async def play(self, ctx, *, song=None):
commandd = "play"
print(f"{ctx.author.name}, {ctx.author.id} used command "+commandd+" used at ")
print(x)
print(" ")
if song is None:
return await ctx.send("You must include a song to play.")
if ctx.voice_client is None:
return await ctx.send("I must be in a voice channel to play a song.")
# handle song where song isn't url
if not ("youtube.com/watch?" in song or "https://youtu.be/" in song):
await ctx.send("Searching for song, this may take a few seconds.")
result = await self.search_song(1, song, get_url=True)
if result is None:
return await ctx.send("Sorry, I could not find the given song, try using my search command.")
song = result[0]
if ctx.voice_client.source is not None:
queue_len = len(self.song_queue[ctx.guild.id])
if queue_len < 10:
self.song_queue[ctx.guild.id].append(song)
return await ctx.send(f"I am currently playing a song, this song has been added to the queue at position: {queue_len+1}.")
else:
return await ctx.send("Sorry, I can only queue up to 10 songs, please wait for the current song to finish.")
await self.play_song(ctx, song)
await ctx.send(f"Now playing: {song}")
this is some other things that you might need
import discord
from discord.ext import commands
from random import choice
import string
from discord.ext.commands.cooldowns import BucketType
import asyncio
import youtube_dl
import pafy
import datetime
from discord_slash import cog_ext, SlashContext
x = datetime.datetime.now()
from ult import *
class music(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.song_queue = {}
self.setup()
def setup(self):
for guild in self.bot.guilds:
self.song_queue[guild.id] = []
async def check_queue(self, ctx):
if len(self.song_queue[ctx.guild.id]) > 0:
ctx.voice_client.stop()
await self.play_song(ctx, self.song_queue[ctx.guild.id][0])
self.song_queue[ctx.guild.id].pop(0)
async def search_song(self, amount, song, get_url=False):
info = await self.bot.loop.run_in_executor(None, lambda: youtube_dl.YoutubeDL({"format" : "bestaudio", "quiet" : True}).extract_info(f"ytsearch{amount}:{song}", download=False, ie_key="YoutubeSearch"))
if len(info["entries"]) == 0: return None
return [entry["webpage_url"] for entry in info["entries"]] if get_url else info
async def play_song(self, ctx, song):
url = pafy.new(song).getbestaudio().url
ctx.voice_client.play(discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url)), after=lambda error: self.bot.loop.create_task(self.check_queue(ctx)))
ctx.voice_client.source.volume = 0.5