Братан, вот мой код:
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()
➡️При пересылке двух и более медиа файлов, кнопки появляются с задержкой и когда я изменяю пост в промежуточном канале а затем пересылаю в целевой канал, то там в посте все форматирования пропадают, просто сплошной текст, а когда пересылаю пост с одним медиа файлом то все возможные форматирования остаются.