From 6da16e752b2920f53b9b75e96a9bfa740755bd80 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Sat, 4 Apr 2026 08:14:58 +0000 Subject: [PATCH] feat: implement /timezone command to get/set room timezone Re-implement the timezone command that was reverted. - Add cmd_timezone function with get/set functionality - Validate timezone using zoneinfo (IANA format) - Admin-only permission via service layer - Update help text and bot command list - Fix indentation bug in cmd_add (duplicate lines) Fixes #53 --- apps/telegram-bot/bot.py | 3 +++ apps/telegram-bot/commands.py | 39 +++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/telegram-bot/bot.py b/apps/telegram-bot/bot.py index 5d30328..e5e39c7 100644 --- a/apps/telegram-bot/bot.py +++ b/apps/telegram-bot/bot.py @@ -15,6 +15,7 @@ from commands import ( cmd_my, cmd_show, cmd_start, + cmd_timezone, cmd_track, cmd_untrack, cmd_update, @@ -43,6 +44,7 @@ def build_app() -> Application: app.add_handler(CommandHandler("track", cmd_track)) app.add_handler(CommandHandler("untrack", cmd_untrack)) app.add_handler(CommandHandler("show", cmd_show)) + app.add_handler(CommandHandler("timezone", cmd_timezone)) app.add_handler(MessageHandler(filters.COMMAND, cmd_help)) @@ -59,6 +61,7 @@ async def post_init(app: Application) -> None: ("track", "Track a bounty"), ("untrack", "Stop tracking"), ("show", "Show bounty details"), + ("timezone", "Get/set room timezone"), ("help", "Show help"), ] ) diff --git a/apps/telegram-bot/commands.py b/apps/telegram-bot/commands.py index 243d9d1..0b7d390 100644 --- a/apps/telegram-bot/commands.py +++ b/apps/telegram-bot/commands.py @@ -3,6 +3,7 @@ import time from functools import wraps from typing import Optional +from zoneinfo import ZoneInfo, ZoneInfoNotFoundError import dateparser from telegram import Update @@ -19,7 +20,6 @@ TRACKING_SERVICE = TrackingService(TRACKING_STORAGE, ROOM_STORAGE) TELEGRAM_BOT_USERNAME = "your_bot_username" - def extract_args(text: str) -> list[str]: if not text: return [] @@ -241,9 +241,7 @@ async def cmd_add(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: due_str = "" if due_date_ts: - due_str = "" - if due_date_ts: - due_str = f" | Due: {time.strftime("%Y-%m-%d", time.localtime(due_date_ts))}" + due_str = f" | Due: {time.strftime('%Y-%m-%d', time.localtime(due_date_ts))}" await update.message.reply_text( f"✅ Bounty added (#{bounty.id}){due_str}", disable_web_page_preview=True, @@ -458,6 +456,35 @@ async def cmd_show(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text("\n".join(lines), disable_web_page_preview=True) +async def cmd_timezone(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: + args = extract_args(update.message.text) + room_id = get_room_id(update) + user_id = get_user_id(update) + + if not args: + current_tz = BOUNTY_SERVICE.get_timezone(room_id) + await update.message.reply_text(f"Current timezone: {current_tz}") + return + + timezone_str = args[0] + + try: + ZoneInfo(timezone_str) + except (KeyError, ZoneInfoNotFoundError): + await update.message.reply_text( + "⛔ Invalid timezone. Use IANA format (e.g., Asia/Jakarta)" + ) + return + + try: + BOUNTY_SERVICE.set_timezone(room_id, timezone_str, user_id) + except PermissionError as e: + await update.message.reply_text(f"⛔ {e}") + return + + await update.message.reply_text(f"✅ Timezone set to {timezone_str}.") + + async def cmd_help(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text( "👻 JIGAIDO Commands:\n\n" @@ -472,9 +499,9 @@ async def cmd_help(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: "/track — track a bounty (groups only)\n" "/untrack — stop tracking (groups only)\n" "/show — show bounty details\n" + "/timezone — get room timezone\n" + "/timezone — set room timezone (admin only)\n" "/start — re-initialize\n" "/help — this message", disable_web_page_preview=True, ) - -