feat: add inline delete button to /bounty list

- Add inline keyboard with delete button on bounty list messages
- Only the user who triggered the command can delete the message
- Message is actually removed from the chat
- Uses callback query handler for button clicks
This commit is contained in:
shokollm
2026-04-04 23:25:20 +00:00
parent d01d147a45
commit dfafefe071
2 changed files with 58 additions and 2 deletions

View File

@@ -6,13 +6,20 @@ import sys
sys.path.insert(0, "/home/shoko/repositories/jigaido") 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 ( from commands import (
cmd_add, cmd_add,
cmd_admin, cmd_admin,
cmd_bounty, cmd_bounty,
cmd_delete, cmd_delete,
cmd_delete_message,
cmd_edit, cmd_edit,
cmd_help, cmd_help,
cmd_my, cmd_my,
@@ -54,6 +61,8 @@ def build_app() -> Application:
app.add_handler(CommandHandler("admin", cmd_admin)) app.add_handler(CommandHandler("admin", cmd_admin))
app.add_handler(CommandHandler("recover", cmd_recover)) app.add_handler(CommandHandler("recover", cmd_recover))
app.add_handler(CallbackQueryHandler(cmd_delete_message))
app.add_handler(MessageHandler(filters.COMMAND, cmd_help)) app.add_handler(MessageHandler(filters.COMMAND, cmd_help))
return app return app

View File

@@ -9,6 +9,7 @@ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
import dateparser import dateparser
from telegram import Update from telegram import Update
from telegram.ext import ContextTypes from telegram.ext import ContextTypes
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from adapters.storage.json_file import JsonFileRoomStorage, JsonFileTrackingStorage from adapters.storage.json_file import JsonFileRoomStorage, JsonFileTrackingStorage
from core.services import BountyService, TrackingService 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) 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: def is_group(update: Update) -> bool:
return update.effective_chat.type != "private" 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: async def cmd_bounty(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
room_id = get_room_id(update) room_id = get_room_id(update)
user_id = get_user_id(update)
args = extract_args(update.message.text) args = extract_args(update.message.text)
show_all = "all" in args 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:") lines.append(f"Showing {total_count} bounties:")
slice_length = 0 slice_length = 0
keyboard = []
for b in displayed_bounties: for b in displayed_bounties:
lines.append(format_bounty(b, show_id=True, slice_length=slice_length)) 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: async def cmd_my(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None: