Мой астрономический чат довольно камерный, поэтому живых людей там мало, а спаммеров много. Но вот, реально пришёл живой человек. Я это определил и по имени (у спаммепров потчти всегда женское имя-фамилия) и по аватарке (космонавт) и по отсутствию премиума (у спаммеров всегда премиум, причём они себе ставят невидимый статус, чтобы было непонятно, что это премиум, но если сразу справа от ника кликнуть, получишь окно покупки премиума).
Я пошёл в административную панель и удалил пользователя из списка заблокированных. После чего немедленно получил сообщение от бота:
"Здравствуйте, zHz01! Из-за атаки ботов всем новым пользователям отключена отправка сообщений на одну неделю. Для досрочного снятия блокировки пишите администраторам чата."
Конечно же, я не был заблокирован. Администраторов может заблокировать только вышестоящий администратор, а бот был самым младшим администратором. Тем не менее такое поведение показывало на явный баг. Почему-то бот считал, что я -- новый пользователь! Стал разбираться.
(цветная врезка: на всякий случай информирую всех, что если вы администратору чата введёте ограничения типа мьюта, т.е. запрета отправки сообщений, то администратор будет автоматически снят с административного поста; не помню, выдаётся ли об этом предупреждение или нет)
Ответы телеграм-бот-апи приходят в виде жсонов. Вот какие поля есть у сообщения о входе (chat_member):
1. chat
2. from
3. date
4. old_chat_member
5. new_chat_member
У сообщения о входе в поле from -- данные вошедшего пользователя. Видя, что у меня есть сообщение о входе, я брал данные из поля from и по ним проводил блокировку пользователя. Был ещё один признак, в new_chat_member должно быть поле status, которое содержит слово member, чтобы не перепутать с сообщением о выходе и о блокировке (тогда бы там были слова left и restricted соответственно)
Какие же поля есть у сообщения о разбане? Да те же самые! В поле new_chat_member статус тоже мембер, потому что после разблокировки статус меняется с restricted на member. А какое различие? В поле from. Если пользователя разбанили, то в поле фром будет администратор, а не сам пользователь.
Вот тут-то я и попался. Полагая, что у сообщения о входе в поле фром всегда вошедший, я совершил ошибку. Я попытался заблокировать себя. Документация говорит, что это поле содержит:
Performer of the action, which resulted in the change
Увы, такое описание лапидарно, и не даёт пояснений, кто же там может быть.
Ошибку я исправил. Теперь я выдаю мьют не по полю фром. Я сравниваю идентификаторы пользователя в поле фром и в поле new_chat_member. Если идентификаторы совпадают, то пользователь вошёл сам. Если идентификаторы различаются, то это административное действие, и реагировать на него не надо.
Тем не менее, это не значит, что проблема решена полностью. Я уже не раз сталкивался с неожиданным поведением телеграм-бот-апи, поэтому просто тестирую и жду необычных ситуаций.