Make /afk command accept numbers not letters in python - python

I want to make it that when someone does /AFK and writes letters instead of numbers, it should show something like "input numbers not letters". Here is my code:
async def afk(ctx, mins : int):
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.", delete_after=5)
await ctx.author.edit(nick=f"[AFK]{ctx.author.name}")
counter = 0
while counter <= int(mins):
counter += 1
await asyncio.sleep(60)
if counter == int(mins):
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK", delete_after=5)
break```

You need to remove the typehint and then use try/except
async def afk(ctx, mins):
try:
mins = int(mins)
except ValueError:
return await ctx.send("input numbers not letters")
# your other code

Try this:
async def afk(ctx, mins : int):
try:
mins = int(mins)
except ValueError:
# ...
# <send the message here.>
# ...
return
current_nick = ctx.author.nick
await ctx.send(f"{ctx.author.mention} has gone afk for {mins} minutes.", delete_after=5)
await ctx.author.edit(nick=f"[AFK]{ctx.author.name}")
asyncio.sleep(60 * mins)
await ctx.author.edit(nick=current_nick)
await ctx.send(f"{ctx.author.mention} is no longer AFK", delete_after=5)
Here, we try to convert mins to an int, and if it fails, send the message. Otherwise, continue as usual. I think you can also remove the while loop and if statement like I did here.

Generally I agree with #Poojan's answer, but there's a much simpler way than try/except:
async def afk(ctx, mins):
if not mins.isdigit():
return await ctx.send("input numbers not letters")
mins = int(mins)

Related

How can i prevent swearwords on the server on discord.py

I am trying to block messages which contain swearwords.Swearwords in a text file btw.So,I got stuck because whenever I write swearwords,bot doesn't response my message.This is my code:
#client.event
async def on_message(message):
global swearword_count
global badwords
if message.author == client.user:
await client.process_commands(message)
else:
msg = message.content
for x in msg:
try:
if x in badwords:
if exception_counter[str(message.author.id)] == 0:
await message.channel.send("Please do not use this word ever")
swearword_count[str(message.author.id)] += 1
if swearword_count[str(message.author.id)] > 5 and exception_counter == 1:
await message.author.send("You've been banned due to bad words that you used.")
elif swearword_count[str(message.author.id)] > 5 and exception_counter == 0:
await message.author.send("You've been banned due to bad words that you used.")
await message.channel.send("Don't use this word")
else:
pass
except KeyError:
exception_handling[str(message.author.id)] = 1
swearword_count[str(message.author.id)] = 0
await message.author.send("If you use this word,you will get banned.")
continue
await client.process_commands(message)
#client.event
async def on_member_join(member):
channel = discord.utils.get(member.guild.text_channels, name="welcome")
await channel.send(f"{member.name},welcome :)")
global swearword_count
swearword_count[str(member.id)] = 0
exception_handling[str(member.id)] = 0
dm_channell = await member.create_dm()
await dm_channell.send(f"{member},welcome mate :)")
I've used dictionaries to store the data of users.So how can i fix this problem?If you have any advice,I'd love to see it
PS:My commands work properly.
It's because for x in msg: splits your message into single letters. You have to slice it for example by spaces: for x in msg.split(" "):, but this way if someone writes "badword" without spaces (ex. "badwordIlikeapples) this won't work. So try this:
for x in badwords:
try:
if x in msg:
...
This will catch all the "badwords", but if you write a word that contains the swear word inside it this will also be caught.

Discord.py bot.wait_for

#commands.command()
async def verify(self, ctx, length=10):
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
print("done")
if verify_msg == answer:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Im trying to do a verify system, but after the bot.wait_for task nothing happens, i guess something in the line is wrong, has anybody solutions?
If you want it to be a dm command we can use the restriction #commands.dm_only()
However we then also have to check where the answer was given, we do that via some kind of custom check. I have modified your command a bit, but you can make the changes again personally.
Take a look at the following code:
#commands.dm_only() # Make it a DM-only command
#commands.command()
async def verify(self, ctx, length=10):
def check(m):
return ctx.author == m.author and isinstance(m.channel, discord.DMChannel)
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number: {verify_msg}")
try: # Try to get the answer
answer = await bot.wait_for("message", check=check)
print(answer.content)
if verify_msg == answer.content:
await ctx.author.send("Verified!")
else:
await ctx.author.send("Verify again!")
except: # Used if you for example want to set a timelimit
pass
Edited to show full answer.
Hey ho done it lol.
Basically the message object contains a lot of data, so you need to pull the content of the message using answer.conent.
https://discordpy.readthedocs.io/en/latest/api.html?highlight=message#discord.Message.content for reference
#bot.command()
async def verify(ctx):
length=10
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message')
print(answer.content)
print("done")
if verify_msg == answer.content:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Give that a test run and let me know what happens ;)

How do I make a command that checks for a message (Discord.py)

I'm here with a question. I made this command that pings someone but I don't know how to make it stop. Originally it would listen for "~stop" and it would break the message sending loop. It wouldn't work though. Please help!
#client.command()
async def ping(ctx, member:discord.User=None):
pingEvent = 0
if (member == None):
await ctx.send("who do you want me to ping stupid")
if "~stop" in ctx.channel
pingEvent = 0
else:
pingEvent = 1
while pingEvent <= 1:
await ctx.send(
f"{member.mention}"
)
if pingEvent == 0:
break
First of all, your bot will get rate limited and eventually banned for doing this, but for educational purposes. Here is the solution.
Checking for stop inside loop
for _ in range(20): #restrict pings to avoid being banned
await ctx.send(member.mention)
try:
msg = await client.wait_for("message", check= lambda x: x.author == ctx.author and x.content.contains('~stop'), timeout=2)
except asyncio.TimeoutError:
continue
else:
break
This will send a message once per two seconds since we set the timeout to 2. which is well below the rate limit but still breaks the ToS
References:
asyncio.TimeoutError - you have to import it with import asyncio
wait_for
Read the Terms of Services
This should do the trick and might look more simple than the answer above/below
def check(m):
return ctx.channel == m.channel and m.author == ctx.author
try:
message = await self.bot.wait_for('message', check=check, timeout=300)
except asyncio.TimeoutError:
await ctx.send("You've used too long to answer!")
else:
return

Discord.py getting unexpected parentheses in output

This is my discord.py bot. When I type m!rate (person) It sends me a text like this. However, I don't want the (' and ',) at the beginning and end of the message.
This is my code:
#client.command()
async def rate(ctx, *member):
if len(member) == 0:
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member} {value}/10")
When I change it, the message works but the error doesn't. I can't find any solution.
Using * in a parameter makes the function pass positional arguments into a tuple, hence the brackets. This is usually for when you want to unpack an arbitrary amount of arguments.
To fix it, just remove *, and also add a type for the parameter if you want:
#client.command()
async def rate(ctx, member: discord.Member = None): # setting a default value of None
if not member: # testing to see if the default value is None
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member.mention} {value}/10")
References:
Using * in Python
discord.Member
Member.mention
If you want your bot to mention one person per command :
#client.command()
async def rate(ctx, *member):
if member:
"".join(member)
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
await ctx.send(f"I rate {user.mention} {value}/10")
else:
await ctx.send("Member not found!")
else:
await ctx.send("You forgot to mention someone")
If you want your bot to mention multiple people per command :
#client.command()
async def rate(ctx, *members):
if members:
embed = Discord.embed(color = discord.color.blue(), title = "title")
count = 0
for member in members:
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
embed.add_field(name = f"{user.mention}", value = f"I rate him {value}/10")
count += 1
if count != 0:
await ctx.send(embed=embed)
else:
await ctx.send("Members not found!")
else:
await ctx.send("You forgot to mention someone")

discord.py rewrite | How would I make this into an integer?

I am trying to make a command which activates a random number guesser game. Obviously, I am stuck in the first few lines. I have written what I THINK will work, however it may be blatantly wrong. I want it to change the message on the discord server to an int, so it will work in my if statement.
It's my first time making a bot in with discord.py, so I am running into many obstacles. I am not fully sure what the error is telling me, so I haven't been able to try any fixes. This is the code:
async def numgame(context):
number = random.randint(1,100)
for guess in range(0,5):
await context.send('Pick a number between 1 and 100')
Message = await client.wait_for('message')
Message = int(Message)
if Message.cleant_content > number:
await context.send(guess + ' guesses left...')
asyncio.sleep(1)
await context.send('Try going lower')
asyncio.sleep(1)
elif Message.clean_content < number:
await context.send(guess + ' guesses left...')
asyncio.sleep(1)
await context.send('Try going higher')
asyncio.sleep(1)
else:
await context.send('You guessed it! Good job!')
if number != Message:
await context.send('Tough luck!')
Whenever I do the command in my discord server, my shell gives me this error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: int() argument must be a string, a bytes-like object or a number, not 'Message'
I am not too sure what it is telling me. As stated, I would like "Message" to be an integer, but I get the error. but help would be appreciated!
[still a beginner, don't be too harsh :(]
wait_for('message') returns a Message object, which int doesn't know how to handle yet. You need to convert Message.content to an int instead. Just below is your code with some other changes:
def check(message):
try:
int(message.content)
return True
except ValueError:
return False
#bot.command()
async def numgame(context):
number = random.randint(1,100)
for guess in range(0,5):
await context.send('Pick a number between 1 and 100')
msg = await client.wait_for('message', check=check)
attempt = int(msg.content)
if attempt > number:
await context.send(str(guess) + ' guesses left...')
await asyncio.sleep(1)
await context.send('Try going lower')
await asyncio.sleep(1)
elif attempt < number:
await context.send(str(guess) + ' guesses left...')
await asyncio.sleep(1)
await context.send('Try going higher')
await asyncio.sleep(1)
else:
await context.send('You guessed it! Good job!')
break
else:
await context.send("You didn't get it")

Categories

Resources