Reputation: 3924
My intended behavior is when someone whose ID is in the list admins
can make the bot kick someone using /kick <mention_user_to_kick> <reason>
, but it ends up with the error message
Ignoring exception in on_message
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/discord/client.py", line 312, in _run_event
await coro(*args, **kwargs)
File "discordbot.py", line 325, in on_message
await target.kick(reason=reason)
AttributeError: 'User' object has no attribute 'kick'
and I can't find a way to convert the user object into a member object, even given the server/guild ID (from message.guild.id
).
Trying to kick using client.kick(user)
fails because kick
is not an attribute of client
.
Doing client.get_user()
returns a user object, so it doesn't work.
Doing a search of message.guild.members
(what I have) doesn't help as it outputs an iterable of user objects.
This is what I have so far:
import discord
import asyncio
import os
import random
import time
import math
client = discord.Client()
# the list of admins is in here
with open('admins.conf', 'r') as f:
for line in f.readlines():
exec(line)
random.seed(os.urandom(32))
searchusers = []
bank_cooldown = {}
bans['global'] = False
@client.event
async def on_ready():
'''Notification on ready.'''
print('Logged in! Bot running.')
await client.change_presence(activity=discord.Game(name='/help'))
@client.event
async def on_member_join(user):
'''Direct message the rules on member join.'''
await user.create_dm()
await user.dm_channel.send(f'Hi **{user.name}**, welcome to the server! Be sure to read the rules to stay out of trouble. Have a great time!')
def isadmin(uid):
'''Return True if user is a bot admin, False otherwise.'''
return True if uid in admins else False
def mention_to_uid(mention):
'''Extract the UID from a mention'''
uid = mention[2:-1]
if uid[0] == '!':
uid = uid[1:]
return uid
@client.event
async def on_message(message):
##########################
# a bunch of setup stuff #
##########################
if message.content.startswith('/') or message.content.startswith('&') or cmd == 2147483647:
user = message.author.id
name = message.author.display_name
text = message.content[1:].strip()
command = text.split(' ')[0]
subcommand = text.split(' ')[1:]
##################
# other commands #
##################
if command == 'kick':
if len(subcommand) < 2:
await message.channel.send('Missing arguments! `/kick <user> <reason>`')
if isadmin(user):
reason = ''
for i in subcommand[1:]:
reason += (' ' + i)
reason = reason[1:]
for member in message.guild.members:
if member.id == int(mention_to_uid(subcommand[0])):
target = member
break
target = client.get_user(int(mention_to_uid(subcommand[0])))
await target.kick(reason=reason)
await message.channel.send('Kicked user from the server')
##################
# other commands #
##################
client.run('Nj*********************************************************')
Upvotes: 0
Views: 2063
Reputation: 60974
What you should be doing is using the discord.ext.commands
extension, which makes all of this really simple:
from discord.ext import commands
from discord import Member
bot = commands.Bot("/")
def called_by(id_list):
def predicate(ctx):
return ctx.author.id in id_list
return commands.check(predicate)
@bot.command(name="kick")
@called_by(admins)
async def kick_command(ctx, target: Member, *, reason=None):
await target.kick(reason=reason)
bot.run("token")
(You would probably want to add an error handler to communicate to users when validations fail).
If you're not willing to do that, you can use Guild.get_member
instead:
target = message.guild.get_member(mention_to_uid(subcommand[0]))
Upvotes: 2