-
Notifications
You must be signed in to change notification settings - Fork 39
Description
Вероятно, нашел косяк в иерархии классов Filter. FileFilter отфильтровывает файлы/медиа с подписями (caption), т.к. VK Teams не возвращает поле text
, если в сообщении в поле parts
есть поле caption
.
Возможные причины:
Так получается, потому что MessageFilter требует наличия поля text
, от него наследуется FileFilter, а data/media-фильтры в свою очередь наследуются от него (ImageFilter/VideoFilter/AudioFilter → FileFilter → MessageFilter).
Что собственно и приводит к такому результату (первое сообщение ботом не обработалось):
Пример сниппета, который использовался для данной демонстрации:
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: Подход сработал, но нашлась еще одна проблема, далее в комментариях рассмотрел.