feat: Primitive 'remindme at' support.

This commit is contained in:
2025-06-24 17:33:06 +10:00
parent 75565d2b3c
commit 6988daccf2

View File

@@ -6,6 +6,8 @@ from typing import Optional
from dataclasses import dataclass from dataclasses import dataclass
from collections import defaultdict from collections import defaultdict
from dateutil.parser import ParserError, parse
import twitchio import twitchio
from twitchio.ext import commands from twitchio.ext import commands
import datetime as dt import datetime as dt
@@ -18,9 +20,10 @@ from . import logger
reminder_regex = re.compile( reminder_regex = re.compile(
r""" r"""
(^)?(?P<type> (?: \b in) | (?: every)) (^)?(?P<type> (?: \b in) | (?: every) | (?P<at> at))
\s*(?P<duration> (?: day| hour| (?:\d+\s*(?:(?:d|h|m|s)[a-zA-Z]*)?(?:\s|and)*)+)) \s*
(?:(?(1) (?:, | ; | : | \. | to)? | $)) (?(at) (?P<time> \d?\d (?: :\d\d)?\s*(?: am | pm)?) | (?P<duration> (?: day| hour| (?:\d+\s*(?:(?:d|h|m|s)[a-zA-Z]*)?(?:\s|and)*)+)))
(?:(?(1) (?:, | ; | : | \. | to)?\s+ | $ ))
""", """,
re.IGNORECASE | re.VERBOSE | re.DOTALL re.IGNORECASE | re.VERBOSE | re.DOTALL
) )
@@ -274,20 +277,53 @@ class ReminderCog(LionCog):
# First parse it # First parse it
match = re.search(reminder_regex, args) match = re.search(reminder_regex, args)
if match: if match:
repeating = match.group('type').lower() == 'every' typ = match.group('type').lower().strip()
duration_str = match.group('duration').lower()
if duration_str.isdigit():
# Default to minutes if no unit given
duration = int(duration_str) * 60
elif duration_str in ('day', 'a day'):
duration = 24 * 60 * 60
elif duration_str in ('hour', 'an hour'):
duration = 60 * 60
else:
duration = parse_dur(duration_str)
content = (args[:match.start()] + args[match.end():]).strip() content = (args[:match.start()] + args[match.end():]).strip()
if typ in ('every', 'in'):
repeating = typ == 'every'
duration_str = match.group('duration').lower()
if duration_str.isdigit():
# Default to minutes if no unit given
duration = int(duration_str) * 60
elif duration_str in ('day', 'a day'):
duration = 24 * 60 * 60
elif duration_str in ('hour', 'an hour'):
duration = 60 * 60
else:
duration = parse_dur(duration_str)
elif typ == 'at':
# Get timezone for this member.
profile = await self.bot.get_cog('ProfileCog').fetch_profile_twitch(ctx.author)
timezone = None
discords = await profile.discord_accounts()
if discords:
userid = discords[0].userid
luser = await self.bot.core.lions.fetch_user(userid)
if luser:
timezone = luser.config.timezone.value
if not timezone:
return await ctx.reply(
"Sorry, to use this you have to link your account with `/profiles link twitch` and set your timezone with '/my timezone' on the Discord!"
)
time_str = match.group('time').lower()
if time_str.isdigit():
# Assume it's an hour
time_str = time_str + ':00'
default = dt.datetime.now(tz=timezone).replace(hour=0, minute=0, second=0, microsecond=0)
try:
ts = parse(time_str, fuzzy=True, default=default)
except ParserError:
return await ctx.reply(
"Sorry, I didn't understand your target time! Please use e.g. !remindme Remember to hydrate at 10pm"
)
while ts < dt.datetime.now(tz=timezone):
ts += dt.timedelta(days=1)
duration = (ts - dt.datetime.now(tz=timezone)).total_seconds()
duration = int(duration)
if content.startswith('to '): if content.startswith('to '):
content = content[3:].strip() content = content[3:].strip()
else: else: