def convert(time):
time_dict = {"s": "seconds", "m": "minutes", "h": "hours", "d": "days"} # pulling your idea, but replacing the seconds with the full name of the acronym.
val = time[:-1] # everything before the last character
unit = time[-1] # the last character
return f"{val} {time_dict[unit]}"
convert("5d") # 5 days
convert("10s") # 10 seconds
#client.command()
#commands.has_permissions(manage_messages=True)
async def gcreate(ctx, time: str, *, prize: str):
time = convert(time)
embed = discord.Embed(title=prize,
description=f"Hosted by - {ctx.author.mention} React with :tada: to enter! Time Remaining: **{time}**",
colour = discord.Colour.purple())
msg = await ctx.channel.send(content=":tada: **GIVEAWAY** :tada:", embed=embed)
await msg.add_reaction("🎉")
await asyncio.sleep(3)
await asyncio.sleep(int(time))
new_msg = await ctx.channel.fetch_message(msg.id)
user_list = [user for user in await new_msg.reactions[0].users().flatten() if
user != client.user]
if len(user_list) == 0:
await ctx.send("No one reacted.")
else:
winner = random.choice(user_list)
await ctx.send(f"{winner.mention} You have won the {prize}!")
I get no errors, it just won't send the winner message.
Related
def convert(time):
pos = ["s", "m", "h", "d"]
time_dict = {"s": 1, "m": 60, "h": 3600, "d": 3600 * 24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#client.command()
#commands.has_permissions(manage_messages=True)
async def gcreate(ctx, time: str, *, prize: str):
time = convert(time)
embed = discord.Embed(title=prize,
description=f"Hosted by - {ctx.author.mention} React with :tada: to enter! Time Remaining: **{time}** seconds",
colour = discord.Colour.purple())
msg = await ctx.channel.send(content=":tada: **GIVEAWAY** :tada:", embed=embed)
await msg.add_reaction("🎉")
await asyncio.sleep(3)
await asyncio.sleep(int(time))
new_msg = await ctx.channel.fetch_message(msg.id)
user_list = [user for user in await new_msg.reactions[0].users().flatten() if
user != client.user]
if len(user_list) == 0:
await ctx.send("No one reacted.")
else:
winner = random.choice(user_list)
await ctx.send(f"{winner.mention} You have won the {prize}!")
Modify your convert method to return a formatted string of your specification instead of the seconds as it does right now. Below is an example implementation:
def convert(time):
time_dict = {"s": "seconds", "m": "minutes", "h": "hours", "d": "days"} # pulling your idea, but replacing the seconds with the full name of the acronym.
val = time[:-1] # everything before the last character
unit = time[-1] # the last character
return f"{val} {time_dict[unit]}" self explanatory, returns a string of your preference.
convert("5d") # 5 days
convert("10s") # 10 seconds
I am doing a giveaway command call =gstart <time> <prize and the giveaway will be held in the channel I use this command and After sending the embed giveaway message it will delete the gstart command. Here is the code:
#bot.command()
async def gstart(ctx,time,*,prize):
time = convert(time)
if time == -1:
await ctx.send("Error, can't identify time unit")
if time == -2:
await ctx.send("Error, can't identify time value")
embed = discord.Embed(title=prize, description = f"React with :tada: to enter\nHosted by: {ctx.author.mention}", color=discord.Color.red())
embed.set_footer(text = f"Ends at {time} from now!")
#delete-command
await ctx.send(":tada: **GIVEAWAY** :tada:")
my_msg = await ctx.send(embed = embed)
await my_msg.add_reaction("🎉")
await asyncio.sleep(time)
new_msg = await ctx.fetch_message(my_msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(bot.user))
winner = random.choice(users)
await ctx.send(f"Congratulations {winner.mention}! You won the {prize}!")
msg_link = my_msg.jump_url
winner_embed = discord.Embed(title=f"Hey {winner}",description=f"You just won a [giveaway]({msg_link}) in {ctx.guild}",color=discord.Color.red())
winner_embed.add_field(name=prize,value=f"Hosted by: {ctx.author.mention}",inline=True)
await winner.send(embed=winner_embed)
By the way the convert() function looks like this:
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d" : 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
Reply you with the discord.Context object and delete the message user sent.
Example:
import asyncio
#bot.command()
async def deleteCommandAfterSent(ctx):
await ctx.send("blablabla ") #REPLY MESSAGE
await asyncio.sleep(1)
await ctx.message.delete()
Here is the code I have, the time is not being converted, and I don't know what to do anymore. If you know what to do, let me know how to do this
Here is what I got so far:
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d": 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
#---------------------------------------------------------------------------
#client.command()
#commands.has_permissions(manage_messages = True)
async def giveaway(ctx, time : str, *, prize: str):
embed = discord.Embed(title=prize,
description=f"Hosted by - {ctx.author.mention}\nReact with :tada: to enter!\nTime Remaining: **{time}** seconds",
color=ctx.guild.me.top_role.color, )
msg = await ctx.channel.send(content=":tada: **GIVEAWAY** :tada:", embed=embed)
await msg.add_reaction("🎉")
await asyncio.sleep(3)
new_msg = await ctx.channel.fetch_message(msg.id)
user_list = [u for u in await new_msg.reactions[0].users().flatten() if u != client.user] # Check the reactions/don't count the bot reaction
if len(user_list) == 0:
await ctx.send("No one reacted.")
else:
winner = random.choice(user_list)
await ctx.send(f"{winner.mention} You have won the {prize}!")
When I type in 2m meaning 2 minutes, it shows 2m seconds remaining, now I know why it says seconds because I have not updated the response yet, but the time is only 2 seconds plus the 3 seconds delay time. Basically a total of around 6 seconds.
I did just throw 2 commands from stack overflow together, and it is like putting in a Lamborghini head gasket and a dodge engine block, I know it should not work, even with the little bit of modifications, I kinda do see whats wrong now, but I don't know how to fix it
So I revised your code and changed the giveaway command a little bit. After a few modifications, the command worked as it should for me. Here is how I re-defined it:
def convert(time):
pos = ["s", "m", "h", "d"]
time_dict = {"s": 1, "m": 60, "h": 3600, "d": 3600 * 24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
# ---------------------------------------------------------------------------
#client.command()
#commands.has_permissions(manage_messages=True)
async def giveaway(ctx, time: str, *, prize: str):
time = convert(time)
embed = discord.Embed(title=prize,
description=f"Hosted by - {ctx.author.mention}\nReact with :tada: to enter!\nTime Remaining: **{time}** seconds",
color=ctx.guild.me.top_role.color)
msg = await ctx.channel.send(content=":tada: **GIVEAWAY** :tada:", embed=embed)
await msg.add_reaction("🎉")
await asyncio.sleep(3)
await asyncio.sleep(int(time))
new_msg = await ctx.channel.fetch_message(msg.id)
user_list = [user for user in await new_msg.reactions[0].users().flatten() if
user != client.user] # Check the reactions/don't count the bot reaction
if len(user_list) == 0:
await ctx.send("No one reacted.")
else:
winner = random.choice(user_list)
await ctx.send(f"{winner.mention} You have won the {prize}!")
You can use this for converting time.
import re
from discord.ext.commands import BadArgument
time_regex = re.compile(r"(?:(\d{1,5})(h|s|m|d))+?")
time_dict = {"h": 3600, "s": 1, "m": 60, "d": 86400}
def convert(argument):
args = argument.lower()
matches = re.findall(time_regex, args)
time = 0
for key, value in matches:
try:
time += time_dict[value] * float(key)
except:
raise BadArgument
return round(time)
I was trying to create a discord bot with giveaway command which updates time left every 1-2 mins in giveaway embed . I have been trying it since 3 days but wasn't able to find a solution. I managed to make it update seconds, but if I specify time more than 1m i.e. 60 seconds it automatically converts it to seconds and starts giveaway with time left in just seconds . I want it to keep time in given unit and update time in --days, --hours, --minutes, --seconds left.
Here are a few images what i mean:
What it currently do:
What i want it to do:
Its just Ends In Or Time remaining what i want to be changed!
My current code:
#commands.command()
#commands.guild_only()
async def gstart(self, ctx, duration, *, prize):
time = self.convert(duration)
if time == -1:
await ctx.send(f'Answer Time With A Proper Unit (s, m, h, d)')
return
elif time == -2:
await ctx.send(f'Time Must Be A Integer!')
return
giveawayembed = discord.Embed(
title="🎉 New Giveaway! 🎉",
description=f"**Prize:** {prize}\n"
f"**Hosted By:** {ctx.author.mention}\n"
f"**Ends In:** {time} Seconds",
colour=discord.Color.green()
)
msg = await ctx.send(embed=giveawayembed)
reactions = await msg.add_reaction("🎉")
while time:
await sleep(10)
time -= 10
giveawayembed.description= f"**Prize:** {prize}\n**Hosted By:** {ctx.author.mention}\n**Ends In:** {time} Seconds"
await msg.edit(embed=giveawayembed)
new_msg = await ctx.fetch_message(msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
endembed = discord.Embed(
title="Giveaway ended!",
description=f"Prize: {prize}\nWinner: {winner.mention}")
await msg.edit(embed=endembed)
await ctx.send(f"🎉 Giveaway Winner: {winner.mention} | Prize: {prize}")
For Converting Time I Have:
class Giveaway(commands.Cog):
def __init__(self, client):
self.client = client
def convert(self, time):
pos = ["s", "m", "h", "d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d" : 3600*24}
unit = time[-1]
if unit not in pos:
return -1
try:
val = int(time[:-1])
except:
return -2
return val * time_dict[unit]
Any help is highly appreciated! 😁
And I m sorry if I wasn't able to make you understand my problem. 😅
I understand your problem as it is actually a very simple fix, you can either import time, or use await asyncio.sleep(time)
Before using the code I am providing, make sure to import asyncio in your imports.
Your code:
#commands.command()
#commands.guild_only()
async def gstart(self, ctx, duration, *, prize):
time = self.convert(duration)
if time == -1:
await ctx.send(f'Answer Time With A Proper Unit (s, m, h, d)')
return
elif time == -2:
await ctx.send(f'Time Must Be A Integer!')
return
giveawayembed = discord.Embed(
title="🎉 New Giveaway! 🎉",
description=f"**Prize:** {prize}\n"
f"**Hosted By:** {ctx.author.mention}\n"
f"**Ends In:** {time} Seconds",
colour=discord.Color.green()
)
msg = await ctx.send(embed=giveawayembed)
reactions = await msg.add_reaction("🎉")
while time:
await sleep(10)
time -= 10
giveawayembed.description= f"**Prize:** {prize}\n**Hosted By:** {ctx.author.mention}\n**Ends In:** {time} Seconds"
await msg.edit(embed=giveawayembed)
new_msg = await ctx.fetch_message(msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
endembed = discord.Embed(
title="Giveaway ended!",
description=f"Prize: {prize}\nWinner: {winner.mention}")
await msg.edit(embed=endembed)
await ctx.send(f"🎉 Giveaway Winner: {winner.mention} | Prize: {prize}")
In both fixes I will fix a slight problem that could easily be fixed, you have it so while time, it will go down by 10, I recommend doing it so it says while time > 0: so that once it hits 0 it wont keep counting down.
Easy fix using await asyncio.sleep(time):
#commands.command()
#commands.guild_only()
async def gstart(self, ctx, duration, *, prize):
time = self.convert(duration)
if time == -1:
await ctx.send(f'Answer Time With A Proper Unit (s, m, h, d)')
return
elif time == -2:
await ctx.send(f'Time Must Be A Integer!')
return
giveawayembed = discord.Embed(
title="🎉 New Giveaway! 🎉",
description=f"**Prize:** {prize}\n"
f"**Hosted By:** {ctx.author.mention}\n"
f"**Ends In:** {time} Seconds",
colour=discord.Color.green()
)
msg = await ctx.send(embed=giveawayembed)
reactions = await msg.add_reaction("🎉")
while time >= 0:
if time <= 60:
giveaway.remove_field(index=1)
giveaway.insert_field_at(index=1, name='Ends:', value=f'{time} second(s) from now')
await my_msg.edit(embed=giveaway)
time -= 10
await asyncio.sleep(10)
elif 60 <= time < 3600:
giveaway.remove_field(index=1)
giveaway.insert_field_at(index=1, name='Ends:', value=f'{time/60} minute(s) from now')
await my_msg.edit(embed=giveaway)
time -= 6
await asyncio.sleep(6)
elif 3600 <= time < 86400:
giveaway.remove_field(index=1)
giveaway.insert_field_at(index=1, name='Ends:', value=f'{time/3600} hour(s) from now')
await my_msg.edit(embed=giveaway)
time -= 360
await asyncio.sleep(360)
elif time >= 86400:
giveaway.remove_field(index=1)
giveaway.insert_field_at(index=1, name='Ends:', value=f'{time/86400} day(s) from now')
await my_msg.edit(embed=giveaway)
time -= 8640
await asyncio.sleep(8640)
if time <= 0:
giveaway.remove_field(index=1)
giveaway.insert_field_at(index=1, name='Ends:', value=f'Ended at {datetime.datetime.now().strftime("%B %d, %I:%M %p")}') # noqa
await my_msg.edit(embed=giveaway)
await asyncio.sleep(time)
new_msg = await ctx.fetch_message(msg.id)
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
endembed = discord.Embed(
title="Giveaway ended!",
description=f"Prize: {prize}\nWinner: {winner.mention}")
await msg.edit(embed=endembed)
await ctx.send(f"🎉 Giveaway Winner: {winner.mention} | Prize: {prize}")
If you are still confused or have any more questions you can contact me on discord at killrebeest#7187 or comment on this answer. Have a good day!
I have a background loop that will spit out an emoji every X amount of minutes with a reaction attached to it. I want for when someone presses on the reaction of the message, it will delete the message and then send another message saying "messageauthor has grabbed the loot" and then add the amount to the cash json file.
Right now, my code is making the background loop work, but I am not sure how to grab the message.author.id in regards to the background loop so I can reference it in on_reaction_add. The current code is making the bot react once when it spits out the background loop and then again in on_reaction_add. I'm trying to make it wait for a user to react to the background loop message with the same emoji and not the bot.
client = discord.Client()
emoji_msg_grab = {}
try:
with open("cash.json") as fp:
cash = json.load(fp)
except Exception:
cash = {}
def save_cash():
with open("cash.json", "w+") as fp:
json.dump(cash, fp, sort_keys=True, indent=4)
def add_dollars(user: discord.User, dollars: int):
id = user.id
if id not in cash:
cash[id] = {}
cash[id]["dollars"] = cash[id].get("dollars", 0) + dollars
print("{} now has {} dollars".format(user.name, cash[id]["dollars"]))
save_cash()
async def background_loop():
await client.wait_until_ready()
while not client.is_closed:
channel = client.get_channel("479919577279758340")
emojigrab = '💰'
emojimsgid = await client.send_message(channel, emojigrab)
await client.add_reaction(emojimsgid, "💵")
user_id = emojimsgid.author.id
emoji_msg_grab[user_id] = {"emoji_msg_id": emojimsgid.id, "emoji_user_id": user_id}
await asyncio.sleep(600)
#client.event
async def on_reaction_add(reaction, user):
msgid = reaction.message.id
chat = reaction.message.channel
if reaction.emoji == "💵" and msgid == emoji_msg_grab[user.id]["emoji_msg_id"] and user.id == emoji_msg_grab[user.id]["emoji_user_id"]:
emoji_msg_grab[user.id]["emoji_msg_id"] = None
await client.send_message(chat, "{} has grabbed the loot!".format(user.mention))
await client.delete_message(reaction.message)
add_dollars(user, 250)
client.loop.create_task(background_loop())
I would use Client.wait_for_reaction instead of on_reaction_add:
async def background_loop():
await client.wait_until_ready()
channel = client.get_channel("479919577279758340")
while not client.is_closed:
emojigrab = '💰'
emojimsg = await client.send_message(channel, emojigrab)
await client.add_reaction(emojimsg, "💵")
res = await client.wait_for_reaction(emoji="💵", message=emojimsg, timeout=600,
check=lambda reaction, user: user != client.user)
if res: # not None
await client.delete_message(emojimsg)
await client.send_message(channel, "{} has grabbed the loot!".format(res.user.mention))
await asyncio.sleep(1)
add_dollars(res.user, 250)