Is there a way to kick members without using client = discord.Client() instead of a bot on Python - python

So, I'm new to programming and I have a discord bot, I used client = discord.Client() instead of using client = commands.Bot(...), and now i want to be able to kick users. But I can't see any command using my client to kick someone using their username.I konw it's simpler to do it with a bot but i have already such a big code that I don't want to redo it.
Help would be appreciated :)

If you change it to commands.Bot everything is going to work just fine (if you add await client.process_commands(message) at the end of the on_message event. But nevertheless here's how to make a kick 'command' using the on_message event:
#client.event
async def on_message(message):
guild = message.guild
if message.startswith('!kick'):
args = message.content.split()[1:]
member_id = int(args[0])
member = guild.get_member(member_id)
reason = ' '.join(args[1:])
await member.kick(reason=reason)
# If you actually change your mind and want to use `commands.Bot`
await client.process_commands(message)
# To invoke
# !kick 172399871237987 drama seeker
I strongly DO NOT recommend using this method at all, just compare how much better, easier and cleaner is with commands
#client.command()
#commands.has_permissions(kick_members=True)
async def kick(ctx, member: discord.Member, *, reason):
await member.kick(reason=reason)
# While invoking here you can actually mention the user
# !kick #some_user drama seeker
# But you also can use the ID
# !kick 761876328716327186 drama seeker
It's only 4 lines, 3 if we don't count the has_permissions decorator.

Related

How to delete messages with discord bot

I made a small discord bot, and I need him to delete a message from the writer and then post something. When I use #bot.event it works fine but it's the only thing working in code(only the delete part works). And how to use ctx.message.delete?
#bot.command(aliases=["IDC"])
async def idc(ctx):
ctx.channel.send("https://cdn.discordapp.com/attachments/586526210469789717/838335535944564756/Editor40.mp4")
You just need to save the channel for later use.
#bot.command(aliases=["IDC"])
async def idc(ctx):
chn = ctx.channel
await ctx.message.delete()
await chn.send("https://cdn.discordapp.com/attachments/586526210469789717/838335535944564756/Editor40.mp4")
Your bot will need the delete messages permission.
EDIT:
This will also work, but it is recommended to use the first way as it can be faster.
#bot.command(aliases=["IDC"])
async def idc(ctx):
await ctx.send("https://cdn.discordapp.com/attachments/586526210469789717/838335535944564756/Editor40.mp4")
await ctx.message.delete()

How to create channel on_ready discord.py?

I was trying to create come channels when bot starts. I want them to create in function on_ready. But await guild.create_text_channel("Channel") requires guild by itself. Usually when I want to create it by command I make something like this:
#client.command()
async def create(ctx):
guild = ctx.guild
await guild.create_text_channel(name="test channel")```
But I need ctx to create guild. So the question is: How do I create a channel without ctx?
You simply need to get a discord.Guild instance, you can get that using Bot.get_guild
async def on_ready():
await client.wait_until_ready()
guild = client.get_guild(id_here)
await guild.create_text_channel(name="whatever")
If you want to create a channel in all the guilds the bot is in you can loop through client.guilds
async def on_ready():
await client.wait_until_ready()
for guild in client.guilds:
await guild.create_text_channel(name="whatever")
Reference:
Bot.get_guild
Bot.guilds
Ran into the same problem with disnake, and it took me reading through the api and testing things to figure it out. Since disnake is supposed to be forked off of discord.py try this
#commands.command(name="obvious", description="given")
async def command(ctx: Context):
await ctx.message.guild.create_text_channel("channel_name")
This solved my issue, and now I just need to add the parameters to properly sort channel creation.

discord.py bot isn't answering when mentioned from phone app

I made recently a discord bot for small server with friends. It is designed to answer when mentioned, depending on user asking. But the problem is, when someone mention bot from a phone app, bot is just not responding. What could be the problem?
Code:
import discord
from discord.ext import commands
from discord.ext.commands import Bot
import asyncio
bot = commands.Bot(command_prefix = '=')
reaction = "🤡"
#bot.event
async def on_ready():
print('Bot is ready.')
#bot.listen()
async def on_message(message):
if str(message.author) in ["USER#ID"]:
await message.add_reaction(emoji=reaction)
#bot.listen()
async def on_message(message):
mention = f'<#!{BOT-DEV-ID}>'
if mention in message.content:
if str(message.author) in ["user1#id"]:
await message.channel.send("Answer1")
else:
await message.channel.send("Answer2")
bot.run("TOKEN")
One thing to keep in mind is that if you have multiple functions with the same name, it will only ever call on the last one. In your case, you have two on_message functions. The use of listeners is right, you just need to tell it what to listen for, and call the function something else. As your code is now, it would never add "🤡" since that function is defined first and overwritten when bot reaches the 2nd on_message function.
The message object contains a lot of information that we can use. Link to docs
message.mentions gives a list of all users that have been mentioned in the message.
#bot.listen("on_message") # Call the function something else, but make it listen to "on_message" events
async def function1(message):
reaction = "🤡"
if str(message.author.id) in ["user_id"]:
await message.add_reaction(emoji=reaction)
#bot.listen("on_message")
async def function2(message):
if bot.user in message.mentions: # Checks if bot is in list of mentioned users
if str(message.author.id) in ["user_id"]: # message.author != message.author.id
await message.channel.send("Answer1")
else:
await message.channel.send("Answer2")
If you don't want the bot to react if multiple users are mentioned, you can add this first:
if len(message.mentions)==1:
A good tip during debugging is to use print() So that you can see in the terminal what your bot is actually working with.
if you print(message.author) you will see username#discriminator, not user_id

How to get discord.py bot to DM a specific user

I have searched around a lot for this answer, and I haven't found it. I want to use a suggestion command, that whenever someone uses it to suggest an idea, it DMs me, and me only.
You'll have to use the send_message method. Prior to that, you have to find which User correspond to yourself.
#client.event
async def on_message(message):
# we do not want the bot to reply to itself
if message.author == client.user:
return
# can be cached...
me = await client.get_user_info('MY_SNOWFLAKE_ID')
await client.send_message(me, "Hello!")
#client.event
async def on_message(message):
if message.content.startswith("#whatever you want it to be")
await client.send_message(message.author, "#The message")
Replace the hashtagged things with the words that you want it to be. eg.: #whatever you want it to be could be "!help". #The message could be "The commands are...".
discord.py v1.0.0+
Since v1.0.0 it's no longer client.send_message to send a message, instead you use send() of abc.Messageable which implements the following:
discord.TextChannel
discord.DMChannel
discord.GroupChannel
discord.User
discord.Member
commands.Context
Example
With bot.command() (recommended):
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
#bot.command()
async def suggest(ctx, *, text: str):
me = bot.get_user(YOUR_ID)
await me.send(text) # or whatever you want to send here
With on_message:
from discord.ext import commands
bot = commands.Bot()
#bot.event
async def on_message(message: discord.Message):
if message.content.startswith("!suggest"):
text = message.content.replace("!suggest", "")
me = bot.get_user(YOUR_ID)
await me.send(text) # or whatever you want to send here

Discord.py trouble with move_member()

Im having trouble with using move_member() for a python bot. The purpose of the command is to "kick" a user by moving them to a channel, then deleting it so that they disconnect from the voice call, but do not need an invite back to the server. I am aware that just moving a user accomplishes this purpose, but I would like for a user to disconnect instead.
import discord
import random
import time
import asyncio
from discord.ext import commands
from discord.ext.commands import Bot
bot = commands.Bot(command_prefix="!")
#bot.event
async def on_ready():
await bot.change_presence(game=discord.Game(name='with fire'))
print("Logged in as " + bot.user.name)
print(discord.Server.name)
#bot.command(pass_context=True)
async def kick(ctx,victim):
await bot.create_channel(message.server, "kick", type=discord.ChannelType.voice)
await bot.move_member(victim,"kick")
await bot.delete_channel("bad boi")
bot.run('TOKEN_ID')
the line gives the error:
The channel provided must be a voice channel
await bot.move_member(victim,"kick")
and this line gives this error:
'str' object has no attribute 'id'
await bot.delete_channel("kick")
Im pretty sure you have to get the channel id instead of "kick", but I don't see exactly how to do so, because the code below isnt working, even when I replace
ChannelType.voice to discord.ChannelType.voice
discord.utils.get(server.channels, name='kick', type=ChannelType.voice)
delete_channel('kick') will not work because you need to pass in a channel object and not a string.
You do not need to use discord.utils to get the channel you want. The create_channel returns a channel object, so you should be able to use that.
But, you do need to get the Member object that you're going to kick. You also made the mistake of referencing message.server rather than ctx.message.server
#bot.command(pass_context=True)
async def kick(ctx, victim):
victim_member = discord.utils.get(ctx.message.server.members, name=victim)
kick_channel = await bot.create_channel(ctx.message.server, "kick", type=discord.ChannelType.voice)
await bot.move_member(victim_member, kick_channel)
await bot.delete_channel(kick_channel)
Now if you're using rewrite library, you would have to do the following
#bot.command()
async def kick(ctx, victim):
victim_member = discord.utils.get(ctx.guild.members, name=victim)
kick_channel = await ctx.guild.create_voice_channel("kick")
await victim_member.move_to(kick_channel, reason="bad boi lul")
await kick_channel.delete()
As abccd mentioned in the comments, this is evaluated as a string, which will not guarantee the fact that you'll be kicking the right person. discord.utils.get will grab the first result, and not necessarily the correct user if multiple users have the same name.
A better approach would be to use #user or to use UserIDs. Here's an example in the old library
#bot.command(pass_context=True)
async def kick(ctx):
victim = ctx.message.mentions[0]
kick_channel = await bot.create_channel(ctx.message.server, "kick", type=discord.ChannelType.voice)
await bot.move_member(victim,kick_channel)
await bot.delete_channel(kick_channel)
I would highly recommend to start using the rewrite library since it's much more Pythonic and it's going to be the new library in the future anyways.
According to the Discord documentation, the call to delete_channel expects a parameter of type Channel.
For more information on the Channel class, refer to the Channel documentation
If I understand what you're attempting to do, for your code to run as expected, you would need to maintain a reference to the channel you are using as your temporary channel, and then change your offending line to:
await bot.delete_channel(tmp_channel)

Categories