From f1f10b454ab22a453dec033c6dcd438c979497a3 Mon Sep 17 00:00:00 2001 From: xtaodada Date: Wed, 7 Aug 2024 23:33:57 +0800 Subject: [PATCH] refa: clean verify user message --- plugins/chat_member_update.py | 99 +++++++++++++++++------------------ plugins/clean_message.py | 17 ++++++ plugins/new_member.py | 23 ++++---- plugins/reverify.py | 66 ++++++++++------------- pyromod/filters/__init__.py | 21 -------- pyromod/filters/filters.py | 28 ---------- pyromod/helpers/__init__.py | 20 ------- pyromod/helpers/helpers.py | 86 ------------------------------ pyromod/listen/listen.py | 45 ++++++++++------ pyromod/nav/__init__.py | 20 ------- pyromod/nav/pagination.py | 93 -------------------------------- sticker/__init__.py | 42 ++++++++++++--- sticker/languages.py | 2 +- sticker/scheduler.py | 24 ++++++++- 14 files changed, 190 insertions(+), 396 deletions(-) create mode 100644 plugins/clean_message.py delete mode 100644 pyromod/filters/__init__.py delete mode 100644 pyromod/filters/filters.py delete mode 100644 pyromod/helpers/__init__.py delete mode 100644 pyromod/helpers/helpers.py delete mode 100644 pyromod/nav/__init__.py delete mode 100644 pyromod/nav/pagination.py diff --git a/plugins/chat_member_update.py b/plugins/chat_member_update.py index f6f4146..87a4464 100644 --- a/plugins/chat_member_update.py +++ b/plugins/chat_member_update.py @@ -1,5 +1,4 @@ import contextlib -from datetime import datetime, timedelta from cashews import cache from pyrogram import filters @@ -8,17 +7,45 @@ from pyrogram.types import ChatMemberUpdated from pyromod.utils.errors import TimeoutConversationError from sticker.languages import MSG_PUBLIC, ADMIN_MSG, MSG, VERIFY_TIME -from sticker.scheduler import add_delete_message_job +from sticker.scheduler import add_ban_chat_member_job from sticker.service_message import ServiceMessage -from sticker.single_utils import Client -from sticker import bot, log +from sticker.single_utils import Client, Message +from sticker import bot, log, LogAction + + +async def start_verify(client: "Client", chat, user): + key = f"wait:{chat.id}:{user.id}" + await cache.set(key, "True", expire=VERIFY_TIME + 5) + try: + msg: "Message" = await client.send_message( + chat.id, MSG % (user.mention, user.mention) + ) + except Exception: + return + await log(chat, user, LogAction.REQUEST) + try: + msg_: "Message" = await client.listen( + chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME + ) + await msg.delay_delete(1) + await msg_.delay_delete(1) + if not msg_.sticker: + add_ban_chat_member_job(chat.id, user.id) + await log(chat, user, LogAction.FAIL_ERROR) + await ServiceMessage.try_delete(user.id, chat.id) + else: + await cache.delete(key) + await log(chat, user, LogAction.ACCEPT) + except TimeoutConversationError: + await msg.delay_delete(1) + add_ban_chat_member_job(chat.id, user.id) + await log(chat, user, LogAction.FAIL_TIMEOUT) + await ServiceMessage.try_delete(user.id, chat.id) @bot.on_chat_member_updated() async def invite(client: Client, chat_member_updated: ChatMemberUpdated): chat = chat_member_updated.chat - if await cache.get(f"cid:{chat.id}"): - return member = chat_member_updated.new_chat_member old_member = chat_member_updated.old_chat_member if not member: @@ -27,6 +54,17 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated): return user = member.user old_user = old_member.user if old_member else None + if user.is_self: + if member.status not in { + ChatMemberStatus.ADMINISTRATOR, + ChatMemberStatus.MEMBER, + }: + return + await log(chat, chat_member_updated.from_user, LogAction.NEW_GROUP) + if chat.username: + with contextlib.suppress(Exception): + await client.send_message(chat.id, MSG_PUBLIC) + return if user.is_verified or user.is_bot or user.is_deleted or user.is_support: return if member.status not in {ChatMemberStatus.MEMBER}: @@ -43,13 +81,6 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated): } ): return - if user.is_self: - with contextlib.suppress(Exception): - await log(chat, chat_member_updated.from_user, "NEW_GROUP") - if chat.username: - with contextlib.suppress(Exception): - await client.send_message(chat.id, MSG_PUBLIC) - return from_user = chat_member_updated.from_user if from_user and from_user.id == user.id: from_user = None @@ -61,42 +92,8 @@ async def invite(client: Client, chat_member_updated: ChatMemberUpdated): and (await bot.get_chat_member(chat.id, from_user.id)).status in {ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER} ): - try: - msg = await client.send_message(chat.id, ADMIN_MSG) - except Exception: - return - add_delete_message_job(msg) + with contextlib.suppress(Exception): + msg: "Message" = await client.send_message(chat.id, ADMIN_MSG) + await msg.delay_delete() return - try: - msg = await client.send_message(chat.id, MSG % (user.mention, user.mention)) - except Exception: - return - try: - with contextlib.suppress(Exception): - await log(chat, user, "REQUEST") - msg_ = await client.listen(chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME) - with contextlib.suppress(Exception): - await msg.delete() - if not msg_.sticker: - with contextlib.suppress(Exception): - await bot.ban_chat_member( - chat.id, user.id, datetime.now() + timedelta(minutes=5) - ) - with contextlib.suppress(Exception): - await log(chat, user, "FAIL_ERROR") - await ServiceMessage.try_delete(user.id, chat.id) - else: - with contextlib.suppress(Exception): - await log(chat, user, "ACCEPT") - with contextlib.suppress(Exception): - await msg_.delete() - except TimeoutConversationError: - with contextlib.suppress(Exception): - await msg.delete() - with contextlib.suppress(Exception): - await bot.ban_chat_member( - chat.id, user.id, datetime.now() + timedelta(minutes=5) - ) - with contextlib.suppress(Exception): - await log(chat, user, "FAIL_TIMEOUT") - await ServiceMessage.try_delete(user.id, chat.id) + await start_verify(client, chat, user) diff --git a/plugins/clean_message.py b/plugins/clean_message.py new file mode 100644 index 0000000..ad76c48 --- /dev/null +++ b/plugins/clean_message.py @@ -0,0 +1,17 @@ +from cashews import cache +from pyrogram import filters + +from sticker import bot +from sticker.single_utils import Message + + +@bot.on_message(filters=filters.group & ~filters.service, group=1) +async def clean_message(_, message: "Message"): + if not message.from_user: + return + cid = message.chat.id + uid = message.from_user.id + key = f"wait:{cid}:{uid}" + result = await cache.get(key) + if result: + await message.delay_delete(1) diff --git a/plugins/new_member.py b/plugins/new_member.py index c220dc4..615d2cb 100644 --- a/plugins/new_member.py +++ b/plugins/new_member.py @@ -1,13 +1,12 @@ import contextlib -from cashews import cache from pyrogram.types import ChatJoinRequest from pyrogram import filters from sticker.languages import MSG, MSG_SUCCESS, MSG_FAILURE, VERIFY_TIME from sticker.single_utils import Client from sticker.scheduler import add_decline_request_job, rem_decline_request_job -from sticker import bot, log +from sticker import bot, log, LogAction from pyromod.utils.errors import TimeoutConversationError @@ -15,24 +14,24 @@ from pyromod.utils.errors import TimeoutConversationError @bot.on_chat_join_request() async def new_member(client: Client, chat_join_request: ChatJoinRequest): chat = chat_join_request.chat - await cache.set(f"cid:{chat.id}", "True", expire=3600, exist=True) user = chat_join_request.from_user add_decline_request_job(chat_join_request) try: - with contextlib.suppress(Exception): - await log(chat, user, "REQUEST") - await client.ask(user.id, MSG % (chat.title, chat.title), filters=filters.sticker, timeout=VERIFY_TIME) + await log(chat, user, LogAction.REQUEST) + await client.ask( + user.id, + MSG % (chat.title, chat.title), + filters=filters.sticker, + timeout=VERIFY_TIME, + ) with contextlib.suppress(Exception): await client.send_message(user.id, MSG_SUCCESS) await chat_join_request.approve() - with contextlib.suppress(Exception): - await log(chat, user, "ACCEPT") - with contextlib.suppress(Exception): - rem_decline_request_job(chat_join_request) + await log(chat, user, LogAction.ACCEPT) + rem_decline_request_job(chat_join_request) except TimeoutConversationError: with contextlib.suppress(Exception): await client.send_message(user.id, MSG_FAILURE) with contextlib.suppress(Exception): await chat_join_request.decline() - with contextlib.suppress(Exception): - await log(chat, user, "FAIL_TIMEOUT") + await log(chat, user, LogAction.FAIL_TIMEOUT) diff --git a/plugins/reverify.py b/plugins/reverify.py index ec0440d..bbc7edc 100644 --- a/plugins/reverify.py +++ b/plugins/reverify.py @@ -1,25 +1,23 @@ -import contextlib - +from cashews import cache from pyrogram import filters from pyrogram.enums import ChatMemberStatus -from datetime import datetime, timedelta - from pyromod.utils.errors import TimeoutConversationError from sticker.languages import RE_MSG, VERIFY_TIME -from sticker.scheduler import add_delete_message_job +from sticker.scheduler import add_ban_chat_member_job from sticker.single_utils import Message, Client -from sticker import bot, log +from sticker import bot, log, LogAction @bot.on_message(filters=filters.group & filters.command("reverify")) async def re_verify(client: Client, message: Message): - if not message.from_user or not message.reply_to_message: + reply_to: "Message" = message.reply_to_message + if not message.from_user or not reply_to: msg: Message = await message.reply("请回复一条消息来使 Ta 重新验证。") - add_delete_message_job(message, 10) - add_delete_message_job(msg, 10) + await message.delay_delete(10) + await msg.delay_delete(10) return - if not message.reply_to_message.from_user: + if not reply_to.from_user: return chat = message.chat user = message.from_user @@ -27,7 +25,7 @@ async def re_verify(client: Client, message: Message): if member.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]: return - user = message.reply_to_message.from_user + user = reply_to.from_user if ( user.is_self or user.is_verified @@ -37,46 +35,36 @@ async def re_verify(client: Client, message: Message): ): return member = await client.get_chat_member(chat.id, user.id) - with contextlib.suppress(Exception): - await message.delete() + await message.delay_delete(1) + key = f"wait:{chat.id}:{user.id}" + await cache.set(key, "True", expire=VERIFY_TIME + 5) try: - msg = await message.reply_to_message.reply(RE_MSG % (user.mention, user.mention)) + msg = await reply_to.reply(RE_MSG % (user.mention, user.mention)) except Exception as _: return try: - msg_ = await client.listen(chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME) - with contextlib.suppress(Exception): - await msg.delete() + msg_ = await client.listen( + chat.id, filters=filters.user(user.id), timeout=VERIFY_TIME + ) + await msg.delay_delete(1) + await msg_.delay_delete(1) if not msg_.sticker: - with contextlib.suppress(Exception): - await message.reply_to_message.delete() + await reply_to.delay_delete(1) if member.status not in [ ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR, ]: - with contextlib.suppress(Exception): - await bot.ban_chat_member( - chat.id, user.id, datetime.now() + timedelta(minutes=5) - ) - with contextlib.suppress(Exception): - await log(chat, user, "FAIL_ERROR") + add_ban_chat_member_job(chat.id, user.id) + await log(chat, user, LogAction.FAIL_ERROR) else: - with contextlib.suppress(Exception): - await log(chat, user, "ACCEPT") - with contextlib.suppress(Exception): - await msg_.delete() + await cache.delete(key) + await log(chat, user, LogAction.ACCEPT) except TimeoutConversationError: - with contextlib.suppress(Exception): - await msg.delete() - with contextlib.suppress(Exception): - await message.reply_to_message.delete() + await msg.delay_delete(1) + await reply_to.delay_delete(1) if member.status not in [ ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR, ]: - with contextlib.suppress(Exception): - await bot.ban_chat_member( - chat.id, user.id, datetime.now() + timedelta(minutes=5) - ) - with contextlib.suppress(Exception): - await log(chat, user, "FAIL_TIMEOUT") + add_ban_chat_member_job(chat.id, user.id) + await log(chat, user, LogAction.FAIL_TIMEOUT) diff --git a/pyromod/filters/__init__.py b/pyromod/filters/__init__.py deleted file mode 100644 index 4b8f182..0000000 --- a/pyromod/filters/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -pyromod - A monkeypatcher add-on for Pyrogram -Copyright (C) 2020 Cezar H. - -This file is part of pyromod. - -pyromod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -pyromod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with pyromod. If not, see . -""" - -from .filters import dice diff --git a/pyromod/filters/filters.py b/pyromod/filters/filters.py deleted file mode 100644 index c52d680..0000000 --- a/pyromod/filters/filters.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -pyromod - A monkeypatcher add-on for Pyrogram -Copyright (C) 2020 Cezar H. - -This file is part of pyromod. - -pyromod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -pyromod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with pyromod. If not, see . -""" - -import pyrogram - - -def dice(ctx, message): - return hasattr(message, "dice") and message.dice - - -pyrogram.filters.dice = dice diff --git a/pyromod/helpers/__init__.py b/pyromod/helpers/__init__.py deleted file mode 100644 index 03dda1a..0000000 --- a/pyromod/helpers/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -""" -pyromod - A monkeypatcher add-on for Pyrogram -Copyright (C) 2020 Cezar H. - -This file is part of pyromod. - -pyromod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -pyromod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with pyromod. If not, see . -""" -from .helpers import ikb, bki, ntb, btn, kb, kbtn, array_chunk, force_reply diff --git a/pyromod/helpers/helpers.py b/pyromod/helpers/helpers.py deleted file mode 100644 index 2c7b9e1..0000000 --- a/pyromod/helpers/helpers.py +++ /dev/null @@ -1,86 +0,0 @@ -from pyrogram.types import ( - InlineKeyboardButton, - InlineKeyboardMarkup, - KeyboardButton, - ReplyKeyboardMarkup, - ForceReply, -) - - -def ikb(rows=None): - if rows is None: - rows = [] - lines = [] - for row in rows: - line = [] - for button in row: - button = btn(*button) # InlineKeyboardButton - line.append(button) - lines.append(line) - return InlineKeyboardMarkup(inline_keyboard=lines) - # return {'inline_keyboard': lines} - - -def btn(text, value, type="callback_data"): - return InlineKeyboardButton(text, **{type: value}) - # return {'text': text, type: value} - - -# The inverse of above -def bki(keyboard): - lines = [] - for row in keyboard.inline_keyboard: - line = [] - for button in row: - button = ntb(button) # btn() format - line.append(button) - lines.append(line) - return lines - # return ikb() format - - -def ntb(button): - for btn_type in [ - "callback_data", - "url", - "switch_inline_query", - "switch_inline_query_current_chat", - "callback_game", - ]: - value = getattr(button, btn_type) - if value: - break - button = [button.text, value] - if btn_type != "callback_data": - button.append(btn_type) - return button - # return {'text': text, type: value} - - -def kb(rows=None, **kwargs): - if rows is None: - rows = [] - lines = [] - for row in rows: - line = [] - for button in row: - button_type = type(button) - if button_type == str: - button = KeyboardButton(button) - elif button_type == dict: - button = KeyboardButton(**button) - - line.append(button) - lines.append(line) - return ReplyKeyboardMarkup(keyboard=lines, **kwargs) - - -kbtn = KeyboardButton - - -def force_reply(selective=True): - return ForceReply(selective=selective) - - -def array_chunk(input_, size): - return [input_[i : i + size] for i in range(0, len(input_), size)] diff --git a/pyromod/listen/listen.py b/pyromod/listen/listen.py index 0309b4c..46e3049 100644 --- a/pyromod/listen/listen.py +++ b/pyromod/listen/listen.py @@ -19,16 +19,18 @@ along with pyromod. If not, see . """ import asyncio +import contextlib import functools import pyrogram -from typing import Dict from sticker.scheduler import add_delete_message_job from ..utils import patch, patchable from ..utils.errors import ListenerCanceled, TimeoutConversationError pyrogram.errors.ListenerCanceled = ListenerCanceled +LOCK = asyncio.Lock() +DONE = [] @patch(pyrogram.client.Client) @@ -63,8 +65,9 @@ class Client: @patchable def clear_listener(self, chat_id, future): - if future == self.listening[chat_id]["future"]: - self.listening.pop(chat_id, None) + with contextlib.suppress(KeyError): + if future == self.listening[chat_id]["future"]: + self.listening.pop(chat_id, None) @patchable def cancel_listener(self, chat_id): @@ -90,25 +93,33 @@ class MessageHandler: @patchable async def resolve_listener(self, client, message, *args): - listener = client.listening.get(message.chat.id) - if listener and not listener["future"].done(): - listener["future"].set_result(message) - else: + global LOCK, DONE + async with LOCK: + listener = client.listening.get(message.chat.id) + if listener: + with contextlib.suppress(ValueError): + DONE.remove(listener) + if listener and not listener["future"].done(): + listener["future"].set_result(message) + return if listener and listener["future"].done(): client.clear_listener(message.chat.id, listener["future"]) - await self.user_callback(client, message, *args) + await self.user_callback(client, message, *args) @patchable async def check(self, client, update): - listener = client.listening.get(update.chat.id) - - if listener and not listener["future"].done(): - return ( - await listener["filters"](client, update) - if callable(listener["filters"]) - else True - ) - + global LOCK, DONE + async with LOCK: + listener = client.listening.get(update.chat.id) + if listener and (listener not in DONE) and (not listener["future"].done()): + if callable(listener["filters"]): + result = await listener["filters"](client, update) + if result: + DONE.append(listener) + return result + else: + DONE.append(listener) + return True return await self.filters(client, update) if callable(self.filters) else True diff --git a/pyromod/nav/__init__.py b/pyromod/nav/__init__.py deleted file mode 100644 index 2d451b8..0000000 --- a/pyromod/nav/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -""" -pyromod - A monkeypatcher add-on for Pyrogram -Copyright (C) 2020 Cezar H. - -This file is part of pyromod. - -pyromod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -pyromod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with pyromod. If not, see . -""" -from .pagination import Pagination diff --git a/pyromod/nav/pagination.py b/pyromod/nav/pagination.py deleted file mode 100644 index 8e0c3f9..0000000 --- a/pyromod/nav/pagination.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -pyromod - A monkeypatcher add-on for Pyrogram -Copyright (C) 2020 Cezar H. - -This file is part of pyromod. - -pyromod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -pyromod is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with pyromod. If not, see . -""" -import math -from ..helpers import array_chunk - - -class Pagination: - def __init__(self, objects, page_data=None, item_data=None, item_title=None): - default_page_callback = lambda x: str(x) - default_item_callback = lambda i, pg: f"[{pg}] {i}" - self.objects = objects - self.page_data = page_data or default_page_callback - self.item_data = item_data or default_item_callback - self.item_title = item_title or default_item_callback - - def create(self, page, lines=5, columns=1): - quant_per_page = lines * columns - page = 1 if page <= 0 else page - offset = (page - 1) * quant_per_page - stop = offset + quant_per_page - cutted = self.objects[offset:stop] - - total = len(self.objects) - pages_range = [ - *range(1, math.ceil(total / quant_per_page) + 1) - ] # each item is a page - last_page = len(pages_range) - - nav = [] - if page <= 3: - for n in [1, 2, 3]: - if n not in pages_range: - continue - text = f"· {n} ·" if n == page else n - nav.append((text, self.page_data(n))) - if last_page >= 4: - nav.append(("4 ›" if last_page > 5 else 4, self.page_data(4))) - if last_page > 4: - nav.append( - ( - f"{last_page} »" if last_page > 5 else last_page, - self.page_data(last_page), - ) - ) - elif page >= last_page - 2: - nav.extend( - [ - ("« 1" if last_page > 5 else 1, self.page_data(1)), - ( - f"‹ {last_page - 3}" if last_page > 5 else last_page - 3, - self.page_data(last_page - 3), - ), - ] - ) - - for n in range(last_page - 2, last_page + 1): - text = f"· {n} ·" if n == page else n - nav.append((text, self.page_data(n))) - else: - nav = [ - ("« 1", self.page_data(1)), - (f"‹ {page - 1}", self.page_data(page - 1)), - (f"· {page} ·", "noop"), - (f"{page + 1} ›", self.page_data(page + 1)), - (f"{last_page} »", self.page_data(last_page)), - ] - - buttons = [ - (self.item_title(item, page), self.item_data(item, page)) for item in cutted - ] - - kb_lines = array_chunk(buttons, columns) - if last_page > 1: - kb_lines.append(nav) - - return kb_lines diff --git a/sticker/__init__.py b/sticker/__init__.py index 9864da1..87d528a 100644 --- a/sticker/__init__.py +++ b/sticker/__init__.py @@ -1,5 +1,7 @@ import contextlib import sys +from enum import Enum + from cashews import cache from datetime import datetime, timezone from logging import getLogger, StreamHandler, CRITICAL, INFO, basicConfig, DEBUG @@ -54,22 +56,48 @@ bot = Client( ) -async def log(chat, user, action): +class LogAction(str, Enum): + FAIL_ERROR = "FAIL_ERROR" + FAIL_TIMEOUT = "FAIL_TIMEOUT" + ACCEPT = "ACCEPT" + NEW_GROUP = "NEW_GROUP" + REQUEST = "REQUEST" + + +async def log(chat, user, action: LogAction): + scheduler.add_job( + _log, + args=[chat, user, action], + replace_existing=False, + ) + + +async def _log(chat, user, action: LogAction): if not Config.LOG_CHANNEL: return me = await bot.get_me() event = { - "FAIL_ERROR": "回答错误", - "FAIL_TIMEOUT": "回答超时", - "ACCEPT": "通过验证", - "NEW_GROUP": "加入群组", - "REQUEST": "发起验证", + LogAction.FAIL_ERROR: "回答错误", + LogAction.FAIL_TIMEOUT: "回答超时", + LogAction.ACCEPT: "通过验证", + LogAction.NEW_GROUP: "加入群组", + LogAction.REQUEST: "发起验证", } msg = """#%s 群组: %s 群组id: %s 用户: #id%s +昵称:%s OPBot: #bot%s 事件: %s""" - msg %= (action, chat.title, chat.id, user.id if user else "", me.id, event[action]) + user_name = user.full_name if user else "" + msg %= ( + action.value, + chat.title, + chat.id, + user.id if user else "", + user_name, + me.id, + event[action], + ) await bot.send_message(Config.LOG_CHANNEL, msg) diff --git a/sticker/languages.py b/sticker/languages.py index 3252201..c0f1e2f 100644 --- a/sticker/languages.py +++ b/sticker/languages.py @@ -1,4 +1,4 @@ -VERIFY_TIME = 60 +VERIFY_TIME = 180 MSG_PUBLIC = """您好,我发现此群组为公开群组,您需要联系创建者打开 `管理员批准后才能入群` 功能,我才能更好地工作。""" MSG_SUCCESS = """验证成功,您已经成为群组的一员了! diff --git a/sticker/scheduler.py b/sticker/scheduler.py index bbef26e..9b259d7 100644 --- a/sticker/scheduler.py +++ b/sticker/scheduler.py @@ -5,6 +5,7 @@ import pytz from apscheduler.schedulers.asyncio import AsyncIOScheduler from pyrogram.types import ChatJoinRequest +from sticker.languages import VERIFY_TIME from sticker.single_utils import Message scheduler = AsyncIOScheduler(timezone="Asia/ShangHai") @@ -24,6 +25,17 @@ async def decline_request(chat_join_request: ChatJoinRequest): return False +async def ban_chat_member(chat_id: int, user_id: int): + from sticker import bot + + with contextlib.suppress(Exception): + await bot.ban_chat_member( + chat_id, user_id, datetime.datetime.now() + datetime.timedelta(minutes=5) + ) + return True + return False + + def add_delete_message_job(message: Message, delete_seconds: int = 60): scheduler.add_job( delete_message, @@ -45,7 +57,17 @@ def add_decline_request_job(chat_join_request: ChatJoinRequest): name=f"{chat_join_request.chat.id}|{chat_join_request.from_user.id}|decline_request", args=[chat_join_request], run_date=datetime.datetime.now(pytz.timezone("Asia/Shanghai")) - + datetime.timedelta(seconds=60), + + datetime.timedelta(seconds=VERIFY_TIME), + replace_existing=True, + ) + + +def add_ban_chat_member_job(chat_id: int, user_id: int): + scheduler.add_job( + ban_chat_member, + id=f"{chat_id}|{user_id}|ban_chat_member", + name=f"{chat_id}|{user_id}|ban_chat_member", + args=[chat_id, user_id], replace_existing=True, )