@Ezekiel4
Охотник на пиратов и сборщик монолитов

Как пересылать медиа группы?

Вопрос отчасти повторяет мой старый (https://qna.habr.com/q/1265138), на который не дали ответ.

Небольшое пояснение темы для джавистов, кто не шарит в тг.

Когда в чате с ботом что-то происходит, прилетает обновление, из которого можно вытащить сообщение. Каждое сообщение может содержать в себе медиа. Но когда вы пересылаете медиа группы (альбомы), они на самом деле уходят как сообщения-одиночки, но имеющие общий идентификатор медиа группы. Для каждого уникального чата в сообщении есть уникальный идентификатор.


С помощью документации, я в итоге написал такую простыню:
код
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMediaGroup;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.PhotoSize;
import org.telegram.telegrambots.meta.api.objects.media.InputMedia;
import org.telegram.telegrambots.meta.api.objects.media.InputMediaDocument;
import org.telegram.telegrambots.meta.api.objects.media.InputMediaPhoto;
import org.telegram.telegrambots.meta.api.objects.media.InputMediaVideo;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MediaGroupHandler {

    private Timer timer;
    private List<InputMedia> mediaList;
    private String currentMediaGroupId;
    private TelegramLongPollingBot bot;
    private long chatId;

    public MediaGroupHandler(TelegramLongPollingBot bot, long chatId) {
        this.bot = bot;
        this.mediaList = new ArrayList<>();
        this.chatId = chatId;
    }

    public bool isInstanceFor(long chatId) {
        return this.chatId == chatId;
    }

    public void handleMediaGroup(Message message) {
        String mediaGroupId = message.getMediaGroupId();
        if (mediaGroupId == null) {
            return;
        }

        if (!mediaGroupId.equals(currentMediaGroupId)) {
            sendMediaList();
            mediaList.clear();
            currentMediaGroupId = mediaGroupId;
        }

        List<PhotoSize> photos = message.getPhoto();
        if (!photos.isEmpty()) {
            PhotoSize photo = photos.get(photos.size() - 1);
            mediaList.add(new InputMediaPhoto(photo.getFileId()));
        } else if (message.getVideo() != null) {
            mediaList.add(new InputMediaVideo(message.getVideo().getFileId()));
        } else if (message.getDocument() != null) {
            mediaList.add(new InputMediaDocument(message.getDocument().getFileId()));
        }

        if (timer != null) {
            timer.cancel();
        }
        timer = new Timer();
        timer.schedule(new MediaGroupTask(), 1000);
    }

    private void sendMediaList() {
        if (mediaList.isEmpty()) {
            return;
        }

        SendMediaGroup sendMediaGroup = new SendMediaGroup();
        sendMediaGroup.setChatId(chatId);
        sendMediaGroup.setMedia(mediaList);
        try {
            bot.execute(sendMediaGroup);
        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }

    private class MediaGroupTask extends TimerTask {
        @Override
        public void run() {
            sendMediaList();
            mediaList.clear();
            currentMediaGroupId = null;
            timer = null;
        }
    }
}


Проблема в том, что апдейт может прилететь от любого пользователя бота в любой момент и мне нужно запускать неизвестное количество инстансов этого класса (для каждого чата по 1). Типа он начинает ждать секунду нового сообщения, а в этот момент 50±50 других пользователей одновременно высылают своё и всё сбивают.

Я пока дошёл только до того, что всякий раз, как когда прилетает альбом от нового пользователя, я создаю для него новый инстанс класса и они все висят до рестарта приложения.

Я не шарю в теме пулов объектов, но что-то мне подсказывает, что задачу можно как-то решить с его помощью. Если нет, то есть ли какие-нибудь ещё способы с этим разобраться? Критично важно, чтобы альбомы приходили такими, какими их отправляли.
  • Вопрос задан
  • 330 просмотров
Пригласить эксперта
Ответы на вопрос 1
EPIDEMIASH
@EPIDEMIASH
Человек швейцарский нож
Только через Long Polling. Сначала получите все сообщения, а потом пройдите их циклом.

import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.ForwardMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

public class YourBot extends TelegramLongPollingBot {
    @Override
    public void onUpdateReceived(Update update) {
        if (update.hasMessage() && update.getMessage().hasMediaGroup()) {
            // Получаем медиа-группу сообщений
            Message[] messages = update.getMessage().getMediaGroup().getItems();

            // Цикл по всем сообщениям в медиа-группе
            for (Message message : messages) {
                // Отправляем каждое сообщение индивидуально с помощью метода forwardMessage()
                ForwardMessage forwardMessage = new ForwardMessage()
                        .setChatId("your_chat_id")
                        .setFromChatId(update.getMessage().getChatId())
                        .setMessageId(message.getMessageId());
                try {
                    execute(forwardMessage);
                } catch (TelegramApiException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public String getBotUsername() {
        return "your_bot_username";
    }

    @Override
    public String getBotToken() {
        return "your_bot_token";
    }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы