How to stop a discord bot from running two or more commands simultaneously - async-await

I'm making a discord bot using discord.py that plays mini-games with a user. The game is working well but while I was debugging it I found out that while the bot is waiting for input from a command and the user enters another command from the same bot, the bot executes the two commands simultaneously. Is there a way to program the bot so that when a command is made and it is currently running a command it should stop the former and execute the latter command without interfering in the games of other users. Just like the way #Pancake is made.
Below is the command for one of the mini-games (Rock, Paper, Scissors).
#bot.command(name="rps", description="Starts a rock, paper, scissors game against the computer")
async def rock_paper_scissors(ctx):
"""Play a game of Rock, Paper, Scissors against the computer"""
print("Game started!") # debug
user_dm = await bot.create_dm(ctx.author)
await user_dm.send("Enter the number of rounds")
def is_int(message):
return message.content.isdigit() and message.channel == user_dm
rounds = await bot.wait_for('message', check=is_int) # get number of rounds input from user
rounds = int(rounds.content)
human = 0
cpu = 0
for _ in range(rounds): # game loop
computer = random.choice(["rock", "scissors", "paper"])
await user_dm.send("Enter rock, paper or scissors")
def is_rps(message):
return message.content.lower() in ['rock', 'paper', 'scissors'] and message.channel == user_dm
player = await bot.wait_for('message', check=is_rps)
player = player.content
await user_dm.send(f"I chose: {computer}")
win = [('R', 'S'), ('P', 'R'), ('S', 'P')]
player, computer = player[0].upper(), computer[0].upper()
if (player, computer) in win:
await user_dm.send("You won! One Point")
human += 1
elif (computer, player) in win:
await user_dm.send("I won! One Point")
cpu += 1
else:
await user_dm.send("Nobody won! No Point")
if human > cpu:
await user_dm.send(f"You won the game! ({human} -> {cpu})")
elif cpu > human:
await user_dm.send(f"I won the game! ({cpu} -> {human})")
else:
await user_dm.send(f"Draw!!! ({cpu} -> {human})")

Related

Discord bot cooldown doesn´t work in the drop down menu

I am here to ask you for some help with my discord bot.
Everything work just a fine, but I wanted my bot to be more like gui thing instead of writing every command to chat. So I made everything to dropdown menu. Everything works, but cooldowns not.
#client.command()
#commands.cooldown(1,3600,commands.BucketType.user)
async def reuploadprace(ctx):
await open_account(ctx.author)
user = ctx.author
users = await get_bank_data()
await ctx.send(f"Přišel ti příjem z reklam od PH. Celkem {reuploadlove} € .")
users[str(user.id)]["moneybag"] += int(reuploadlove)
with open("banka.json", "w") as f:
json.dump(users, f)
#client.command()
async def vyberprace(ctx):
await ctx.send("Co dnes chceš dělat ??",
components=[
Select(placeholder="Vyber práci",
options=[
SelectOption(label="Sockovat",
value="socka",
description="Vysockuješ nějaký love na autobusáku. Sockovat můžeš jednou za 30 vteřin."),
SelectOption(label="Oprava stroje v Hamečku 🔨",
value="oprava",
description="Jedeš ve 3 ráno opravit stroj do Hamečka. Opravovat můžeš jednou za 30 minut."),
SelectOption(label="Stahovat premium videa a uploudovat to na PH 🧡🖤",
value="reupload",
description="dalčí popis není nutný. Stahovat můžeš jednou za 1 hodinu.")],
custom_id="pracevyber")])
interaction = await client.wait_for("select_option", check=lambda inter: inter.custom_id == "pracevyber")
pracevyber = interaction.values[0]
if pracevyber == "socka":
await ctx.invoke(sockovat)
if pracevyber == "reupload":
await ctx.invoke(reuploadprace)
With this code When I trigger it by using chat everything works, money added to balance and Cooldown works too. But when I trigger it from dropdown menu it add´s money, and everything, but cooldown wont start. Any experience with this ? Thanks for reading guys.. and I hope someon can help me with this trouble.
Have a nice rest of the day !

Discord.py not sending message with on_message event

So I've been working on my bot with discord.py and it's been working, but when I woke up this morning it wasn't sending any messages but it did every other function. I can't spot the error. It is supposed to respond and change member roles but only the roles change. The bot will not send the embed in the chat. The error is in the image. If anyone is able to find my error it would be greatly appreciated.
if "sign" in message.content:
if message.channel.id == 920821651627712514:
signer=message.author
signee=message.mentions[0].mention
signeeid=message.mentions[0].id
server=bot.get_guild(920821650096812063)
teamsidslist=[920821650180694104]
teamnames=['Philadelphia Eagles']
teamemojis=['AFREagles']
FO = discord.utils.get(message.author.guild.roles, id=920821650285539374)
GM = discord.utils.get(message.author.guild.roles, id=920821650285539373)
HC = discord.utils.get(message.author.guild.roles, id=920821650285539372)
staffroles = [FO, GM, HC]
FA = discord.utils.get(message.author.guild.roles, id=920821650180694097)
Suspended = discord.utils.get(message.author.guild.roles, id=920821650159702055)
roster=[]
agency=[]
teams=[]
for rolesids in message.author.roles:
if rolesids.id in teamsidslist:
teams.append(rolesids.id)
step2=str(teams)
step3=step2.replace("[","")
step4=step3.replace("]","")
print(step4)
step5=teamsidslist.index(int(step4))
print(step5)
emote=discord.utils.get(server.emojis,name=teamemojis[step5])
teamname=teamnames[step5]
team = discord.utils.get(message.author.guild.roles,id=int(step4))
for agents in server.members:
if FA in agents.roles:
agency.append(agents.id)
if signeeid not in agency:
embedno = discord.Embed(title="Transaction Failed!", description=None, color=discord.Color.red())
embedno.add_field(name="This Transaction Couldn't Be Completed.", value="This player is signed already! Have them demand from their team or get released.")
await message.channel.send(embed=embedno)
elif FO in message.author.roles:
for guys in server.members:
if guys.id==signeeid:
await guys.add_roles(team)
await guys.remove_roles(FA)
if Suspended in guys.roles:
await message.channel.send("This player is signable, but is ineligible as they are suspended.")
roster.append(guys)
roster_size=str(len(roster))
SignEmbed= discord.Embed(title="AFR Transactions", description=None, color=discord.Color.green())
SignEmbed.add_field(name='Successful Transaction.', value=signee+" has been signed to the "+str(emote)+" "+teamname+" by "+signer+"!")
SignEmbed.add_field(name="Roster Size is now ", value=roster_size+'/24', inline=True)
await message.channel.send(embed=SignEmbed)
await bot.process_commands(message)
The signer variable is a discord.Member object and you can't concatenate discord.Member to string, i.e (discord.Member + "some string")
also concatenation makes code unreadable and are slow as well. Use f-strings instead.
here is an example:
nice = 3
some_variable = "one two " + str(nice) + " we continue"
print(some_variable)
>>> one two 3 we continue
nice = 3
some_variable = f"one two {nice} we continue"
print(some_variable)
>>> one two 3 we continue
For your issue, just cast signer as string, i.e str(signer)
but I do highly recommend for you to switch to f-strings instead of using concatenation

Getting input from reactions not working discord.py

I wanted to make a rock paper scissor game for my bot:
The bot creates an embed with instructions and reacts with a "rock", "paper", and "scissor" emoji, which the user has to click to input his/her choice.
But the problem is that the code doesn't go any further and shows an error.
Here is the code:
#client.command(aliases = ["rock_paper_scissors","rps"])
async def _rps(ctx): #rps is short for rock, paper, scissor
emojis = ['✊', '🖐️', '✌️']
embedVar = discord.Embed(title="CHOOSE YOUR WEAPON!",description = "Choose between rock, paper, or scissors, {}." . format(ctx.author.mention), color = 0xff9900)
embedVar.add_field(name=":fist: ROCK", value="React with :fist: emoji to choose rock.", inline = False)
embedVar.add_field(name=":hand_splayed: PAPER", value="React with :hand_splayed: emoji to choose paper.", inline = False)
embedVar.add_field(name=":v: SCISSORS", value="React with :v: emoji to choose scissors.", inline = False)
emb = await ctx.send(embed = embedVar)
for emoji in emojis:
await emb.add_reaction(emoji)
def chk(reaction):
return reaction.emb == emb and reaction.channel == ctx.channel
react = await client.wait_for('reaction_add', check=chk)
if react == '✊':
await ctx.send("You chose rock!")
elif react == '🖐️':
await ctx.send("You chose paper!")
elif react == '✌️':
await ctx.send("You chose scissors!")
I am getting this error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: chk() takes 1 positional argument but 2 were given
I tried many fixes but in vain.
Also, I want the bot to accept the input only from the user who had asked for the rock paper scissor game by the command in the first place (the author of the message, in other words), But I am not sure how to implement that, I tried, but it did not work.
How can I fix this?
reaction_add gives a tuple of a reaction and a user so in the chk function you need to have both the reaction and user. You should also use and user == ctx.author within the chk function to ensure the user is the same.
#client.command(aliases = ["rock_paper_scissors","rps"])
async def _rps(ctx): #rps is short for rock, paper, scissor
emojis = ['✊', '🖐️', '✌️']
embedVar = discord.Embed(title="CHOOSE YOUR WEAPON!",description = "Choose between rock, paper, or scissors, {}." . format(ctx.author.mention), color = 0xff9900)
embedVar.add_field(name=":fist: ROCK", value="React with :fist: emoji to choose rock.", inline = False)
embedVar.add_field(name=":hand_splayed: PAPER", value="React with :hand_splayed: emoji to choose paper.", inline = False)
embedVar.add_field(name=":v: SCISSORS", value="React with :v: emoji to choose scissors.", inline = False)
emb = await ctx.send(embed = embedVar)
for emoji in emojis:
await emb.add_reaction(emoji)
def chk(reaction, user):
return reaction.emb == emb and reaction.channel == ctx.channel and user == ctx.author
react, user = await client.wait_for('reaction_add', check=chk)
if react == '✊':
await ctx.send("You chose rock!")
elif react == '🖐️':
await ctx.send("You chose paper!")
elif react == '✌️':
await ctx.send("You chose scissors!")

Trying to make a kind of pls dep all or pls dep max kind of thing

I'm making a currency bot but I can't seem to figure out how to do something like: [prefix] deposit all/[prefix] withdraw all or [prefix] deposit max/[prefix] withdraw max but I can't seem to figure out how to do it. This is my code so far for deposit:
#client.command()
async def dep(ctx, amount=0):
users = await get_bank_data()
user = ctx.author
if amount > 0:
users[str(user.id)]['wallet'] -= amount
users[str(user.id)]['bank'] += amount
with open("mainbank.json", "w") as f:
json.dump(users, f)
await ctx.send(f"You have deposited {amount} coins!")
elif amount < 0:
await ctx.send(f"You can't deposit a negative amount of coins stupid!")
elif amount == 0:
await ctx.send(f"You can't deposit 0 coins stupid!")```
You can simply use the in keyword to check if the amount arg is either max or all, to check if it's a digit use str.isdigit()
async def dep(ctx, amount: str):
if amount.lower() in ["max", "all"]:
# Deposit all the money here
elif amount.isdigit() and int(amount) > 0:
amount = int(amount)
# The `amount` variable is now a positive integer, deposit it here
You can do the withdraw command on the same basis

discord.py rewrite | Problem with getting author message

I've been making a number game command in my server, and someone recommended I add difficulties. So, I have 3 difficulties for the user to chose from.
I have already got a bit of code which got the author's response and worked, so I re-used it in my code, and now I am stumped. It may be glaringly obvious, but I cannot find it:
#client.command(name='numgame',
brief='Guess a number between 1 and 100',
pass_ctx=True)
async def numgame(ctx):
if ctx.author.id != 368442355382222849:
await ctx.send('Command currently disabled')
return
await ctx.send('Difficulties: a] 1-10 b] 1-50 c] 1-100')
msg = await client.wait_for('message', check=check(ctx.author), timeout=30)
diff = str(msg.content)
if diff == 'a':
max = 10
number = random.randint(1,10)
await ctx.send('You have 5 guesses')
await ctx.send('Pick a number between 1 and 10')
elif diff == 'b':
max = 50
number = random.randint(1,50)
await ctx.send('You have 5 guesses')
await ctx.send('Pick a number between 1 and 50')
elif diff == 'c':
max = 100
number = random.randint(1,100)
await ctx.send('You have 5 guesses')
await ctx.send('Pick a number between 1 and 100')
else:
ctx.send('Please try the command again...')
return
msg = None
This is the check I am using:
def check(author):
def inner_check(message):
# author check
if message.author != author:
return False
# inner check
try:
int(message.content)
return True
except ValueError:
return False
When I respond to the bot in-chat with "a", "b" or "c", I get no response.
I disabled the command for everyone but me whilst I tried to fix it, but I have no idea how to start.
I would appreciate an answer, as I don't see the solution myself, thanks!
[I didn't show the actual number game, because it is irrelevant and long]
Just create a new check function that does what you want.
def abc_check(author):
def inner_check(message):
return author == message.author and message.content in ('a', 'b', 'c')
return inner_check

Resources