inline keyboard fix
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-09-06 12:27:17 +09:00
parent 5c81aae29c
commit a22ba094db

View File

@@ -15,6 +15,7 @@ from sqlalchemy import select as sa_select
from db import AsyncSessionLocal
from models import Channel, Group
from .permissions import get_or_create_admin, list_channels_for_admin, has_scope_on_channel, SCOPE_POST
from models import Channel, Group, Button
SELECT_MEDIA, SELECT_TEXT, SELECT_TARGET = range(3)
@@ -161,12 +162,28 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
return ConversationHandler.END
channel = (await session.execute(sa_select(Channel).where(Channel.id == channel_id))).scalar_one_or_none()
chat_id = channel.link if channel else None
if not channel:
await query.edit_message_text("Канал не найден.")
return ConversationHandler.END
chat_id = channel.link
# КНОПКИ ДЛЯ КАНАЛА
btns = (await session.execute(sa_select(Button).where(Button.channel_id == channel_id))).scalars().all()
if btns:
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns])
elif data and data.startswith('group_'):
group_id = int(data.split('_')[1])
group = (await session.execute(sa_select(Group).where(Group.id == group_id))).scalar_one_or_none()
chat_id = group.link if group else None
if not group:
await query.edit_message_text("Группа не найдена.")
return ConversationHandler.END
chat_id = group.link
# КНОПКИ ДЛЯ ГРУППЫ
btns = (await session.execute(sa_select(Button).where(Button.group_id == group_id))).scalars().all()
if btns:
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns])
if not chat_id:
await query.edit_message_text('Ошибка: объект не найден.')
@@ -181,11 +198,11 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
text: str = ud.get("text", "") or ""
entities: List[MessageEntity] = ud.get("entities", []) or []
# санация перед отправкой
# санация перед отправкой (custom_emoji/UTF-16)
entities = _strip_broken_entities(entities)
entities = _split_custom_emoji_by_utf16(text, entities)
# 1) Пытаемся «бит-в-бит» копию
# 1) Пытаемся «бит-в-бит» копию + КЛАВИАТУРУ
has_media_parts = any(k in ud for k in ("photo","animation","video","document","audio","voice","sticker"))
try:
if ud.get("src_chat_id") and ud.get("src_msg_id") and not has_media_parts:
@@ -193,46 +210,55 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id=chat_id,
from_chat_id=ud["src_chat_id"],
message_id=ud["src_msg_id"],
reply_markup=markup, # <— ВАЖНО
)
await query.edit_message_text("Пост отправлен!")
return ConversationHandler.END
except BadRequest:
pass # упадем в fallback
pass # упадём в fallback
# 2) fallback — отправка с entities/caption_entities (без parse_mode)
# 2) fallback — отправка с entities/caption_entities и КЛАВИАТУРОЙ
try:
sent = False
if "photo" in ud:
await context.bot.send_photo(chat_id=chat_id, photo=ud["photo"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "animation" in ud:
await context.bot.send_animation(chat_id=chat_id, animation=ud["animation"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "video" in ud:
await context.bot.send_video(chat_id=chat_id, video=ud["video"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "document" in ud:
await context.bot.send_document(chat_id=chat_id, document=ud["document"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "audio" in ud:
await context.bot.send_audio(chat_id=chat_id, audio=ud["audio"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "voice" in ud:
await context.bot.send_voice(chat_id=chat_id, voice=ud["voice"],
caption=(text or None), caption_entities=(entities if text else None))
caption=(text or None), caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
elif "sticker" in ud:
await context.bot.send_sticker(chat_id=chat_id, sticker=ud["sticker"])
# Можно прикрепить клавиатуру и к стикеру (Telegram поддерживает reply_markup)
await context.bot.send_sticker(chat_id=chat_id, sticker=ud["sticker"], reply_markup=markup)
# Если есть текст — отправим вторым сообщением (кнопки уже в первом)
if text:
await context.bot.send_message(chat_id=chat_id, text=text, entities=entities)
sent = True
else:
await context.bot.send_message(chat_id=chat_id, text=text, entities=entities)
await context.bot.send_message(chat_id=chat_id, text=text, entities=entities, reply_markup=markup)
sent = True
await query.edit_message_text('Пост отправлен!' if sent else 'Ошибка: не удалось отправить сообщение.')
@@ -241,6 +267,7 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
return ConversationHandler.END
new_post_conv = ConversationHandler(
entry_points=[CommandHandler("new_post", new_post_start)],
states={