trying to make a nice embed for my diceroll command to output to but my issue is that the embed keeps just displaying raw value rather than the int value i'm trying to get (image for reference bellow) i’ve tried to find workarounds or solutions online but cant find anything that works or is specific to my issue
#bot.command()
async def rolldice(ctx):
messagetwo = await ctx.send("Choose a number:\n**4**, **6**, **8**, **10**, **12**, **20** ")
user = ctx.message.author.display_name
def check(m):
return m.author == ctx.author
try:
messageone = await bot.wait_for("message", check = check, timeout = 30.0)
m = messageone.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...")
asyncio.sleep(1)
await coming.delete()
await messagetwo.delete()
await ctx.channel.purge(limit=2)
embedVar = discord.Embed(title="{user}'s Dice",color=0x00ffff)
embedVar.add_field(name="rolled", value="D{m}", inline=True)
embedVar.add_field(name="landed", value="{random.randint(1, int(m))}", inline=True)
embedVar.set_footer(text='Booty Police | Dungeon Dice',icon_url="http://canvaswrite.com/PI/pybot/attachments/server-icon-full.png")
await ctx.send(embed=embedVar)
await ctx.send(f"{user} rolled a **D{m}** and got a **{random.randint(1, int(m))}**")
except asyncio.TimeoutError:
await messageone.delete()
await ctx.send("Procces has been canceled because you didn't respond in **30** seconds.")
I think you are trying to use f-string but forgot to place the f before the string. Without the f it will not format the string. Here's a guide on f-strings if you want to read more about them
x = 3
print(f"This is the value {x}")
>>> This is the value 3
so in order for your code to work you need to just prepend the string with an f. the fixed code would look something like this:
#bot.command()
async def rolldice(ctx):
messagetwo = await ctx.send("Choose a number:\n**4**, **6**, **8**, **10**, **12**, **20** ")
user = ctx.message.author.display_name
def check(m):
return m.author == ctx.author
try:
messageone = await bot.wait_for("message", check = check, timeout = 30.0)
m = messageone.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...")
asyncio.sleep(1)
await coming.delete()
await messagetwo.delete()
await ctx.channel.purge(limit=2)
embedVar = discord.Embed(title=f"{user}'s Dice",color=0x00ffff)
embedVar.add_field(name="rolled", value=f"D{m}", inline=True)
embedVar.add_field(name="landed", value=f"{random.randint(1, int(m))}", inline=True)
embedVar.set_footer(text='Booty Police | Dungeon Dice',icon_url="http://canvaswrite.com/PI/pybot/attachments/server-icon-full.png")
await ctx.send(embed=embedVar)
await ctx.send(f"{user} rolled a **D{m}** and got a **{random.randint(1, int(m))}**")
except asyncio.TimeoutError:
await messageone.delete()
await ctx.send("Procces has been canceled because you didn't respond in **30** seconds.")
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!
I am currently trying to code a quiz bot in discord, and right now I want to find a way to have my bot pull a random question from specific parameters. I'm not so sure this was the right way to phrase it, but here is my code:
#client.command()
async def ask1(ctx , q):
quiz_data = {
'question1' : (["1" , "one"] , "one") ,
'question2' : (["2" , "two"] , "two") ,
}
questionp1 = random.choice(list(quiz_data.keys()))
answersp1 , hintp1 = quiz_data[questionp1]
quiz_data1 = {
'question3' : (["3" , "three"] , "three") ,
'question4' : (["4" , "four"] , "four")
}
questionp2 = random.choice(list(quiz_data1.keys()))
answersp2 , hintp2 = quiz_data1[questionp2]
global var
if var == 0:
var = 1
if q == "1":
await ctx.send("What is the answer to this question?")
await asyncio.sleep(1)
await ctx.send(questionp1)
def check_sender(msg):
return msg.channel == ctx.channel
def check_answer(msg):
return any(answer in msg.content.lower() for answer in answersp1)
try:
async with timeout(10):
while var == 1:
msg = await client.wait_for('message', check=check_sender)
if check_answer(msg):
await ctx.send("Well done.")
var = 0
break
else:
print(msg.content)
except asyncio.TimeoutError:
if var != 1:
var = 0
else:
await ctx.send(f"What is the answer to this question? hint: {hintp1}")
await ctx.send(questionp1)
try:
async with timeout(5):
while var == 1:
msg = await client.wait_for('message', check=check_sender)
if check_answer(msg):
await ctx.send("Well done.")
var = 0
break
else:
print(msg.content)
except asyncio.TimeoutError:
await ctx.send("No one got it right.")
var = 0
elif q == "2":
await ctx.send("What is the answer to this question?")
await asyncio.sleep(1)
await ctx.send(questionp2)
def check_sender(msg):
return msg.channel == ctx.channel
def check_answer(msg):
return any(answer in msg.content.lower() for answer in answersp2)
try:
async with timeout(10):
while var == 1:
msg = await client.wait_for('message', check=check_sender)
if check_answer(msg):
await ctx.send("Well done.")
var = 0
break
else:
print(msg.content)
except asyncio.TimeoutError:
if var != 1:
var = 0
else:
await ctx.send(f"What is the answer to this question? hint: {hintp2}")
await ctx.send(questionp2)
try:
async with timeout(5):
while var == 1:
msg = await client.wait_for('message', check=check_sender)
if check_answer(msg):
await ctx.send("Well done.")
var = 0
break
else:
print(msg.content)
except asyncio.TimeoutError:
await ctx.send("No one got it right.")
var = 0
else:
await ctx.send("A round has already begun.")
This is the concept that I'm currently using. The command $ask1 1 and $ask1 2 are working fine, but I want the user to have a choice to put $ask1 q:1,2 or something like that, which the bot then pulls a question from either the first quizdata set or the second. Note that this whole code is working well and is executed without any errors. I've been racking my brain for a few days and I think to do this I should be using keyword args instead of positional args, but I'm not entirely sure nor do I know how to apply the concept of kwargs properly in this situation. The vars are necessary for a different command btw, a stop command, so you don't have to pay attention to it.
Sorry if this is hard to understand, I'll be willing to answer any questions to make this more clear. Any answer wil be appreciated, thanks!
You can just use random lib,here is the documentation https://docs.python.org/3/library/random.html. What I was thinking you could at first generate random number between 1 and 2 if the random number is 1 you would go to quiz data if 2 to quiz data2 and then generate another random number between 1 and to and that would indicate which question from this quiz data would be used
I am doing a giveaway command call =gstart <time> <prize and the giveaway will be held in the channel I use this command and After sending the embed giveaway message it will delete the gstart command. Here is the code:
#bot.command()
async def gstart(ctx,time,*,prize):
time = convert(time)
if time == -1:
await ctx.send("Error, can't identify time unit")
if time == -2:
await ctx.send("Error, can't identify time value")
embed = discord.Embed(title=prize, description = f"React with :tada: to enter\nHosted by: {ctx.author.mention}", color=discord.Color.red())
embed.set_footer(text = f"Ends at {time} from now!")
#delete-command
await ctx.send(":tada: **GIVEAWAY** :tada:")
my_msg = await ctx.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await ctx.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await ctx.send(f"Congratulations {winner.mention}! You won the {prize}!")
msg_link = my_msg.jump_url
winner_embed = discord.Embed(title=f"Hey {winner}",description=f"You just won a [giveaway]({msg_link}) in {ctx.guild}",color=discord.Color.red())
winner_embed.add_field(name=prize,value=f"Hosted by: {ctx.author.mention}",inline=True)
await winner.send(embed=winner_embed)
By the way the convert() function looks like this:
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d" : 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
Reply you with the discord.Context object and delete the message user sent.
Example:
import asyncio
#bot.command()
async def deleteCommandAfterSent(ctx):
await ctx.send("blablabla ") #REPLY MESSAGE
await asyncio.sleep(1)
await ctx.message.delete()
So I was making a work command, and I needed some help. The bot was not responding unless I put my id into the json file instead of the bot doing it automatically. I don't get any error either. Again, it only works unless I manually put the id into the json file.
Here's the code:
youtuber = {}
def youtube():
global youtuber
try:
with open ('youtuber.json', "a") as f:
youtuber = json.load(f)
except FileNotFoundError:
print("File not found")
developer = {}
def developing():
global developer
try:
with open('developer.json', "a") as f:
developer = json.load(f)
except FileNotFoundError:
print("Error")
scientist = {}
def science():
global scientist
try:
with open('scientist.json', "a") as f:
scientist = json.load(f)
except FileNotFoundError:
print("Error")
#commands.command()
async def work(self, ctx):
await open_account(ctx.author)
#Variables
salary = 2000
id = str(ctx.author.id)
#If user is unemployed :laughard:
if id not in developer and scientist and youtuber:
await ctx.send("Your unemployed, You can work as a `developer` or a `scientist` or a `youtuber` or a `doctor`. Pick one.\n\nNote: All jobs have the same amount of salary")
message = await self.bot.wait_for('message', check = lambda: message.author == ctx.author)
#Developer
if message.content == "developer":
developer[id] = 1
with open('developer.json', 'a') as f:
json.dump(developer, f)
await ctx.send("Congratualations! You now work as a developer!")
return
#youtuber
elif message.content == "youtuber":
youtuber[id] = 1
with open('scientist.json', 'a') as f:
json.dump(scientist, f)
await ctx.send("Congratualations! You now work as a youtuber!")
return
#scientist
elif message.content == "scientist":
scientist[id] = 1
with open('youtuber.json', 'a') as f:
json.dump(youtuber, f)
await ctx.send("Congratualations! You now work as a scientist!")
return
#Dev work
elif id in developer:
dev_work = ["Type the following: `Python is the best. Everything else is trash.`", "Type the following: `Time to steal some code.`", "Answer the following question: `Which is the best bot in the world?`"]
rand_dev = random.choice(dev_work)
await ctx.send(rand_dev)
message = await self.bot.wait_for('message', check=lambda : message.author == ctx.author)
if rand_dev == dev_work[0]:
if message.content == "Python is the best. Everything else is trash.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? You get 0 coins")
return
elif rand_dev == dev_work[1]:
if message.content == "Time to steal some code.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? Dumb")
return
elif rand_dev == dev_work[2]:
if message.content == "LeBot":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("It's LeBot......")
return
#Youtube work
elif id in youtuber:
youtuber_work = ["Type the following: `I wish I had 100mil sub's like pewdiepie.`", "Type the following: `The Hair Trilogy is the best trilogy to ever exist.`", "Type the following: `Papa Franku please come back.`"]
rand_youtube = random.choice(youtuber_work)
await ctx.send(rand_dev)
message = await self.bot.wait_for('message', check=lambda : message.author == ctx.author)
if rand_youtube == youtuber_work[0]:
if message.content == "I wish I had 100mil sub's like pewdiepie.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? Dumb")
return
elif rand_youtube == youtuber_work[1]:
if message.content == "The Hair Trilogy is the best trilogy to ever exist.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? Dumb")
return
elif rand_youtube == youtuber_work[2]:
if message.content == "Papa Franku please come back.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly?")
return
#scientist work
elif id in scientist:
science_work = ["Type the following: `I wonder if waterproof spray can make me walk on water.`", "Type the following: `Don't trust atoms! They make everything up!`", "Type the following: `No I'm not Elon Musk, I can't make a rocket land by itself.`"]
rand_science = random.choice(science_work)
await ctx.send(rand_science)
message = await self.bot.wait_for('message', check=lambda : message.author == ctx.author)
if rand_science == science_work[0]:
if message.content == "I wonder if waterproof spray can make me walk on water.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? Dumb")
return
elif rand_science == science_work[1]:
if message.content == "Don't trust atoms! They make everything up!":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly? Dumb")
return
elif rand_science == science_work[2]:
if message.content == "No I'm not Elon Musk, I can't make a rocket land by itself.":
await ctx.send("You have earned 2000 coins!")
else:
await ctx.send("You can't even type a sentence properly?")
return
Any help will be appreciated!
So I have a piece of code and it requires user input multiple times (and what is inputed is not alway the same). Instead of passing the code to everyone in my discord I would like to make it directly into a discord bot so everyone can use it. How do I all the bot to take in a user msg after a code is given
here is an example of kinda what I want:
-.botcalc
--this is discord bot, enter first number:
-1
--enter second number:
-2
--1+2 = 3
There are two ways you could write this command: one is using the "conversation" style in your question
from discord.ext.commands import Bot
bot = Bot("!")
def check(ctx):
return lambda m: m.author == ctx.author and m.channel == ctx.channel
async def get_input_of_type(func, ctx):
while True:
try:
msg = await bot.wait_for('message', check=check(ctx))
return func(msg.content)
except ValueError:
continue
#bot.command()
async def calc(ctx):
await ctx.send("What is the first number?")
firstnum = await get_input_of_type(int, ctx)
await ctx.send("What is the second number?")
secondnum = await get_input_of_type(int, ctx)
await ctx.send(f"{firstnum} + {secondnum} = {firstnum+secondnum}")
The second is to use converters to accept arguments as part of the command invocation
#bot.command()
async def calc(ctx, firstnum: int, secondnum: int):
await ctx.send(f"{firstnum} + {secondnum} = {firstnum+secondnum}")
Using wait_for
async def botcalc(self, ctx):
author = ctx.author
numbers = []
def check(m):
return m.author == author
for _ in ('first', 'second'):
await ctx.send(f"enter {_} number")
num = ""
while not num.isdigit():
num = await client.wait_for('message', check=check)
numbers.append[int(num)]
await channel.send(f'{numbers[0]}+{numbers[1]}={sum{numbers)}')
edit
Added a check