diff --git a/apps/telegram-bot/bot.py b/apps/telegram-bot/bot.py index 5d30328..e2879d8 100644 --- a/apps/telegram-bot/bot.py +++ b/apps/telegram-bot/bot.py @@ -8,6 +8,7 @@ from telegram.ext import Application, CommandHandler, MessageHandler, filters from commands import ( cmd_add, + cmd_admin, cmd_bounty, cmd_delete, cmd_edit, @@ -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("admin", cmd_admin)) 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"), + ("admin", "Manage admins"), ("help", "Show help"), ] ) diff --git a/apps/telegram-bot/commands.py b/apps/telegram-bot/commands.py index 243d9d1..029a08b 100644 --- a/apps/telegram-bot/commands.py +++ b/apps/telegram-bot/commands.py @@ -19,7 +19,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 +240,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 +455,65 @@ async def cmd_show(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text("\n".join(lines), disable_web_page_preview=True) +def _find_user_id_by_username(room_id: int, username: str) -> int | None: + """Find user_id by username from bounty creators in the room.""" + bounties = BOUNTY_SERVICE.list_bounties(room_id) + for bounty in bounties: + if ( + bounty.created_by_username + and bounty.created_by_username.lower() == username.lower() + ): + return bounty.created_by_user_id + return None + + +async def cmd_admin(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: + args = extract_args(update.message.text) + if not args or args[0] not in ("add", "remove"): + await update.message.reply_text( + "Usage:\n" + "/admin add @username — add admin\n" + "/admin remove @username — remove admin" + ) + return + + subcommand = args[0] + + if len(args) < 2: + await update.message.reply_text(f"Usage: /admin {subcommand} @username") + return + + raw_username = args[1] + if not raw_username.startswith("@"): + await update.message.reply_text(f"Usage: /admin {subcommand} @username") + return + + username = raw_username[1:] + + user_id = get_user_id(update) + room_id = get_room_id(update) + + if not BOUNTY_SERVICE.is_admin(room_id, user_id): + await update.message.reply_text("⛔ Only admins can perform this action.") + return + + target_user_id = _find_user_id_by_username(room_id, username) + + if target_user_id is None: + await update.message.reply_text(f"⛔ User @{username} not found.") + return + + try: + if subcommand == "add": + BOUNTY_SERVICE.add_admin(room_id, target_user_id, user_id) + await update.message.reply_text(f"✅ @{username} is now an admin.") + elif subcommand == "remove": + BOUNTY_SERVICE.remove_admin(room_id, target_user_id, user_id) + await update.message.reply_text(f"✅ @{username} is no longer an admin.") + except PermissionError as e: + await update.message.reply_text(f"⛔ {e}") + + async def cmd_help(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text( "👻 JIGAIDO Commands:\n\n" @@ -476,5 +532,3 @@ async def cmd_help(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: "/help — this message", disable_web_page_preview=True, ) - -