diff --git a/apps/telegram-bot/bot.py b/apps/telegram-bot/bot.py index d530b44..2b43179 100644 --- a/apps/telegram-bot/bot.py +++ b/apps/telegram-bot/bot.py @@ -6,13 +6,20 @@ import sys sys.path.insert(0, "/home/shoko/repositories/jigaido") -from telegram.ext import Application, CommandHandler, MessageHandler, filters +from telegram.ext import ( + Application, + CommandHandler, + MessageHandler, + CallbackQueryHandler, + filters, +) from commands import ( cmd_add, cmd_admin, cmd_bounty, cmd_delete, + cmd_delete_message, cmd_edit, cmd_help, cmd_my, @@ -54,6 +61,8 @@ def build_app() -> Application: app.add_handler(CommandHandler("admin", cmd_admin)) app.add_handler(CommandHandler("recover", cmd_recover)) + app.add_handler(CallbackQueryHandler(cmd_delete_message)) + app.add_handler(MessageHandler(filters.COMMAND, cmd_help)) return app diff --git a/apps/telegram-bot/commands.py b/apps/telegram-bot/commands.py index 79bf96c..b51eefd 100644 --- a/apps/telegram-bot/commands.py +++ b/apps/telegram-bot/commands.py @@ -9,6 +9,7 @@ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError import dateparser from telegram import Update from telegram.ext import ContextTypes +from telegram import InlineKeyboardButton, InlineKeyboardMarkup from adapters.storage.json_file import JsonFileRoomStorage, JsonFileTrackingStorage from core.services import BountyService, TrackingService @@ -137,6 +138,39 @@ def format_bounty(b, show_id: bool = True, slice_length: int = 0) -> str: return " | ".join(parts) +async def cmd_delete_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: + query = update.callback_query + if not query: + return + + data = query.data + if not data.startswith("del_msg:"): + return + + parts = data.split(":") + if len(parts) != 3: + return + + try: + message_id = int(parts[1]) + expected_user_id = int(parts[2]) + except ValueError: + return + + user_id = get_user_id(update) + if user_id != expected_user_id: + await query.answer("You can't delete this message", show_alert=True) + return + + try: + await ctx.bot.delete_message( + chat_id=query.message.chat_id, message_id=message_id + ) + await query.answer("Deleted") + except Exception: + await query.answer("Could not delete message", show_alert=True) + + def is_group(update: Update) -> bool: return update.effective_chat.type != "private" @@ -162,6 +196,7 @@ def get_room_id(update: Update) -> int: async def cmd_bounty(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: room_id = get_room_id(update) + user_id = get_user_id(update) args = extract_args(update.message.text) show_all = "all" in args @@ -211,10 +246,22 @@ async def cmd_bounty(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: lines.append(f"Showing {total_count} bounties:") slice_length = 0 + keyboard = [] for b in displayed_bounties: lines.append(format_bounty(b, show_id=True, slice_length=slice_length)) + keyboard.append( + [ + InlineKeyboardButton( + "🗑️ Delete", + callback_data=f"del_msg:{update.message.message_id + len(lines)}:{user_id}", + ) + ] + ) - await update.message.reply_text("\n".join(lines), disable_web_page_preview=True) + reply_markup = InlineKeyboardMarkup(keyboard) if keyboard else None + await update.message.reply_text( + "\n".join(lines), disable_web_page_preview=True, reply_markup=reply_markup + ) async def cmd_my(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: