This commit is contained in:
@@ -15,6 +15,7 @@ from sqlalchemy import select as sa_select
|
|||||||
from db import AsyncSessionLocal
|
from db import AsyncSessionLocal
|
||||||
from models import Channel, Group
|
from models import Channel, Group
|
||||||
from .permissions import get_or_create_admin, list_channels_for_admin, has_scope_on_channel, SCOPE_POST
|
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)
|
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
|
return ConversationHandler.END
|
||||||
|
|
||||||
channel = (await session.execute(sa_select(Channel).where(Channel.id == channel_id))).scalar_one_or_none()
|
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_'):
|
elif data and data.startswith('group_'):
|
||||||
group_id = int(data.split('_')[1])
|
group_id = int(data.split('_')[1])
|
||||||
group = (await session.execute(sa_select(Group).where(Group.id == group_id))).scalar_one_or_none()
|
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:
|
if not chat_id:
|
||||||
await query.edit_message_text('Ошибка: объект не найден.')
|
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 ""
|
text: str = ud.get("text", "") or ""
|
||||||
entities: List[MessageEntity] = ud.get("entities", []) or []
|
entities: List[MessageEntity] = ud.get("entities", []) or []
|
||||||
|
|
||||||
# санация перед отправкой
|
# санация перед отправкой (custom_emoji/UTF-16)
|
||||||
entities = _strip_broken_entities(entities)
|
entities = _strip_broken_entities(entities)
|
||||||
entities = _split_custom_emoji_by_utf16(text, 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"))
|
has_media_parts = any(k in ud for k in ("photo","animation","video","document","audio","voice","sticker"))
|
||||||
try:
|
try:
|
||||||
if ud.get("src_chat_id") and ud.get("src_msg_id") and not has_media_parts:
|
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,
|
chat_id=chat_id,
|
||||||
from_chat_id=ud["src_chat_id"],
|
from_chat_id=ud["src_chat_id"],
|
||||||
message_id=ud["src_msg_id"],
|
message_id=ud["src_msg_id"],
|
||||||
|
reply_markup=markup, # <— ВАЖНО
|
||||||
)
|
)
|
||||||
await query.edit_message_text("Пост отправлен!")
|
await query.edit_message_text("Пост отправлен!")
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
except BadRequest:
|
except BadRequest:
|
||||||
pass # упадем в fallback
|
pass # упадём в fallback
|
||||||
|
|
||||||
# 2) fallback — отправка с entities/caption_entities (без parse_mode)
|
# 2) fallback — отправка с entities/caption_entities и КЛАВИАТУРОЙ
|
||||||
try:
|
try:
|
||||||
sent = False
|
sent = False
|
||||||
if "photo" in ud:
|
if "photo" in ud:
|
||||||
await context.bot.send_photo(chat_id=chat_id, photo=ud["photo"],
|
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
|
sent = True
|
||||||
elif "animation" in ud:
|
elif "animation" in ud:
|
||||||
await context.bot.send_animation(chat_id=chat_id, animation=ud["animation"],
|
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
|
sent = True
|
||||||
elif "video" in ud:
|
elif "video" in ud:
|
||||||
await context.bot.send_video(chat_id=chat_id, video=ud["video"],
|
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
|
sent = True
|
||||||
elif "document" in ud:
|
elif "document" in ud:
|
||||||
await context.bot.send_document(chat_id=chat_id, document=ud["document"],
|
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
|
sent = True
|
||||||
elif "audio" in ud:
|
elif "audio" in ud:
|
||||||
await context.bot.send_audio(chat_id=chat_id, audio=ud["audio"],
|
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
|
sent = True
|
||||||
elif "voice" in ud:
|
elif "voice" in ud:
|
||||||
await context.bot.send_voice(chat_id=chat_id, voice=ud["voice"],
|
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
|
sent = True
|
||||||
elif "sticker" in ud:
|
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:
|
if text:
|
||||||
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)
|
||||||
sent = True
|
sent = True
|
||||||
else:
|
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
|
sent = True
|
||||||
|
|
||||||
await query.edit_message_text('Пост отправлен!' if sent else 'Ошибка: не удалось отправить сообщение.')
|
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
|
return ConversationHandler.END
|
||||||
|
|
||||||
|
|
||||||
new_post_conv = ConversationHandler(
|
new_post_conv = ConversationHandler(
|
||||||
entry_points=[CommandHandler("new_post", new_post_start)],
|
entry_points=[CommandHandler("new_post", new_post_start)],
|
||||||
states={
|
states={
|
||||||
|
|||||||
Reference in New Issue
Block a user