didier/didier/utils/discord/converters/time.py

72 lines
2.0 KiB
Python

import contextlib
import datetime
from datetime import date, timedelta
from typing import Optional, Union
import discord
from discord import app_commands
from discord.ext import commands
from overrides import overrides
from didier.utils.discord.autocompletion.time import autocomplete_day
from didier.utils.types.datetime import (
forward_to_next_weekday,
parse_dm_string,
str_to_weekday,
)
__all__ = ["date_converter", "DateTransformer"]
def date_converter(argument: Optional[str]) -> date:
"""Converter to turn a string into a date"""
# Store original argument for error message purposes
original_argument = argument
# Default to today
if not argument:
return date.today()
argument = argument.lower()
# Manual offsets
if argument in (
"tomorrow",
"tmrw",
"morgen",
):
return date.today() + timedelta(days=1)
if argument in ("overmorgen",):
return date.today() + timedelta(days=2)
# Weekdays passed in words
with contextlib.suppress(ValueError):
weekday = str_to_weekday(argument)
return forward_to_next_weekday(date.today(), weekday, allow_today=False)
# Date strings
with contextlib.suppress(ValueError):
return parse_dm_string(argument)
# Unparseable
raise commands.ArgumentParsingError(f"Unable to interpret `{original_argument}` as a date.")
class DateTransformer(commands.Converter, app_commands.Transformer):
"""Application commands transformer for dates"""
@overrides
async def autocomplete(
self, interaction: discord.Interaction, value: Union[int, float, str]
) -> list[app_commands.Choice[Union[int, float, str]]]:
return autocomplete_day(str(value))
@overrides
async def convert(self, ctx: commands.Context, argument: str) -> datetime.date:
return date_converter(argument)
@overrides
async def transform(self, interaction: discord.Interaction, value: str) -> datetime.date:
return date_converter(value)