Skip to content

Проблема с фильтрами медиа при наличии подписей #52

@SnipGhost

Description

@SnipGhost

Вероятно, нашел косяк в иерархии классов Filter. FileFilter отфильтровывает файлы/медиа с подписями (caption), т.к. VK Teams не возвращает поле text, если в сообщении в поле parts есть поле caption.

Возможные причины:

Так получается, потому что MessageFilter требует наличия поля text, от него наследуется FileFilter, а data/media-фильтры в свою очередь наследуются от него (ImageFilter/VideoFilter/AudioFilter → FileFilter → MessageFilter).

Что собственно и приводит к такому результату (первое сообщение ботом не обработалось):
Image

Пример сниппета, который использовался для данной демонстрации:

from bot.bot import Bot
from bot.filter import Filter
from bot.handler import MessageHandler,

def download_cb(bot, event):
    chat_id = event.data['chat']['chatId']
    for p in event.data.get('parts', []):
        file_id = p['payload'].get('fileId')
        bot.send_text(chat_id=chat_id, text=f"File (ID: {file_id}) downloaded!")

if __name__ == "__main__":
    bot = Bot(token=TOKEN, name=NAME, version=VERSION, api_url_base=API_URL)
    bot.dispatcher.add_handler(MessageHandler(filters=Filter.file, callback=download_cb))
    bot.start_polling()
    bot.idle()

Первое сообщение (с подписью):

{
    'chat': {
        'chatId': '<REPLACED>',
        'type': 'private'
    },
    'from': {
        'firstName': 'Михаил', 'lastName': 'Кучеренко', 'userId': '<REPLACED>'
    },
    'msgId': '7535851623587774697',
    'parts': [
        {'payload': {'caption': 'test', 'fileId': 'kIZF0HRomMiAQgwbE4XESm6894b9201ai'}, 'type': 'file'}
    ],
    'timestamp': 1754577184
}

Второе сообщение (без подписи):

{
    'chat': {
        'chatId': '<REPLACED>',
        'type': 'private'
    },
    'from': {
        'firstName': 'Михаил', 'lastName': 'Кучеренко', 'userId': '<REPLACED>'
    },
    'msgId': '7535851988659994815',
    'parts': [
        {'payload': {'fileId': 'r7kYziEDN6elgM7t91Qp5f6894b9751ai'}, 'type': 'file'}
    ],
    'text': '<REPLACED>/get/r7kYziEDN6elgM7t91Qp5f6894b9751ai',
    'timestamp': 1754577269
}

Почему это плохо:

  • Приходится либо убирать фильтр из MessageHandler - что может ломать обработку других сообщений
  • Либо колхозить свой фильтр с наследованием от FilterBase и выстраиванием параллельной иерархии классов

Как можно исправить

Быстрое исправление - изменить MessageFilter так:

class MessageFilter(FilterBase):
    def filter(self, event):
        return ("text" in event.data and isinstance(event.data["text"], six.string_types)) or (
            "parts" in event.data and any(p.get("payload", {}).get("caption") for p in event.data["parts"])
        )

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

Однако, этот подход не сработал, вызова MessageFilter.filter на событие сообщения с подписью - просто не происходит. Ищу в чем дело.
UPD: Подход сработал, но нашлась еще одна проблема, далее в комментариях рассмотрел.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions