Check which reaction a user picked [Discord.py] - discord.py

This should be fairly simple and I've been trying what I've googled but no luck. All I want to do is send a message regarding which emoji had more reactions. But nothing is being sent out.
#bot.event
async def on_message(message):
if 'aoe2' in message.content and message.channel.id == 1048127088688889866:
BlueEmbed = discord.Embed(title='AOE Lobby',
description='**Lobby Link:** ' + '<' +
str(message.content) + '>',
colour=discord.Colour.blue())
message = await message.channel.send(embed=BlueEmbed)
await message.add_reaction('❤️')
await message.add_reaction('💙')
msg = await message.channel.fetch_message(message.id)
highest_reaction = ""
highest_reaction_number = 0
for reaction in msg.reactions:
if reaction.count - 1 > highest_reaction_number:
highest_reaction = reaction.emoji
highest_reaction_count = reaction.count - 1
await message.channel.send(f"{highest_reaction} wins with {highest_reaction_count} votes!")
the issue seems to be the program not waiting to check for votes, but rather executing the code instantly. Ignoring future reactions added. Not sure on a work around at this time. Seems I may need some sort of delay before running the if statement.

Use asyncio.sleep()
#bot.event
async def on_message(message):
if 'aoe2' in message.content and message.channel.id == 1048127088688889866:
BlueEmbed = discord.Embed(title='AOE Lobby',
description='**Lobby Link:** ' + '<' +
str(message.content) + '>',
colour=discord.Colour.blue())
message = await message.channel.send(embed=BlueEmbed)
await message.add_reaction('❤️')
await message.add_reaction('💙')
await asyncio.sleep(5) #however long u want in seconds
msg = await message.channel.fetch_message(message.id)
highest_reaction = ""
highest_reaction_number = 0
for reaction in msg.reactions:
if reaction.count - 1 > highest_reaction_number:
highest_reaction = reaction.emoji
highest_reaction_count = reaction.count - 1
await message.channel.send(f"{highest_reaction} wins with {highest_reaction_count} votes!")
or you can have another phrase trigger it
#bot.event
async def on_message(message):
global messageid
if 'aoe2' in message.content and message.channel.id == 1048127088688889866:
BlueEmbed = discord.Embed(title='AOE Lobby',
description='**Lobby Link:** ' + '<' +
str(message.content) + '>',
colour=discord.Colour.blue())
message = await message.channel.send(embed=BlueEmbed)
await message.add_reaction('❤️')
await message.add_reaction('💙')
messageid = message.id
if "trigger" in message.content and message.channel.id == 1048127088688889866::
msg = await message.channel.fetch_message(messageid)
highest_reaction = ""
highest_reaction_number = 0
for reaction in msg.reactions:
if reaction.count - 1 > highest_reaction_number:
highest_reaction = reaction.emoji
highest_reaction_count = reaction.count - 1
await message.channel.send(f"{highest_reaction} wins with {highest_reaction_count} votes!")

Related

discord.py problems with the checking

im trying to do a trivial discord bot, but with a "helper" it reveals you letter by letter the answer, each "x" senconds, but the problem is i can't to send the answer till the help is fully displayed
in the image the problem is cleary visible
this is the whole code
await ctx.send(a) #question
respuestas = b #answer
#reveal
string = respuestas[0]
blanked_string = [x if x.isspace() else "-" for x in string]
nonspace_indexes = [i for i, _ in enumerate(string)]
random.shuffle(nonspace_indexes)
for i in nonspace_indexes:
blanked_string[i] = string[i]
await ctx.send(''.join(blanked_string))
await asyncio.sleep(2)
#checking
def check(msg=discord.Message) -> True:
return msg.content.lower() in respuestas and msg.channel == ctx.message.channel
try:
guess = await bot.wait_for('message', timeout=6, check=check)
return await ctx.send(f"{guess.author.mention} first")
except asyncio.TimeoutError:
await ctx.send("time over")
#problem
https://i.stack.imgur.com/jlatG.png
note: im not trying to do a hangman
async def letters(response: str, channel: discord.TextChannel):
blanked_string = [x if x.isspace() else "-" for x in response]
nonspace_indexes = [i for i, _ in enumerate(response)]
random.shuffle(nonspace_indexes)
for i in nonspace_indexes:
blanked_string[i] = response[i]
await channel.send(''.join(blanked_string))
await asyncio.sleep(1)
#client.command()
async def game(ctx: commands.Context):
await ctx.send("Author of Python programming language...")
response = "Guido van Rossum"
letters_func = asyncio.create_task(letters(response, ctx.channel))
try:
player_response = await client.wait_for('message', check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=30)
except asyncio.TimeoutError:
letters_func.cancel()
await ctx.send("Time's up!")
else:
letters_func.cancel()
if player_response.content == response:
await ctx.send("Correct!")
else:
await ctx.send("Incorrect!")
Here is a possible resolution path for your problem. I took advantage of asyncio's presence to do this. You can test it, it works very well.
Be careful to adapt your response time to the length of your answer

Manually picking users from reaction roles

I have a command which allows people to react to a message to enter into a "battle". Then with another command, 2 people are chosen. This is my code:
#client.command(aliases=['start', 'g'])
async def startbattle(ctx):
msg = await ctx.send("React to enter battle")
await msg.add_reaction("🎉")
await asyncio.sleep(10000000000000000)
message = await ctx.fetch_message(msg.id)
for reaction in message.reactions:
if str(reaction.emoji) == "🎉":
users = await reaction.users().flatten()
if len(users) == 1:
return await msg.edit(embed=discord.Embed(title="Nobody has won the giveaway."))
try:
user1 = random.choice(users)
user2 = random.choice(users)
except ValueError:
return await ctx.send("not enough participants")
await ctx.send(f'Battle will be against {user1} and {user2}')
#client.command()
async def pick(ctx):
async for message in ctx.channel.history(limit=100, oldest_first=False):
if message.author.id == client.user.id and message.embeds:
reroll = await ctx.fetch_message(message.id)
users = await reroll.reactions[0].users().flatten()
users.pop(users.index(client.user))
winner1 = random.choice(users)
winner2 = random.choice(users)
await ctx.send(f"The battle will be against {winner1.mention} and {winner2.mention}")
break
else:
await ctx.send("No giveaways going on in this channel.")
This is the error which I get while using the "pick" command,
users = await reroll.reactions[0].users().flatten()
IndexError: list index out of range
the error is in the for loop as it gets the msg and the msg doesnt have any reaction so it there is no list so list is out of range to fix this u have to add try and except there so it skips the msg with no reactions.
code :
#client.command()
async def pick(ctx):
async for message in ctx.channel.history(limit=100, oldest_first=False):
if message.author.id == client.user.id and message.embeds:
reroll = await ctx.fetch_message(message.id)
try:
users = await reroll.reactions[0].users().flatten()
except:
break
users.pop(users.index(client.user))
winner1 = random.choice(users)
winner2 = random.choice(users)
await ctx.send(f"The battle will be against {winner1.mention} and {winner2.mention}")
return # <--- was the break
else:
await ctx.send("No giveaways going on in this channel.")
and a suggestion dont add break in the if statement as it will continuously check for msg if already it got one

I'm having a problem with my modmail bot code that was written my discord.py

So, I'm making a modmail bot for my discord server. But when I run, the bot can connect but when I send a test messange in the bot DM, I receive this error: AttributeError: 'NoneType' object has no attribute 'send'.
I'm using python 3.9.1 on Arch Linux. Here is my code:
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
client = commands.Bot(command_prefix="!")
#client.event
async def on_ready():
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name='for moderation mail'))
print("Thunderbird is ready")
#client.event
async def on_message(message):
empty_array = []
modmail_channel = discord.utils.get(client.get_all_channels(), name="modmail-box")
if message.author == client.user:
return
if str(message.channel.type) == "private":
if message.attachments != empty_array:
files = message.attachments
await modmail_channel.send("<#" + message.author.id + ">: ")
for file in files:
await modmail_channel.send(file.url)
else:
await modmail_channel.send("<#" + str(message.author.id) + ">: " + message.content)
elif str(message.channel) == "modmail" and message.content.startswith("<"):
member_object = message.mentions[0]
if message.attachments != empty_array:
files = message.attachments
await member_object.send("**[MOD]** " + "**" + message.author.display_name + "**: ")
for file in files:
await member_object.send(file.url)
else:
index = message.content.index(" ")
string = message.content
mod_message = string[index:]
await member_object.send("**[MOD]** " + "**" + message.author.display_name + "**: " + mod_message)
client.run('No leaking here')
I am assuming that the error is on this line:
await member_object.send("**[MOD]** " + "**" + message.author.display_name + "**: ")
and member_object is coming from this block:
elif str(message.channel) == "modmail" and message.content.startswith("<"):
member_object = message.mentions[0]
if message.attachments != empty_array:
files = message.attachments
await member_object.send("**[MOD]** " + "**" + message.author.display_name + "**: ")
for file in files:
await member_object.send(file.url)
You are defining member_object as the first element in the message.mentions array, however your error of NoneType has no attribute suggests that there are no elements in that array and so member_object is actually equal to None not an instance of a class which has a send method.
You need to check your input to that function and ensure that when your code reaches that block it actually has the attributes that you are expecting

Slots command doesn't work exactly how I want it to | discord.py

Im making a slots command. Im using a YouTube tutorial, however in the tutorial they make it so that when there is a 3 in a row you get double the money instead of triple. I tried a few methods but none of them work. There is on method where it does work however the bot sends the embed for 2 and 3 in a row. Its a bit hard to explain but here's an img. And eventually I just gave up
Here's the code:
#commands.command()
#commands.cooldown(1, 30, commands.BucketType.user)
async def slots(self, ctx, amount=None):
await open_account(ctx.author)
if amount == None:
await ctx.send("Please enter an amount")
return
bal = await update_bank(ctx.author)
amount = int(amount)
if amount > bal[0]:
await ctx.send("You don't have that much money!")
return
if amount < 0:
await ctx.send("Amount must be positive")
return
final = []
for i in range(3):
a = random.choice([":apple:", ":star:", ":full_moon:"])
final.append(a)
if final[0] == final[1] or final[0] == final[2] or final[2] == final[1]:
await update_bank(ctx.author, 2 * amount)
embed = discord.Embed(title="Result", color=discord.Color.green())
embed.add_field(name="The result", value=final)
embed.add_field(
name="\u200b", value=f"You won {2*amount} coins", inline=False)
await ctx.send(embed=embed)
else:
await update_bank(ctx.author, -1 * amount)
embed = discord.Embed(title="Result", color=discord.Color.red())
embed.add_field(name="The result", value=final)
embed.add_field(
name="\u200b",
value=f"You lost {-1*amount} coins",
inline=False)
await ctx.send(embed=embed)
if final[0] == final[1] and final[0] == final[2] and final[1] == final[2]:
await update_bank(ctx.author, 3 * amount)
embed = discord.Embed(title="Result", colour=discord.Color.green())
embed.add_field(name="The result", value=final)
embed.add_field(
name="\u200b",
value=
f"You won {3*amount} coins. Woah, dude 3 in row? That's sick",
inline=False)
await ctx.send(embed=embed)
I want it so that when the you get 3 in a row, the bot sends the 3 in a row embed
#client.command(pass_context=True)
async def slots(ctx, amount=None):
if amount == None:
await ctx.send("Please enter an amount")
return
bal = await update_bank(ctx.author)
amount = int(amount)
if amount > bal[0]:
await ctx.send("You don't have that much money!")
return
if amount < 0:
await ctx.send("Amount must be positive")
return
slots = ['bus', 'train', 'horse', 'tiger', 'monkey', 'cow']
slot1 = slots[random.randint(0, 5)]
slot2 = slots[random.randint(0, 5)]
slot3 = slots[random.randint(0, 5)]
slotOutput = '| :{}: | :{}: | :{}: |\n'.format(slot1, slot2, slot3)
ok = discord.Embed(title = "Slots Machine", color = discord.Color(0xFFEC))
ok.add_field(name = "{}\nWon".format(slotOutput), value = f'You won {2*amount} coins')
won = discord.Embed(title = "Slots Machine", color = discord.Color(0xFFEC))
won.add_field(name = "{}\nWon".format(slotOutput), value = f'You won {3*amount} coins')
lost = discord.Embed(title = "Slots Machine", color = discord.Color(0xFFEC))
lost.add_field(name = "{}\nLost".format(slotOutput), value = f'You lost {1*amount} coins')
if slot1 == slot2 == slot3:
await update_bank(ctx.author, 3 * amount)
await ctx.send(embed = won)
return
if slot1 == slot2:
await update_bank(ctx.author, 2 * amount)
await ctx.send(embed = ok)
return
else:
await update_bank(ctx.author, -1 * amount)
await ctx.send(embed = lost)
return
This seems to work maybe you can change the emojis and stuff
#client.command(aliases = ["slot"])
#commands.cooldown(1, 60, commands.BucketType.user)
async def slots(ctx,amount = None):
await open_account(ctx.author)
if amount == None:
em11 = discord.Embed(title = f"Please enter the amount as well",color =
discord.Color.red())
await ctx.send(embed = em11)
ctx.command.reset_cooldown(ctx)
return
bal = await update_bank(ctx.author)
amount = int(amount)
if amount > bal[0]:
em15 = discord.Embed(title = f"You dont have that much money",color =
discord.Color.red())
await ctx.send(embed = em15)
ctx.command.reset_cooldown(ctx)
return
if amount < 100:
em16 = discord.Embed(title = f"Amount must be greater than 100",color =
discord.Color.red())
await ctx.send(embed = em16)
ctx.command.reset_cooldown(ctx)
return
slot = ['<:one:840824304937598976>', '<:two:840824558642003998>',
'<:three:840824657434378250>', '<:four:840824764539863061>',
'<:five:840828099170926592>', '<:six:840828181622947841>']
slot1 = random.choice(slot)
slot2 = random.choice(slot)
slot3 = random.choice(slot)
slotOutput = f'| {slot1} | {slot2} | {slot3} |'.format(slot1, slot2, slot3)
if slot1 == slot2 == slot3:
await update_bank(ctx.author,2*amount)
em18 = discord.Embed(title = "Slots Machine",color = discord.Color.green())
em18.add_field(name = slotOutput.format(slotOutput), value = f"You won
{2*amount} coins!")
await ctx.send(embed = em18)
return
elif slot1 == slot2 or slot1 == slot3 or slot2 == slot3:
await update_bank(ctx.author,amount)
em17 = discord.Embed(title = "Slots Machine",color = discord.Color.green())
em17.add_field(name = slotOutput.format(slotOutput), value = f"You won {amount} coins!")
await ctx.send(embed = em17)
return
else:
await update_bank(ctx.author,-1*amount)
em19 = discord.Embed(title = "Slots Machine",color = discord.Color.red())
em19.add_field(name = slotOutput.format(slotOutput), value = f"You lost
{amount} coins!")
await ctx.send(embed = em19)
return

Discord.py how to add a countdown to an embed

I have been trying to find a way to add a countdown in an embed but can't find anything. So when current_time reaches a certain time, it sends an embed and starts counting down in one of the fields.
await client.wait_until_ready()
channel = client.get_channel(auth)
while not client.is_closed():
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print(current_time)
if current_time == "03:09:00":
embed = discord.Embed(
colour = discord.Colour.green(),
title = "test"
)
embed.set_image(url = "(img)") #
embed.set_thumbnail(url = "(img)") #
**embed.add_field(name="Timer", value ="??:??:??", inline = True) #Timer goes at ??:??:??
embed.add_field(name="Location", value ="adding later", inline = True)
await channel.send(embed=embed)
client.loop.create_task(background_task())```
Since its all in a async function, you could do something like this
#client.command()
async def countdown(ctx, *args):
embed = discord.Embed(
title='foo',
description='bar'
)
now = datetime.datetime.now()+datetime.timedelta(minutes=5)
embed.insert_field_at(
index=0,
name='countdown',
value=str(datetime.timedelta(minutes=5))
)
msg = await ctx.send(embed=embed)
while datetime.datetime.now() < now:
embed.remove_field(index=0)
embed.insert_field_at(
index=0,
name='countdown',
value=str(now-datetime.datetime.now())
)
await msg.edit(embed=embed)
asyncio.sleep(5)

Resources