I am a beginner in python and i am to trying to code a discord game bot in which you have to choose your paths.
I want that the user first run !adv command and then can press 'c' to continue but my code is not able to do so.
I am not getting any error but after running the !adv command ,i am not able to run the 'c' command to further do something.
client = discord.Client()
#client.event
async def on_ready():
general_channel = client.get_channel(864471185907908608)
await general_channel.send('Hey!')
#client.event
async def on_message(message):
count = 0
msg = message.content.lower()
general_channel = client.get_channel(864471185907908608)
if count == 0:
if msg == '!adv':
await general_channel.send('Hello '+ message.author.name +'. \nWelcome to the Lands of The Supreme Lord , The Godfather.\nYou woke up in the marketplace with crowd bustling everywhere.\nYou have many questions.\nWhat led you to this place and whats your destiny?\nYou are set to write your own path here.\nPress c to continue.')
count += 1
async def on_message(message):
msg = message.content.lower()
if count == 1:
if msg == 'c':
await general_channel.send('\nYou see a vase shop and an weaponsmith ahead.\nDecide who you want to talk.\nType v or w')
Please include the code for the solution as well because it is easy to understand with code.
Thanks in advance
You cannot really have more than one on_message (though you're not registering the second one as an event). To wait for a user response you should use client.wait_for:
#client.event
async def on_message(message):
def check(m): # simple check to wait for the correct user
return m.author == message.author and m.channel == message.channel
count = 0
msg = message.content.lower()
general_channel = client.get_channel(864471185907908608)
if count == 0:
if msg == '!adv':
await general_channel.send('Hello '+ message.author.name +'. \nWelcome to the Lands of The Supreme Lord , The Godfather.\nYou woke up in the marketplace with crowd bustling everywhere.\nYou have many questions.\nWhat led you to this place and whats your destiny?\nYou are set to write your own path here.\nPress c to continue.')
# Waiting for the response
resp = await client.wait_for("message", check=check)
if resp.content.lower() == "c":
# continue the story
await general_channel.send('\nYou see a vase shop and an weaponsmith ahead.\nDecide who you want to talk.\nType v or w')
resp2 = await client.wait_for("message", check=check)
if resp2.content.lower() in ["v", "w"]:
# continue the story
...
count += 1
You might wanna use some return statements to not have such deep indentation.
Related
I have mostly rebuilt the code and made changes.
When I do !embed everything works as it should, the bot creates the embed, and reacts with the emojis set, it just doesn't give user the roles once they react with the emojis the bot reacts to the post with..
I decided to add in some random print statements to hit the console per step and found I can see up to while True as commented in my code but after that the print statements don't respond.
My error handler/trace back has been pretty good so far and picked up everything, so its like after while True nothing exists, I believe the problem lies within this line:
reaction = await bot.wait_for("reaction_add", check=lambda reaction, user: user == reaction.message.id == msg.id)
Any help would be greatly appreciated.
desc1 = ("React with the corresponding emoji to game specific channels you want\n"
"\nš - Counter Strike\n"
"š - Warframe\n"
"š¤ - Lost Ark\n"
"š - Chiller\n"
"šŖ - Warhammer")
#bot.command()
async def embed(ctx: commands.Context):
embed=discord.Embed(title="Create Your Profile", description=(desc1))
embed.set_footer(text="Jammys Bot")
msg = await ctx.send(embed=embed)
await msg.add_reaction('š')
await msg.add_reaction('š')
await msg.add_reaction('š¤')
await msg.add_reaction('š')
await msg.add_reaction('šŖ')
print('it works here')
while True:
print('it works here 1') ## makes it up to here. Error handle/trace back isn't picking anything below up so its like its non-existent.
reaction = await bot.wait_for("reaction_add", check=lambda reaction, user: user == reaction.message.id == msg.id) # stops working here
print('it works here 2')
if reaction.emoji == 'š':
print('it works here 3')
CSGO = ctx.guild.get_role(780182144747569193)
print('it works here 4')
await bot.add_roles(CSGO)
print('it works here 5')
if reaction.emoji == 'š':
WF = ctx.guild.get_role(780244861130768395)
await ctx.add_roles(WF)
if reaction.emoji == 'š¤':
LA = ctx.guild.get_role(947231964753170473)
await bot.add_roles(LA)
if reaction.emoji == 'š':
CHILL = ctx.guild.get_role(896853904384458772)
await bot.add_roles(CHILL)
if reaction.emoji == 'šŖ':
WH = ctx.guild.get_role(896882687816630293)
await bot.add_roles(WH)
To send it to a specific channel you can try this code
channel =client.get_channel(your channelid)
msg = await channel.send(embed = embed)
async def ė²ģėŖØė(ctx, number, tonumber):
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
print("{} and {}".format(number, tonumber))
#if number > 3 or tonumber>3 or number < 1 or tonumber < 1 or number == tonumber:
# await ctx.send("There is a problem with the command. Please try again.")
# return
# 1 == kor, 2 == eng, 3 == jpn
await ctx.send("Please enter the sentence you want to translate.")
while True:
sentence = await client.wait_for("message", check=check)
print("translation {}".format(sentence.content))
if sentence.content == "stop":
await ctx.send("The translation mode has ended.")
break
if sentence.content is not None:
await ctx.send("I received a sentence.")
if number == 1 and tonumber == 2:
print("let's start translation")
result1 = translator.translate(sentence.content, dest='en')
print("{}".format(result1.text))
await ctx.send("{}".format(result1.text))
I'm making a translation bot on Discord.
The number and tonumber is to choose a language. ex) 1 == kor, 2 == eng, 3 == jpn
Receiving sentences was successful. So it's printed out that it was delivered well.
But
if number == 1 and tonumber == 2:
print("let's start a translation")
result1 = translator.translate(sentence.content, dest='en')
print("{}".format(result1.text))
await ctx.send("{}".format(result1.text))
It doesn't go over here.
I added a print("let's start a translation") to see if it's moving on.
It's not being printed out
Just in case, I'll write down all the codes.
from asyncio.windows_events import NULL
from discord.ext import commands
import discord
import time
import difflib
import asyncio
import googletrans
translator = googletrans.Translator()
client = discord.Client()
token = "I'll cover it up."
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(intents=intents, command_prefix='>')
#client.event
async def on_ready():
print(client.user.name)
print("Let's start driving the bot.")
game = discord.Game("Somethin' on your mind? ")
await client.change_presence(status=discord.Status.online, activity=game)
#client.event
async def on_voice_state_update(member, before, after):
if before.channel is None and after.channel is not None:
await member.guild.system_channel.send(
"{} has logged on to the voice channel.".format(member.name)
)
#client.command()
async def ģ ė³“(ctx):
members = [member.name for member in ctx.guild.members]
await ctx.send(
"{} server is {} server and Members {} and Total {} people.".format(
ctx.guild.name,
ctx.guild.region,
members,
ctx.guild.member_count
)
)
#client.command()
async def ģ“ėėƼ(ctx):
await ctx.send("This server admin is {}".format(
ctx.guild.owner
))
#client.command()
async def ģė
(ctx):
await ctx.send("You said {}, Nice to meet you {}!"
.format(ctx.message.content, ctx.author.name
))
#client.command(aliases=['translate', 'tl'])
async def ė²ģėŖØė(ctx, number, tonumber):
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
print("{} and {}".format(number, tonumber))
#if number > 3 or tonumber>3 or number < 1 or tonumber < 1 or number == tonumber:
# await ctx.send("There is a problem with the command. Please try again.")
# return
# 1 == kor, 2 == eng, 3 == jpn
await ctx.send("Please enter the sentence you want to translate.")
while True:
sentence = await client.wait_for("message", check=check)
print("translation {}".format(sentence.content))
if sentence.content == "stop":
await ctx.send("The translation mode has ended.")
break
if sentence.content is not None:
await ctx.send("I received a sentence.")
if number == 1 and tonumber == 2:
print("let's start translation")
result1 = translator.translate(sentence.content, dest='en')
print("{}".format(result1.text))
await ctx.send("{}".format(result1.text))
client.run(token)
I can't think of a way because I'm not good enough.
I used a translator, so I hope it's delivered well.
Oh, and...
import "googletrans" could not resolved
There's a warning, too.
Note the variable number and tonumber is not an integer instead it is a string so number will be "1" not 1 similarly tonumber will be "2" not 2. You can fix thix problem in two ways: 1) First way :
Before def check() function just add number=int(number) and tonumber=int(tonumber)
Second way:
async def ė²ģėŖØė(ctx, number, tonumber): to async def ė²ģėŖØė(ctx, number:int, tonumber:int):
I'm quite new to both Python and Discord.py, and I'm trying to find how to make the bot wait for either a message or reaction from user at the same time.
I tried separating each but just resulted in the bot needing a message response before a reaction.
Here's a similar code I'm trying to do:
#bot.event
async def on_message(ctx):
if ctx.author == bot.user:
return
if ctx.content == "$respond":
message = await ctx.send("Waiting for response...")
while True:
try:
response = #Will wait for a message(Yes or No) or reaction(Check or Cross) from ctx.author for 30 secs
except asyncio.TimeoutError:
await message.edit(content=f"{ctx.author} did not respond anymore!")
break
if response.content == "yes":
await message.edit(content=f"{ctx.author} said yes!")
continue
elif response.content == "no":
await message.edit(content=f"{ctx.author} said nyo!")
continue
#These are reactions
elif str(response.emoji) == "ā
":
await message.edit(content=f"ctx.author reacted ā
!")
continue
elif str(response.emoji) == "ā":
await messave.edit(content=f"Stopped listening to responses.")
break
bot.wait_for is what you're looking for here.
I would recommend using bot.command() for command handling purposes but this is fine as well.
This is how you wait for specific events (provided as the first argument) with specific conditions (as provided in the check param)
#bot.event
async def on_message(msg):
if msg.author == bot.user:
# if the author is the bot itself we just return to prevent recursive behaviour
return
if msg.content == "$response":
sent_message = await msg.channel.send("Waiting for response...")
res = await bot.wait_for(
"message",
check=lambda x: x.channel.id == msg.channel.id
and msg.author.id == x.author.id
and x.content.lower() == "yes"
or x.content.lower() == "no",
timeout=None,
)
if res.content.lower() == "yes":
await sent_message.edit(content=f"{msg.author} said yes!")
else:
await sent_message.edit(content=f"{msg.author} said no!")
This would result in :
Listening for multiple events is a rather a bit interesting,
Replace the existing wait_for with this snippet :
done, pending = await asyncio.wait([
bot.loop.create_task(bot.wait_for('message')),
bot.loop.create_task(bot.wait_for('reaction_add'))
], return_when=asyncio.FIRST_COMPLETED)
and you can listen for two events simultaneously
Here's how you can handle this using #bot.command()
import discord
import os
from discord.ext import commands
bot = commands.Bot(command_prefix="$", case_insensitive=True)
#bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
#bot.command()
async def response(ctx):
sent_message = await ctx.channel.send("Waiting for response...")
res = await bot.wait_for(
"message",
check=lambda x: x.channel.id == ctx.channel.id
and ctx.author.id == x.author.id
and x.content.lower() == "yes"
or x.content.lower() == "no",
timeout=None,
)
if res.content.lower() == "yes":
await sent_message.edit(content=f"{ctx.author} said yes!")
else:
await sent_message.edit(content=f"{ctx.author} said no!")
bot.run(os.getenv("DISCORD_TOKEN"))
which would get you the same result.
So I'm making this weird kinda discord bot. It displays a set of obstacles, and adds a corresponding key that you need to press to a string. It adds a 'w' for every '...', and an 's' for every '***'. In Discord, the player has to type the correct string in to pass the level. So it all works and displays properly. The call function is '!go', and that displays the level. But it fails me before I can type in the string. I want to know, why is it automatically activating? My message.content function is outside that loop. I think it is because I type '!go' and it doesn't reset my message. Here is the code:
#client.event
async def on_message(message):
global correct_answerS
correct_answerS = ""
obstacleList = []
for i in range (0, 24):
randNum = random.randint(1,2)
if randNum == 1:
obstacleList.append('...')
correct_answerS += 'w'
if randNum == 2:
obstacleList.append('***')
correct_answerS += 's'
if message.content == ('!practice'):
sky = str("```css\n A ... ... *** ...```")
skyembed = discord.Embed(title="!============================!")
skyembed.add_field(name='When you see three dots, it is a w. When you see 3 asteriks, it is an s.', value = sky)
await message.channel.send(embed=skyembed)
if message.content == ('wwsw'):
await message.channel.send("Success.")
if message.content == ('!go'):
randlev = (str("```css\n A "))
for i in range(0, 24):
randlev += (str(obstacleList[i]) + " ")
randlev += "```"
randlevembed = discord.Embed(title="!===============================================!")
randlevembed.add_field(name='Good luck!', value = randlev)
await message.channel.send(embed=randlevembed)
print(correct_answerS)
if message.content == (correct_answerS):
await message.channel.send("Success!")
else:
await message.channel.send("Fail.")
#client.event
async def on_ready():
print("Ready")
print(client.user.id)
print('--------------------------')
await client.change_presence(activity=discord.Game(name='up and away'))
client.run(Token)
There is no error message, just as soon as I type '!go', it displays the level and then continually says 'Fail.' until I stop it.
I don't know what to do, any help is just that, helpful. Thanks.
The bot is stuck in a loop where it's sending a message, and then processing that message, which causes it to send another message, etc. You can add a check to the beginning of on_message to force it to ignore bot-generated messages:
#client.event
async def on_message(message):
if message.author.bot:
return
...
New python-enthusiast here.
I am currently making a discord bot that responds with 16 pictures in a 4x4-grid when a specific user types in the chat:
XXXX
XXXX
XXXX
XXXX
This is my current code:
import discord
from secrets import TOKEN
from emotes import *
# user IDs
bonvang_ID = "417010736988946444"
djursing_ID = "124806046568022016"
jonathan_ID = "151788707760832512"
alex_ID = "151745760935936001"
snuffles_ID = "221360712222507009"
# bot = commands.Bot(command_prefix='!')
client = discord.Client()
# prints message in terminal when bot is ready
#client.event
async def on_ready():
print(f"Logged in as {client.user}")
# #client.event
# async def on_member_join(member):
# await message.channel.send(f"""Welcome to the server {member}!\n
# I'm just a simple bot made by Mr.Nofox.\n
# If you want to know more about the commands, ask him or try your luck with the others! :)""")
def member_amount():
# create a variable that contains all the servers
active_servers = client.servers
# create a variable to store amount of members per server
sum = 0
# loop through the servers, get all members and add them up, this includes bots
for s in active_servers:
sum += len(s.members)
return sum
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n)
#client.event
async def on_message(message):
# print(f"{message.channel}: {message.author}: \"{message.content}\"")
guild = client.get_all_members()
if "!count()" == message.content:
await client.send_message(message.channel, f"```py\nTotal members: {member_amount()}```")
elif "!report()" == message.content:
online = 0
idle = 0
offline = 0
for member in guild:
if str(member.status) == "online":
online += 1
if str(member.status) == "offline":
offline += 1
if str(member.status) == "idle" or str(member.status) == "dnd":
idle += 1
await client.send_message(message.channel, f"```Online: {online}\nIdle/busy.dnd: {idle}\nOffline: {offline}```")
#TODO: Make a neat function for the pictures in message that responds with 4x4 image in chat when a given user types
if (message.author.id == alex_ID or message.author.id == snuffles_ID):
await client.send_message(message.channel, "DET ER MIN SĆN!")
await client.send_message(message.channel, picture_grid())
# add bot-token found on website
client.run(TOKEN)
All the emotes are in a file called "emotes.py" which I import.
Each emote is a string-code, example:
pic01 = '<:1_:543049824644235265>'
The line I am using to get this to work atm. is:
await client.send_message(message.channel, f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This is awful coding practice and therefore I want to make a function that returns:
f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n"
My initial thought was something like:
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This does the trick and converts the first code to:
await client.send_message(message.channel, picture_grid())
But merely moves the bad code to another place.. I am currently stuck by what should be a simple task.
Any ideas?