diff --git a/src/helpers.py b/src/helpers.py index b8f57e2..8d240e5 100644 --- a/src/helpers.py +++ b/src/helpers.py @@ -82,6 +82,13 @@ def me(message: types.Message): 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): return parse.quote_plus(detect_args(message)) diff --git a/src/stan.py b/src/stan.py index 42b7e56..7039075 100644 --- a/src/stan.py +++ b/src/stan.py @@ -1,12 +1,13 @@ """ Stan's commands and reactions. """ import asyncio import html +import logging import random -from telebot import types +from telebot import types, util 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 .robot import bot @@ -63,3 +64,21 @@ async def remove_stan_quote(message: types.Message): async def tease_nongrata(message: types.Message): """Reply to non grata mentions.""" 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) diff --git a/tests/test_bot.py b/tests/test_bot.py index c6da398..e4d20c5 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -26,16 +26,7 @@ logger.setLevel(logging.ERROR) RESULTS = [] -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='') +def _all_nones(): edited_message = None 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 chat_member = None chat_join_request = None - return types.Update(1001234038283, mess, edited_message, channel_post, edited_channel_post, inline_query, - chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request) + return (edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, + shipping_query, pre_checkout_query, poll, poll_answer, 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): """Замена для тестов, чтобы не слать запросы в телегу""" 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 @@ -343,6 +362,15 @@ class TestBot(IsolatedAsyncioTestCase): self.assertEqual(RESULTS[1][1], 'deleteMessage') 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__': main() diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 9ad709b..e8ef1c7 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -32,7 +32,6 @@ class TestSpam(TestCase): self.assertTrue(is_mixed("hi guys! #%^&%^$ ghb привет g! пQ")) - class TestOthers(TestCase): def test_ban(self): for word in BAN_WORDS: