Discord.py slots command add moving animations of emojis - python

I'm making a Discord bot with Python that's basically an all-in-one bot. One of the features it has is a slot machine system, as part of its economy system. I have already worked out all the logic for the slot machine. My code is really long, so I'm only going to show the slot machine's function:
#bot.command(name="slots")
async def slots(ctx, amount = None):
await open_account(ctx.author)
if amount == None:
await ctx.send("Kid you gotta bet some actual omegas (bob's currency)")
return
bal = await update_bank(ctx.author)
amount = int(amount)
if amount > bal[0]:
await ctx.send("Imaginary omegas don't work here sunny boi, you don't have enough omegas for that transaction")
return
if amount < 0:
await ctx.send("Did ya ever learn about money in school? Give a positive value")
return
final = []
for i in range(3):
a = random.choice([":apple:", ":banana:", ":watermelon:"])
final.append(a)
for i in final:
realfinal = str(final).replace("[", " ")
for j in realfinal:
realREALfinal = str(realfinal).replace("]", " ")
for k in realREALfinal:
absfinal = str(realREALfinal).replace("'", " ")
for l in absfinal:
finalfinal = str(absfinal).replace(",", " | ")
slotem = discord.Embed(title=str(finalfinal), color=0xff9966)
slotem.add_field(name="SLOT MACHINE", value="Let's see if ya win kid")
await ctx.send(embed=slotem)
if final[0] == final[1] or final[0] == final[2] or final[1] == final[2]:
await update_bank(ctx.author, 2*amount, "pocket")
slotwinem = discord.Embed(title=f"Good job kid, you won `Ω{2*amount}`", color=0xccff66)
await ctx.send(embed=slotwinem)
elif final[0] == final[1] == final[2]:
await update_bank(ctx.author, 3*amount, "pocket")
slotallwinem = discord.Embed(title=f"Wow, sweet victory kid, you got `Ω{3*amount}`", color=0xccff66)
await ctx.send(embed=slotallwinem)
else:
await update_bank(ctx.author, -1*amount, "pocket")
slotloseem = discord.Embed(title=f"Oooh, tough luck kid- you lost `Ω{amount}`", color=0xff3300)
await ctx.send(embed=slotloseem)
This code is definitely extremely inefficient, but it works for now. What I want to do is for the slot machine to look like a real slot machine. To be more specific, I want the embed to be edited so all the emojis look like they are scrolling through all the choices. After two seconds, the first emoji scrolling stops and falls into place. After another two seconds, the second emoji falls into its place. After another two seconds, the third emoji falls into place. For example, this is a visual representation of what I mean: https://th.bing.com/th/id/Rd55e38b55c9ae007a4ffa1c5616bccd5?rik=iQ6wFZblIMc4pQ&pid=ImgRaw
How could I replicate this in Discord.py? Thanks.

Related

how to make client.wait_for look at one person

im making a guessing game and im trying to use the client.wait_for function for it but the problem is this function looks at all the messages being sent after you have run it but I want it to only look at one person's messages. I also tried this:
if guess.author != user: return
which did work, it would stop the code if someone else talked when you are using the bot but if someone speaks on another server when you are using the bot it will still be stopped.
if it could only read one person's messages it would be nice.
my full code:
user=message.author
number = random.randint(1, 100)
await message.channel.send('I have a number in mind between 1 and 100, you have 7 guesses, guess.')
for guesses in range(0, 7):
guess = await client.wait_for('message')
if guess.author !=user:
await message.channel.send("sorry game ended cus someone talked mid game.(this can happen if people talk even if not in this sever)")
return
if int(guess.content) < number:
if guesses == 6:
await message.channel.send("Too many guesses, try again.")
await message.channel.send("The number I was thinking of was " + str(number) + ".")
break
else:
await message.channel.send("Higher!")
elif int(guess.content) > number:
if guesses == 6:
await message.channel.send("Too many guesses, try again.")
await message.channel.send("The number I was thinking of was " + str(number) + ".")
break
else:
await message.channel.send("Lower!")
else:
await message.channel.send("You got it! You guessed " + str(guesses + 1) + " times.")
break
You can pass a check to your wait_for like this:
guess = await client.wait_for("message", check=lambda message: message.author.id == user_id)
Using a custom check allows you to actually use custom checks, you can use any method returning a bool, that way you can even use things unrelated to the bot itself, python is the limit.
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
msg = await self.client.wait_for("message", check=check)

Unix Time not displaying correctly | NEXTCORD

I have a bot with a giveaway command.
Info
API: Discord API via Nextcord
Language: Python
The module that interprets time (from human time [1m | 1h | 1d] to seconds): humanfriendly
Expectations
I wanted a sort of... uh... a "ends in" thing. Discord has a built-in Unix Time thingy that's syntax is this:
<t:UNIX:type>
Unix is the UNIX time, type is the- well... type. E.g., R as relative time
Result
Well, I met this when I used 1m (1 minute):
Ends in [some whole 2 months!]
Yes, it appeared as two months there. The actual time was working correctly. The giveaway can end in one minute. But my problem is with the time display.
Code
#commands.command(name="gstart")
#commands.has_permissions(manage_guild=True)
async def gquickStart(self, ctx, gtime, *, gprize: str):
if gtime == None:
return await ctx.send("Include a time.")
elif gprize == None:
return await ctx.send("How are we gonna giveaway nothing?")
gawtime = humanfriendly.parse_timespan(gtime)
gawtimetuple = nextcord.utils.utcnow() + datetime.timedelta(gawtime)
gwembed = nextcord.Embed(
title=f"**:tada: {gprize} :tada:**",
description=f"Ends in <t:{int(time.mktime(gawtimetuple.timetuple()))}:R> <t:{int(time.mktime(gawtimetuple.timetuple()))}:T> \n {ctx.author.mention} is giving away **{gprize}**!",
color=nextcord.Colour.green())
gwemend = nextcord.Embed(
title=f"**:tada: GIVEAWAY ENDED :tada:**",
description = f"{ctx.author.mention} has gave away **{gprize}**!",
color=nextcord.Colour.red()
)
gwembed.set_footer(text=f"Giveaway ends in {gtime}")
gaw_msg = await ctx.send(embed=gwembed)
await ctx.message.delete()
await gaw_msg.add_reaction('🎉')
await asyncio.sleep(gawtime)
global new_gaw_msg
new_gaw_msg = await ctx.channel.fetch_message(gaw_msg.id)
global users
users = await new_gaw_msg.reactions[0].users().flatten()
users.pop(users.index(client.user))
try:
winner = random.choice(users)
await ctx.send(f"{winner.mention} has won the giveaway for **{gprize}**")
await new_gaw_msg.edit(embed=gwemend)
except IndexError:
await new_gaw_msg.reply("1 Winner needed for the giveaway, 0 provided")
await new_gaw_msg.edit(embed=gwemend)
BTW, if it matters, I use the command in a category.
Please answer if you can.
Thanks in advance,
Beedful
Explanation
When constructing the timedelta, the first positional argument is days. So, by adding timedelta(60) to utcnow, you add 60 days to the current time.
An easier method would be simply to convert utcnow to a float with .timestamp(), then sum that with gawtime.
Code
#commands.command(name="gstart")
#commands.has_permissions(manage_guild=True)
async def gquickStart(self, ctx, gtime, *, gprize: str):
if gtime is None:
return await ctx.send("Include a time.")
elif gprize is None:
return await ctx.send("How are we gonna giveaway nothing?")
gawtime = humanfriendly.parse_timespan(gtime)
end_time = nextcord.utils.utcnow().timestamp() + gawtime
gwembed = nextcord.Embed(
title=f"**:tada: {gprize} :tada:**",
description=f"Ends in <t:{int(end_time)}:R> <t:{int(end_time)}:T> \n {ctx.author.mention} is giving away **{gprize}**!",
color=nextcord.Colour.green()
)
Unrelated: From PEP 8
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
Reference
parse_timestamp
utcnow
timedelta

Stopping an "await" in a function, from another function (Discord.py)

So I am new to programming. I decide to take on a project to help me learn how to code. I am currently working on a discord bot using discord.py to create a game similar to the mobile game "BitLife". However, I am running into an issue where I run a command to restart my life and then start a new one directly afterwards and each message is repeated twice.
Here is a simplified version of my code:
import discord
from discord.ext import commands
import asyncio
bot = discord.Client()
TOKEN = 'bot_token'
yesno = ['✅', '❌']
#bot.event
async def on_message(message):
if (message.content.lower() == 'lb! startlife') or (message.content.lower() == 'lb! sl'):
if life == 0 or life == None:
life = 1
#Variables get set up here, such as age
age = 0
await gameRun(message, life)
else:
embed=discord.Embed(title='Hold On!', description='You already have a life started! Please use "LB! ContinueLife" to continue you life, or "LB! Reset" to restart your life.', color=0x0000ff)
await message.reply(embed=embed)
elif (message.content.lower() == 'lb! endlife') or (message.content.lower() == 'lb! el'):
if life == 1:
embed=discord.Embed(title='Are You Sure?', description='You are about to commit suicide and end your life. This CANNOT be reversed. \n\nTo confirm your death, please react with :white_check_mark: below, to cancel, please react with :x: \n\nAction will be canceled automatically after 1 minute!', color=0x0000ff)
botmsg = await message.reply(embed=embed)
for emoji in yesno:
await botmsg.add_reaction(emoji)
def check(reaction, user):
return user == message.author and (str(reaction.emoji) == '✅' or str(reaction.emoji) == '❌')
try:
reaction, user = await bot.wait_for('reaction_add', timeout=60.0, check=check)
except asyncio.TimeoutError:
await message.reply('Action canceled ❌')
else:
if reaction.emoji == '✅':
life = 0
commandLoop = 0
#Death message
elif reaction.emoji == '❌':
await message.reply('Action canceled ❌')
else:
embed=discord.Embed(title='Hold On!', description='You have no life to end! Begin your life by doing "LB! StartLife"', color=0x0000ff)
await message.reply(embed=embed)
elif (message.content.lower() == 'lb! continuelife') or (message.content.lower() == 'lb! cl'):
if life == 1:
if commandLoop == 0:
await gameRun(message, life)
else:
embed=discord.Embed(title='Hold On!', description='You already have a game active. Please wait for the game to timeout to use this command', color=0x0000ff)
await message.reply(embed=embed)
else:
embed=discord.Embed(title='Hold On!', description='You have no life to continue! Please use "LB! StartLife" to start your life.', color=0x0000ff)
await message.reply(embed=embed)
async def gameRun(message, life):
commandLoop = 1
while (life == 1) and (commandLoop == 1):
if (age == 0) and (age < 1):
#Embed is set up here for users to view their stats
botmsg = await message.reply(embed=embed)
await botmsg.add_reaction('🆙')
def check(reaction, user):
return user == message.author and (str(reaction.emoji) == '🆙')
try:
reaction, user = await bot.wait_for('reaction_add', timeout=120.0, check=check)
except asyncio.TimeoutError:
commandLoop = 0
await message.reply('Action timed out, please use "LB! ContinueLife" to continue')
else:
elif reaction.emoji == '🆙':
age = age + 1
elif (age[id] >= 1) and (age[id] < 4):
#Same proccess is repeated just with more options
elif (age[id] >= 4) and (age[id] < 16):
#Same proccess is repeated just with more options
elif (age[id] >= 16) and (age[id] < 18):
#Same proccess is repeated just with more options
else:
#Same proccess is repeated just with more options
I'm almost certain that the reason the messages are repeating is due to the code still waiting for the user to react from the await in "reaction, user = await bot.wait_for('reaction_add', timeout=120.0, check=check)". I need the await in order for the bot to work correctly. I need to know how to get around the await when I use the "LB! EndLife" command.
Here are some pictures that show what happens:
Image 1: First LB! StartLife command
Works fine. Click the reaction, age up, and view the next year's info
Image 2: LB! EndLife command
Ends the life fine as it should
Image 3: Using the LB! StartLife again right after ending the previous life
This is when the bug happens. As shown, when the user reacts, the responding bot message is repeated
Image 4: Reverts back after a timeout
Everything works fine after the timeout. This is what's letting me know that is the "await" that is causing this
I recommend you to use the commands extension, so you can actually write commands, instead of doing everything in an on_message event.
To use that, you'll need commands.Bot instead of discord.Client
Take a look here: https://gist.github.com/dank-tagg/42349435b675573094c5891ce7605f0f
That is so much easier, right?
If you run into any problems, just comment beneath the gist.

How do I choose a number out of a predefined matrix in discord.py?

I have been attempting to code a bot for a client, but as I am self-taught, sometimes the easiest aspects escape me. I know that I have known how to do this before, but I need to fix the following code:
#client.command()
async def rroulette(ctx):
await ctx.send(f"Aye, {ctx.author.mention}! Choose a number beween **1** and **6**! We all know what happens if your number is chosen, though, Comrade! ;)")
rroulette1 = await client.wait_for("Message")
await ctx.send("Alright, Comrade! Here goes nothing!")
await asyncio.sleep(2)
rroulette2 = (random.randint(1, 6))
if rroulette2 == rroulette1.content:
await ctx.send("Oops! The number was " + rroulette1.content + "! You know what that means!")
else:
await ctx.send("Ah, you are safe, Comrade! The number was not yours.")
The bot always responds with the else function, that being that your number is never chosen. I do not know how to fix this.
The overall purpose of the code is, as you probably guessed, to play Russian roulette. If your number is chosen, you get muted for 5 minutes. Any help would be greatly appreciated.
rroulette2 = (random.randint(1, 6))
if rroulette2 == int(rroulette1.content):
await ctx.send("Oops! The number was " + rroulette1.content + "! You know what that means!")
else:
await ctx.send("Ah, you are safe, Comrade! The number was not yours.")
As #Oli said, the content of rroulette1 is always a string, you need to convert it to int and this should work

My python code freezes once it gets to "await ctx.wait_for_message(author=author, timeout=20)" for my discord bot

I have been trying to debug this for ages now and it could just be something really obvious that I just haven't seen but does anyone know what is going on here. I am trying to create a discord bot that can play blackjack and I am trying to ask the user a question in the server, read it and respond. everything else works perfectly fine on the bot but it is just this one part, here is the code for this specific part, I do not get any error it just reaches that line and then doesn't do anything but I can still call other commands. Thanks in advance:)
#bot.command(pass_context=True)
async def blackjack(ctx, bet):
sender = (str(ctx.message.author.name))
author = ctx.message.author
rwallet = open(sender + ".txt", "r")
wallet = rwallet.read()
global dealer_cards
dealer_cards = []
global player_cards
player_cards = []
# Deal the cards
# Display the cards
# Dealer Cards
# Player Cards
while len(dealer_cards) != 2:
dealer_cards.append(random.randint(1, 11))
player_cards.append(random.randint(1, 11))
if len(dealer_cards) == 2:
if len(player_cards) == 2:
print("test")
await ctx.send("Dealer has ? & " + str(dealer_cards[1]) + " You have " + str(player_cards))
# Sum of the Dealer cards
if sum(dealer_cards) == 21:
await ctx.send("Dealer has 21 and wins!")
elif sum(dealer_cards) > 21:
await ctx.send("Dealer has busted!")
# Sum of the Player cards
while sum(player_cards) < 21:
print("test")
await ctx.send(str("Do you want to stay or hit? "))
print("test")
response = await ctx.wait_for_message(author=author, timeout=20,)
if response.content.lower() == "hit":
player_cards.append(random.randint(1, 11))
print("test")
await ctx.send("You now have a total of " + str(sum(player_cards)) + " from these cards ", player_cards)```
There is no wait_for_message function in a context object.
https://discordpy.readthedocs.io/en/latest/migrating.html#waiting-for-events
Prior to v1.0, the machinery for waiting for an event outside of the event itself was done through two different functions, Client.wait_for_message and Client.wait_for_reaction. One problem with one such approach is that it did not allow you to wait for events outside of the ones provided by the library.
In v1.0 the concept of waiting for another event has been generalised to work with any event as Client.wait_for().
You could have fairly easily solved this problem by using a debugger and running
dir(ctx)
I also recommend using their discord server, they have the ability to search the documentation using a bot.

Categories

Resources