Discord Bot in Python Reaction Response - python

I want that when someone reacts to one emoji the bot writes as a log on chat like this:
#Santa has press 4️⃣
I tried to make it but I'm stuck.
import discord
import time
import random
from discord.ext import commands
client = discord.Client()
bot = client.user
if message.content.startswith('ººrandgame'):
original = await message.channel.send('Discover the number I my mind...')
uno = await original.add_reaction('1️⃣')
dos = await original.add_reaction('2️⃣')
tres = await original.add_reaction('3️⃣')
cuatro = await original.add_reaction('4️⃣')
cinco = await original.add_reaction('5️⃣')
seis = await original.add_reaction('6️⃣')
siete = await original.add_reaction('7️⃣')
ocho = await original.add_reaction('8️⃣')
nueve = await original.add_reaction('9️⃣')
diez = await original.add_reaction('🔟')
numbers = ['1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟']
#this part fails::
if(reaction.emoji == "1️⃣"):
await message.channel.send(author + "has press 1️⃣")
#the same idea with the other numbers
time.sleep(15)
finalnum = random.choice(numbers)
await message.channel.send('My number is: ' + finalnum)
print(finalnum)
client.run('blabla')

You can use a reaction_wait_for, this will always wait for the author of the message input of the specified reaction.
Below I've made a simple user reaction command but I'll leave it up to you how you would further like to improve it.
message = await ctx.send("React to a number")
one = '1️⃣'
two = '2️⃣'
await message.add_reaction(one)
await message.add_reaction(two)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in [one, two]
member = ctx.author
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=600.0, check=check)
if str(reaction.emoji) == one:
await ctx.send("You choose 1")
if str(reaction.emoji) == two:
await ctx.send("You choose 2")
In your code, I would also reccomend using asyncio.sleep(15) instead of time.sleep, as this causes the whole bot to stop, meaning no one can use it at all.
Make sure to import asyncio
You can also set it as a command, instead of using if message.content.startswith('ººrandgame'): , You can use
#client.command()
async def ººrandgame(ctx):
.... Rest of your code ...

Ibidem, I think that something is missing
import discord
import os
import random
import asyncio
from discord.ext import commands
client = discord.Client()
horaact = time.strftime('%H:%M:%S')
os.system('cls')
os.system('color 1f')
#client.event
async def on_ready():
print("Encendido")
print("logged in as {0.user}".format(client))
#client.command()
async def ººrandgame(ctx):
message = await ctx.send("React to a number")
one = '1️⃣'
two = '2️⃣'
await message.add_reaction(one)
await message.add_reaction(two)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in [one, two]
member = ctx.author
while True:
try:
reaction, user = await client.wait_for("reaction_add", timeout=600.0, check=check)
if str(reaction.emoji) == one:
await ctx.send("You choose 1")
if str(reaction.emoji) == two:
await ctx.send("You choose 2")
client.run('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
Remember, this is not the original code, it's just a test for trying your funtion

Related

Cogs Help In Discord Py

I am trying to create a command wherein if you react on the embed, the bot sends something back. If I add this code to a cog, it won't work. If possible, can you tell me why?
#bot.command(aliases=['test','t'])
async def Test(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
With the help of the people in the comment section, I have found the problem with my code. I had to change bot.command into commands.command. (I've tried both bot and command, and it still works splendidly). The other crucial thing I had to add was "self" under bot.wait_for. Without the self, the command wouldn't work. Thank you so much for the help.
#commands.command(aliases=['test','t'])
async def Testing(self, ctx):
TestEmbed = discord.Embed(title="Definition", description="This is just a test embed", color=11027200)
TestEmbed.add_field(name="\u200b", value="▹❁❁▹❁◃❁❁◃",inline=False)
emojis = ['⬅️','➡️']
TestEmbedAdd = await ctx.send(embed=TestEmbed)
for emoji in emojis:
await TestEmbedAdd.add_reaction(emoji)
def check(reaction, user):
return user == ctx.author and str(reaction.emoji) in ['⬅️', '➡️']
try:
reaction, user = await self.bot.wait_for('reaction_add', timeout=5, check=check)
if reaction.emoji == '➡️':
await ctx.send("Reaction 2!")
elif reaction.emoji == '⬅️':
await ctx.send("Reaction 1!")
except asyncio.TimeoutError:
await ctx.send("Time is out!")
you need #commands.command instead of #bot.command

Getting error on discord bot discord.py for typing in role

I get this error on my bot when mentioning a role,here is the error,
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: unhashable type: 'set'
my code:
import os
import discord
from discord.ext import commands
from discord import Intents
from apikeys import *
intents = Intents.all()
client = commands.Bot(intents = intents, command_prefix="-", case_insensitive=True)
#client.event
async def on_ready():
for emoji in client.emojis:
print("Name:", emoji.name + ",", "ID:", emoji.id)
print('Bot is Online {0.user}'.format(client))
print("--------------------------------------------------------------------------------------------------------------------------------------------------------")
client.remove_command('help')
emojigood = '\N{THUMBS UP SIGN}'
emojibad="\N{THUMBS DOWN SIGN}"
#client.command()
async def war(ctx):
await client.wait_until_ready()
embed = discord.Embed(title='War', description='You are starting a war, do you want to continue?', color=0x00000)
msg = await ctx.send(embed=embed)
await msg.add_reaction(emojigood)
await msg.add_reaction(emojibad)
def check(r, user):
return (r.emoji == emojigood or r.emoji == emojibad) and r.message == msg and user != client.user
r, user = await client.wait_for('reaction_add',check=check)
if r.emoji == emojigood:
embed = discord.Embed(title='War', description='Please now choose a country', color=0x00000)
await ctx.send(embed=embed)
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
msg = await client.wait_for('message', check=check)
if len(msg.role_mentions) > 0:
role = msg.role_mentions[0]
channel = client.get_channel({849549009038344262})
await channel.send(f"{role.mention} {ctx.author} has declared war on you.")
else:
await ctx.send("Invalid role mentioned")
else:
await ctx.send("Cancelled")
client.run(token)
What's meant to happen:
Me:-war
Bot:Are you sure
Me:reacts
Bot:Type in role
Me:(role name)
Bot:....
{849549009038344262}
is a set literal for a set containing a number. discord.py is using hashing under the hood to look up channels, which is failing because it is not possible to hash sets. You should be passing a regular int instead of a set:
channel = client.get_channel(849549009038344262)

bot executes next command without waiting for message

Hello I have been trying to create a application bot for my server the bot sends you a questions then the person answers then its noted down ect but my problem is that sometimes the next question would send without waiting for the answer to the previous question. this only happens most of the time. try i might i have not been able to fix the problem. I’m pretty new to python and at the end of my wits.
my code for reference:
import os
from discord.ext import commands
from discord.utils import get
BOT_PREFIX = ("!")
client = commands.Bot(command_prefix=BOT_PREFIX)
a_list = []
#client.event
async def on_ready():
print ("------------------------------------")
print ("Bot Name: " + client.user.name)
print ("------------------------------------")
submit_wait = False
a_list = []
b_list = []
c_list = []
d_list = []
#client.command(aliases=['application'])
async def app(ctx):
a_list = []
b_list = []
c_list = []
d_list = []
submit_wait = False
submit_channel = client.get_channel(806404345830047744)
channel = await ctx.author.create_dm()
await channel.send("starting applaction!")
await ctx.send(ctx.author.mention + "check your dms!")
time.sleep(2)
def check(m):
return m.content is not None and m.channel == channel
await channel.send("Do you have any prior milli sim experiance?")
msg = await client.wait_for('message', check=check)
a_list.append(msg.content)
await channel.send("What time zone are you in?")
msg2 = await client.wait_for('message', check=check)
b_list.append(msg2.content)
await channel.send("If a officer ordered you to break the genva convention would you do it?")
msg3 = await client.wait_for('message', check=check)
c_list.append(msg3.content)
await channel.send("Is there any particular dvision you want to be in?")
msg4 = await client.wait_for('message', check=check)
d_list.append(msg4.content)
await channel.send('thank you for applying! a officer will do your application as soon as they can - respound with "submit" to submit your application')
msg = await client.wait_for('message', check=check)
if "submit" in msg.content.lower():
submit_wait = False
answers = "\n".join(f'{a}. {b}' for a, b in enumerate(a_list, 1))
answer = "\n".join(f'{a}. {b}' for a, b in enumerate(b_list, 2))
answerr = "\n".join(f'{a}. {b}' for a, b in enumerate(c_list, 3))
answerss = "\n".join(f'{a}. {b}' for a, b in enumerate(d_list, 4))
submit_msg = f'Application from {msg.author} \nThe answers are:\n{answers}'
submit_msg2 = f'{answer}'
submit_msg3 = f'{answerr}'
submit_msg4 = f'{answerss}'
await submit_channel.send(submit_msg)
await submit_channel.send(submit_msg2)
await submit_channel.send(submit_msg3)
await submit_channel.send(submit_msg4)
client.run(os.getenv('TOKEN'))
I tested code using print() and I think problem is because check() sometimes gets bot's question and it treats it as user's answer.
You have to check m.author in check() - something like this
#client.command(aliases=['application'])
async def app(ctx):
submit_channel = client.get_channel(806404345830047744)
#print('submit_channel:', submit_channel)
channel = await ctx.author.create_dm()
author = ctx.author
def check(m):
#print('m.author:', m.author)
#print('m.content:', m.content)
#print('m.channel:', m.channel, m.channel == channel)
return m.author == author and m.content and m.channel == channel
Minimal working code with other changes
import os
import time
from discord.ext import commands
client = commands.Bot(command_prefix="!")
#client.event
async def on_ready():
print ("------------------------------------")
print ("Bot Name:", client.user.name)
print ("------------------------------------")
#client.command(aliases=['application'])
async def app(ctx):
submit_channel = client.get_channel(806404345830047744)
print('submit_channel:', submit_channel)
channel = await ctx.author.create_dm()
author = ctx.author
def check(m):
print('m.author:', m.author)
print('m.content:', m.content)
print('m.channel:', m.channel, m.channel == channel)
return m.author == author and m.content and m.channel == channel
await channel.send("starting applaction!")
await ctx.send(ctx.author.mention + " check your dms!")
time.sleep(2)
await channel.send("Do you have any prior milli sim experiance?")
answer_a = await client.wait_for('message', check=check)
answer_a = answer_a.content
await channel.send("What time zone are you in?")
answer_b = await client.wait_for('message', check=check)
answer_b = answer_b.content
await channel.send("If a officer ordered you to break the genva convention would you do it?")
answer_c = await client.wait_for('message', check=check)
answer_c = answer_c.content
await channel.send("Is there any particular dvision you want to be in?")
answer_d = await client.wait_for('message', check=check)
answer_d = answer_d.content
await channel.send('thank you for applying! a officer will do your application as soon as they can - respound with "submit" to submit your application')
msg = await client.wait_for('message', check=check)
if "submit" in msg.content.lower():
submit_msg = f'''Application from {msg.author}
The answers are:
1. {answer_a}
2. {answer_b}
3. {answer_c}
4. {answer_d}'''
await submit_channel.send(submit_msg)
client.run(os.getenv('TOKEN'))
Ok so at first glance I'm picking up a few errors
Firstly, minor issue, but using time.sleep(2) will pause your entire bot, so if you want to let other people to run this command at the same time you may want to change this
import asyncio # instead of import time
await asyncio.sleep(2) # instead of time.sleep(2)
Also you needn't repeat so much code, this should make it work exactly how you want it to
import os
from discord.ext import commands
from discord.utils import get
import asyncio
client = commands.Bot(command_prefix="!")
#client.event
async def on_ready():
print ("------------------------------------")
print ("Bot Name: " + client.user.name)
print ("------------------------------------")
submit_wait = False
questions = ["Do you have any prior milli sim experiance?",
"What time zone are you in?",
"If a officer ordered you to break the genva convention would you do it?",
"Is there any particular dvision you want to be in?"]
#client.command(aliases=['application'])
async def app(ctx):
submit_channel = client.get_channel(810118639234973719)
channel = await ctx.author.create_dm()
await channel.send("starting applaction!")
await ctx.send(ctx.author.mention + "check your dms!")
await asyncio.sleep(2)
def check(m):
return m.content != "" and m.channel == channel
answers = []
for question in questions:
await channel.send(question)
msg = await client.wait_for("message", check=check)
answers.append(msg.content)
await channel.send('thank you for applying! a officer will do your application as soon as they can - respound with "submit" to submit your application')
msg = await client.wait_for("message", check=check)
if "submit" in msg.content.lower():
submit_wait = False
answers = [f"{no+1}. {ans}" for no, ans in enumerate(answers)]
submit_msg = [f"Application from {msg.author}",
"The answers are:", *answers]
await submit_channel.send("\n".join(submit_msg))
client.run(os.getenv('TOKEN'))

send questions in dm, and post answers in embed to a channel discord.py

I am trying to make it where when the user initiates the command $createprofile the bot will dm the user with the questions provided in the list, one after the other then post the answers in an embed to a specified channel. Now I have already built the list, but I am unsure of how to build in asking each question one after another, I am possibly thinking of using asyncio wait_for
import discord
from discord.ext import commands
import platform
import cogs._json
class Profile(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_ready(self):
print("Profile Cog has been loaded\n-----")
# #commands.command(aliases=['pm'])
# async def dm(self, ctx, user: discord.User, *, message=None):
# message = message or "This message is sent via dm"
# await user.send(message)
# await ctx.message.delete()
#commands.command()
async def createprofile(ctx, member: discord.Member = None):
userName = ""
userAge = ""
questions = [
"Please input your name/nickname:",
"Please input your age:"
]
dmChannel = await ctx.author.send(
"You will be receiving two questions. One involving your name and the other your age.")
def check(message):
return message.author == ctx.author and message.channel == dmChannel.channel
async def askQuestion(question):
await ctx.author.send(question)
print("Waiting for reply...")
userReply = await client.wait_for('message', check=check)
print("User replied")
return userReply.content
userName = await askQuestion(questions[0])
userAge = await askQuestion(questions[1])
e = discord.Embed(title=str(userName) + "'s Profile", description=f"""
Age: `{str(userAge)}`
""")
await ctx.send(embed=e)
def setup(bot):
bot.add_cog(Profile(bot))
#client.command()
async def createprofile(self, ctx, member: discord.Member = None):
userName = ""
userAge = ""
questions = [
"Please input your name/nickname:",
"Please input your age:"
]
dmChannel = await ctx.author.send(
"Yo will be receiving two questions. One involving your name and the other your age.")
def check(message):
return message.author == ctx.author and message.channel == dmChannel.channel
async def askQuestion(question):
await ctx.author.send(question)
print("Waiting for reply...")
userReply = await client.wait_for('message', check=check)
print("User replied")
return userReply.content
userName = await askQuestion(questions[0])
userAge = await askQuestion(questions[1])
e = discord.Embed(title=str(userName) + "'s Profile", description=f"""
Age: `{str(userAge)}`
""")
await ctx.send(embed=e)
First, you need to send the user a question, so how you do that is through await ctx.author.send("this is a question"). You then store that message into a variable. You then create a check function that makes sure that the user who replied is in fact the user who sent the $createprofile message in the first place. You will also need to check if the message's channel is the dm channel. So that's where the message you stored earlier takes action. It will make sure that the channel of the message is the same as the channel of the dm message you sent to the user earlier. After that, you create an async function to ask a question. From there on it's pretty straightforward. Feel free to optimize your code using for loops. Hope this helps.

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