feat(aurora): migrated to Red's builtin timedelta/relativedelta parsing
All checks were successful
Actions / Lint Code (Ruff & Pylint) (push) Successful in 26s
Actions / Build Documentation (MkDocs) (push) Successful in 20s

This commit is contained in:
Seaswimmer 2024-03-08 14:19:48 -05:00
parent 6035aea5c6
commit f4efcb8ea5
Signed by: cswimr
GPG key ID: B8953EC01E5C4063
5 changed files with 50 additions and 62 deletions

View file

@ -15,12 +15,11 @@ from math import ceil
import discord import discord
import humanize import humanize
from discord.ext import tasks from discord.ext import tasks
from pytimeparse2 import disable_dateutil, parse
from redbot.core import app_commands, commands, data_manager from redbot.core import app_commands, commands, data_manager
from redbot.core.app_commands import Choice from redbot.core.app_commands import Choice
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import (box, error, humanize_list, from redbot.core.commands.converter import parse_relativedelta, parse_timedelta
warning) from redbot.core.utils.chat_formatting import box, error, humanize_list, warning
from aurora.importers.aurora import ImportAuroraView from aurora.importers.aurora import ImportAuroraView
from aurora.importers.galacticbot import ImportGalacticBotView from aurora.importers.galacticbot import ImportGalacticBotView
@ -29,17 +28,10 @@ from aurora.menus.guild import Guild
from aurora.menus.immune import Immune from aurora.menus.immune import Immune
from aurora.menus.overrides import Overrides from aurora.menus.overrides import Overrides
from aurora.utilities.config import config, register_config from aurora.utilities.config import config, register_config
from aurora.utilities.database import (connect, create_guild_table, fetch_case, from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log
mysql_log) from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed
from aurora.utilities.factory import (addrole_embed, case_factory,
changes_factory, evidenceformat_factory,
guild_embed, immune_embed,
message_factory, overrides_embed)
from aurora.utilities.logger import logger from aurora.utilities.logger import logger
from aurora.utilities.utils import (check_moddable, check_permissions, from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat, timedelta_from_relativedelta
convert_timedelta_to_str,
fetch_channel_dict, fetch_user_dict,
generate_dict, log, send_evidenceformat)
class Aurora(commands.Cog): class Aurora(commands.Cog):
@ -84,7 +76,6 @@ class Aurora(commands.Cog):
super().__init__() super().__init__()
self.bot = bot self.bot = bot
register_config(config) register_config(config)
disable_dateutil()
self.handle_expiry.start() self.handle_expiry.start()
def format_help_for_context(self, ctx: commands.Context) -> str: def format_help_for_context(self, ctx: commands.Context) -> str:
@ -332,13 +323,10 @@ class Aurora(commands.Cog):
return return
if duration is not None: if duration is not None:
try: parsed_time = parse_timedelta(duration)
parsed_time = parse( if parsed_time is None:
sval=duration, as_timedelta=True, raise_exception=True
)
except ValueError:
await interaction.response.send_message( await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True content=error("Please provide a valid duration!"), ephemeral=True
) )
return return
else: else:
@ -440,16 +428,15 @@ class Aurora(commands.Cog):
return return
try: try:
parsed_time = parse(sval=duration, as_timedelta=True, raise_exception=True) parsed_time = parse_timedelta(duration, maximum=timedelta(days=28))
except ValueError: if parsed_time is None:
await interaction.response.send_message( await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True error("Please provide a valid duration!"), ephemeral=True
) )
return return
except commands.BadArgument:
if parsed_time.total_seconds() / 1000 > 2419200000:
await interaction.response.send_message( await interaction.response.send_message(
error("Please provide a duration that is less than 28 days.") error("Please provide a duration that is less than 28 days."), ephemeral=True
) )
return return
@ -684,15 +671,13 @@ class Aurora(commands.Cog):
pass pass
if duration: if duration:
try: parsed_time = parse_relativedelta(duration)
parsed_time = parse( if parsed_time is None:
sval=duration, as_timedelta=True, raise_exception=True
)
except ValueError:
await interaction.response.send_message( await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True content=error("Please provide a valid duration!"), ephemeral=True
) )
return return
parsed_time = timedelta_from_relativedelta(parsed_time)
await interaction.response.send_message( await interaction.response.send_message(
content=f"{target.mention} has been banned for {humanize.precisedelta(parsed_time)}!\n**Reason** - `{reason}`" content=f"{target.mention} has been banned for {humanize.precisedelta(parsed_time)}!\n**Reason** - `{reason}`"
@ -1380,11 +1365,8 @@ class Aurora(commands.Cog):
case_dict = await fetch_case(case, interaction.guild.id) case_dict = await fetch_case(case, interaction.guild.id)
if case_dict: if case_dict:
if duration: if duration:
try: parsed_time = parse_timedelta(duration)
parsed_time = parse( if parsed_time is None:
sval=duration, as_timedelta=True, raise_exception=True
)
except ValueError:
await interaction.response.send_message( await interaction.response.send_message(
error("Please provide a valid duration!"), ephemeral=True error("Please provide a valid duration!"), ephemeral=True
) )
@ -1700,15 +1682,28 @@ class Aurora(commands.Cog):
) )
@aurora.command(aliases=["tdc", "td", "timedeltaconvert"]) @aurora.command(aliases=["tdc", "td", "timedeltaconvert"])
async def timedelta(self, ctx: commands.Context, *, duration: str): async def timedelta(self, ctx: commands.Context, *, duration: str) -> None:
"""This command converts a duration to a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) Python object. """This command converts a duration to a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) Python object.
You cannot convert years or months as they are not fixed units. Use `[p]aurora relativedelta` for that.
**Example usage** **Example usage**
`[p]aurora timedelta 1 day 15hr 82 minutes 52s` `[p]aurora timedelta 1 day 15hr 82 minutes 52s`
**Output** **Output**
`1 day, 16:22:52`""" `1 day, 16:22:52`"""
try: parsed_time = parse_timedelta(duration)
parsed_time = parse(duration, as_timedelta=True, raise_exception=True) if parsed_time is None:
await ctx.send(f"`{str(parsed_time)}`")
except ValueError:
await ctx.send(error("Please provide a convertible value!")) await ctx.send(error("Please provide a convertible value!"))
await ctx.send(f"`{parsed_time}`")
@aurora.command(aliases=["rdc", "rd", "relativedeltaconvert"])
async def relativedelta(self, ctx: commands.Context, *, duration: str) -> None:
"""This command converts a duration to a [`relativedelta`](https://dateutil.readthedocs.io/en/stable/relativedelta.html) Python object.
**Example usage**
`[p]aurora relativedelta 3 years 1 day 15hr 82 minutes 52s`
**Output**
`relativedelta(years=+3, days=+1, hours=+15, minutes=+82, seconds=+52)`"""
parsed_time = parse_relativedelta(duration)
if parsed_time is None:
await ctx.send(error("Please provide a convertible value!"))
await ctx.send(f"`{parsed_time}`")

View file

@ -5,7 +5,7 @@
"short" : "A full replacement for Red's core Mod cogs.", "short" : "A full replacement for Red's core Mod cogs.",
"description" : "Aurora is a fully-featured moderation system. It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.", "description" : "Aurora is a fully-featured moderation system. It is heavily inspired by GalacticBot, and is designed to be a more user-friendly alternative to Red's core Mod cogs. This cog stores all of its data in an SQLite database.",
"end_user_data_statement" : "This cog stores the following information:\n- User IDs of accounts who moderate users or are moderated\n- Guild IDs of guilds with the cog enabled\n- Timestamps of moderations\n- Other information relating to moderations", "end_user_data_statement" : "This cog stores the following information:\n- User IDs of accounts who moderate users or are moderated\n- Guild IDs of guilds with the cog enabled\n- Timestamps of moderations\n- Other information relating to moderations",
"requirements": ["humanize", "pytimeparse2"], "requirements": ["humanize"],
"hidden": false, "hidden": false,
"disabled": false, "disabled": false,
"min_bot_version": "3.5.0", "min_bot_version": "3.5.0",

View file

@ -1,8 +1,10 @@
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
import json import json
from datetime import datetime
from datetime import timedelta as td from datetime import timedelta as td
from typing import Union from typing import Union
from dateutil.relativedelta import relativedelta as rd
from discord import Guild, Interaction, Member, SelectOption, User from discord import Guild, Interaction, Member, SelectOption, User
from discord.errors import Forbidden, NotFound from discord.errors import Forbidden, NotFound
from redbot.core import commands from redbot.core import commands
@ -283,3 +285,9 @@ def create_pagesize_options() -> list[SelectOption]:
) )
) )
return options return options
def timedelta_from_relativedelta(relativedelta: rd) -> td:
"""Converts a relativedelta object to a timedelta object."""
now = datetime.now()
then = now - relativedelta
return now - then

16
poetry.lock generated
View file

@ -1677,20 +1677,6 @@ files = [
[package.dependencies] [package.dependencies]
six = ">=1.5" six = ">=1.5"
[[package]]
name = "pytimeparse2"
version = "1.7.1"
description = "Time expression parser."
optional = false
python-versions = ">=3.6"
files = [
{file = "pytimeparse2-1.7.1-py3-none-any.whl", hash = "sha256:a162ea6a7707fd0bb82dd99556efb783935f51885c8bdced0fce3fffe85ab002"},
{file = "pytimeparse2-1.7.1.tar.gz", hash = "sha256:98668cdcba4890e1789e432e8ea0059ccf72402f13f5d52be15bdfaeb3a8b253"},
]
[package.extras]
dateutil = ["python-dateutil (>=2.8.2,<2.9.0)"]
[[package]] [[package]]
name = "pytz" name = "pytz"
version = "2023.3.post1" version = "2023.3.post1"
@ -2536,4 +2522,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.11,<3.12" python-versions = ">=3.11,<3.12"
content-hash = "a32cda21d6b46347f4432a29a4f4b7b030b36406e030c839a55112670fa335e5" content-hash = "b10a8c8d11a74351402e4663ba61655905a1939aa72701f9905c8a63bfd8f1ed"

View file

@ -9,7 +9,6 @@ readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.11,<3.12" python = ">=3.11,<3.12"
Red-DiscordBot = "^3.5.5" Red-DiscordBot = "^3.5.5"
pytimeparse2 = "^1.7.1"
humanize = "^4.8.0" humanize = "^4.8.0"
py-dactyl = "^2.0.4" py-dactyl = "^2.0.4"
websockets = "^12.0" websockets = "^12.0"