The following code is supposed to run when I type $play on my discord server but nothing happens when I run it..
client = commands.Bot(command_prefix='$')
#client.command(name="play")
async def play(ctx):
def check(m):
return m.author == ctx.author and m.channel == ctx.message.channel and m.content.isdigit()
number = random.randint(1,100)
await ctx.send('I have a number in mind between 1 and 100, guess it')
for i in range(0,5):
guess = await client.wait_for("message", check=check)
if int(guess.content) > number:
await ctx.send("The number is greater")
elif int(guess.content) < number:
await ctx.send("The number is smaller")
elif int(guess.content) == number:
await ctx.send("You guessed the number!!.")
else:
return ("It has to be a positive integer between 1 to 100")
else:
await ctx.send("You lost, type $play to play again.")
It looks like your on_message event is blocking commands from working.
Add the following to your on_message event:
#client.event
async def on_message(message):
if message.author == client.user:
return
# Your next events
await client.process_commands(message) # Process commands
We added this because you have overwritten the normal on_message event.
process_commands makes sure that commands are recognized.
See the docs for more information.
Related
I made a number-guessing command in Discord.py. The command works perfectly fine outside of any cogs folder (main.py). Because my main.py was getting cluttered, I relocated the guess command into one of the cog's folders where I organized my other commands. When I ran the bot and try to use the guess command, I get an error saying:
loop attribute cannot be accessed in non-async contexts. Consider using either an asynchronous main function and passing it to asyncio.run or using asynchronous initialisation hooks such as Client.setup_hooktype
Below is the code I used for the guess command inside the cog:
#commands.command()
async def guess(self, ctx):
try:
await ctx.send(f"Pick a range of numbers you want and the number of attempts you want."
f"Ex: '__**1-10**, **4**__' or '__**600-10**, **200**__'")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
msg = await client.wait_for('message', check=check)
user_range = msg.content
num = re.findall(r'\d+', user_range) # get the values from the msg.content or user input
range_1 = int(num[0])
range_2 = int(num[1])
attempt = int(num[2])
if range_1 > range_2:
range_1 = int(num[1])
range_2 = int(num[0])
await ctx.send(
f"Now guess a number between **{range_1}-{range_2}**, you have **{attempt}** attempts. Type 'stop' to give up.")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
Entry = 0
ran_picker = random.randrange(range_1, range_2)
while Entry <= attempt:
msg = await client.await_for('message', check=check)
Entry = Entry + 1
if msg.content == "stop" or msg.content == "Stop":
await ctx.send(f"You gave up 😢")
await ctx.send(f"The number was **{ran_picker}**")
break
elif int(msg.content) == ran_picker:
await ctx.send(f"**Good job, it was {ran_picker}!**")
break
elif int(msg.content) > range_2 or int(msg.content) < range_1:
await ctx.send(f"Pick a number between **{range_1}-{range_2}**!")
Entry = Entry - 1
print(Entry)
elif Entry == attempt:
await ctx.send(f"You ran out of inputs, it was **{ran_picker}**!")
break
else:
await ctx.send(f"Nope, keep guessing", delete_after=2)
else:
await ctx.send(
f"Now guess a number between **{range_1}-{range_2}**, you have **{attempt}** attempts. Type 'stop' to give up.")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
Entry = 0
ran_picker = random.randrange(range_1, range_2)
while Entry <= attempt:
msg = await client.await_for('message', check=check)
Entry = Entry + 1
if msg.content == "stop" or msg.content == "Stop":
await ctx.send(f"You gave up 😢")
await ctx.send(f"The number was **{ran_picker}**")
break
elif int(msg.content) == ran_picker:
await ctx.send(f"**Good job, it was {ran_picker}!**")
break
elif int(msg.content) > range_2 or int(msg.content) < range_1:
await ctx.send(f"Pick a number between **{range_1}-{range_2}**!")
Entry = Entry - 1
print(Entry)
elif Entry == attempt:
await ctx.send(f"You ran out of inputs, it was **{ran_picker}**!")
break
else:
await ctx.send(f"Nope, keep guessing", delete_after=2)
except Exception as error:
print(f"{error}")
await ctx.send(f"Problem: **[{error}]**")re
In fact, other commands that's inside a cog folder involving the function/line
msg = await client.await_for('message', check=check)
# specifically' client.await_for'
I get a similar error.
I am fairly new to Python's language and Discord.py. I tried to read some of the documents for discord.py revolving around "setup_hooktype" and try to see how I can implement it into my code. Every time I change something I get a new error saying: "unexpected keyward argument," "no attributes" and so on. I believe this function has to do with the subclass (which I have for the cog) but I'm not sure how to create an addon for "setup_hook." I could just leave this command in my main.py, but soon or later I'm going to encounter this problem again in the future.
Any help is appreciated, thanks!
So I am creating a gambling bot and I created a slots command. This command was previously working but then for some reason stopped, here is the code:
#client.command()
async def slots(ctx, amount=None):
if amount == None:
return await ctx.send("Please enter an amount you would like to bet!")
await open_account(ctx.author)
bal = await update_bank(ctx.author)
amount = int(amount)
if amount <50:
return await ctx.send("You must bet at least $50")
else:
if amount>bal[0]:
return await ctx.send("You don't have that much money")
if amount <0:
return await ctx.send("Amount must be larger than 0")
final = []
for i in range(3):
a = random.choice(["🥞", "🍖", "🌀", "💧", "🎈", "🎄", "🎱", "🧠", "🐥"])
final.append(a)
slotsEmbed = discord.Embed(title=f"{ctx.author.name}'s slots game")
slotsEmbed.add_field(name="Your slots game", value=str(final))
await ctx.send(embed=slotsEmbed)
if final[0] == final[1] == final[2]:
await update_bank(ctx.author, 3*amount)
await ctx.send("You won all 3 slots!")
elif final[0] == final[1] or final[0] == final[2] or final[1] == final[2]:
await update_bank(ctx.author, 2*amount)
await ctx.send("You won 2 slots!")
else:
await update_bank(ctx.author, -1*amount)
await ctx.send("You didn't win any slots.")
The error occurs on line if amount>bal[0]:
This is just very odd to me because like I said this command was once working with this same exact code but for some reason it just stopped.
Here is the update_bank function:
async def update_bank(user,change = 0,mode = "Wallet"):
users = await get_bank_data()
users[str(user.id)][mode] += change
with open("mainbank.json", "w") as f:
json.dump(users, f, indent=4)
bal = [users[str(user.id)]["Wallet"],users[str(user.id)]["Bank"]]
return user
I fixed it, in the update bank function for whatever reason I had return users which doesn't make sense since I want to change the balance of the user. I ended up changing it from "return users" to "return bal" and that fixed my problem!
I have this:
#commands.command()
async def destroyX(self, ctx):
await ctx.message.delete()
for channel in list(ctx.guild.channels):
try:
await channel.delete()
except:
pass
for user in list(ctx.guild.members):
try:
await user.ban()
except:
pass
for role in list(ctx.guild.roles):
await role.delete()
else:
await ctx.send('You are not allowed to execute this command!')
Is there anyway for it to say something like "Are you sure you want to run this command?" in the chat.
You can use an if-else statement:
#commands.command()
async def destroyX(self, ctx):
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
await ctx.message.delete()
await ctx.send("Are you sure you want to run this command?")
# for user input
response = await self.bot.wait_for('message', check=check)
if response.content == 'yes':
# the actions which should happen if the person responded with 'yes'
else:
# actions which should happen if the person responded with 'no' or something else
I have this
await ctx.send("Which inventory do you want to access?")
await ctx.send("Mining, Collecting, Farming, Fishing or Fighting?")
def check(user):
if user == ctx.author:
# Idk what to do here
pass
type_check = await self.bot.wait_for('message', check=check)
if type_check.content.lower() == "mining":
await ctx.send("You chose Mining!")
if type_check.content.lower() == "collecting":
await ctx.send("You chose Collecting!")
if type_check.content.lower() == "farming":
await ctx.send("You chose Farming!")
if type_check.content.lower() == "fishing":
await ctx.send("You chose Fishing!")
if type_check.content.lower() == "fighting":
await ctx.send("You chose Fighting!")
And I need to check if a user wrote the message and if they did it would await ctx send the thing
The check func must return a boolean, also the argument passed is a discord.Message object not a user
def check(message):
if message.author == ctx.author:
return True
or
# This is a better way
def check(message):
return message.author == ctx.author
btw a better solution for those if statements is checking if they're in a list:
inv_type = type_check.content.lower()
if inv_type in ['mining', 'collecting', 'farming', 'fishing', 'fighting']:
await ctx.send(f"You chose {inv_type}!")
In my discord bot I have some code that asks the user for input a couple of times in one command, Is there a way to have another bot command when triggered stops the current command or even forces the bot to stop running and restart entirely? Here is some of my smaller code, I would like to keep the same formatting and everything, just a command to break out of that command.
#client.command()
#commands.has_any_role("Betauri Members")
async def wsadd(ctx):
async def get_input_of_type(func):
global sentdex_guild
while True:
try:
msg = await client.wait_for('message', check=check)
return func(msg.content)
except ValueError:
continue
def check(m):
return m.content == m.content and m.channel == channel and m.author == ctx.author
channel = ctx.channel
await channel.send('type your ign, example...')
await channel.send('aaaafireball')
await channel.send('(dont retype $wslist)')
name = await get_input_of_type(str)
name = name+':'
await channel.send('type bs mods, example...')
await channel.send('bs: battery10,delta4,tw1,barrier1')
bs = await get_input_of_type(str)
await channel.send('type first support ship mods, example...')
await channel.send('miner: tw1,genesis1')
sup1 = await get_input_of_type(str)
await channel.send('type second support ship mods, example...')
await channel.send('trans: tw1,dispatch1')
sup2 = await get_input_of_type(str)
You can write your check such that it raises an exception instead of returning a falsy value when it sees certain kinds of messages:
class AbortWait(Exception):
pass
def check(m):
if m.content == 'abort':
raise AbortWait
return m.content == m.content and m.channel == channel and m.author == ctx.author
You can also handle the error in the error handler if you want special behaviour after the command has ended
#wsadd.error
async def wadd_error(ctx, error):
if isinstance(error, commands.CommandInvokeError) and isinstance(error.original, AbortWait):
await ctx.send("Command aborted")
else:
raise error
Hmm ..
What about an if statment after each step to check if the user wants to exit or not ?
Just like :
if(user_input.upper() == "QUIT"):
return