I have been trying to make a discord bot which starts a game when !play message is sent. In the game there is a variable whose value is chosen randomly and if you predict the right number (between 1 and 10) then a "You win" message will be sent and if the it is greater or less then a message will be sent accordingly. I know I am messing it because I am using discord.py for the first time.
My code:
if message.content.startswith("!play"):
await message.channel.send("Choose a number between 1-10. Enter numerical values only.")
num = random.randint(1,10)
try:
if message.content.startswith(str(num)):
await message.channel.send("You won.")
elif int(message.content) > num:
await message.channel.send("Go a bit lower.")
elif int(message.content) < num:
await message.channel.send("Go a bit up.")
except Exception as e:
await message.channel.send("Check inputs.")
Please help
Here:
# imports the discord module and the random module.
import discord
from discord.ext import commands
import random
client = discord.Client()
client = commands.Bot(command_prefix = "!")
Token = "" #your token
#client.event
async def on_message(message):
if message.content.startswith("!play"): #the play command to start the guessing game.
channel = message.channel
await channel.send("Choose a number between 1-10. Enter numerical values only.") #message that tells about the start of the game
# generates a random number and turns it into a string
number1 = random.randint(1,10)
number2 = str(number1)
def check(m):
return m.content == number2 and m.channel == channel
"""
The check function, first it checks if the message is the correct number.
Then it checks if the channel is the same channel as the channel that the play command was sent in.
If both is true, then it returns true. Else it returns false.
"""
msg = await client.wait_for('message', check=check) #waits for the check function to return true
await channel.send("Correct answer {.author}" .format(msg)) #sends the correct answer message
client.run(Token)
This should work.
I have a working bot here: https://discord.com/api/oauth2/authorize?client_id=793152585346711573&permissions=8&scope=bot
Example: https://i.stack.imgur.com/ou60F.png
Related
the bot offers to guess a number from 0 to 10. But for the correct answer, it answers "False"
I guess the problem is using asynchronous functions, but I'm not good at them
from aiogram import Bot, Dispatcher, executor, types
import random
bot = Bot(token=BOT_TOKEN)
dp = Dispatcher(bot)
# number to guess
NUMBER = 0
# comes up with a number
def setRand():
NUMBER = random.randrange(10)
print(NUMBER)
# handler for /start
#dp.message_handler(commands=['start'])
async def start(msg: types.Message):
setRand()
await msg.answer("Try to guess the number from 0 to 10")
# handler for getting answer
#dp.message_handler()
async def getNumber(msg: types.Message):
if msg.text == str(NUMBER):
await msg.answer('True!')
else:
await msg.answer('False :с')
await msg.answer('But I came up with new number!')
setRand()
executor.start_polling(dp)```
Use global for global variables!
def setRand():
global NUMBER
NUMBER = random.randrange(10)
print(NUMBER)```
What I've tried
StackOverflow articles
Need help to fix a certain bug in rock, scissor and paper.
discord.py documentation
How can I add reaction to a message
(checked plenty of articles, but I'm not going to add them in order to get into the point)
I've managed to retrieve the emoji from the user in the check method, but still the issue with timeouterror appears, so there is something I'm missing which I can't get a hold on.
In this senario im using Cog,
The issue
Even though the wait_for passes the check method, I'm not sure how to send it forward to the logical conditon. The result I get is passed in the exception.
bot.py
import os
from dotenv import load_dotenv
from discord import Intents
# lib
from lib.cog.miniGames import miniGames # Games
from lib.client.krigjo25 import krigjo25
# Importing .evn file
load_dotenv()
def botSetup ():
# necsessary values from .env
botKey = os.getenv('Token')
server = os.getenv('server')
# discord configs
intents= Intents.all()
#retrieving the module command prefix is created in the bot module
bot=krigjo25(intents=intents)
# adding cogs into the bot
bot.add_cog(miniGames(bot))
bot.run(botKey)
if __name__ == '__main__':
botSetup()
miniGames.py
class miniGames(Cog, name='miniGames module'):
def __init__(self, bot):
self.bot = bot
#command(name='rsp')
#Cog.listener()
# 1: Creating a game where the user has three choices to choose between from
# 2: The bot adds 3 reactions, where you have to choose one of them as an answer
# 3: The bot checks wheter the conditions is true or false, in order to send the correct messge:
async def RockscissorsPaper(self, message:Message):
# Declearing variables
# Rock, Scissors, Paper
rock,scissor, paper = '\U0001FAA8', '\U00002702','\U0001F4C4'
answer = { 0:'\U0001FAA8',
1:'\U00002702',
2:'\U0001F4C4'}
# Randomizing the answer and assign it to the variable
shuffle(answer)
x = randrange(0,2)
answer = '\U0001FAA8' #answer.get(x)
print(answer)
# Creating Embed message
embed = Embed(color = Color.blurple())
embed.title = 'Rock, Scissors & Paper'
embed.description = ' In order to play the game, please click one one of the following reactions'
# Sending & adding reactions
ch = await message.channel.send(embed=embed)
await ch.add_reaction(rock)
await ch.add_reaction(scissor)
await ch.add_reaction(paper)
# passes the check method
def check( user, reaction):
print('check function', reaction, user)
return user == message.author and reaction == str(reaction.emoji)
# Checks the user's input¨'
# Questions : Is it possible to use dictionaries in order to find the given emoji?
try :
# How does this work? If wait_for is a "asynico" function how can it work like this?
reaction, user = await self.bot.wait_for('reaction_add', timeout=30, check=check)
except TimeoutError as e:
print(e)
else:
reaction = str(reaction.emoji)
# Checking if its the bots reaction
if user == self.bot.user:
return None
else:
if reaction == '\U0001F4C4' and answer == '\U0001FAA8':
await message.channel.send(' you won')
Add this at the beginning of your code:
intents = discord.Intents.all()
Then add this into your discord.Bot's declaration:
bot = discord.commands.Bot(prefixes=['!'], intents=intents)
Then go to Discord Developer Portal and enable all the intents writing from the Application's "bot" page.
can u remove this line?
#command(name='rsp')
--> #Cog.listener()
# 1: Creating a game where the user has three choices to choose between from
What is this listener supposed to answer?
It appears that i had to change :
def check( user, reaction):
print('check function', reaction, user)
return user == message.author and reaction == str(reaction.emoji)
New
def emojiCheck(reaction, member):
reaction = str(reaction)
member == ctx.author.name
# Do not return the bot's last reaction
return member !=self.bot.user and reaction
--
I also had to add the code block in the try - except statement.
** OLD **
try :
# How does this work? If wait_for is a "asynico" function how can it work like this?
reaction, user = await self.bot.wait_for('reaction_add', timeout=30, check=check)
except TimeoutError as e:
print(e)
else:
reaction = str(reaction.emoji)
# Checking if its the bots reaction
if user == self.bot.user:
return None
else:
if reaction == '\U0001F4C4' and answer == '\U0001FAA8':
await message.channel.send(' you won')
New
try:
# Timer Check
reaction, member = await self.bot.wait_for('reaction_add', timeout=60.0, check=emojiCheck)
print(member, reaction, answer)
# Dictionaries
# Tie
tie = {
0:f'{self.bot.user} draws a **tie** for {member}',
1:'Sir, lets **tie** a **tie**',
2:'What did the **tie** say to the bowtie? You\'re a weirdo',
3:'lets have a wii-match',
}
reactionRock = {
}
# Randomize the dictionary
shuffle(tie)
x = randrange(0,3)
tie = tie.get(x)
# If the situation is a draw / tie
if str(reaction) == answer:
self.embed.description = tie
await ctx.send(embed = self.embed)
The point is if-elif or else statement has to be inside the try-except statement.
Hope this is for help for other developers which has the same issue.
Thanks for the assistance which I received. Its appreciated.
I have an excuse generator and decided to transfer it over to a bot. From what I have seen the command is a branching path. It asks, you respond, and then it asks again based on your previous answer.
The problem is the QuestionOneOne = int(input()), QuestionOneTwo = int(input()), and QuestionOneThree = int(input()). I understand what they do but not how to make it work on Discord where the questions are asked like how those 3 lines look for the response in the command prompt.
TL;DR: int(input()) makes the bot look for response in command prompt. I don't know how to make it look in chat.
Here's the code that is the issue. The bit after it would work ok if this part is fixed.
#client.command()
async def yote(ctx):
await ctx.send("Welcome to the EXCUSE GENERATOR")
await ctx.send("This is a generator that creates a random EXCUSE for you")
await ctx.send("What do you need an excuse for?")
await ctx.send("1: I forgot")
await ctx.send("2: I lost")
await ctx.send("3: I didn't do")
QuestionOne = int(input())
if QuestionOne == 1:
await ctx.send("What did you forget?")
await ctx.send("1: Homework")
await ctx.send("2: An object")
await ctx.send("3: A concept")
QuestionOneOne = int(input())
elif QuestionOne == 2:
await ctx.send("What did you lose?")
await ctx.send("1: Something expensive")
await ctx.send("2: Something cheap")
await ctx.send("3: Someone")
QuestionOneTwo = int(input())
elif QuestionOne == 3:
await ctx.send("What didn't you do?")
await ctx.send("1: Your homework")
await ctx.send("2: An errand")
await ctx.send("3: Something important")
QuestionOneThree = int(input())
Thing = str(input())
You should use the Client.wait_for / Bot.wait_for method and specify "message" for the event.
You'll want to add a check as well, e.g. for the channel or author, integer input, etc.
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
I am trying to build up discord bot through pip discord.py. After command !random I want to ask user for any number and bot will then generate random number between 0 and entered number. It doesn't rly work for me and because i don't know much things about discord.py, I ask there :)
code:
import random
elif message.content.startswith("!random"):
await client.send_message(message.channel, "Enter a number: ")
num = await client.wait_for_message(int)
numm = int(num)
randomnum = random.randint(0, numm)
await client.send_message(message.channel, randomnum)
Try this:
import random
elif message.content.startswith("!random"):
await client.send_message(message.channel, "Enter a number: ")
def check(msg):
return msg.content
reaction.content = await client.wait_for_message(author=message.author, check=check)
numm = int(reaction)
randomnum = random.randint(0, numm)
await client.send_message(message.channel, randomnum)
You should also check if the reaction is a int
(added squaswin's reaction. note that the code is not tested)