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