how to make a roll dice simulator [duplicate] - python

Hello guys i'm coding a Discord bot in Python and i wanted to code a roll dice command. And i think im doing something wrong. Here is the code:
#client.command()
async def rolldice(ctx):
dice4 = ["1","2","3","4"]
dice6 = ["1","2","3","4","5","6"]
dice8 = ["1","2","3","4","5","6","7","8"]
dice10 = ["1","2","3","4","5","6","7","8","9","10"]
dice12 = ["1","2","3","4","5","6","7","8","9","10","11","12"]
dice20 = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]
message = await ctx.send("Choose a number:\n**4**, **6**, **8**, **10**, **12**, **20** ")
def check4(m):
return m.author == ctx.author and m.content == "4"
try:
await client.wait_for('message', check=check4, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice4)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
def check6(m):
return m.author == ctx.author and m.content == "6"
try:
await client.wait_for('message', check=check6, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice6)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
def check8(m):
return m.author == ctx.author and m.content == "8"
try:
await client.wait_for('message', check=check8, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice8)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
def check10(m):
return m.author == ctx.author and m.content == "10"
try:
await client.wait_for('message', check=check10, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice10)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
def check12(m):
return m.author == ctx.author and m.content == "12"
try:
await client.wait_for('message', check=check12, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice12)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
def check20(m):
return m.author == ctx.author and m.content == "20"
try:
await client.wait_for('message', check=check20, timeout=30.0)
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.choice(dice20)}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't answer in **30** second!")
When i type the command and select number 4 my command does works but when i try another number, for an example 6, it doesn't work. What am i doing wrong? Please help.

That's because it checks for 4 first, then 6, and so on... Even after you send 4, it'll check for 6, 8 and so on.. And when you send 6, it'll check for 4 first, then 6 and so on.. Why don't you try something like this instead:
#client.command()
async def rolldice(ctx):
message = await ctx.send("Choose a number:\n**4**, **6**, **8**, **10**, **12**, **20** ")
def check(m):
return m.author == ctx.author
try:
message = await client.wait_for("message", check = check, timeout = 30.0)
m = message.content
if m != "4" and m != "6" and m != "8" and m != "10" and m != "12" and m != "20":
await ctx.send("Sorry, invalid choice.")
return
coming = await ctx.send("Here it comes...")
time.sleep(1)
await coming.delete()
await ctx.send(f"**{random.randint(1, int(m))}**")
except asyncio.TimeoutError:
await message.delete()
await ctx.send("Procces has been canceled because you didn't respond in **30** seconds.")
Note: I recommend using await asyncio.sleep(1) instead of time.sleep(1). That way other commands will still be functional. Remember to import asyncio in this case.

Related

<coroutine object Messageable.send at 0x00000228114ADE00> error

I'm just code a bot its ask before kick and ban and its have an error:
<coroutine object Messageable.send at 0x00000228114ADE00>
The message to kick is:
!bot/kick #user
Code(the part make it error):
#bot.command()
#commands.has_permissions(manage_messages = True, administrator = True)
async def kick(ctx,self, member : discord.Member, *, reason=None):
message = ctx.send(f"Are you sure to kick {member.mention}(Timeout 20 seconds)")
await ctx.send(message)
await message.add_reaction(":thumbsup:")
await message.add_reaction(":thumbsdown:")
check = lambda r, u: u == ctx.author and str(r.emoji) in ":thumbsup::thumbsdown:"
try:
reaction, user = await self.bot.wait_for("reaction_add", check=check, timeout=20)
except asyncio.TimeoutError:
await message.edit(content="Kick cancelled, timed out.")
return
if str(reaction.emoji) == ":thumbsup:":
await member.ban()
await message.edit(content=f"{member.mention} has been kicked.")
await member.kick(reason=reason)
return
elif str(reaction.emoji) == ":thumbsdown:":
await message.edit(content=f"Kick has been cancelled")
return
await message.edit(content="Kick cancelled.")

Bot is not responding to the input given (Discord.py)

I watched a tutorial on how to get Input from users in Discord.py. The bot however, does not respond to the input given to it.
The bot sends the "This is a bot test. Type (YES/NO)" message. But when I type "yes" or "no" it does not respond.
#client.command()
async def bot(ctx):
await ctx.channel.send("This is a bot test. Type (YES/NO)")
try:
message = await bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=30.0)
except asyncio.TimeoutError:
await ctx.channel.send("I have been ignored")
else:
if message.content.lower() == "yes":
await ctx.channel.send("The test was succesfull!")
elif message.content.lower() == "no":
await ctx.channel.send("Thank you for your response")
else:
await ctx.channel.send("I cannot understand you")
You're decorating with client but calling bot in your function.
Change
#client.command()
async def bot(ctx):
await ctx.channel.send("This is a bot test. Type (YES/NO)")
try:
message = await bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=30.0)
To
#client.command()
async def bot(ctx):
await ctx.channel.send("This is a bot test. Type (YES/NO)")
try:
message = await client.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=30.0)

How to make a Discord.Py random reaction game

How can I make the bot choose a right random answer (as a reaction)
And if the user gets it right send a winner message
if its wrong send a loser message.
redcrew = '<:redcrewmates:776867415514153031>'
bluecrew = '<:bluecrewmates:776867439085617153>'
limecrew = '<:limecrewmates:776867489866711041>'
whitecrew = '<:whitecrewmates:776867529900425217>'
await msg1.add_reaction(redcrew)
await msg1.add_reaction(bluecrew)
await msg1.add_reaction(limecrew)
await msg1.add_reaction(whitecrew)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) ==
try:
reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await ctx.send('Sorry, you took too long to vote!')
else:
await ctx.send('hello')
def setup(bot):
bot.add_cog(games(bot))```
**DONT WORRY ABOUT THE INDENTS**
import random
#bot.command()
async def reaction_game(ctx):
reactions = [
'<:redcrewmates:776867415514153031>',
'<:bluecrewmates:776867439085617153>',
'<:limecrewmates:776867489866711041>',
'<:whitecrewmates:776867529900425217>'
]
winning_reaction = random.choice(reactions)
message = await ctx.send('some message')
for reaction in reactions:
await ctx.add_reaction(reaction)
def check(reaction, user):
return user == ctx.author and str(reaction) == winning_reaction
try:
reaction, user = await bot.wait_for('reaction_add', check=check, timeout=60.0)
await ctx.send('You reacted with the winning emoji')
except asyncio.TimeoutError:
await ctx.send('You took too long to react')
else:
await ctx.send('hello')

How to stop a command during execution discord.py

#client.command()
async def spam(ctx):
while True:
time.sleep(2)
await ctx.send("spam")
#client.event
async def on_message(message):
if message.content == "!stop":
# stop spamming
I want the code to stop spamming but I'm not sure how.
Try this example using wait_for:
#client.command()
async def spam(ctx):
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
stopped = False
await ctx.send("spam")
while not stopped:
try:
message = await client.wait_for("message", check=check, timeout=2)
stopped = True if message.content.lower() == "!stop" else False
except asyncio.TimeoutError: # make sure you've imported asyncio
await ctx.send("spam")
await ctx.send("spam finished!")
References:
Client.wait_for()
Message.author
Message.channel

How to cancel a pending wait_for

Assuming a command similar to this:
#bot.command()
async def test(ctx):
def check(r, u):
return u == ctx.message.author and r.message.channel == ctx.message.channel and str(r.emoji) == '✅'
await ctx.send("React to this with ✅")
try:
reaction, user = await bot.wait_for('reaction_add', timeout=300.0, check=check)
except asyncio.TimeoutError:
await ctx.send('Timeout')
else:
await ctx.send('Cool, thanks!')
Is there any way to cancel that wait_for if the user sends the same command multiple times before actually reacting to the message? So the bot stop waiting for reactions on previously sent messages and only waits for the last one.
Would something like this work for you?
pending_tasks = dict()
async def test(ctx):
def check(r, u):
return u == ctx.message.author and r.message.channel == ctx.message.channel and str(r.emoji) == '✅'
await ctx.send("React to this with ✅")
try:
if ctx.message.author in pending_tasks:
pending_tasks[ctx.message.author].close()
pending_tasks[ctx.message.author] = bot.wait_for('reaction_add', timeout=300.0, check=check)
reaction, user = await pending_tasks[ctx.message.author]
except asyncio.TimeoutError:
await ctx.send('Timeout')
else:
await ctx.send('Cool, thanks!')
You store all of the pending requests in a dict, and before creating another request you check if you are already have an existing task for this user, if you do you cancel it and create a new one

Categories