How can I use youtube_dl with a discord.py bot? - discord.py

I am making a music discord bot using python and I am having an issue where I download the video as a .webm file but then ffmpeg is not able to read this file and throws the error below.
ERROR: WARNING: unable to obtain file audio codec with ffprobe
2022-11-30 20:57:06 ERROR discord.ext.commands.bot Ignoring exception in command play
Traceback (most recent call last):
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 2115, in post_process
files_to_delete, info = pp.run(info)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\postprocessor\ffmpeg.py", line 277, in run
raise PostProcessingError('WARNING: unable to obtain file audio codec with ffprobe')
youtube_dl.utils.PostProcessingError: WARNING: unable to obtain file audio codec with ffprobe
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\willf\Desktop\DiscordBots\code.py", line 31, in play
ydl.download([url])
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 2068, in download
res = self.extract_info(
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 808, in extract_info
return self.__extract_info(url, ie, download, extra_info, process)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 815, in wrapper
return func(self, *args, **kwargs)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 847, in __extract_info
return self.process_ie_result(ie_result, download, extra_info)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 881, in process_ie_result
return self.process_video_result(ie_result, download=download)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 1692, in process_video_result
self.process_info(new_info)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 2050, in process_info
self.post_process(filename, info_dict)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 2117, in post_process
self.report_error(e.msg)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 628, in report_error
self.trouble(error_message, tb)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\youtube_dl\YoutubeDL.py", line 598, in trouble
raise DownloadError(message, exc_info)
youtube_dl.utils.DownloadError: ERROR: WARNING: unable to obtain file audio codec with ffprobe
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\discord\ext\commands\bot.py", line 1349, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke
await injected(*ctx.args, **ctx.kwargs) # type: ignore
File "C:\Users\willf\Desktop\DiscordBots\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: DownloadError: ERROR: WARNING: unable to obtain file audio codec with ffprobe
Here is my current code. It breaks between line 30 and 35.
import discord
from discord.ext import commands
import youtube_dl
import os
client = commands.Bot(command_prefix="q!", intents=discord.Intents.all())
#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 the 'stop' command")
# return
voiceChannel = discord.utils.get(ctx.guild.voice_channels, name='General')
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
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"))
#client.command()
async def leave(ctx):
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
if voice.is_connected():
await voice.disconnect()
else:
await ctx.send("The bot is not connected to a voice channel.")
#client.command()
async def pause(ctx):
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
if voice.is_playing():
voice.pause()
else:
await ctx.send("Currently no audio is playing.")
#client.command()
async def resume(ctx):
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
if voice.is_paused():
voice.resume()
else:
await ctx.send("The audio is not paused.")
#client.command()
async def stop(ctx):
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
voice.stop()
client.run('Token')
I have tried converting the file to an mp3 but I am unsure how to get this to work properly. All I need is for the .webm file to be converted to a .mp3 file so that discord can read this.

You need to add ffmpeg to path
Open windows search bar and open up 'edit the system environment variables'
Then click on environment variables on the bottom
Click on path and edit
after that just find where you downloaded ffmpeg and add it

Related

how do I send files with an discord bot py

I m trying to send a file with my bot but if I search how to do this I alway get somthing I cant use because I m using
#client.tree.command and Interaction
and not #bot.command and ctx
I tried:
#client.tree.command()
async def download(interaction: discord.Interaction,link:str):
await interaction.response.defer(ephemeral=True)
link1 = link
yt = YouTube(link1)
yd = yt.streams.get_highest_resolution()
yd.download("C:\\Users\\phili\\OneDrive\\code\\discord bot")
await interaction.followup.send(file=f"{yd.title}.mp4")
I got:
Traceback (most recent call last):
File "C:\Program Files\Python311\Lib\site-packages\discord\app_commands\commands.py", line 862, in _do_call
return await self._callback(interaction, **params) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\phili\OneDrive\code\discord bot\main.py", line 512, in download
await interaction.followup.send(file=f"{yd.title}.mp4")
File "C:\Program Files\Python311\Lib\site-packages\discord\webhook\async_.py", line 1706, in send
params = handle_message_parameters(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Python311\Lib\site-packages\discord\http.py", line 241, in handle_message_parameters
attachments_payload.append(attachment.to_dict())
^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'to_dict'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Program Files\Python311\Lib\site-packages\discord\app_commands\tree.py", line 1242, in _call
await command._invoke_with_namespace(interaction, namespace)
File "C:\Program Files\Python311\Lib\site-packages\discord\app_commands\commands.py", line 887, in _invoke_with_namespace
return await self._do_call(interaction, transformed_values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Python311\Lib\site-packages\discord\app_commands\commands.py", line 880, in _do_call
raise CommandInvokeError(self, e) from e
In discord.py, the file argument (for any Messageable) is expected to be an instance of the File class. So to send a locally saved file or downloaded file, you need to use the File class constructor.
file = discord.File("exact/path/to/the/file.mp4")
await interaction.followup.send(file=file)
Its first argument expects to be a path to the file or a file-like object.

PyNaCl Is installed but my terminal says that PyNaCl Library needs to be installed

the piece of code this is about:
#bot.slash_command(name="join")
async def join(ctx):
channel = ctx.author.voice.channel
await channel.connect()
#bot.slash_command(name="leave")
async def leave(ctx):
await ctx.voice_client.disconnect()
The error message:
Traceback (most recent call last):
File "C:\Users\Travm\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 127, in wrapped
ret = await coro(arg)
File "C:\Users\Travm\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 911, in _invoke
await self.callback(ctx, **kwargs)
File "C:\Users\Travm\Desktop\hikari\hikaricomd.py", line 58, in join
await channel.connect()
File "C:\Users\Travm\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\abc.py", line 1830, in connect
voice = cls(client, self)
raise RuntimeError("PyNaCl library needed in order to use voice")
RuntimeError: PyNaCl library needed in order to use voice
Can someone please help me?

Discord.py new timeout command error: "AttributeError: 'User' object has no attribute 'timeout_for'"

Hello all and happy new year 2022!!
Since the recent add of "timeouts" for discord, I have tried to make the timeout command following some tutorials like:
https://docs.pycord.dev/en/master/api.html?highlight=timeout#discord.Member.timeout
https://youtu.be/c5V4OaTNDtM
But I may get the following error for a reason I don't know:
Ignoring exception in command timeout2:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/home/runner/Russia-Bot/moderator.py", line 42, in timeout2
await member.timeout_for(time)
AttributeError: 'Member' object has no attribute 'timeout_for'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Member' object has no attribute 'timeout_for'
Here's the command code, i have made 2 different commands but both give the same issue:
Variant 1:
#client.command()
async def timeout(ctx, member: discord.Member, time=None, reason=None):
time = humanfriendly.parse_timespan(time)
await member.timeout(until = discord.utils.utcnow() + datetime.timedelta(seconds=time), reason=reason)
await ctx.send (f"{member} callate un rato anda {time}")
Variant 2
#client.command(pass_context =True)
async def timeout2(ctx, member:discord.User=None, time=None):
#time = humanfriendly.parse_timespan(time)
# tiempo = datetime.timedelta(seconds=time)
user = await client.fetch_user(member)
#await ctx.send (f"{user}")
#await ctx.send (f"{member}")
await user.timeout_for(time)
await ctx.send (f"{user} callate un rato anda {time}")
Best Regards,
Engineer
Update your py-cord library by using pip install -U git+https://github.com/pycord-development/pycord
If works , pls consider accepting answer

How come I can't use message.user.tag?

I'm trying to get the 4-digit tag of the person who used the command !hours, but discord won't recognize user.tag
import discord
from discord import message
from discord.ext import commands
client = commands.Bot(command_prefix = '!')
##########HOURS##########
chung_victor = [21, 10]
##########HOURS##########
# chung_victor
if usertag == 5308:
h = chung_victor[0]
m = chung_victor[1]
await ctx.send(f'> You currently have {h} hours and {m} minutes!')
And when I use !hours, I get the error message
Ignoring exception in command hours:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 36, in hours
usertag = message.user.tag
AttributeError: module 'discord.message' has no attribute 'user'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: module 'discord.message' has no attribute 'user'
Well, as you see to get user name you need to use it as user.name and same goes for the discriminator user.discriminator. You can refer to the code below :
#bot.command()
async def test(ctx, member : discord.Member, *,reason = None) :
user = member.discriminator
await ctx.send(f" User Tag is : {user} ")
In the example above, I set a command test and user must tag someone after a command like:
!test #Victor Chung and ! is a command_prefix.
Thank You :)

How do you get the main "function" of a command in discord.py?

I'm trying to create a command that sends the code of another command in discord.py. For example, if I had a command for rock paper scissors and i ran .code rps, It would send the code for the rps command. Here is my code so far:
import inspect
import discord
from discord.ext.commands import Bot, cooldown, BucketType, CommandOnCooldown
from discord.ext import commands, tasks
#bot.command(hidden=True)
#commands.is_owner()
async def code(ctx, *, command_name):
"""Sends code of a command"""
com = bot.get_command(command_name)
if com is None:
await ctx.reply(f"Bruh that isn't a command", mention_author=False)
elif com:
source = inspect.getsource(com)
try:
await ctx.reply(f"```\n{source}\n```", mention_author=False)
except discord.HTTPException:
await ctx.reply(f"That command's code is too long for me to send lmao", mention_author=False)
print(source)
But there's an error because it can't find the source code of a command type
Ignoring exception in command code:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/test.py", line 351, in code
source = inspect.getsource(com)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 985, in getsource
lines, lnum = getsourcelines(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 967, in getsourcelines
lines, lnum = findsource(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 780, in findsource
file = getsourcefile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 696, in getsourcefile
filename = getfile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 676, in getfile
raise TypeError('module, class, method, function, traceback, frame, or '
TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
Is there a way to find the source code of a command object or figure out a loophole that lets me do that? Thanks!!
Simply use the callback attribute
func = com.callback
source = inspect.getsource(func)
Reference:
Command.callback

Resources