Братан, вот мой код:
import os
import asyncio
import logging
from collections import defaultdict
from dotenv import load_dotenv
from telethon import TelegramClient, events, Button

Загрузка переменных окружения из файла .env
load_dotenv()

API_ID = os.getenv("API_ID")
API_HASH = os.getenv("API_HASH")
BOT_TOKEN = os.getenv("BOT_TOKEN")
CHANNEL_ID = int(os.getenv("CHANNEL_ID")) # Идентификатор целевого канала
INTERIM_CHAT_ID = int(os.getenv("INTERIM_CHAT_ID")) # Идентификатор промежуточного канала
ALLOWED_USER_ID = int(os.getenv("ALLOWED_USER_ID"))

client = TelegramClient('bot', API_ID, API_HASH)
client.start(bot_token=BOT_TOKEN)

logging.basicConfig(filename="bot.log", level=logging.INFO)

Словари для хранения информации о сообщениях в процессе обработки
pending_albums = {}
pending_messages = {}

Словарь для хранения группированных сообщений (альбомов)
grouped_messages = defaultdict(list)

Таймаут для сбора сообщений альбома (в секундах)
ALBUM_TIMEOUT = 1.0

@client.on(events.NewMessage(func=lambda e: e.is_private and e.sender_id == ALLOWED_USER_ID))
async def handle_message(event):
message = event.message

Проверяем, является ли сообщение частью альбома
if message.grouped_id:
group_id = str(message.grouped_id) # Приводим к строке
# Добавляем сообщение в список соответствующей группы
grouped_messages[group_id].append(message)


# Если это первое сообщение альбома, запускаем таймер обработки
if len(grouped_messages[group_id]) == 1:
    asyncio.create_task(schedule_group_send(group_id))
else:
# Обработка одиночных сообщений
buttons = [
[Button.inline("✅ Отправить", data=f"send_message:{message.id}"), Button.inline("❌ Отменить", data=f"cancel_message:{message.id}")]
]


sent = await client.send_message(
    INTERIM_CHAT_ID,
    message,
    buttons=buttons
)

pending_messages[sent.id] = {
    'original_message_id': message.id,
    'sender_id': event.sender_id
}

await event.delete()
Use code with caution.
async def schedule_group_send(group_id):
await asyncio.sleep(ALBUM_TIMEOUT)

if group_id in grouped_messages:
messages = grouped_messages.pop(group_id)
media_list = [msg.media for msg in messages]
captions = [msg.text for msg in messages if msg.text]
caption = "\n".join(captions) if captions else ''


# Отправляем альбом в промежуточный канал без кнопок
sent_messages = await client.send_file(
    INTERIM_CHAT_ID,
    media_list,
    caption=caption
)

# Получаем список идентификаторов сообщений альбома
if isinstance(sent_messages, list):
    album_message_ids = [msg.id for msg in sent_messages]
else:
    album_message_ids = [sent_messages.id]

# Отправляем сообщение с кнопками после альбома
buttons = [
    [Button.inline("✅ Отправить", data=f"send_album:{group_id}"), Button.inline("❌ Отменить", data=f"cancel_album:{group_id}")]
]

buttons_message = await client.send_message(
    INTERIM_CHAT_ID,
    "Выберите действие для альбома:",
    buttons=buttons
)

pending_albums[group_id] = {  # Используем строковый ключ
    'message_ids': album_message_ids,
    'buttons_message_id': buttons_message.id,
    'sender_id': messages[0].sender_id
}

# Удаляем исходные сообщения от пользователя
for msg in messages:
    await msg.delete()
Use code with caution.
@client.on(events.CallbackQuery)
async def callback_handler(event):
data = event.data.decode('utf-8')

if ':' in data:
parts = data.split(':', 1)
command = parts[0]
identifier = parts[1]
else:
command = data
identifier = None

Проверяем, что запрос от пользователя, отправившего сообщение
if command in ['send_album', 'cancel_album']:
pending = pending_albums.get(identifier)
else:
pending = pending_messages.get(event.message_id)

if not pending or pending['sender_id'] != event.sender_id:
await event.answer("Вы не имеете доступа к этой функции.", alert=True)
return

if command == 'send_message':
edited_message = await client.get_messages(INTERIM_CHAT_ID, ids=event.message_id)
await client.send_message(CHANNEL_ID, edited_message)
await edited_message.delete()
del pending_messages[event.message_id]
await event.answer("Сообщение успешно отправлено в канал.")

elif command == 'cancel_message':
message_to_delete = await client.get_messages(INTERIM_CHAT_ID, ids=event.message_id)
await message_to_delete.delete()
del pending_messages[event.message_id]
await event.answer("Отправка сообщения отменена.")

elif command == 'send_album':
pending = pending_albums.get(identifier)
if not pending:
await event.answer("Ошибка при отправке альбома.", alert=True)
return


album_messages = await client.get_messages(INTERIM_CHAT_ID, ids=pending['message_ids'])
media_list = [msg.media for msg in album_messages]
caption = album_messages[0].message if album_messages[0].message else ''

await client.send_file(
    CHANNEL_ID,
    media_list,
    caption=caption
)

# Удаляем сообщения альбома и сообщение с кнопками
await client.delete_messages(INTERIM_CHAT_ID, pending['message_ids'] + [pending['buttons_message_id']])
del pending_albums[identifier]
await event.answer("Альбом успешно отправлен в канал.")
elif command == 'cancel_album':
pending = pending_albums.get(identifier)
if not pending:
await event.answer("Ошибка при отмене альбома.", alert=True)
return


# Удаляем сообщения альбома и сообщение с кнопками
await client.delete_messages(INTERIM_CHAT_ID, pending['message_ids'] + [pending['buttons_message_id']])
del pending_albums[identifier]
await event.answer("Отправка альбома отменена.")
else:
await event.answer("Неизвестная команда.", alert=True)
Use code with caution.
Игнорируем сообщения в промежуточном канале
@client.on(events.NewMessage(func=lambda e: e.chat_id == INTERIM_CHAT_ID))
async def ignore_messages(event):
pass

with client:
print("Бот запущен!")
client.run_until_disconnected()
➡️При пересылке двух и более медиа файлов, кнопки появляются с задержкой и когда я изменяю пост в промежуточном канале а затем пересылаю в целевой канал, то там в посте все форматирования пропадают, просто сплошной текст, а когда пересылаю пост с одним медиа файлом то все возможные форматирования остаются.