При тексте с HTML разметкой + медиа дублирует текст
Пишу телеграм бота (автоматический постинг в чаты) на aiogram и столкнулся с такой ошибкой: Если отправлять текст с медиа и подписью, с форматированием HTML, то оно очень странно отображается:
Последняя строчка дублируется, хотя так не должно быть. Код:
async def process_content(message: types.Message, state: FSMContext):
original_message_id = message.message_id
text = message.text or message.caption or ""
if len(text) > 1000:
await message.answer(
"Текст слишком длинный! До 1000 символов!",
reply_markup=cancel_menu()
)
return
if message.text and message.entities:
html_text = message.html_text
await state.update_data(text=html_text)
elif message.caption and message.caption_entities:
html_text = get_html_text_from_entities(message.caption, message.caption_entities)
await state.update_data(text=html_text)
else:
await state.update_data(text=text)
media_id = None
media_type = None
if message.photo:
media_id = message.photo[-1].file_id
media_type = 'photo'
elif message.video:
media_id = message.video.file_id
media_type = 'video'
elif message.animation:
media_id = message.animation.file_id
media_type = 'animation'
await state.update_data(
media_id=media_id,
media_type=media_type,
original_message_id=original_message_id
)
await message.answer(
POST_TYPE_MESSAGE,
parse_mode='HTML',
reply_markup=post_type_menu()
)
await AutopostingStates.waiting_for_post_type.set()
def get_html_text_from_entities(text, entities):
if not entities:
return text
entities = sorted(entities, key=lambda x: x.offset)
result = ""
last_offset = 0
for entity in entities:
result += text[last_offset:entity.offset]
entity_text = text[entity.offset:entity.offset + entity.length]
if entity.type == "bold":
result += f"<b>{entity_text}</b>"
elif entity.type == "italic":
result += f"<i>{entity_text}</i>"
elif entity.type == "underline":
result += f"<u>{entity_text}</u>"
elif entity.type == "code":
result += f"<code>{entity_text}</code>"
elif entity.type == "pre":
result += f"<pre>{entity_text}</pre>"
elif entity.type == "text_link":
result += f"<a href='{entity.url}'>{entity_text}</a>"
elif entity.type == "mention":
result += entity_text
elif entity.type == "url":
result += entity_text
else:
result += entity_text
last_offset = entity.offset + entity.length
result += text[last_offset:]
return result
async def preview_autoposting(callback_query: CallbackQuery, state: FSMContext, db):
await callback_query.answer()
try:
subscription_id = int(callback_query.data.split('_')[2])
logging.info(f"Previewing autoposting with ID: {subscription_id}")
subscription = await db.get_subscription_by_id(subscription_id)
if not subscription or subscription['user_id'] != callback_query.from_user.id:
await callback_query.message.edit_text(
"Автопостинг не найден!",
reply_markup=back_menu("my_posts")
)
return
await callback_query.message.edit_text(
"<b>Предпросмотр сообщения</b>\n\n"
"Вот так ваш автопостинг будет выглядеть в чатах:",
parse_mode='HTML'
)
text = subscription.get('text', '')
media_id = subscription.get('media_id')
media_type = subscription.get('media_type')
post_type = subscription.get('post_type')
buttons = subscription.get('buttons', [])
original_message_id = subscription.get('original_message_id')
logging.info(f"Preview data: type={post_type}, message_id={original_message_id}, media={media_type}")
else:
try:
keyboard = None
if buttons:
keyboard = InlineKeyboardMarkup()
for button in buttons:
keyboard.add(InlineKeyboardButton(
text=button['text'],
url=button['url']
))
if keyboard:
keyboard.add(InlineKeyboardButton("‹ Назад", callback_data=f"view_post_{subscription_id}"))
else:
keyboard = back_menu(f"view_post_{subscription_id}")
if media_id:
logging.info(f"Sending preview with media: {media_type}, {media_id}")
if media_type == 'photo' or not media_type:
await callback_query.bot.send_photo(
chat_id=callback_query.message.chat.id,
photo=media_id,
caption=text,
parse_mode='HTML',
reply_markup=keyboard
)
elif media_type == 'video':
await callback_query.bot.send_video(
chat_id=callback_query.message.chat.id,
video=media_id,
caption=text,
parse_mode='HTML',
reply_markup=keyboard
)
elif media_type == 'animation':
await callback_query.bot.send_animation(
chat_id=callback_query.message.chat.id,
animation=media_id,
caption=text,
parse_mode='HTML',
reply_markup=keyboard
)
else:
logging.info(f"Sending preview as text message")
await callback_query.message.answer(
text,
parse_mode='HTML',
reply_markup=keyboard,
disable_web_page_preview=True
)
except Exception as e:
await callback_query.message.answer(
f"<b>Ошибка при показе предпросмотра:</b>\n\n{str(e)}",
parse_mode='HTML',
reply_markup=back_menu(f"view_post_{subscription_id}")
)
except Exception as e:
await callback_query.message.answer(
"Произошла непредвиденная ошибка при показе",
reply_markup=back_menu("my_posts")
)
async def _send_message_with_media(self, chat_id, text, media_id, media_type, reply_markup):
try:
if not media_id:
return await self.bot.send_message(
chat_id=chat_id,
text=text,
parse_mode='HTML',
reply_markup=reply_markup,
disable_web_page_preview=True
)
else:
if media_type == 'photo' or not media_type:
return await self.bot.send_photo(
chat_id=chat_id,
photo=media_id,
caption=text,
parse_mode='HTML',
reply_markup=reply_markup
)
elif media_type == 'video':
return await self.bot.send_video(
chat_id=chat_id,
video=media_id,
caption=text,
parse_mode='HTML',
reply_markup=reply_markup
)
elif media_type == 'animation':
return await self.bot.send_animation(
chat_id=chat_id,
animation=media_id,
caption=text,
parse_mode='HTML',
reply_markup=reply_markup
)
else:
return await self.bot.send_message(
chat_id=chat_id,
text=text,
parse_mode='HTML',
reply_markup=reply_markup,
disable_web_page_preview=True
)
except Exception as e:
logging.error(f"Ошибка при отправлении в чат {chat_id}: {e}")
return None
