ADD: join and leave handler

- добавлено отслеживание входа и выхода юзеров
- удаляем оба сообщения
- логируем при входе основную инфу юзера включая его био, на этой основе можно тоже добавить фильтр
- добавлены тесты на новую функцию
This commit is contained in:
kotolex
2023-12-24 13:16:55 +05:00
parent e9cb03814f
commit d9ea26381c
4 changed files with 70 additions and 17 deletions
+7
View File
@@ -82,6 +82,13 @@ def me(message: types.Message):
return msg return msg
def short_user_data(from_user: types.User) -> dict:
info = {'first_name': from_user.first_name, 'last_name': from_user.last_name, 'username': from_user.username,
'full_name': from_user.full_name, 'id': from_user.id, 'code': from_user.language_code,
'is_bot': from_user.is_bot, 'is_premium': from_user.is_premium}
return info
def represent_as_get(message: types.Message): def represent_as_get(message: types.Message):
return parse.quote_plus(detect_args(message)) return parse.quote_plus(detect_args(message))
+21 -2
View File
@@ -1,12 +1,13 @@
""" Stan's commands and reactions. """ """ Stan's commands and reactions. """
import asyncio import asyncio
import html import html
import logging
import random import random
from telebot import types from telebot import types, util
from .filters import is_white_id from .filters import is_white_id
from .helpers import is_nongrata from .helpers import is_nongrata, short_user_data
from .models import all_chat_quotes, add_quote, is_quote_in_chat, delete_quote_in_chat from .models import all_chat_quotes, add_quote, is_quote_in_chat, delete_quote_in_chat
from .robot import bot from .robot import bot
@@ -63,3 +64,21 @@ async def remove_stan_quote(message: types.Message):
async def tease_nongrata(message: types.Message): async def tease_nongrata(message: types.Message):
"""Reply to non grata mentions.""" """Reply to non grata mentions."""
await bot.reply_to(message, "у нас тут таких не любят") await bot.reply_to(message, "у нас тут таких не любят")
@bot.message_handler(content_types=util.content_type_service)
async def check_new_members(message: types.Message):
if message.content_type == "new_chat_members":
from_user = message.from_user
info = short_user_data(from_user)
await bot.delete_message(message.chat.id, message.id)
# мы не знаем как быстро получим инфу о био, потому сначала удаляем сообщение, потом запрашиваем био/логируем
more_data = await bot.get_chat(from_user.id)
info['bio'] = more_data.bio
info['photo'] = more_data.photo.big_file_id
logging.info("[JOIN] User join chat: %s", info)
if message.content_type == "left_chat_member":
from_user = message.from_user
info = short_user_data(from_user)
logging.debug("[LEAVE] User left chat: %s", info)
await bot.delete_message(message.chat.id, message.id)
+42 -14
View File
@@ -26,16 +26,7 @@ logger.setLevel(logging.ERROR)
RESULTS = [] RESULTS = []
def get_update(text, reply_to=None, user_id=10): def _all_nones():
"""Хелпер, генерирующий событие обновления для бота"""
params = {'text': text}
chat = types.Chat(id=11, type='group')
user = types.User(id=user_id, is_bot=False, first_name='Some User')
if reply_to:
params["reply_to_message"] = types.Message(message_id=2, from_user=user, date=None, chat=chat,
content_type='text', options={'text': reply_to}, json_string="")
mess = types.Message(message_id=1, from_user=user, date=None, chat=chat, content_type='text', options=params,
json_string='')
edited_message = None edited_message = None
channel_post = None channel_post = None
edited_channel_post = None edited_channel_post = None
@@ -49,15 +40,43 @@ def get_update(text, reply_to=None, user_id=10):
my_chat_member = None my_chat_member = None
chat_member = None chat_member = None
chat_join_request = None chat_join_request = None
return types.Update(1001234038283, mess, edited_message, channel_post, edited_channel_post, inline_query, return (edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query,
chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request)
my_chat_member, chat_member, chat_join_request)
def get_update(text, reply_to=None, user_id=10):
"""Хелпер, генерирующий событие обновления для бота"""
params = {'text': text}
chat = types.Chat(id=11, type='group')
user = types.User(id=user_id, is_bot=False, first_name='Some User')
if reply_to:
params["reply_to_message"] = types.Message(message_id=2, from_user=user, date=None, chat=chat,
content_type='text', options={'text': reply_to}, json_string="")
mess = types.Message(message_id=1, from_user=user, date=None, chat=chat, content_type='text', options=params,
json_string='')
return types.Update(1001234038283, mess, *_all_nones())
def member(leave: bool = False):
"""Хелпер, генерирующий событие входа и выхода юзера"""
type_ = 'left_chat_member' if leave else 'new_chat_members'
chat = types.Chat(id=11, type='group')
params = {'content_type': type_}
user = types.User(id=555, is_bot=False, first_name='Some User')
mess = types.Message(message_id=1, from_user=user, date=None, chat=chat, content_type=type_,
options=params, json_string='')
return types.Update(100100, mess, *_all_nones())
async def custom_sender(token, url, method='get', params=None, files=None, **kwargs): async def custom_sender(token, url, method='get', params=None, files=None, **kwargs):
"""Замена для тестов, чтобы не слать запросы в телегу""" """Замена для тестов, чтобы не слать запросы в телегу"""
RESULTS.append((params, url)) RESULTS.append((params, url))
result = {"message_id": 1000, "date": 1, "chat": {"id": 1000, "type": "group"}} chat = {"id": 1000, "type": "group", "bio": "bio",
"photo": {"big_file_id": "file_id", "small_file_id": "file_id", "small_file_unique_id": "file_id",
"big_file_unique_id": "file_id"}}
result = {"message_id": 1000, "date": 1, "chat": chat}
if url == "getChat":
result = chat
return result return result
@@ -343,6 +362,15 @@ class TestBot(IsolatedAsyncioTestCase):
self.assertEqual(RESULTS[1][1], 'deleteMessage') self.assertEqual(RESULTS[1][1], 'deleteMessage')
self.assertEqual(RESULTS[0][0]['text'], '➖ \n └ good text') self.assertEqual(RESULTS[0][0]['text'], '➖ \n └ good text')
async def test_new_user_in_chat(self):
await self.bot.process_new_updates([member()])
self.assertEqual(RESULTS[0][1], 'deleteMessage')
self.assertEqual(RESULTS[1], ({'chat_id': 555}, 'getChat'))
async def test_user_leave_chat(self):
await self.bot.process_new_updates([member(leave=True)])
self.assertEqual(RESULTS[0][1], 'deleteMessage')
if __name__ == '__main__': if __name__ == '__main__':
main() main()
-1
View File
@@ -32,7 +32,6 @@ class TestSpam(TestCase):
self.assertTrue(is_mixed("hi guys! #%^&%^$ ghb привет g! пQ")) self.assertTrue(is_mixed("hi guys! #%^&%^$ ghb привет g! пQ"))
class TestOthers(TestCase): class TestOthers(TestCase):
def test_ban(self): def test_ban(self):
for word in BAN_WORDS: for word in BAN_WORDS: