Im Trying To Make A Rapid Fire Type Question, Basically "j" is the variable for points and i want it to change/decrease (and to check for messages) every 0.5 seconds ... The Problem Is That No Matter How Late I Try I get 1000 points. Also Im New. (btw sorry for bad english)
The Code:
def check(m):
return m.author == message.author and m.channel
mn = randint(5, 15)
mn1 = randint(5, 10)
mz = mn * mn1
membed = discord.Embed(
title="Here's The Question",
description=str(mn) + " * " + str(mn1) + ''' Type Your Answer Below.. ''',
url=None,
color=discord.Color.blue())
mzz = await message.send(embed=membed)
j = 1100
for i in range(0, 5):
sleep(0.5)
j = j - 100
gt = await bot.wait_for('message', check=check)
if int(gt.content) == int(mz):
await message.send(f'Its Right.. You Got **{j}** Points')
else:
await message.send(f'Its Wrong.. The Answer Is **{j}**')
Please Help...
The issue is because you're misunderstanding how await works.
await foo() causes your program to sleep until foo() returns a value.
When you type await bot.wait_for(), you are saying:
Sleep until bot.wait_for() returns a value
bot.wait_for() only returns a value when it receives a message.
The full flow of your program is thus:
You enter the first loop i = 0. j gets set to 1000.
You sleep until you receive a message. Because you can receive a message any time in the future (say, ten seconds or ten minutes or fifteen hours, etc.), you never enter the second loop i = 1. Basically, your program is frozen at this point until somebody sends you a message.
The solution here is to ask your bot to time out waiting for a message, so it can continue to the next value of i. A timeout tells your bot to sleep only for a specified amount of time before continuing your program. Conveniently, the wait_for command provides a timeout parameter:
j = 1100
for i in range(0, 5):
j = j - 100
try: # A try/except block is needed because this throws an error if bot times out
gt = await bot.wait_for('message', check=check, timeout=0.5)
if int(gt.content) == int(mz):
await message.send(f'Its Right.. You Got **{j}** Points')
break
else:
await message.send(f'Its Wrong.. The Answer Is **{j}**')
except:
continue
else:
await message.send("Whoops, you're out of time! You got zero points.")
Related
im making a bot for my discord server but i have problem and my problem is this:
There is a command for the warning which is $warn and a command to remove the warnings is $clrw and another command to show the warnings is $warns but there is a problem.
When the user uses the $clrw command, it means that the variable that is accumulated during the warning becomes 0, but for all users, it means when the user use $clrw #moonboyInstead of only the desired person's warren being deleted, all people's warrens are deleted and this is a big problem!
my code:
#app.command()
# #commands.has_permissions(Warning = True)
async def warn(ctx,member: discord.Member,*,reason = None):
global num
if reason == None:
await ctx.send(f"hey {ctx.author.mention} pls enter a reason!")
else:
num += 1
# await member.send(f"hey {ctx.author.mention} you have been warned bequase {reason} from {ctx.guild.name} pls dont do it again!")
await ctx.send(f"{member} has been warned bequase {reason} ! ")
return num
#app.command()
async def clrw(ctx,member:discord.Member):
global num
num = 0
await ctx.send(f"{member} warns has been deleted!")
#app.command()
async def warns(ctx,member: discord.Member):
if num <= 0:
await ctx.send(f"{member} has no warns!")
else:
await ctx.send(f"{member} has {num} warns!")
the global variable num is not related to any particular user. If you wanted to do it per user, you could use a dictionary of their user ids.
warns = dict()
# add a warning
userid = member.id # not sure if this is exactly how to get id, check docs
if userid not in warns:
warns[userid] = 1
else:
warns[userid] += 1
# clear warnings
warns[userid] = 0
# display warnings
if warns[userid] == 0:
await ctx.send(f"{member} has no warnings")
else:
await ctx.send(f"{member} has {warns[userid]} warnings")
(This is all pseudocode to show how dicts work. This will obviously not work when pasted directly into your code)
You're lacking understanding of the variable num.
The Problem:
Atm what you are doing is, just adding and removing to the same variable or number in this case.
The code cannot know if u meant a diff user this way.
The Fix:
You should convert ur variable num to a dictionary. If the bot is gonna be for just one server then a simple dictionary should be enough.
Example:
When doing the current num +=1 replace it with num[member.id] +=1
For reset instead of num = 0 do num[member.id] = 0
For the getting of warnings, instead of num do num[member.id]
In this case u will mention who exactly u want to reset the warns for, get it from or add to.
Also don't forget to convert the current num value where u set it the first time to num = []
Hope this helps!
PS. The amount of warns will reset on bot restart, as this is a variable in the code its not saved anywhere outside. I would recommend saving it in a file or redis server.
Example code for the error in the comment:
Use this for the command where u add the warning.
The reason u got that error is that u cannot add a +1 warning to an user who is not added in the array itself.
if member.id not in num:
num[member.id] = 1
else:
num[member.id] +=1
So u don't get a similar error with the getting of the warn.
Example:
if member.id not in the num or num[member.id] == 0:
await ctx.send(f"{member} has no warns!")
else:
await ctx.send(f"{member} has {num[member.id]} warns!")
This question already has answers here:
Why does on_message() stop commands from working?
(2 answers)
Closed last year.
So I've been writing a bot using discord.py, and I've found an error I can't seem to be able to fix.
First, I have something like this:
#client.command()
async def ping(ctx):
await ctx.send("Pong!")
Then I added an entire section here:
#client.event
async def on_message(message):
# print(message)
if message.content.startswith('$random'):
if len(message.content) == 7:
await message.channel.send("**You need to provide a valid number range. Examples: *$random 7 69 | $random 69 (automatically sets the first number as 1)***")
else:
if message.content.split(" ",1)[1] == "help":
await message.channel.send("**You need to provide a valid number range. Examples: *$random 7 69 | $random 69 (automatically sets the first number as 1)***")
try:
if message.content.split(" ",2)[2] != "":
number1 = int(message.content.split(" ",2)[1])
number2 = int(message.content.split(" ",2)[2])
number2send = str(random.randint(number1,number2))
await message.channel.send("Your random number is: **" + number2send + "**")
return
except:
try:
if message.content.split(" ",1)[1] != "":
number = int(message.content.split(" ",1)[1])
number2send = str(random.randint(1,number))
await message.channel.send("Your random number is: **" + number2send + "**")
return
except:
await message.channel.send("**You need to provide a valid number range. Examples: *$random 7 69 | $random 69 (automatically sets the first number as 1)***")
return
if message.content.startswith('$timein'):
if len(message.content) == 7:
await message.channel.send("**You need to provide a valid country***")
else:
try:
lad = message.split(" ",1)[1]
print("Location address:", lad)
location = geolocator.geocode(lad)
print("Latitude and Longitude of the said address:")
print((location.latitude, location.longitude))
# pass the Latitude and Longitude
# into a timezone_at
# and it return timezone
obj = TimezoneFinder()
# returns 'Europe/Berlin'
result = obj.timezone_at(lng=location.longitude, lat=location.latitude)
print("Time Zone : ", result)
except:
return
And any command made like the first section and $timein command does not work anymore, while both worked on their own, and I have no idea why.
I feel like the errors are caused by the differences in
#client.command
and
#client.event
So this is probably what's causing the issue.
Anyways, to any kind people helping me with these, thanks in advance!
Your commands doesn't work because of on_message. What happens is you are overriding the default on_message and defaut on_message is the one that handles the commands. You can fix it by adding a bot.process_commands(message) line at the end of your on_message.
Discord.py has this issue covered on it's F.A.Q, read more here.
Also, a side note. Please don't handle commands by yourself, Discord.py's commands extension has a lot of features you probably didn't discover. Please learn more about commands, it will save tons of work from your shoulders and will be easier to develop your dream bot.
I am running something similar to a guessing game where you are given boundaries and my bot will tell you if your guess is higher or lower. I'm wondering how I would stop the user from opening multiple games? (as in, it would overlap messages and get real ugly and I want to avoid that.) Here is my code:
aliases=['gg', 'guessinggame'])
async def guessing_game(ctx, num):
number = random.randint(0, int(num))
await ctx.send("Game started!")
num_of_tries = 0
user = ctx.author.id
await ctx.send('Take a guess.')
while True:
response = await bot.wait_for('message')
currentsender = response.author.id
if currentsender != user or currentsender == bot.user.id:
continue
# if not response.content.lower().startswith('b&'):
# continue
if response.content == "stop bot pls":
await ctx.send(f'Stopped game, {response.author.mention}')
return
if not response.content.isdigit():
continue
num_of_tries += 1
guess = int(response.content)
if guess < number:
await ctx.send(f'My number is larger, {response.author.mention}.')
await ctx.send('Take a guess.')
elif guess > number:
await ctx.send(f'My number is smaller, {response.author.mention}.')
await ctx.send('Take a guess.')
else:
await ctx.send(f'Hey, {response.author.mention}, you got it! (with {num_of_tries} tries)')
return
How do you make a bot respond to a message and ask a question, like
Me:!guess 10
bot: pick a number between 1 and 10
me: 4
bot: incorrect, it was 5!
I can't figure out how to do this,
because once you respond to a command, I don't know how to have something like a global variable to save the answer.
This is some code I used, hopefully this will help, this give you 5 guesses to get it right and it gives you hints with bigger and expands on what you wanted, so you could adapt it if you don't want the bigger and smaller!
#commands.command()
async def game(self, ctx):
number = random.randint(0, 100)
for i in range(0, 5):
await ctx.send('guess')
response = await self.bot.wait_for('message')
guess = int(response.content)
if guess > number:
await ctx.send('bigger')
elif guess < number:
await ctx.send('smaller')
else:
await ctx.send('yes!')
I want my bot to edit the int(time) value sent by the user and keep editing it over a loop until it reaches 0. Here's my current code:
#bot.command()
async def settimer(ctx, time: int):
await ctx.send('Timer set for ' + str(time) + ' seconds')
if int(time) > 10:
await asyncio.sleep(time)
message = await ctx.send(str(time))
while int(time) > 0:
while int(newtime) > 0:
await asyncio.sleep(4)
newtime = int(time) - 4
await message.edit(content = str(newtime))
newtime = newtime - 4
await asyncio.sleep(4)
else:
await asyncio.sleep(time)
await ctx.send('Timer Over! ' + ctx.message.author.mention)
print ('time was less than 10')
The outer loop will infinitely loop since time never changes. The inner loop will also infinitely loop when time is > 8, since newtime is set to time in every iteration of the loop.
Also, you're sleeping 4 seconds twice in between each message edit after the first.
Additionally, the entire method is improperly indented twice, and the code inside the inner loop is improperly indented twice as well.
I'm not sure if this is intended, but you're also sleeping time seconds before the timer message is even sent.
time should already be an int, so there's no reason to cast it to int again.
You can simply use a single loop and decrement the single variable with a single sleep, e.g.:
while time > 0:
await asyncio.sleep(4)
time -= 4
await message.edit(content = str(time))
For -=, see Python's documentation on augmented assignment statements.
You might also want to look into string formatting.
Also, these are normal while loops, not "asyncio loop"s, which generally refer to event loops.