discord.py adding mentioned users to list - python

I want to make disposable register system by using list which makes adding the discord user to list when you mentioned it but when i try to get user input from message it fails
#bot.command()
async def gameset(ctx,playernum:int):
if playernum <= 10:
await ctx.send('player 1 "<assign #player" mention yourself like this!')
else:
await ctx.send('maximum 10 player!')
num = 1
while num < playernum:
playerlist = []
#bot.command()
async def assign(user):
if user == discord.User.mentioned_in(message=user):
listadd = user
playerlist.append(listadd)
await user.send(f"player {num + 1} mention yourself!")
elif user != discord.User:
await user.send("not user")
else:
await user.send("go fix it dumb")
if playerlist[num - 1] == discord.User:
num = num + 1
else:
await gameset.send("problem with the listing")
also i think this is not the only problem i tried like this too but then my mention/user percaption logic failed i think
#bot.command()
async def ata(user : discord.User):
if not user:
await user.send("go fix it dumb")
else:
listadd = user
playerlist.append(listadd)
await user.send(f"player {num + 1} mention yourself!")
I've tried with #bot.event but i made more progress with #bot.command so if this is able to do with #bot.event i would be pleased if you guys help me understand how can i do with event but command is sufficient too.
Edit: I tried using wait_for() command like this:
num = 1
while num < playernum:
playerlist = []
def check(msg2 : discord.member):
return msg2 == discord.mentions
msg2 = await bot.wait_for("message", check=check)
# player = await bot.fetch_member(msg2.id)
if msg2 == discord.member:
player = str(msg2.id)
listadd = player
playerlist.append(listadd)
await ctx.send(f"player {num + 1} mention yourself!")
num = num + 1
else:
await msg2.send("go fix it dumb")
and i think it worked but now i have another problem which is
discord.ext.commands.errors.CommandNotFound: Command "#!id>" is not found
i get this when i try to mention someone

Related

client.await_for unresponsive In a Loop Under Cogs Folder | Discord.py

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!

Using multiple values for one parameter in a command in discord.py

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

Discord.py bot.wait_for

#commands.command()
async def verify(self, ctx, length=10):
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
print("done")
if verify_msg == answer:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Im trying to do a verify system, but after the bot.wait_for task nothing happens, i guess something in the line is wrong, has anybody solutions?
If you want it to be a dm command we can use the restriction #commands.dm_only()
However we then also have to check where the answer was given, we do that via some kind of custom check. I have modified your command a bit, but you can make the changes again personally.
Take a look at the following code:
#commands.dm_only() # Make it a DM-only command
#commands.command()
async def verify(self, ctx, length=10):
def check(m):
return ctx.author == m.author and isinstance(m.channel, discord.DMChannel)
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number: {verify_msg}")
try: # Try to get the answer
answer = await bot.wait_for("message", check=check)
print(answer.content)
if verify_msg == answer.content:
await ctx.author.send("Verified!")
else:
await ctx.author.send("Verify again!")
except: # Used if you for example want to set a timelimit
pass
Edited to show full answer.
Hey ho done it lol.
Basically the message object contains a lot of data, so you need to pull the content of the message using answer.conent.
https://discordpy.readthedocs.io/en/latest/api.html?highlight=message#discord.Message.content for reference
#bot.command()
async def verify(ctx):
length=10
verify_characters = []
for _ in range(length):
verify_characters.append(random.choice(string.ascii_letters + string.digits + "!§$%&/()=?`-.<>"))
verify_msg = "".join(verify_characters)
print(verify_msg)
await ctx.author.send(f"Verify with the number {verify_msg}")
answer = await bot.wait_for('message')
print(answer.content)
print("done")
if verify_msg == answer.content:
await ctx.author.send("Verified")
else:
await ctx.author.send(f"Verify again!")
Give that a test run and let me know what happens ;)

Discord.py getting unexpected parentheses in output

This is my discord.py bot. When I type m!rate (person) It sends me a text like this. However, I don't want the (' and ',) at the beginning and end of the message.
This is my code:
#client.command()
async def rate(ctx, *member):
if len(member) == 0:
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member} {value}/10")
When I change it, the message works but the error doesn't. I can't find any solution.
Using * in a parameter makes the function pass positional arguments into a tuple, hence the brackets. This is usually for when you want to unpack an arbitrary amount of arguments.
To fix it, just remove *, and also add a type for the parameter if you want:
#client.command()
async def rate(ctx, member: discord.Member = None): # setting a default value of None
if not member: # testing to see if the default value is None
await ctx.send("You forgot to mention someone")
else:
value = random.randint(1,10)
await ctx.send(f"I rate {member.mention} {value}/10")
References:
Using * in Python
discord.Member
Member.mention
If you want your bot to mention one person per command :
#client.command()
async def rate(ctx, *member):
if member:
"".join(member)
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
await ctx.send(f"I rate {user.mention} {value}/10")
else:
await ctx.send("Member not found!")
else:
await ctx.send("You forgot to mention someone")
If you want your bot to mention multiple people per command :
#client.command()
async def rate(ctx, *members):
if members:
embed = Discord.embed(color = discord.color.blue(), title = "title")
count = 0
for member in members:
value = random.randint(1,10)
for user in ctx.guild.members:
if user.name.lower() == member.lower() or user.nick.lower() == member.lower():
embed.add_field(name = f"{user.mention}", value = f"I rate him {value}/10")
count += 1
if count != 0:
await ctx.send(embed=embed)
else:
await ctx.send("Members not found!")
else:
await ctx.send("You forgot to mention someone")

how do you convert a python code that requires user input to work in a discord bot?

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

Categories

Resources