Discord bot command not working (Discord.py) - python

I've been trying to create a discord bot with Python. One of the commands was suppose to remove of the user's roles and add a specific one. And then if they were on a voice channel send them to another specific voice channel. I tried the following code:
#client.command()
async def prisioner(member:discord.member):
role=await guild.get_role(702269742014005248)
channel=await guild.get_channel(690488036781195294)
await client.add_roles(member, role)
if member.activity!=None:
await move_to(channel)
It's not working and doesn't show any errors on the IDLE. Can someone help?

A couple of things to mention:
When using command decorators, Context is always the first argument (see references).
Be careful with your spelling, as I'm guessing the command was supposed to be called prisoner, and if that's the case, then you made a typo; prisioner.
It seems that some of the code's syntax is based off of the old discord.py version, so when using documentation, stick to the most recent one (see references).
You seem to be awaiting a few things unnecessarily. The await keyword should only be used for coroutines (it'll tell you in the docs).
You're setting parameter types really well - definitely a good habit to get into from the get-go.
And before we move onto your command, please make sure you have await client.process_commands(message) if you're using an on_message(message) event.
Your command, rewritten:
#client.command()
async def prisoner(ctx, member: discord.Member):
role = ctx.guild.get_role(702269742014005248)
v_channel = ctx.guild.get_channel(690488036781195294) # assuming this is a voice channel?
await member.add_roles(role)
if member.voice.channel: # checks user is connected to a voice channel
await member.move_to(v_channel)
await ctx.send(f"Successfully imprisoned {member.mention}!")
References:
Member.move_to()
Guild.get_role()
Guild.get_channel()
VoiceState.channel
commands.Context
discord.on_message
Bot.process_commands()

Related

How to detect if a role was mention Discord py

So I'm creating a bot that can change the perms of roles. and to start I wanted to code a thing that allows me see and check what role has been mentioned. I want the identification to be open to all roles not just one because later on I want to be able to change the perms of multiple roles at once.
#client.event
async def on_message(message):
if message == client.user:
return
if message.channel.name in ['general']:
if message.content.lower().startswith('!rc'):
role = str(message.role.id)
await message.channel.send (f'{message.role.mention}')
return
So far I have tried doing this where I create a .startswith for the initial command then I create a "role" variable that I then use to mention that role but this doesn't work, can someone help/point me in the right direction in getting this?
Don't use on_message event for these type of commands because you would need to put a bunch of code to solve this problem with that event. Use the below code which helps to solve your problem in an easy manner
#client.command()
async def role(ctx,role:discord.Role):
if ctx.channel.name=="general":
await ctx.send(role.mention)

Discord bot that deletes messages by "x" amount in python

So the bot I created (in python) can currently delete all messages with the command "!clear all". However, I would also like to add a function to it, so that people can type in "x" amount and for that to be deleted instead of all. Is this possible? or would I need to redo this function a different way?
I should add I'm new to python and still learning the ropes.
Here is my code:
if '!clear all' in message.content and message.author.permissions_in(message.channel).manage_messages:
await message.channel.send('__**This will delete all messages (even pinned)**__')
await message.channel.send('**Type:**')
await message.channel.send('```"!yes" to continue```')
await message.channel.send('```"!no" to stop```')
if '!no' in message.content and message.author.permissions_in(message.channel).manage_messages:
await message.channel.send('**This proccess has stopped**')
exit()
else:
if '!yes' in message.content and message.author.permissions_in(message.channel).manage_messages:
await message.channel.send('**This proccess will continue in:**')
await message.channel.send('**3**')
await asyncio.sleep(0.5)
await message.channel.send('**2**')
await asyncio.sleep(0.5)
await message.channel.send('**1**')
deleted = await message.channel.purge(limit=3000)
await message.channel.send('**All messages deleted. Have a nice day**'.format(deleted))
await asyncio.sleep(3)
deleted = await message.channel.purge(limit=3000)
Many thanks!
Discord.py actually provides functionality to implement something like this, you can add parameters to your command via function arguments, and you can ask discord.py to automatically convert them to specific types (such as integer/numbers) with converters.
If you're not using discord.py or commands yet, I recommend you do, it helps a lot!
To solve the question without these features though, you can take the user input (here message.content and split it after every space (message_arguments = message.content.split()) this will give you a list of words (where message_arguments[0] is the command, here !clear, and message_arguments1 is the second argument, for example all or potentially a number) and from there you need to check whether that second argument is all or a number by using int(message_arguments[1]), more on that here for example. Once you have the number you can simply use it as a variable and use it to delete the messages: await message.channel.purge(limit=variable_that_holds_a_number).

How can I reset a command cooldown for a discord user?

I would like to avoid as many errors as possible, but the bot may have errors during its runtime. You can run a command only once every 7 days. If it comes to errors that would be doofy of course. Is there a way to make a command usable once again/reset the cooldown for certain users?
My approach:
#trivia_channel.command(aliases=["reset"])
async def reset_cooldown(self, ctx, member: discord.Member):
await self.start.reset_cooldown(ctx, member)
await ctx.send(f"Resetted cooldown for {member}.")
trivia_channel.command is a group command.
This obviously throws errors and I don't know how to accommodate the member argument.
Command.reset_cooldown only takes one argument, the Context. You can reset the cooldown for someone else if you overwrite the Context.author and Context.message.author attributes with the member variable.
#trivia_channel.command(aliases=["reset"])
async def reset_cooldown(self, ctx, member: discord.Member):
ctx.author = member
ctx.message.author = member
self.start.reset_cooldown(ctx)
await ctx.send(f"Resetted cooldown for {member.mention}")
This worked for me, it's not the best solution though. If you want a much better way you can create a custom cooldown but it's not worth for only one command.
Reference:
Command.reset_cooldown

Can a discord.py bot mute the voice of others in a voice call?

I am the owner of an Among Us Discord guild with some bots I implemented into it. When we play over on of the voice calls, sometimes people forget to mute themselves so we can hear them which often reveals valuable information.
I am trying to design a set of commands that will allow one person to easily mute everyone the voice channel. They use the command claim "VC Name" to claim command over the indicated voice channel, then use the command set_mute "true/false" to either mute or unmute everyone. The first part I have down, but I am struggling with the code of the second part that actually mutes/unmutes the voice channel members.
While reading the documentation for discord.py, I found a few options that might work, but I don't know how to execute any of them.
discord.VoiceState (Documentation): discord.VoiceState has attributes mute, muted, and self_mute. Perhaps it is possible to modify the voice state of the member with something like member.VoiceState.mute = True, member.VoiceState.muted = True or member.VoiceState.self_mute = True. I'm not sure how to use this method since using the above line of code results in an AttributeError.
discord.Member.edit (Documentation): member.Member.edit has the option to set mute to True. This actually sets the member to a server mute (and I can't seem to undo it), so I would rather avoid this option unless there is a solution through this method.
I could set a unique role that is assigned to all the members in the voice channel and the bot can set the speak permissions on command. This is the method I am using right now but I would like to use an alternative one, if it exists.
This is the code that I have right now. Under the last if/else statement is where I will put the solution to mute and unmute the members in the call.
async def mute(ctx, setting):
regex, claimed = re.compile(f"_VC: (Lobby [0-9])_"), False
for role in cx.message.author.roles:
if regex.search(role.name):
claimed = True
break
if not claimed:
await ctx.send("You have not claimed any of the game lobbies")
return
voice_channel = discord.utils.get(ctx.guild.channels, name=regex.search(role.name).group(1))
for member in voice_channel.members:
if setting.lower() == 'true':
await member.voice_state.set_to_muted()
elif setting.lower() == 'false':
await member.voice_state.set_to_not_muted()
For your first option, if you look at the API references of discord.VoiceState.self_mute, you'll see a description of this attribute:
Indicates if the user is currently muted by their own accord.
So this means that you cannot set any value, this attribute returns True/False depending on user muted his/herself or not.
For your second option, it seems the best way to do this. And yes, members who has no permission, can't undo their mute but you can unmute them from code or manually.
For your third option, it's another solution but I won't suggest it while you can use member.edit.
So I guess you're trying to make 2 methods named set_to_muted and set_to_unmuted but for this, you have to edit the main python files of discord.py library. Instead of that, you can create 2 async functions that takes member as parameter and you can mute them by this way.
async def set_to_muted(member: discord.Member):
await member.edit(mute=True)
async def set_to_unmuted(member: discord.Member):
await member.edit(mute=False)
#client.command()
async def mute(ctx, setting):
voice_channel = discord.utils.get(ctx.guild.channels, name='')
if setting.lower() == 'true':
for member in voice_channel.members:
await set_to_muted(member)
elif setting.lower() == 'false':
for member in voice_channel.members:
await set_to_unmuted(member)

on_reaction_add not being run

I'm new to discord.py and trying to make a translator bot. When the user reacts with a certain flag, the bot translates it, but the event is never getting called hence I have no code to translate any messages yet. I know it's not getting called because the program isn't printing an 'x' to the console.
#client.event
async def on_reaction_add(reaction, user):
channel = reaction.message.channel
print('x')
await client.send_message(channel, '{} has added {} to the the message {}'.format(user.name, reaction.emoji, reaction.message.content))
await client.process_commands(reaction.message)
Probably a bit late to this thread but, the answer above is a valid answer. But you can also use on_raw_reaction_add which gets called even if the messages aren't in the Bot's cache.
Called when a message has a reaction added. Unlike on_reaction_add(), this is called regardless of the state of the internal message cache.
Documentation Link
Example:
#commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
channel = await self.bot.fetch_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
user = await self.bot.fetch_user(payload.user_id)
emoji = payload.emoji
await channel.send("Hello")
There isn't much valid reason for why the event isn't registered/called.
One of which is stated in the docs: http://discordpy.readthedocs.io/en/async/api.html#discord.on_reaction_add. Try adding a reaction immediately to a message that is sent after the bot is online. Since messages sent before the bot is online will not be recognized by the bot (not in Client.messages).
if the message is not found in the Client.messages cache, then this
event will not be called.
Another possible reason is that this function was never defined before the client loop commenced. Verify your indentation. And/Or try placing the function directly under client = Bot(...), to check if this is the problem.
If neither of the aforementioned solves your problem, please post a minimal, complete, verifiable example (a short runnable code from top to bottom that indicates your problem).

Categories