Как отправить медиагруппу с помощью Aiogram? Есть ли какие-то готовые методы для этого?

Как можно реализовать передачу группы медиа-сообщений от обычного пользователя админу в боте Aiogram? Как собрать медиагруппу и передать ее админу, учитывая отсутствие в Aiogram специальных методов для работы с медиагруппами и возможностью обрабатывать сообщения на лету? Как справиться с тем, что нельзя получить размер медиагруппы или определить последнее сообщение медиагруппы в Aiogram?
  • 1 июля 2024 г. 11:42
Ответы на вопрос 3
Для отправки медиагруппы с помощью Aiogram, вы можете использовать метод `send_media_group` объекта `aiogram.Bot`. Этот метод принимает идентификатор чата, а также список `aiogram.types.InputMedia` объектов, представляющих медиа-элементы группы, которую вы хотите отправить.

Пример:

```python
from aiogram import Bot, types

bot = Bot(token='YOUR_API_TOKEN')

async def send_media_group(chat_id, media_group):
    await bot.send_media_group(chat_id=chat_id, media=media_group)

media_group = [
    types.InputMediaPhoto(media='URL_TO_PHOTO1'),
    types.InputMediaPhoto(media='URL_TO_PHOTO2'),
    types.InputMediaPhoto(media='URL_TO_PHOTO3'),
]

chat_id = 'CHAT_ID'

await send_media_group(chat_id, media_group)
```

Чтобы реализовать передачу медиагруппы от обычного пользователя админу в боте Aiogram, вы можете создать соответствующий обработчик для сообщения пользователя, собрать медиагруппу и отправить ее админу.

Пример:

```python
from aiogram import Dispatcher, types

async def forward_media_group(message):
    if message.media_group_id:
        media_group = await bot.get_media_group(chat_id=message.chat.id, media_group_id=message.media_group_id)
        for admin_id in ADMIN_IDS:
            await send_media_group(admin_id, media_group)

dp.register_message_handler(forward_media_group, content_types=types.ContentTypes.PHOTO)

async def send_media_group(chat_id, media_group):
    await bot.send_media_group(chat_id=chat_id, media=media_group)
```

Если в Aiogram нет специальных методов для работы с медиагруппами, вы можете создать свою логику обработки медиагрупп в обработчиках сообщений. Например, вы можете сохранить все медиа-элементы сообщения в базу данных и отправить их админу по завершении или при обработке следующего сообщения.

Надеюсь, эти примеры помогут вам решить ваши задачи по отправке и обработке медиагрупп в Aiogram.
На aiogram 2 делал так, через middleware: 
class AlbumMiddleware(BaseMiddleware):
    """This middleware is for capturing media groups."""

    album_data: dict = {}

    def __init__(self, latency = 0.6):
        """
        You can provide custom latency to make sure
        albums are handled properly in highload.
        """
        self.latency = latency
        super().__init__()

    async def on_process_message(self, message: types.Message, data: dict):
        if not message.media_group_id:
            if message.photo :
                data["one_photo"] = message
            elif message.animation or message.video or message.video_note or message.voice or message.audio:
                data["album"] = [message]
            return
        try:
            self.album_data[message.media_group_id].append(message)
            raise CancelHandler()  # Tell aiogram to cancel handler for this group element
        except KeyError:
            self.album_data[message.media_group_id] = [message]
            await asyncio.sleep(self.latency)

            message.conf["is_last"] = True
            data["album"] = self.album_data[message.media_group_id]

    async def on_post_process_message(self, message: types.Message, result: dict, data: dict):
        """Clean up after handling our album."""
        if message.media_group_id and message.conf.get("is_last"):
            del self.album_data[message.media_group_id]

И потом при обработке сообщения, будет 2 переменные album, one_photo:
async def func(
    message: types.Message,
    album: Optional[List[types.Message]] = None,
    one_photo: Optional[types.Message] = None
):

если в сообщении только одна картинка, она будет в one_photo, в остальном случае все будет в album
На aiogram 2 делал так, через middleware: 
class AlbumMiddleware(BaseMiddleware):
    """This middleware is for capturing media groups."""

    album_data: dict = {}

    def __init__(self, latency = 0.6):
        """
        You can provide custom latency to make sure
        albums are handled properly in highload.
        """
        self.latency = latency
        super().__init__()

    async def on_process_message(self, message: types.Message, data: dict):
        if not message.media_group_id:
            if message.photo :
                data["one_photo"] = message
            elif message.animation or message.video or message.video_note or message.voice or message.audio:
                data["album"] = [message]
            return
        try:
            self.album_data[message.media_group_id].append(message)
            raise CancelHandler()  # Tell aiogram to cancel handler for this group element
        except KeyError:
            self.album_data[message.media_group_id] = [message]
            await asyncio.sleep(self.latency)

            message.conf["is_last"] = True
            data["album"] = self.album_data[message.media_group_id]

    async def on_post_process_message(self, message: types.Message, result: dict, data: dict):
        """Clean up after handling our album."""
        if message.media_group_id and message.conf.get("is_last"):
            del self.album_data[message.media_group_id]

И потом при обработке сообщения, будет 2 переменные album, one_photo:
async def func(
    message: types.Message,
    album: Optional[List[types.Message]] = None,
    one_photo: Optional[types.Message] = None
):

если в сообщении только одна картинка, она будет в one_photo, в остальном случае все будет в album
Похожие вопросы