How do I fix "discord.NotFound" - discord.py

This is my first question ever on Stackoverflow, so if I screw up, let me know and I'll either edit this post, or take it down. Anyways I made an emojiinfo command, and thee is an error on line 8, and that is; except discord.NotFound:.
Heres my code;
#client.command(aliases=['ei','emoji'])
async def emojiinfo(self, ctx, emoji: discord.Emoji = None):
if not emoji:
return await ctx.invoke(self.bot.get_command('help'), entity='emojiinfo')
try:
emoji= await emoji.guild.fetch_emoji(emoji.id)
exept discord.NotFound:
return await ctx.send("I could not find this emoji.")
is_managed = 'Yes' if emoji.managed else 'No'
is_animated = 'Yes' if emoji.animated else 'No'
requires_colons = 'Yes' if emoji.requires_colons else 'No'
creaton_time = emoji.created_at.strftime('%I:% %p %B %d, %Y')
can_use_emoji= 'Everyone' if not emoji.roles else ' '.join(role.name for role in emoji.roles)
description = f'''
**General;**
**- Name: {emoji.name}
**- ID:** {emoji.id}
**- URL:** [Link To Emoji]({emoji.url})
**- Author:** {emoji.user.mention}
**- Time Created:** {creaton_time}
**- Usable By:** {can_use_emoji}
**Other;**
**- Animated:** {is_animated}
**- Managed:** {is_managed}
**- Requires Colons:** {requires_colons}
**- Guild Name** {emoji.guild.name}
'''
embed = discord.Embed(title=f'**Emoji information for:** {emoji.name}', description=description, color=discord.Color.from_rgb(61, 31, 103))
embed.set_thumbnail(url=emoji.url)
await ctx.send(embed=embed)
If you could reply with what I need to fix it, or a fixed version of my code..that'd be great! Thank you!

Related

Nextcord (discord.py) slash commands, bot doesn't ping even with admin perms

#nextcord.slash_command(name = "chatrevive", description = "pings for chat revive", guild_ids=[ServerId])
#application_checks.has_role(982582539376025640)
#commands.cooldown(1, 7200, commands.BucketType.guild)
async def chatrevive(self, interaction: Interaction, msg: str):
"""Revive the chat!"""
ping_role = interaction.guild.get_role(855720035426631690)
embed = nextcord.Embed(title = '<a:tj_mochicat:941582560390160415> Chat Revive', color = 0xff0000)
embed.set_author(name = interaction.guild.name, icon_url = interaction.guild.icon.url)
embed.set_thumbnail(url=interaction.guild.icon.url)
embed.description = f"<:tj_greendash:931018157689282581> **Message:** {msg}\n<:tj_greendash:931018157689282581> **Moderator:** {interaction.user.mention}"
await interaction.send(content = ping_role.mention, embed = embed)
await post_pinglog(self.bot, interaction.guild, "server-ping", interaction.user, ping_role, "N/A")
basically this is working, the only problem is that it mentions the role without pinging it.
image that shows it
before anyone comments yes I did check the bot's permissions
You need to set the allowed mentions for the message, for example, to allow mentioning roles:
await interaction.send(
content=ping_role.mention,
allowed_mentions=nextcord.AllowedMentions(roles=True),
)
It seems that this is discord's fault, basically it's impossible to ping using interaction.send we'll have to use the following:
await interaction.send("Interaction completed.", ephemeral = True)
await interaction.channel.send(f"{ping_role.mention} yadi yadi yada")

Is there a way to record the specific user of a command for future use without a database?

So I'm working on a discord bot using discord.py and I'm trying to create a bot for the moderation team in a server, the bot will swap the 'Moderator' role with a 'Leave of absence' role for when they're not active, however the code I have come up with has a slight loopholing problem that I just can't figure out, the code for the commands is this
...
#client.command()
#commands.has_role('Moderator')
async def sl(ctx, member: discord.Member = None):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
await member.add_roles(loa)
await member.remove_roles(mod)
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
#client.command()
async def sr(ctx, member: discord.Member = None):
if not member:
member = ctx.author
mod = ctx.guild.get_role(848032880709074944)
loa = ctx.guild.get_role(848032714715561985)
await member.add_roles(mod)
await member.remove_roles(loa)
await ctx.send("Welcome back!")
...
as you can see anyone could use the second command to just give themselves a moderator role, I can't set the second command to be moderator only use as the moderator will no longer have said role from using the first command, I'm racking my brain to think of a work around i.e. logging the command users id to a whitelist and having only those whitelisted id's be able to use the second command, I've done many googlesearches for this but have come back with no results, any suggestions would be appreciated, please forgive that this question is a bit lengthy and I'm still very new to coding in general so any help at all, even if you don't fully understand what I'm blabbering on about would be very appreciated, thank you.
Check for the loa role in the command (ex):
mod = None
for role in ctx.author.roles:
if role.id == 848032714715561985: mod = True
if mod:
#your code here
So from your question, I'm guessing that you would like to code basically a "storage" file and make sure the person on the leave of absence was previously a moderator.
What you could do is create a csv file, for example records.csv (in the same folder as your main .py file of course), and every time someone calls the sl command, the program will record the user that used it.
import csv
#client.command()
#commands.has_role('Moderator')
async def sl(ctx, member: discord.Member = None):
if not member:
member = ctx.author
loa = ctx.guild.get_role(848032714715561985)
mod = ctx.guild.get_role(848032880709074944)
await member.add_roles(loa)
await member.remove_roles(mod)
file = open("records.csv", "w")
file.writelines(str(ctx.author.id))
file.close()
await ctx.send("I have filed your Leave, take care, we look forward to your return!")
#client.command()
async def sr(ctx, member: discord.Member = None):
if not member:
member = ctx.author
mod = ctx.guild.get_role(848032880709074944)
loa = ctx.guild.get_role(848032714715561985)
found = False
with open('records.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
if row[0] == str(ctx.author.id):
found = True
break
if found = False:
await member.add_roles(mod)
await member.remove_roles(loa)
await ctx.send("Welcome back!")
else:
await ctx.send("We do not have history of you having a moderator role.")
Are you running the program through an online environment like Repl.it? If so, this may not be the best way to approach this problem since people would have access to your this records.csv file (which you may not care about but just in case). If you are running the program through your desktop file directories, then there should be no privacy concerns.

Discord.py don't require space for tempmute command

I have this code for my discord.py bot, for my tempmute command:
#bot.command()
async def tempmute(ctx, member: discord.Member, time: int, d, *, reason=None):
guild = ctx.guild
mutedRole = discord.utils.get(guild.roles, name="Muted")
if not mutedRole:
mutedRole = await guild.create_role(name="Muted")
for channel in guild.channels:
await channel.set_permissions(mutedRole, speak=False, send_messages=False)
for role in guild.roles:
if role.name == "Muted":
await member.add_roles(role)
embed = discord.Embed(title="TempMuted!", description=f"{member.mention} has been tempmuted.", colour=discord.Colour.red())
embed.add_field(name="Reason:", value=reason, inline=False)
embed.add_field(name="Time for the mute:", value=f"{time}{d}", inline=False)
await ctx.send(embed=embed)
if d == "s":
await asyncio.sleep(time)
if d == "m":
await asyncio.sleep(time*60)
if d == "h":
await asyncio.sleep(time*60*60)
if d == "d":
await asyncio.sleep(time*60*60*24)
await member.remove_roles(role)
embed = discord.Embed(title="Unmute (temp mute expired) ", description=f"Unmuted -{member.mention} ", colour=discord.Colour.light_gray())
await ctx.send(embed=embed)
return
However, when using the command, it has to be typed like this: "!tempmute #user 10 m" if I wanted a 10 minute mute. Notice how it is "10 m". How would I make it so "10m" would work (without a space). So "!tempmute #user 10m"? If a user writes it without a space at the moment, the error "discord.ext.commands.errors.BadArgument: Converting to "int" failed for parameter "time"." occurs, probably as it isn't recognising a number with the letter at the end. Thanks
The best way to solve this would be to create your own Converter and typehint the class in the argument. As documented here
So instead of converting your time in your command function, you would do it in the converter making the syntax more cleaner.
Example of a converter
time_regex = re.compile(r"(\d{1,5}(?:[.,]?\d{1,5})?)([smhd])")
time_dict = {"h":3600, "s":1, "m":60, "d":86400}
class TimeConverter(commands.Converter):
async def convert(self, ctx, argument):
matches = time_regex.findall(argument.lower())
time = 0
for v, k in matches:
try:
time += time_dict[k]*float(v)
except KeyError:
raise commands.BadArgument(f"{k} is an invalid time-key! h/m/s/d are valid!")
except ValueError:
raise commands.BadArgument(f"{v} is not a number!")
return time
This is an example of a Time converter, where it will use a regex and converts it into an int in seconds. Which accepts <number><smhd>, example 2d.
The library calls TimeConverter().convert during the command invocation, hence we create a method called convert, which accepts Context object and arguments as str. All you have to do is return something, or raise an error if there is an error.
In order to use this, you would do it as follows
#bot.command()
async def tempmute(ctx, member: discord.Member, time: TimeConverter, *, reason=None):
...
await member.add_roles(role)
await asyncio.sleep(time)
await member.remove_roles(role)
...
The command invocation would be
!tempmute #user 2d here's the reason
I have been working on a tempmute command myself. I would say the command would work fine with a simple dictionary. If you want to convert time units a simple dictionary would do it and you wouldn't require a hell lot of code.
First I would add the code and then give a brief explanation.
Code:
#MyBot.command()
#commands.has_permissions(manage_roles=True)
async def tempmute(ctx, member: discord.Member, time, *, reason=None):
await ctx.message.delete()
if member.guild_permissions.administrator:
ifadmin_embed = discord.Embed(title='Member is Administrator!', description=f'The user, {member.mention} can\'t be muted as he/she is an administrator.', color=0xff0000)
ifadmin_embed.set_author(name='NucleoBot')
ifadmin_embed.set_footer(text=ctx.author)
await ctx.channel.send(embed=ifadmin_embed, delete_after=10.0)
else:
if discord.utils.get(ctx.guild.roles, name='Muted'):
muted_role = discord.utils.get(ctx.guild.roles, name='Muted')
else:
perms = discord.Permissions(send_messages=False, add_reactions=False, connect=False, speak=False)
await ctx.guild.create_role(name='Muted', permissions=perms)
muted_role = discord.utils.get(ctx.guild.roles, name='Muted')
time_convert = {'s' : 1 , 'm' : 60 , 'h' : 3600 , 'd' : 86400, 'y' : 31536000}
mute_time = int(time[0]) * time_convert[time[-1]]
await ctx.message.delete()
role_if_muted = discord.utils.find(lambda r: r.name == 'Muted', ctx.guild.roles)
if role_if_muted in member.roles:
alreadymuted_embed = discord.Embed(title='Already Muted!', description=f'The user, {member.mention} is already muted for {mute_time} seconds.', color=0xff0000)
alreadymuted_embed.set_footer(text=ctx.author)
alreadymuted_embed.set_author(name='NucleoBot')
await ctx.channel.send(embed=alreadymuted_embed, delete_after=10.0)
else:
if reason == None:
await member.add_roles(muted_role)
tempmuted_embed = discord.Embed(title='Temporary Mute Successfull!', description=f'{member.mention} has been muted for {mute_time} seconds successfully! \n \n Reason: No reason given.', color=0x4fff4d)
tempmuted_embed.set_author(name='NucleoBot')
tempmuted_embed.set_footer(text=ctx.author)
else:
await member.add_roles(muted_role)
tempmuted_embed = discord.Embed(title='Temporary Mute Successfull!', description=f'{member.mention} has been muted for {mute_time} seconds successfully! \n \n Reason: {reason}', color=0x4fff4d)
tempmuted_embed.set_author(name='NucleoBot')
tempmuted_embed.set_footer(text=ctx.author)
await ctx.channel.send(embed=tempmuted_embed, delete_after=10.0)
await asyncio.sleep(mute_time)
await member.remove_roles(muted_role)
Explanation:
My code has almost everything here that you need for a mute command. Only the members with roles that have manage_role permissions to execute this command. Also if someone try to mute a member who is an administrator of the server, an embed would pop up to say, Member is an admin.
The code also has the aspect that if no reason is given it would not show any error but post an embed made for No Reason command, i.e., if no reason is mentioned. It also checks that if the server doesn't have a role named Muted. It the role exist it would simply use it otherwise first it would create a role named Muted with denial of important permissions and use it for the mute.
Now the time conversion. The line which is used for this:
time_convert = {'s' : 1 , 'm' : 60 , 'h' : 3600 , 'd' : 86400, 'y' : 31536000}
This command takes second as basic value for the conversion then converts every other unit in terms of seconds. Here s is equated to 1 and m is equated to 60 as I minute is equal to 60 seconds. Similarly doing that same with other units we derive everything to seconds. This dictionary turns everything to seconds and using asyncio we create a timer for mute.
Hope this helps, if you still get any doubt, please feel free to ask me.
Thank You!

how do i resolve this [ discord.py ]

how are you doing today i sure hope your doing great im sorry for the spam on other account i apologize. ok so my problem is that i switched from client to bot basically bot = commands.Bot i tried renaming all the commmands to bot.event or bot.command can someone pls help me pls i would appreciate it thank you here is the code :)
#bot.command()
async def ping(ctx):
await ctx.send(f'Pong!\n`{round(client.latency*1000)}ms`')
#bot.command(aliases=['8ball'])
async def _8ball(ctx, *, question):
responses = [ "It is certain.",
"As I see it, yes",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count it",
"It is certain.",
"It is decidedly so.",
"Most likely.",
"My reply is no."
"My sources say no.",
"Outlook not so good.",
"Outlook good.",
"Reply hazy, try again.",
"Signs point to yes.",
"Very doubtful.",
"Without a doubt.",
"Yes.",
"Yes – definitely.",
"You may rely on it." ]
await ctx.send(f'Question: {question}\nAnswer: {random.choice(responses)}')
#commands.has_permissions(ban_members=True)
#bot.command()
async def kick(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
kick = discord.Embed(title=f":boom: Kicked {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=kick)
await user.send(embed=kick)
#commands.has_permissions(ban_members=True)
#bot.command()
async def ban(ctx, user: discord.Member, *, reason="No reason provided"):
await user.ban(reason=reason)
ban = discord.Embed(title=f":boom: Banned {user.name}!", description=f"Reason: {reason}\nBy: {ctx.author.mention}")
await ctx.message.delete()
await ctx.channel.send(embed=ban)
await user.send(embed=ban)
#bot.command()
async def unban(ctx, *, member):
banned_users = await ctx.guild.bans()
member_name, member_discriminator = member.split('#')
for ban_entry in banned_users:
user = ban_entry.user
if (user.name, user.discriminator) == (member_name, member_discriminator):
await ctx.guild.unban(user)
await ctx.channel.send(f"Unbanned: {user.mention}")
#bot.command(pass_context = True)
async def mute(ctx, user_id, userName: discord.User):
if ctx.message.author.server_permissions.administrator:
user = ctx.message.author
role = discord.utils.get(user.server.roles, name="Muted")
#bot.command()
async def serverinfo(ctx):
name = str(ctx.guild.name)
description = str(ctx.guild.description)
owner = str(ctx.guild.owner)
id = str(ctx.guild.id)
region = str(ctx.guild.region)
memberCount = str(ctx.guild.member_count)
icon = str(ctx.guild.icon_url)
embed = discord.Embed(
title=name + " Server Information",
description=description,
color=discord.Color.blue()
)
embed.set_thumbnail(url=icon)
embed.add_field(name="Owner", value=owner, inline=True)
embed.add_field(name="Server ID", value=id, inline=True)
embed.add_field(name="Region", value=region, inline=True)
embed.add_field(name="Member Count", value=memberCount, inline=True)
await ctx.send(embed=embed)
await client.add_roles(user, role)
#bot.command()
async def setdelay(ctx, seconds: int):
await ctx.channel.edit(slowmode_delay=seconds)
await ctx.send(f"Set the slowmode delay in this channel to {seconds} seconds!")
#bot.command()
async def afk(ctx, mins):
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.")
await ctx.author.edit(nick=f"{ctx.author.name} [AFK]")
counter = 0
while counter <= int(mins):
counter += 1
await asyncio.sleep(60)
if counter == int(mins):
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK")
break
def setup(bot):
bot.add_cog(Afk(bot))
def user_is_me(ctx):
return ctx.message.author.id == "Your ID"
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d": 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#bot.command()
#commands.has_permissions(kick_members=True)
async def giveaway(ctx):
await ctx.send("Let's start with this giveaway! Answer these questions within 15 seconds!")
questions = ["Which channel should it be hosted in?", "What should be the duration of the giveaway? (s|m|h|d)", "What is the prize of the giveaway?"]
answers = []
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
for i in questions:
await ctx.send(i)
try:
msg = await bot.wait_for('messsage', timeout=15.0, check=check)
except asyncio.TimeoutError:
await ctx.send('You didn\'t answer in time, please be quicker next time!')
return
else:
answers.append(msg.content)
try:
c_id = int(answers[0][2:-1])
except:
await ctx.send(f"You didn't mention a channel properly. Do it like this {ctx.channel.mention} next time.")
return
channel = bot.get_channel(c_id)
time = convert(answers[1])
if time == -1:
await ctx.send(f"You didn't answer with a proper unit. Use (s|m|h|d) next time!")
return
elif time == -2:
await ctx.send(f"The time just be an integer. Please enter an integer next time.")
return
prize = answers[2]
await ctx.send(f"The giveaway will be in {channel.mention} and will last {answers[1]} seconds!")
embed = discord.embed(title = "Giveaway!", description = f"{prize}", color = ctx.author.color)
embed.add_field(name = "Hosted by:", value = ctx.author.mention)
embed.set_footer(text = f"Ends {answers[1]} from now!")
my_msg = await channel.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await channel.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations! {winner.mention} won the prize: {prize}!")
#bot.command()
#commands.has_permissions(kick_members=True)
async def reroll(ctx, channel : discord.TextChannel, id_ : int):
try:
new_msg = await channel.fetch_message(id_)
except:
await ctx.send("The ID that was entered was incorrect, make sure you have entered the correct giveaway message ID.")
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await channel.send(f"Congratulations the new winner is: {winner.mention} for the giveaway rerolled!")
if you want me to answer anything to help you solve it feel free to comment thank you so much have a great day!
It seems like you copied most of the code from the internet and bashed it together to create a bot or a cog (based on your question I would guess a bot).
Assuming this is a snippet of your main bot file and not a cog there are a couple of things that could be different:
Put your utility functions in one place (peferably after your import statatements). It's good practise overall and makes more readeable code.
Unless you have a cog class in the same file as your bot instance (which is bad practise) you shouldn't need this:
def setup(bot):
bot.add_cog(Afk(bot))
If there is a cog class named Afk you should move it into a separate file (putting the cog class into the main bot file defeats the purpose of the cog)
In your mute command you have pass_context = True. This is from the old version of discord.py and is no longer needed.
I can't tell you much more since there's no point in trying to debug your code since you didn't give us any errors or stacktrace to work with.
It is very exhausting, so you can just leave client in every command, just write this client = commands.Bot(command_prefix = 'your prefix') it is the same bot, but it just has a different name.
If you meant that, because i didn't really understand what you need

Pagination - Discord.py rewrite

I've been trying to make a command that will display some information and then, when i react to an emote, its supposed to display another set of information.
I tried to use parts of this, specifically the parts in line 335 to 393
to get it to work. However, it just does nothing. Not even an error message.
This is the code I use right now.
def check_react(reaction, user):
if reaction.message.id != msg.id:
return False
if user != ctx.message.author:
return False
return True
res, user = await bot.wait_for('reaction_add', check=check_react, timeout=None,)
if user != ctx.message.author:
print('if user != ctx.message.author:')
elif '⬅️' in str(res.emoji):
page -=1
print(page)
embed = discord.Embed(title='generic title', description='generic description', color=0x52fffc)
await msg.edit(embed=embed)
elif '➡️' in str(res.emoji):
page +=1
print(page)
embed = discord.Embed(title='generic title 2', description='generic description 2', color=0x52fffc)
await msg.edit(embed=embed)
It seems to stop at
await bot.wait_for('reaction_add', ..)
why is that? and how can i make the code work? Thats in a cog btw. I'll happily provide more code if needed.
Better and easier way is to use DiscordUtils
Here is an example:
#commands.command()
async def paginate(self, ctx):
embed1 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 1")
embed2 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 2")
embed3 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 3")
paginator = DiscordUtils.Pagination.CustomEmbedPaginator(ctx, remove_reactions=True)
paginator.add_reaction('⏮️', "first")
paginator.add_reaction('⏪', "back")
paginator.add_reaction('🔐', "lock")
paginator.add_reaction('⏩', "next")
paginator.add_reaction('⏭️', "last")
embeds = [embed1, embed2, embed3]
await paginator.run(embeds)
Forgot about this, and i figured it out eventually. Here's how i did it:
At first i put all the content of the pages in a list. Each entry is a page.
Then i define a function that will act as a check. This one will restrict the reaction listener to the actual embed that was sent and prevents anyone from reaction other than the command invoker. Sorry for any Formatting Errors.
def check(reaction, user):
return reaction.message.id == msg.id and user == ctx.author #msg.id is the id of the embed sent by the bot.
page = 0
while True: #can be changed to a variable to let it work a certain amount of times.
try:
reaction, _ = await bot.wait_for('reaction_add', timeout= 20.0, check=check)
if reaction.emoji == 'emote of choice here' and page > 0:
page -= 1
embed = discord.Embed(title='Title Here', description=pages[page]
await msg.edit(embed=embed)
if reaction.emoji == 'emote of choice here' and page < len(pages) -1:
page += 1
embed = discord.Embed(title='Title Here', description= pages[page]
await msg.edit(embed=embed)
except asyncio.TimeoutError:
#do stuff here, could be pass or a message saying the timeout has been reached or something similar.

Resources