I'm making a discord bot and it has a move command that moves all the members in a voice channel to another, well the main problem is this command should only work for those with move members permission but it does not! It doesn't work even if the user has that permission and it always show me an error. Here is the code:
def in_voice_channel():
def predicate(ctx):
return ctx.author.voice and ctx.author.voice.channel
return check(predicate)
#in_voice_channel()
#client.command()
#commands.has_permissions(move_members=True)
async def moveall(ctx, *, channel : discord.VoiceChannel):
author_ch = ctx.author.voice.channel.mention
for members in ctx.author.voice.channel.members:
await members.move_to(channel)
await ctx.send(f'Moved everyone in {author_ch} to {channel.mention}!')
The problem in this code is not with the permissions setup.
#commands.has_permissions(move_members=True) is the way to go.
What is the use of #in_voice_channel() decorator?
As far as I know this is not from discord.py
Update
After testing it myself, even though "Move Members" is the right permission to go for depending on discord.py docs, it does not seem to work properly.
You can instead use another check like #commands.has_role() to make this work or wait until the bug gets fixed.
#commands.has_permissions() checks the channel permissions, and text channels do not have move_members or mute_members permissions.
What you are looking for is #commands.has_guild_permissions() which checks to see if that user has server wide permissions to move/mute members.
This means that to check if the user has move_member you will need to put #commands.has_guild_permissions(move_members=True) before your function/command.
Related
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)
I'm making a command test.
I only want the user to be able to use the command when they either;
Are the bot owner
Have the manage_channels permission
At the moment I am doing
#client.command()
#commands.has_permissions(manage_channels=True)
#commands.check(commands.is_owner())
async def test(ctx):
await ctx.reply("Success!")
But as soon as I - the bot owner - try to use it without the manage_channels permission it does not work. I assume it is blocked by #commands.has_permissions() as soon as it sees I don't have the permission?
I know I could always just check in the method itself, but I understand using the decorators is the better way?
Thanks in advance.
You can use the commands.check_any decorator
#client.command()
#commands.check_any(commands.is_owner(), commands.has_permissions(manage_channels=True))
async def ...
Reference:
commands.check_any
I want my bot to display some information about a user when they leave. Here's my code:
#client.event
async def on_member_remove(member):
channel = client.get_channel(810613415185350666)
mention = []
for role in member.roles:
if role.name != "#everyone":
mention.append(role.mention)
b = ", ".join(mention)
await channel.send(f"{member} has left the server. Roles: {b}")
Now when the event is triggered, it tells me that they've left (as expected). However, it does not show any roles even though they had several. I would assume this is because they are no longer in the server, which means they technically don't have any roles.
How would I fix this?
on the doc the return is member, but i think that when the member left the server the argument of on_member_remove from memberbecome user so it doesn't haves roles. So if that is correct you need to save in file/database the roles of the members at every on_members_update
MY BAD! This code works fine, but the user that was leaving simply didn't have any roles to display... I'm an idiot, sorry about that. Have a good day :)
(Would delete this question if it'd let me)
I want to get the user that was mentioned in a message and send him a private message. That's working without problems, but now I want to add a message for the case, that the mentioned member is not on the same server.
I searched a lot and try now for over 3 hours to find a solution.
Showcase of the problem: https://youtu.be/PYZMVXYtxpE
Heres my code:
#bot.event
async def on_message(message):
if len(message.mentions) == 1:
membe1 = message.mentions[0].id
membe2 = bot.get_user(membe1)
guild = bot.get_guild(message.author.guild.id)
if guild.get_member(membe1) is not None:
await membe2.send(content=f"you was mentioned in the server chat")
else:
embed2 = discord.Embed(title=f"ยป :warning: | PING not possible", description=f"not possible")
await message.channel.send(content=f"{message.author.mention}", embed=embed)
await message.delete()
return
The first part is working without problems, but at the "else" part, does the bot nothing. He still posts the message with the "invalid" ping in the chat and just ignores it. What can I do to fix that?
There is an error of design in what you are trying to do.
In Discord, you are not able to mention a user if he is not on that same server, so what you are checking will never work at all, currently your code is pretty much checking if the mentioned user exists, which will always happen unless he leaves the guild at the same time the command is executed.
Say for example, to make your command work you want to mention the user user123, who is in your server, you do the following:
#user123 blablabla
And that works because Discord internal cache can find user123 in your server and it is mentioned, which means that clicking on "#user123" will show us a target with his avatar, his roles or whatsoever.
But if you try to do the same for an invalid user, let's say notuser321:
#notuser321 blablabla
This is not a mention, take for example that you know who notuser321 is but he is in the same server as the bot is. Discord cannot retrieve this user from the cache and it is not considered a mention, just a single string, so not a single part of your code will be triggered, because len(message.mentions) will be 0.
Something that you could try would be using regular expressions to find an attempt to tag within message.content. An example would be something like this:
import re
message = "I love #user1 and #user2"
mention_attempt = re.findall(r'[#]\S*', message) # ['#user1', '#user2']
I'm trying to capture a users input, what they say in a message, and have it returned to them in a message from the bot. More specifically, when they run a command, it'll return what ever text they have entered after that.
So far, I'm here:
async def on_message(message):
if message.content.startswith["=ok"]:
await client.send_message(message.channel, message.content[6:])
...unfortunately, I believe this was valid for the previous version of Discord.py before the rewrite. Essentially I want someone to be able to run the command =pressf and have the bot return the message "Everyone, lets pay respects to (string)!" An event probably isn't the best way to go about this but I'm stumped.
I've been struggling to find a specific answer online for my issue so I greatly appreciate anyone who could point me in the proper direction. Thanks!
I would recommend using the newer Commands Extension, it is much simpler to implement what you are wanting. See this bit specifically for passing everything a user types after the command into a variable.
There is an official example I would recommend looking at here: https://github.com/Rapptz/discord.py/blob/master/examples/basic_bot.py
You should use commands instead of on_message event. Here is a simple command:
#client.command()
async def test(ctx):
await ctx.send('A Simple Command')
ctx parameter is the parameter that all commands must have. So, when you type =test, it will send to that channel A Simple Command.
If we come to what you try to do, you can use more parameters than ctx. Here is how you can do it:
#client.command()
async def pressf(ctx, *, mess):
await ctx.send(mess)
In this code, you have 1 more parameter called mess and also there's a *. That means mess parameter includes every message after =pressf. So when a user type =pressf Hello, it will send the channel Hello.