fix: parse dates using group's timezone when adding/updating bounties

The parse_args function now accepts timezone_str parameter and uses it
to localize parsed dates. This ensures dates are interpreted in the
group's timezone, not the server's local timezone.
This commit is contained in:
shokollm
2026-04-05 00:25:59 +00:00
parent 58614fbda2
commit cecf71da5d

View File

@@ -59,6 +59,7 @@ def extract_args(text: str) -> list[str]:
def parse_args(
args: list[str],
timezone_str: str = "UTC",
) -> tuple[Optional[str], Optional[str], Optional[int], bool, bool]:
text = None
link = None
@@ -66,6 +67,11 @@ def parse_args(
clear_link = False
clear_date = False
try:
tz = ZoneInfo(timezone_str)
except (KeyError, ZoneInfoNotFoundError):
tz = ZoneInfo("UTC")
def is_url(s: str) -> bool:
if not s:
return False
@@ -87,6 +93,13 @@ def parse_args(
except ValueError:
return False
def parse_date_with_tz(date_str: str) -> int | None:
parsed = dateparser.parse(date_str)
if parsed:
localized = parsed.replace(tzinfo=tz)
return int(localized.timestamp())
return None
i = 0
while i < len(args):
arg = args[i]
@@ -100,9 +113,8 @@ def parse_args(
i += 1
elif arg == "-date":
if i + 1 < len(args):
parsed = dateparser.parse(args[i + 1])
if parsed:
due_date_ts = int(parsed.timestamp())
due_date_ts = parse_date_with_tz(args[i + 1])
if due_date_ts is not None:
i += 2
if i < len(args) and is_time(args[i]):
time_parts = args[i].split(":")
@@ -120,9 +132,8 @@ def parse_args(
link = arg
i += 1
elif due_date_ts is None:
parsed = dateparser.parse(arg)
if parsed:
due_date_ts = int(parsed.timestamp())
due_date_ts = parse_date_with_tz(arg)
if due_date_ts is not None:
i += 1
if i < len(args) and is_time(args[i]):
time_parts = args[i].split(":")
@@ -343,14 +354,15 @@ async def cmd_add(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
)
return
text, link, due_date_ts, _, _ = parse_args(args)
user_id = get_user_id(update)
room_id = get_room_id(update)
timezone_str = BOUNTY_SERVICE.get_timezone(room_id)
text, link, due_date_ts, _, _ = parse_args(args, timezone_str)
if not text and not link:
await update.message.reply_text("A bounty needs at least text or a link.")
return
user_id = get_user_id(update)
room_id = get_room_id(update)
try:
bounty = BOUNTY_SERVICE.add_bounty(
room_id=room_id,
@@ -397,7 +409,11 @@ async def cmd_update(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Invalid bounty ID.")
return
text, link, due_date_ts, clear_link, clear_date = parse_args(args[1:])
user_id = get_user_id(update)
room_id = get_room_id(update)
timezone_str = BOUNTY_SERVICE.get_timezone(room_id)
text, link, due_date_ts, clear_link, clear_date = parse_args(args[1:], timezone_str)
if (
not text
and not link
@@ -408,9 +424,6 @@ async def cmd_update(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Nothing to update.")
return
user_id = get_user_id(update)
room_id = get_room_id(update)
old_bounty = BOUNTY_SERVICE.get_bounty(room_id, bounty_id)
if not old_bounty:
await update.message.reply_text("Bounty not found.")