how do I send files with an discord bot py - discord.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.

Related

Discord.py error: "ValueError: <class 'str'> is not a valid ChannelType"

I don't understand what the error is.
> Ignoring exception in command weather:
> Traceback (most recent call last):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/enums.py", line 168, in __call__
> return cls._enum_value_map_[value]
> KeyError: <class 'str'>
> During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 124, in wrapped
ret = await coro(arg)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 980, in _invoke
await self.callback(ctx, **kwargs)
File "/home/timoha/discord_bot/main.py", line 166, in weather
async with discord.channel.ChannelType(value=str):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/enums.py", line 170, in __call__
> raise ValueError(f"{value!r} is not a valid {cls.__name__}")
> ValueError: <class 'str'> is not a valid ChannelType
>
> The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/bot.py", line 1114, in invoke_application_command
await ctx.command.invoke(ctx)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 375, in invoke
await injected(ctx)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 132, in wrapped
> raise ApplicationCommandInvokeError(exc) from exc
> discord.errors.ApplicationCommandInvokeError: Application Command raised an exception: ValueError: <class 'str'> is not a valid ChannelType
Code:
#bot.slash_command(name="weather", description="Погода")
async def weather(ctx, *, city: str):
city_name = city
complete_url = base_url + "appid=" + api_key + "&q=" + city_name
response = requests.get(complete_url)
x = response.json()
channel = ctx.message
if x["cod"] != "404":
async with discord.channel.ChannelType(value=str):
value=str
y = x["главный"]
current_temperature = y["температура"]
current_temperature_celsiuis =str(round(current_temperature - 273.15))
current_pressure = y["давление"]
current_humidity = y["влажность"]
z = x["погода"]
weather_description = z[0]["описание"]
weather_description = z[0]["описание"]
embed = discord.Embed(title=f"Погода в {city_name}",
color=ctx.guild.me.top_role.color,
timestamp=ctx.message.created_at,)
embed.add_field(name="Описание", value=f"**{weather_description}**", inline=False)
embed.add_field(name="Температура(C)", value=f"**{current_temperature_celsiuis}°C**", inline=False)
embed.add_field(name="Влажность(%)", value=f"**{current_humidity}%**", inline=False)
embed.add_field(name="Atmospheric Pressure(hPa)", value=f"**{current_pressure}hPa**", inline=False)
embed.set_thumbnail(url="https://i.ibb.co/CMrsxdX/weather.png")
embed.set_footer(text=f"Запрошенный {ctx.author.name}")
await channel.send(embed=embed)
else:
await channel.send("Город не найден.")
I tried to change a lot of things, but I still can't figure out what the problem is.
There's a few issues with your code - that error is probably just the first one. I've attempted to rewrite what you've provided with some explanation but hopefully it replicates what you're trying to do.
#bot.slash_command(name="weather", description="Погода")
async def weather(ctx, *, city: str):
# as we're doing an API call here - let's defer so the interaction doesn't timeout
await ctx.defer()
# no reason to redefine another variable called 'city_name' equal to 'city' - just use 'city' everywhere
# could also use a f-string for creating the URL here
# complete_url = f"{base_url}appid={api_key}&q={city}"
complete_url = base_url + "appid=" + api_key + "&q=" + city
response = requests.get(complete_url)
json_response = response.json()
if json_response["cod"] == "404":
# if it's 404, let's send the error message and return early
# means we don't have a big nested "if" block
await channel.send("Город не найден.")
return
y = json_response["главный"]
z = json_response["погода"]
current_temperature = y["температура"]
current_temperature_celsiuis =str(round(current_temperature - 273.15))
current_pressure = y["давление"]
current_humidity = y["влажность"]
weather_description = z[0]["описание"]
weather_description = z[0]["описание"]
# create the embed
embed = discord.Embed(
title=f"Погода в {city}",
color=ctx.guild.me.top_role.color,
timestamp=ctx.message.created_at
)
embed.add_field(name="Описание", value=f"**{weather_description}**", inline=False)
embed.add_field(name="Температура(C)", value=f"**{current_temperature_celsiuis}°C**", inline=False)
embed.add_field(name="Влажность(%)", value=f"**{current_humidity}%**", inline=False)
embed.add_field(name="Atmospheric Pressure(hPa)", value=f"**{current_pressure}hPa**", inline=False)
embed.set_thumbnail(url="https://i.ibb.co/CMrsxdX/weather.png")
embed.set_footer(text=f"Запрошенный {ctx.author.name}")
# now let's send our response
# ctx.send will send to the channel that the user used the slash command in
await ctx.send(embed=embed)
The ctx variable docs.
What I changed:
removed creating a variable called city_name that was exactly equal to city - seemed redundant
added ctx.defer() - if our code takes a little while it's good to defer so the interaction doesn't timeout
removed channel = ctx.message. We can get the channel later if we need to (we don't in this case) but this was setting it equal to the message that invoked the application command (which isn't really a message) so we aren't accomplishing anything here anyways
if we get a 404 response; send error message and return. Better to do this than have a big nested if block in my opinion.
I also renamed x to json_response as I prefer descriptive variable names but I gave up on y and z.
got rid of the whatever the async with statement was trying to accomplish
used ctx.send(embed=embed) at the bottom to send your created embed to the channel that the user used the application command in
Hopefully, this is what you want it to do and hopefully you understand what's going on a bit now. It might be worth having a look through some of the examples and documentation to get a better grasp on how it all works.
Another change you could make, is swapping out requests for aiohttp-requests to make non-blocking API calls.
I took advantage of your help, and I am grateful to you in many ways, but I am just starting my way in programming and learning from a real example. So I corrected my code to yours and I was given a new set of errors, which I also can't figure out a little.
gnoring exception in command weather: Traceback (most recent call
last):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 124, in wrapped
ret = await coro(arg)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 980, in _invoke
await self.callback(ctx, **kwargs) File
"/home/timoha/discord_bot/main.py", line 162, in weather
y = json_response["главный"] KeyError: 'главный'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/bot.py", line 1114, in invoke_application_command
await ctx.command.invoke(ctx)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 375, in invoke
await injected(ctx)
File "/home/timoha/discord_bot/venv/lib/python3.10/site-packages/discord/commands/core.py", line 132, in wrapped
raise ApplicationCommandInvokeError(exc) from exc
discord.errors.ApplicationCommandInvokeError: Application Command
raised an exception: KeyError: 'главный'

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

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

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