I'd like to make a dc bot, and I want to kick members from voice channel by mention the user
#client.command()
async def kick(ctx):
victim = ctx.message.mentions[0]
await move_to(victim,none)
I use this code, but it don't work, it says "'Bot' object has no attribute 'move_members'"
How should I solve this?
You can eject a member from voice by editing their vocie_channel to None. I am also using a converter to get the member:
#client.command()
async def kick(ctx, member: discord.Member):
await member.edit(voice_channel=None)
Related
i need a ban command that bans a member and than dms the banned member to inform them about it and when it happened.
I have a few problems:
What if the user's dms are closed?
It is not dming the banned member.
Also includes a perm ban like `!Ban
If anyone can help me out that will be great and i will greatly appricate it.
Thanks!
Like you want, this is example of simple ban member for discord.py
#client.command()
async def ban(ctx, member:discord.Member, *, reason=None)
await member.ban
await member.send(f"You've been banned by {ctx.author}\nReason = {reason}")
If you looking for .cogs version
#commands.command()
async def ban(self, ctx, member:discord.Member, *, reason = None)
await member.ban
await member.send(f"You've been banned by {ctx.author}\nReason = {reason}") ##this send message by DMs for banned member to tell him/her why getting banned
If you using discord-py-slash-command you can create new question
for the 1:
try:
await user.send("msg")
except discord.errors.Forbidden:
code here
I don't know if this can help you
So, what I want to do is stop a specific role from speaking in a channel on discord using discord.py.
Here's what I have so far.
import discord
import os
from keep_alive import keep_alive
client = discord.Client()
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.members, name='Foo'), send_messages=False)
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
keep_alive()
client.run(os.getenv('TOKEN'))
This doesn't cause any errors when I run the bot, but when I say test in discord it says: target parameter must be either Member or Role. I don't understand because I made a role named Foo.
Can you pls help?
Tysm.
The error itself tells you what went wrong. Your await function does not make any sense in that case. You are looking for guild.members with the name Foo but what you want is the role.
Have a look at the following code:
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.roles, name='Foo'), send_messages=False) # Get the role
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
Here we are looking for a role in the guild named Foo. You can also just use the ID to change the name to whatever you want to without editing the code (id=RoleID).
The output:
So I am working on a little project here, and pretty much, I want to have one of those "Please type the name of a channel in this server" feature.
So pretty much, the bot asks for a channel name, and I put in for example "#changelog" - and then it will ask for what it should write in that channel, etc etc.
So need to get the channel id (I am guessing), but I don't want users to write the ID, instead only writing the #server-name. And then whenever I have done that, the bot shall write in that channel.
Here is my current code!
class Changelog(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_ready(self):
print('Changelog is loaded')
#commands.command()
async def clhook(self, ctx):
await ctx.send('Write text-channel: ')
text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
clhook = self.client.get_channel(text_channel)
def setup(client):
client.add_cog(Changelog(client))
Edit:
The channel ID shall be saved "forever", meaning that I do not have to re-write the channel name where the message should go!
You can use discord.utils.get() with this example:
text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
channel = discord.utils.get(ctx.guild.text_channels, name=text_channel)
await channel.send('Bla Bla')
So when you type (prefix)clhook then only the channel name, for example general, it will send Bla Bla to the channel named general .
There is another way to do this and I think it's simple than the first option, here it is:
#commands.command()
async def clhook(self, ctx, channel: discord.TextChannel):
await channel.send('Bla Bla')
So in this command, usage is changed. You can use that with this: (prefix)clhook #general(mention the channel). I suggest this solution and I think it's more useful.
You can use message.channel_mentions. This will return a list of all channels that were mentioned using the #channel-name notation. That way, you can just use channel.id to get the id of the channel they mentioned.
Don't forget, however, to check if the user did in fact tag a channel (which you can also put in your check). I put it in a separate function to make it a bit more readable for the sake of this reply, but you can fit that in your lambda if you really want to.
Also, make sure to check if it's a Text Channel and not a Voice Channel or Category Channel.
#commands.command()
async def clhook(self, ctx):
def check(self, message):
author_ok = message.author == ctx.author # Sent by the same author
mentioned_channel = len(message.channel_mentions) == 1 and isinstance(message.channel_mentions[0], discord.TextChannel)
return author_ok and mentioned_channel
await ctx.send("Write text-channel: ")
text_channel = await self.client.wait_for("message", check=check)
chlhook = text_channel.channel_mentions[0]
I put two conditions on the mentioned_channel line, because if the first one fails, the second one could cause an IndexError. Alternatively you can also use an if-statement to return sooner at that place to solve the same issue.
lets say on_member_join event
#commands.Cog.listener()
async def on_member_join(self, member):
# On member joins we find a channel called general and if it exists,
# send an embed welcoming them to our guild
channel = discord.utils.get(member.guild.text_channels, name="welcome")
if channel:
embed = discord.Embed(
description="Welcome to our guild!",
color=random.choice(self.bot.color_list),
)
embed.set_thumbnail(url=member.avatar_url)
embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.set_footer(text=member.guild, icon_url=member.guild.icon_url)
embed.timestamp = datetime.datetime.utcnow()
await channel.send(embed=embed)
This is my event (I know it works) how can I test it in any way to execute command to emit the event (not manually by adding and removing someone)?
[something like .emit on_member_join #user where arg1 is event and if needed arg2 is mention or id of channel ]
Any command for that ?
something like Discord.js: Manually triggering events but in discord.py not in JavaScript
Currently there isn't official support in the discord.py api to do something like that but you can always make a command in the cog like follows:
#commands.command()
async def test_join(self, ctx, member: discord.Member):
await self.on_member_join(member)
Technically there is a way to probably do it that isn't documented...
Line 131 in here. I will not offer addition support for that because it isn't documented.
I want to ensure my bot only responds to commands/messages and responds only in 1 specific channel is this possible I have tried multiple variations to no success. even better if I could define it for any event. Anyone got any ideas?
You can check message.channel in the on_message event and if it matches your criteria, in this case a specific channel, then do process_commands.
Below is an example where the !ping command will only work when channel.name is "general".
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.command()
async def ping():
await client.say('Pong')
#client.event
async def on_message(message):
if message.channel.name == 'general':
await client.process_commands(message)
client.run('token')