diff --git a/README.md b/README.md index 85803db..2e8c3e6 100755 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Main goal of this project is to get Robocop functionality done, secondary goal i

[ ] Reduce code repetition on mod_timed.py -[ ] Allow non-hour values on timed bans +[x] Allow non-hour values on timed bans the following require me to rethink some of the lockdown code, which I don't feel like diff --git a/cogs/common.py b/cogs/common.py index 7759e8d..dd92d0b 100644 --- a/cogs/common.py +++ b/cogs/common.py @@ -2,6 +2,9 @@ import asyncio import traceback import datetime import humanize +import time +import math +import parsedatetime class Common: @@ -18,6 +21,13 @@ class Common: self.bot.aiogetbytes = self.aiogetbytes self.bot.get_relative_timestamp = self.get_relative_timestamp self.bot.escape_message = self.escape_message + self.bot.parse_time = self.parse_time + + def parse_time(self, delta_str): + cal = parsedatetime.Calendar() + time_struct, parse_status = cal.parse(delta_str) + res_timestamp = math.floor(time.mktime(time_struct)) + return res_timestamp def get_relative_timestamp(self, time_from=None, time_to=None, humanized=False, include_from=False, @@ -29,7 +39,7 @@ class Common: if not time_to: time_to = datetime.datetime.utcnow() if humanized: - humanized_string = humanize.naturaltime(time_to - time_from) + humanized_string = humanize.naturaltime(time_from - time_to) if include_from and include_to: str_with_from_and_to = f"{humanized_string} "\ f"({str(time_from).split('.')[0]} "\ @@ -40,7 +50,8 @@ class Common: f"({str(time_from).split('.')[0]})" return str_with_from elif include_to: - str_with_to = f"{humanized_string} ({str(time_to).split('.')[0]})" + str_with_to = f"{humanized_string} "\ + f"({str(time_to).split('.')[0]})" return str_with_to return humanized_string else: diff --git a/cogs/mod_timed.py b/cogs/mod_timed.py index 32bb3c0..6da053c 100644 --- a/cogs/mod_timed.py +++ b/cogs/mod_timed.py @@ -1,6 +1,7 @@ import discord import config import time +from datetime import datetime from discord.ext import commands from helpers.checks import check_if_staff from helpers.robocronp import add_job @@ -20,8 +21,8 @@ class ModTimed: @commands.check(check_if_staff) @commands.command() async def timeban(self, ctx, target: discord.Member, - hours: int, *, reason: str = ""): - """Bans a user for a specified amount of hours, staff only.""" + duration: str, *, reason: str = ""): + """Bans a user for a specified amount of time, staff only.""" # Hedge-proofing the code if target == ctx.author: return await ctx.send("You can't do mod actions on yourself.") @@ -29,7 +30,14 @@ class ModTimed: return await ctx.send("I can't ban this user as " "they're a member of staff.") - userlog(target.id, ctx.author, f"{reason} (Timed, for {hours}h)", + expiry_timestamp = self.bot.parse_time(duration) + expiry_datetime = datetime.utcfromtimestamp(expiry_timestamp) + duration_text = self.bot.get_relative_timestamp(time_to=expiry_datetime, + include_to=True, + humanized=True) + + userlog(target.id, ctx.author, f"{reason} (Timed, until " + f"{duration_text})", "bans", target.name) safe_name = self.bot.escape_message(str(target)) @@ -37,7 +45,7 @@ class ModTimed: dm_message = f"You were banned from {ctx.guild.name}." if reason: dm_message += f" The given reason is: \"{reason}\"." - dm_message += f"\n\nThis ban will expire in {hours} hours." + dm_message += f"\n\nThis ban will expire {duration_text}." try: await target.send(dm_message) @@ -49,7 +57,7 @@ class ModTimed: await target.ban(reason=f"{ctx.author}, reason: {reason}", delete_message_days=0) chan_message = f"⛔ **Timed Ban**: {ctx.author.mention} banned "\ - f"{target.mention} for {hours} hours | {safe_name}\n"\ + f"{target.mention} for {duration_text} | {safe_name}\n"\ f"🏷 __User ID__: {target.id}\n" if reason: chan_message += f"✏️ __Reason__: \"{reason}\"" @@ -58,19 +66,19 @@ class ModTimed: ", it is recommended to use `.ban [reason]`"\ " as the reason is automatically sent to the user." - expiry_timestamp = time.time() + (hours * 3600) add_job("unban", target.id, {"guild": ctx.guild.id}, expiry_timestamp) log_channel = self.bot.get_channel(config.log_channel) await log_channel.send(chan_message) - await ctx.send(f"{safe_name} is now b& for {hours} hours. 👍") + await ctx.send(f"{safe_name} is now b&. " + f"It will expire {duration_text}. 👍") @commands.guild_only() @commands.check(check_if_staff) @commands.command() async def timemute(self, ctx, target: discord.Member, - hours: int, *, reason: str = ""): - """Mutes a user for a specified amount of hours, staff only.""" + duration: str, *, reason: str = ""): + """Mutes a user for a specified amount of time, staff only.""" # Hedge-proofing the code if target == ctx.author: return await ctx.send("You can't do mod actions on yourself.") @@ -78,7 +86,14 @@ class ModTimed: return await ctx.send("I can't mute this user as " "they're a member of staff.") - userlog(target.id, ctx.author, f"{reason} (Timed, for {hours}h)", + expiry_timestamp = self.bot.parse_time(duration) + expiry_datetime = datetime.utcfromtimestamp(expiry_timestamp) + duration_text = self.bot.get_relative_timestamp(time_to=expiry_datetime, + include_to=True, + humanized=True) + + userlog(target.id, ctx.author, f"{reason} (Timed, until " + f"{duration_text})", "mutes", target.name) safe_name = self.bot.escape_message(str(target)) @@ -86,7 +101,7 @@ class ModTimed: dm_message = f"You were muted!" if reason: dm_message += f" The given reason is: \"{reason}\"." - dm_message += f"\n\nThis mute will expire in {hours} hours." + dm_message += f"\n\nThis mute will expire {duration_text}." try: await target.send(dm_message) @@ -100,7 +115,7 @@ class ModTimed: await target.add_roles(mute_role, reason=str(ctx.author)) chan_message = f"🔇 **Timed Mute**: {ctx.author.mention} muted "\ - f"{target.mention} for {hours} hours | {safe_name}\n"\ + f"{target.mention} for {duration_text} | {safe_name}\n"\ f"🏷 __User ID__: {target.id}\n" if reason: chan_message += f"✏️ __Reason__: \"{reason}\"" @@ -109,12 +124,12 @@ class ModTimed: "it is recommended to use `.mute [reason]`"\ " as the reason is automatically sent to the user." - expiry_timestamp = time.time() + (hours * 3600) add_job("unmute", target.id, {"guild": ctx.guild.id}, expiry_timestamp) log_channel = self.bot.get_channel(config.log_channel) await log_channel.send(chan_message) - await ctx.send(f"{target.mention} can no longer speak.") + await ctx.send(f"{target.mention} can no longer speak. " + f"It will expire {duration_text}.") add_restriction(target.id, config.mute_role) diff --git a/requirements.txt b/requirements.txt index 0ad0d08..de97058 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ git+https://github.com/Rapptz/discord.py@rewrite asyncio python-dateutil -humanize \ No newline at end of file +humanize +parsedatetime \ No newline at end of file