I am making a blackjack game using discord.py, I am changing the value of Ace from 11 to 1 instead but no message is being sent to the channel and I am not getting any errors.
def ask_A(self):
num_A = []
for c in range(0, len(self.deck)):
if self.deck[c].get_value() == "A" and self.deck[c].get_points() == 11:
num_A.append(c)
for i in num_A:
message.channel.send(
"Your current cards are " + str(self.print_cards()) + ", Total is " + str(self.sum_cards()) + "\n")
self.deck[i].change_points(1)
message.channel.send("Changed value of Ace to prevent loss")
message.channel.send("Your cards are " + str(self.print_cards()) + ", Total is " + str(self.sum_cards()) + "\n")
You're forgetting to await your statements. Anything in the docs that is a coroutine needs to have await expression.
Example:
await message.channel.send("Hello! This is my message")
Read up about Async IO here.
Related
I would like when a person clicks the button, the code starts from if player1! = player2. But once bet 1000 is written the code is all executed and does not wait for the button to be pressed to confirm player 2
class Counter(nextcord.ui.View):
#THIS IS WHAT HAPPEN WHEN A PLAYER CLICK THE BUTTON
#nextcord.ui.button(label='Join the bet', style=nextcord.ButtonStyle.green)
async def count(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
button.disabled = True
player2 = interaction.user
button.label = 'Bet closed'
with open("opponent", "w") as f:
f.write(str(player2))
print(player2)
await interaction.response.edit_message(view=self)
#THIS IS THE LISTEN OF THE COMMAND BET (AMOUNT)
#client.listen()
async def on_message(message):
if message.content.startswith('bet'):
player1 = message.author
with open("opponent", "w") as f:
f.write(str(player1))
with open("opponent", "r") as f:
player2 = str(f.read())
x = message.content.split(" ")
bet = int(x[1])
try:
with open("Players/"+str(message.author.id), "x") as f:
money = 1000
except:
with open("Players/"+str(message.author.id), "r") as f:
money = int(f.read())
try:
r=random.randint(1,100)
if bet<=money and bet>0:
player1 = str(player1)
await message.channel.send(message.author.mention + " is waiting for a player...", view=Counter())
print(player1)
print(player2)
#check = player1 != player2 THIS DON'T WORK
#await client.wait_for('interaction', check=check) THIS DON'T WORK
if player2 != player1:
print(player2)
if r%2==0:
money = money + bet
with open("Players/"+str(message.author.id), "w") as file:
file.write(str(money))
await message.channel.send(message.author.mention + " won " + str(bet)+ "\n($" + str(money) + ").")
else:
money = money - bet
with open("Players/"+str(message.author.id), "w") as file:
file.write(str(money))
await message.channel.send(message.author.mention + " lost " + str(bet)+ "\n($" + str(money) + ").")
else:
with open("opponent", "r") as f:
player2 = str(f.read())
else:
await message.channel.send(message.author.mention + " you don't have enough money. You only have ($" + str(money) + ").")
except ValueError:
await message.channel.send(message.author.mention + " wrong value.")
I tried using a while and looping if player1! = player2 so that when a player clicks the button the code should start. But since the button is an AWAIT it never updates and it doesn't work as the while loops the code
another problem is that I'm using the files because from what I have seen GLOBAL does not work and I can't bring the variables between functions. for example interaction.user
Put interaction.response.defer at the top of your button's code. It ask discord to wait for your interaction.response since the default response time for bots is 3 seconds only.
#nextcord.ui.button(label='Join the bet', style=nextcord.ButtonStyle.green)
async def count(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
await interaction.response.defer(with_message=True,ephemeral=True)
#do your stuff here
I'm trying to reply a function from another file called "blockchain.py" but when I tried to await for ctx.reply(blq.blockchain_connection) it gives me this on Discord:
<function blockchain_connection at 0x000001922A5AEEF0>
The code is:
# bot = scrt.bot
bot = commands.Bot(command_prefix = "!")
login = 0
blq.tokens_dict
# Login
#bot.event
async def on_ready():
global login
print('We have logged in as {0.user}'.format(bot))
login = 1
my_background_task.start()
# Coin Price Command
#bot.command()
async def coin(ctx, arg1):
if blq.tokens_dict == blq.tokens_dict:
blq.blockchain_connection
else:
await ctx.reply("The token " + str(arg1) + " is not in the token list, if you want to add " + str(arg1) + " to the list please use the command : " + '\n' + "!add_token and insert key and value with an space on each")
#bot.command()
async def add_token(ctx, key, value):
global tokens_dict
if(key in blq.tokens_dict.keys()):
await ctx.reply('I already have this token on my list, please add another Contract or another Value')
else:
blq.tokens_dict[key] = value
This other file (blockchain) has a dict and this function:
async def blockchain_connection(ctx, arg1):
async with aiohttp.ClientSession() as cs:
async with cs.get('https://api.pancakeswap.info/api/v2/tokens/' + tokens_dict[arg1]) as r:
res = await r.json() # returns dict
await ctx.reply(res['data']['price'])
It looks like the issue is here:
# Coin Price Command
#bot.command()
async def coin(ctx, arg1):
if blq.tokens_dict == blq.tokens_dict:
blq.blockchain_connection
else:
await ctx.reply("The token " + str(arg1) + " is not in the token list, if you want to add " + str(arg1) + " to the list please use the command : " + '\n' + "!add_token and insert key and value with an space on each")
blq.blockchain_connection is a function, receiving two arguments, which are named the same. It looks like you have to call it like so:
# Coin Price Command
#bot.command()
async def coin(ctx, arg1):
if blq.tokens_dict == blq.tokens_dict:
await blq.blockchain_connection(ctx, arg1)
else:
await ctx.reply("The token " + str(arg1) + " is not in the token list, if you want to add " + str(arg1) + " to the list please use the command : " + '\n' + "!add_token and insert key and value with an space on each")
This will actually call the function, which then internally (conditionally) calls ctx.reply(...) with the message you actually want to send.
I have some code for a discord bot I am building that I want to make cleaner. Instead of writing a new if statement when a new enemy is made, I would like to check if a user input is already an enemy(class object) and then preform an action on that class object of the same name.
Below is the code for building an enemy.
class EnemyCreator:
type = 'enemy'
def __init__(self, name, enemy_type, health, ap):
self.name = name
self.enemy_type = enemy_type
self.health = health
self.ap = ap
info = (name + ', ' + str(health) + ', ' + str(ap))
npc_info.append(info)
And here is an example enemy:
skeleton = EnemyCreator('Randy Bones', 'skeleton', 100, 2)
I have an attack function:
def attack(enemy):
enemy.health = enemy.health - playerChar.ap
if enemy.health > 0:
playerChar.health = playerChar.health - enemy.ap
return ('You attacked ' + enemy.name + '. ' + str(enemy.health) + ' life remaining. \n'
+ enemy.name + ' attacks back! You take ' + str(enemy.ap) + ' damage. You have ' + str(playerChar.health)
+ ' remaining!')
if enemy.health <= 0:
return enemy.name + ' has been defeated!'
if playerChar.health <= 0:
return 'You died idiot.'
Then I have the input checked with this code:
async def on_message(message):
print(message.content)
if message.author != client.user:
if 'test' in message.content.lower():
print(npc_info)
if '!attack' in message.content.lower():
await message.channel.send(
attack(message.content[8::))
However, this causes an issue because the object passed into the attack(enemy) function is a string, and I need it to be a class object. Any ideas on how to add this functionaliy?
I found a solution. I have made a list of all enemy's along side their name. Then I return the index of the corresponding value to the enemies name. Below is what I came up with.
Enemy creation:
boss = EnemyCreator('Charles Hammerdick', 'boss', 10000, 200)
npc_list.append(boss)
npc_list.append(boss.name)
attack function:
def attack(enemy):
for thing in npc_list:
if str(enemy) in str(thing):
enemy = (npc_list[npc_list.index(thing) - 1])
enemy.health = enemy.health - playerChar.ap
if enemy.health > 0:
playerChar.health = playerChar.health - enemy.ap
return ('You attacked ' + enemy.name + '. ' + str(enemy.health) + ' life remaining. \n'
+ enemy.name + ' attacks back! You take ' + str(enemy.ap) + ' damage. You have ' + str(playerChar.health)
+ ' remaining!')
if enemy.health <= 0:
return enemy.name + ' has been defeated!'
if playerChar.health <= 0:
return 'You died idiot.'
You should have a way of getting the existing enemies.
I will propose something using an in-memory solution, but for a more robust/scalable solution, you should use a database (sqlite, Postgresql, Mysql), and for easy development, an ORM (SQLalchemy or Django).
An EnemyList would be:
class EnemyList:
def __init__(self):
self._enemies = {}
def new_enemy(name, enemy_type, health, ap):
enemy = EnemyCreator(name, enemy_type, health, ap)
self._enemies[name] = enemy
return enemy
def find_enemy(name):
return self._enemies[name]
Then you would need to change your on_message function to use it
async def on_message(message):
print(message.content)
if message.author != client.user:
if 'test' in message.content.lower():
print(npc_info)
if '!attack' in message.content.lower():
await message.channel.send(
attack(EnemyList.find_enemy(message.content[8::)))
This is the short answer, I won't add here other advice because they are not related to the question but you can also check:
String Formating
OO -> The attack function maybe should be a method of a playerChar object?
The DB thing I already spoke of.
I have been making a bot that adds people who react to a message to an array, and then #'s everyone on the array once a goal is met. I have gotten it to send out the message that should # everyone but it just shows the text instead of actually notifying the people. "Names" is the list that it gathers and "send_out" is supposed to format it.
#client.event
async def on_raw_reaction_add(payload):
if payload.message_id == messageid and payload.member.bot == False:
if str(payload.emoji.name) == "🦍":
name = str(payload.member.name + "#" + payload.member.discriminator)
global count
count += 1
global names
names.append(name)
print (names)
if (count == goal_actual):
print("Goal has been reached.")
channel = client.get_channel(channel_id)
await channel.send("We now have " + str(goal_actual) + " for " + game_actual + "!")
print(channel)
global send_out
for x in names:
send_out += ("#" + x +" ")
await channel.send(send_out)
send_out = []
else:
print("Detected reaction from " + name + ". There are is now " , count , " people ready.")
It's best to use the member object that payload gives you
Here (discord.py docs) we can see that discord.on_raw_reaction_add(payload) gives a RawReactionActionEvent object.
RawReactionActionEvent also has a member object, which is a normal member object, this has an attribute member.mention
You could use this instead to tag people
#client.event
async def on_raw_reaction_add(payload):
if payload.message_id == messageid and payload.member.bot == False:
if str(payload.emoji.name) == "🦍":
global count
count += 1
global names
names.append(payload.member)
print (names)
if (count == goal_actual):
print("Goal has been reached.")
channel = client.get_channel(channel_id)
await channel.send("We now have " + str(goal_actual) + " for " + game_actual + "!")
print(channel)
global send_out
for member in names:
send_out += (member.mention)
await channel.send(send_out)
send_out = []
else:
print("Detected reaction from " + name + ". There are is now " , count , " people ready.")
A relatively simple command that takes 3 arguments (reportedTag, reporterTag, and reasons) with the simple intent of deleting the message from #report and sending one to #reported my issue is that it doesn't see the original command and hence does not send the reported message
I've tried using the channel ids, the channel names but to no avail
#---Report Command---#
#bot.command(pass_context=True)
async def report(ctx, reportedTag, reporterTag, *reasons):
if int(ctx.message.channel.id) == 416164062901305345:
reason = ' '.join(reasons)
await bot.delete_message(ctx.message)
mesg = "Report by "+ reporterTag + " for " + reportedTag + "Reason is: " + reason
return await bot.say("Report recieved. Staff have been notified :)\nEnjoy your day and we'll take care of this")
return await bot.send_message(bot.get_channel("534496148149370900"), mesg)
else:
print ("Something went wrong")
Expected result: command line deleted from #report and message sent to #reported
Actual result: "Something went wrong"
Two things wrong:
There's a problem in the return statement you used in the code. return exits a subroutine, so the line bot.send_message(bot.get_channel("534496148149370900"), mesg) is never actually called. So your code should change to something like this:
#---Report Command---#
#bot.command(pass_context=True)
async def report(ctx, reportedTag, reporterTag, *reasons):
if int(ctx.message.channel.id) == 416164062901305345:
reason = ' '.join(reasons)
await bot.delete_message(ctx.message)
mesg = "Report by "+ reporterTag + " for " + reportedTag + "Reason is: " + reason
await bot.send_message(bot.get_channel("534496148149370900"), mesg)
return await bot.say("Report recieved. Staff have been notified :)\nEnjoy your day and we'll take care of this")
else:
print ("Something went wrong")
Apart from that, if "Something went wrong" is actually outputted, that means that int(ctx.message.channel.id) == 416164062901305345 is false. Please check the ID and the channel you're writing in.