Tempmute command with converting time in discord.py - python

i want to make something like time convert in my discord bot. Now, to use tempmute command, i need to set time only in seconds, and i want to make converting e.g. 1s = 1; 1h = 3600 etc.
Answer, what i found, do not solving my problem.
Here's my code:
# tempmute
#client.command()
#commands.has_permissions(kick_members=True)
async def tempmute(ctx, member: discord.Member, time=0, reason=None):
if not member or time == 0 or time == str:
return
elif reason == None:
reason = 'no reason provided'
tempmuteembed = discord.Embed(colour=discord.Colour.from_rgb(0, 255, 0))
tempmuteembed.set_author(icon_url=member.avatar_url, name=f'{member} has been tempmuted!')
tempmuteembed.set_footer(text=f"{ctx.guild.name} • {datetime.strftime(datetime.now(), '%d.%m.%Y at %I:%M %p')}")
tempmuteembed.add_field(name=f'ID:', value=f'{member.id}', inline=False)
tempmuteembed.add_field(name='Reason:', value=f"{reason}")
tempmuteembed.add_field(name='Duration:', value=f"{time}")
tempmuteembed.add_field(name=f'By:', value=f'{ctx.author.name}#{ctx.author.discriminator}', inline=False)
await ctx.channel.purge(limit=1)
guild = ctx.guild
for role in guild.roles:
if role.name == 'Muted':
await member.add_roles(role)
await ctx.send(embed=tempmuteembed)
await asyncio.sleep(time)
await member.remove_roles(role)
return

If your input may be 15s, 20min, 1h, 2d, your possible solution is:
import re
def tempmute(time=0):
time_list = re.split('(\d+)',time)
if time_list[2] == "s":
time_in_s = int(time_list[1])
if time_list[2] == "min":
time_in_s = int(time_list[1]) * 60
if time_list[2] == "h":
time_in_s = int(time_list[1]) * 60 * 60
if time_list[2] == "d":
time_in_s = int(time_list[1]) * 60 * 60 * 60
return time_in_s
print(tempmute("15h"))
>>> 54000
Update: so the complete code should look something like this. Your Input will be a string, dont return None if its not a string! You input will be in the form of like 15min, 3s or 5h, otherwise the timeout will be 0 seconds.
# tempmute
#client.command()
#commands.has_permissions(kick_members=True)
async def tempmute(ctx, member: discord.Member, time=0, reason=None):
if not member or time == 0:
return
elif reason == None:
reason = 'no reason provided'
try:
if time_list[2] == "s":
time_in_s = int(time_list[1])
if time_list[2] == "min":
time_in_s = int(time_list[1]) * 60
if time_list[2] == "h":
time_in_s = int(time_list[1]) * 60 * 60
if time_list[2] == "d":
time_in_s = int(time_list[1]) * 60 * 60 * 60
except:
time_in_s = 0
tempmuteembed = discord.Embed(colour=discord.Colour.from_rgb(0, 255, 0))
tempmuteembed.set_author(icon_url=member.avatar_url, name=f'{member} has been tempmuted!')
tempmuteembed.set_footer(text=f"{ctx.guild.name} • {datetime.strftime(datetime.now(), '%d.%m.%Y at %I:%M %p')}")
tempmuteembed.add_field(name=f'ID:', value=f'{member.id}', inline=False)
tempmuteembed.add_field(name='Reason:', value=f"{reason}")
tempmuteembed.add_field(name='Duration:', value=f"{time}")
tempmuteembed.add_field(name=f'By:', value=f'{ctx.author.name}#{ctx.author.discriminator}', inline=False)
await ctx.channel.purge(limit=1)
guild = ctx.guild
for role in guild.roles:
if role.name == 'Muted':
await member.add_roles(role)
await ctx.send(embed=tempmuteembed)
await asyncio.sleep(time_in_s)
await member.remove_roles(role)
return

Related

Giveaway Command nextcord

my discord bot needs a giveaway command. it is correctly sending the giveaway message, but for some reason, it isn't capable to determine the winner. this is the command:
#commands.command()
#commands.has_permissions(administrator=True)
async def giveaway(self, ctx, time, winners: int, prize):
channel = ctx.channel
embed = nextcord.Embed(title="Giveaway!",description=f"{prize}",color=nextcord.Color.green())
embed.add_field(name="Giveaway de:", value=ctx.author.mention)
embed.set_footer(text=f"Fini dans {time}!")
msg = await ctx.channel.send(embed=embed)
await msg.add_reaction("🎉")
d = time[-1]
num = int(time[:-1])
if d == "s":
await asyncio.sleep(num)
elif d == "m":
await asyncio.sleep(num * 60)
elif d == "h":
await asyncio.sleep(num * 60 * 60)
elif d == "d":
await asyncio.sleep(num * 60 * 60 * 24)
winners_number = winners[:-1]
new_msg = await channel.fetch_message(msg.id)
users_mention = []
for i in range(winners_number):
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.bot.user))
winner = random.choice(users)
users_mention.append(winner.mention)
users.remove(winner)
await ctx.send(f"Congratulations {users_mention} you won the giveaway !")
error:

I am trying to have my give away time say 5 days reminding instend of 432000 seconds

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

Winners message wont send

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.

DiscordPy Tempmute Command with more than only one duration option

I want to code a temp mute command, but I dont get how to make it, that I can give 2 arguments, not just only one like the code below. I want to make a command like this: "!tempmute #user 1d3h10m1s" and not just only "!tempmute #user 1h" or "!tempmute #user 1s".
Please help me I've spent the hole day on this and I don't get it...
#bot.command(aliases=['tempmute'])
#commands.has_permission(manage_messages=True)
async def mute(ctx, member: discord.Member=None, time=None, *, reason=None):
if not member:
await ctx.send("You must mention a member to mute!")
elif not time:
await ctx.send("You must mention a time!")
else:
if not reason:
reason="No reason given"
#Now timed mute manipulation
try:
seconds = time[:-1] #Gets the numbers from the time argument, start to -1
duration = time[-1] #Gets the timed maniulation, s, m, h, d
if duration == "s":
seconds = seconds * 1
elif duration == "m":
seconds = seconds * 60
elif duration == "h":
seconds = seconds * 60 * 60
elif duration == "d":
seconds = seconds * 86400
else:
await ctx.send("Invalid duration input")
return
except Exception as e:
print(e)
await ctx.send("Invalid time input")
return
guild = ctx.guild
Muted = discord.utils.get(guild.roles, name="Muted")
if not Muted:
Muted = await guild.create_role(name="Muted")
for channel in guild.channels:
await channel.set_permissions(mutedRole, speak=False, send_messages=False, read_message_history=True, read_messages=False)
await member.add_roles(Muted, reason=reason)
muted_embed = discord.Embed(title="Muted a user", description=f"{member.mention} Was muted by {ctx.author.mention} for {reason} to {time}")
await ctx.send(embed=muted_embed)
await asyncio.sleep(seconds)
await member.remove_roles(Muted)
unmute_embed = discord.Embed(title="Mute over!", description=f'{ctx.author.mention} muted to {member.mention} for {reason} is over after {time}")
await ctx.send(embed=unmute_embed)
Since you want your input in the format 1d3h10m1s, we can use regex split to handle the time input.
I haven't checked the rest of your code. But now you have seconds calculated, so give it a go. You're on the right track.
import re
...
#bot.command(aliases=['tempmute'])
#commands.has_permissions(manage_messages=True) # not .has_permission
async def mute(ctx, member:discord.Member=None, userInput=None, *, reason="No reason given"):
inputSplit = re.split('(\d+)', userInput)
# inputSplit looks like ['', '1', 'd', '3', 'h', '10', 'm', '1', 's']
del inputSplit[0]
# inputSplit now looks like ['1', 'd', '3', 'h', '10', 'm', '1', 's']
seconds = 0
# Looping through inputSplit, from first to last letter
for i in range(1, len(inputSplit),2):
timeModifier = inputSplit[i] # Modifier is the letter
timeValue = int(inputSplit[i-1]) # Value is number before modifier
# Same if loop as yours. Checking modifiers and adding the value
if timeModifier == "d":
seconds += 86400 * timeValue
elif timeModifier == "h":
seconds += 3600 * timeValue
elif timeModifier == "m":
seconds += 60 * timeValue
elif timeModifier == "s":
seconds += timeValue
# just for checking
print(f"Timeout time in seconds: {seconds}. Reason: {reason}")
...
From my test:
input:
>> mute #member 1d3h10m1s You know what you did
output:
>> Timeout time in seconds: 97801. Reason: You know what you did

Giveaway command time converting error Discord.Py

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)

Categories

Resources