/
new_chat_members.py
132 lines (115 loc) · 4.72 KB
/
new_chat_members.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import asyncio
import datetime
import random
from contextlib import suppress
from aiogram import types
from aiogram.dispatcher.handler import SkipHandler
from aiogram.utils.callback_data import CallbackData
from aiogram.utils.exceptions import BadRequest, MessageToDeleteNotFound
from loguru import logger
from app import config
from app.misc import dp, i18n
from app.models.chat import Chat
from app.services.join_list import join_list
_ = i18n.gettext
cb_join_list = CallbackData("join_chat", "answer")
@dp.message_handler(content_types=types.ContentTypes.NEW_CHAT_MEMBERS)
async def new_chat_member(message: types.Message, chat: Chat):
if not chat.join_filter:
return False
if message.date < datetime.datetime.now() - datetime.timedelta(minutes=1):
logger.warning(
"Join message {message} in chat {chat} is too old. Skip filtering. (Age: {age})",
message=message.message_id,
chat=chat.id,
age=datetime.datetime.now() - message.date,
)
return False
if message.from_user not in message.new_chat_members:
logger.opt(lazy=True).info(
"User {user} add new members to chat {chat}: {new_members}",
user=lambda: message.from_user.id,
chat=lambda: message.chat.id,
new_members=lambda: ", ".join([str(u.id) for u in message.new_chat_members]),
)
# TODO: Validate is admin add new members
else:
logger.opt(lazy=True).info(
"New chat members in chat {chat}: {new_members}",
chat=lambda: message.chat.id,
new_members=lambda: ", ".join([str(u.id) for u in message.new_chat_members]),
)
users = {}
for new_member in message.new_chat_members:
try:
await message.chat.restrict(
new_member.id, permissions=types.ChatPermissions(can_send_messages=False)
)
users[new_member.id] = new_member.get_mention()
except BadRequest as e:
logger.error(
"Cannot restrict chat member {user} in chat {chat} with error: {error}",
user=new_member.id,
chat=chat.id,
error=e,
)
continue
buttons = [
types.InlineKeyboardButton(_("I'm human"), callback_data=cb_join_list.new(answer="human")),
types.InlineKeyboardButton(_("I'm bot"), callback_data=cb_join_list.new(answer="bot")),
types.InlineKeyboardButton(_("I'm pet"), callback_data=cb_join_list.new(answer="pet")),
]
random.shuffle(buttons)
msg = await message.reply(
_(
"{users}, Welcome to the chat. \n"
"Please confirm that you are a human. "
"User filter is enabled in this chat, so if you don't answer my question, "
"I will be forced to remove you from this chat."
).format(users=", ".join(users.values())),
reply_markup=types.InlineKeyboardMarkup(inline_keyboard=[buttons]),
)
await join_list.create_list(
chat_id=message.chat.id, message_id=msg.message_id, users=users.keys()
)
return True
@dp.message_handler(content_types=types.ContentTypes.LEFT_CHAT_MEMBER)
async def left_chat_member(message: types.Message):
# TODO: Remove user from join-list when user was left from chat
raise SkipHandler
@dp.callback_query_handler(cb_join_list.filter())
async def cq_join_list(query: types.CallbackQuery, callback_data: dict):
answer = callback_data["answer"]
logger.info(
"User {user} choose answer {answer} in join-list in chat {chat} and message {message}",
user=query.from_user.id,
chat=query.message.chat.id,
answer=repr(answer),
message=query.message.message_id,
)
in_list = await join_list.pop_user_from_list(
chat_id=query.message.chat.id,
message_id=query.message.message_id,
user_id=query.from_user.id,
)
if not in_list:
return await query.answer(_("This message is not for you!"), show_alert=True)
if answer == "human":
await query.answer(_("Good answer!"))
await query.message.chat.restrict(
query.from_user.id,
permissions=types.ChatPermissions(can_send_messages=True),
until_date=config.JOIN_NO_MEDIA_DURATION,
)
else:
await query.answer(_("Bad answer."), show_alert=True)
await asyncio.sleep(2)
await query.message.chat.kick(query.from_user.id)
await query.message.chat.unban(query.from_user.id)
users_list = await join_list.check_list(
chat_id=query.message.chat.id, message_id=query.message.message_id
)
if not users_list:
with suppress(MessageToDeleteNotFound):
await query.message.delete()
return True