feat: implement /admin add|remove @username command

- Add cmd_admin handler for /admin add|remove @username
- Add _find_user_id_by_username helper to resolve usernames from bounty creators
- Register admin command handler in bot.py
- Add 'admin' to bot command list
- Addresses issue #51
This commit is contained in:
shokollm
2026-04-04 08:20:35 +00:00
parent e805a6428a
commit ce864d9fdc
2 changed files with 62 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ from telegram.ext import Application, CommandHandler, MessageHandler, filters
from commands import ( from commands import (
cmd_add, cmd_add,
cmd_admin,
cmd_bounty, cmd_bounty,
cmd_delete, cmd_delete,
cmd_edit, cmd_edit,
@@ -45,6 +46,7 @@ def build_app() -> Application:
app.add_handler(CommandHandler("untrack", cmd_untrack)) app.add_handler(CommandHandler("untrack", cmd_untrack))
app.add_handler(CommandHandler("show", cmd_show)) app.add_handler(CommandHandler("show", cmd_show))
app.add_handler(CommandHandler("timezone", cmd_timezone)) app.add_handler(CommandHandler("timezone", cmd_timezone))
app.add_handler(CommandHandler("admin", cmd_admin))
app.add_handler(MessageHandler(filters.COMMAND, cmd_help)) app.add_handler(MessageHandler(filters.COMMAND, cmd_help))
@@ -62,6 +64,7 @@ async def post_init(app: Application) -> None:
("untrack", "Stop tracking"), ("untrack", "Stop tracking"),
("show", "Show bounty details"), ("show", "Show bounty details"),
("timezone", "Get/set room timezone"), ("timezone", "Get/set room timezone"),
("admin", "Manage admins"),
("help", "Show help"), ("help", "Show help"),
] ]
) )

View File

@@ -485,6 +485,65 @@ async def cmd_timezone(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text(f"✅ Timezone set to {timezone_str}.") await update.message.reply_text(f"✅ Timezone set to {timezone_str}.")
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: async def cmd_help(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text( await update.message.reply_text(
"👻 JIGAIDO Commands:\n\n" "👻 JIGAIDO Commands:\n\n"