import contextlib from asyncio import sleep from random import uniform from pyrogram.enums import ChatMemberStatus from pyrogram import filters from pyrogram.errors import ( ChatAdminRequired, FloodWait, UserAdminInvalid, PeerIdInvalid, BadRequest, ) from datetime import datetime, timedelta from pagermaid.listener import listener from pagermaid.enums import Message, Client from pagermaid.services import bot async def check_self_and_from(message: Message): cid = message.chat.id data = await bot.get_chat_member(cid, (await bot.get_me()).id) if data.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]: return False if not message.from_user: return False if message.outgoing: return True data = await bot.get_chat_member(cid, message.from_user.id) return data.status in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER] async def kick_chat_member(cid, uid, only_search: bool = False): if only_search: return try: with contextlib.suppress(UserAdminInvalid, PeerIdInvalid, BadRequest): await bot.ban_chat_member(cid, uid, datetime.now() + timedelta(minutes=5)) except FloodWait as e: await sleep(e.value + uniform(0.5, 1.0)) await kick_chat_member(cid, uid, only_search) async def process_clean_member( message: Message, mode: str, day: int, only_search: bool = False ): member_count = 0 try: async for member in bot.get_chat_members(message.chat.id): if ( mode == "1" and member.user.last_online_date and member.user.last_online_date < datetime.now() - timedelta(days=day) ): member_count += 1 await kick_chat_member(message.chat.id, member.user.id, only_search) if mode == "2": now = datetime.now() - timedelta(days=day) async for message in bot.search_messages( message.chat.id, limit=1, from_user=member.user.id ): if message.date < now: member_count += 1 await kick_chat_member( message.chat.id, member.user.id, only_search ) elif mode == "3": try: count = await bot.search_messages_count( message.chat.id, from_user=member.user.id ) except PeerIdInvalid: continue if count < day: member_count += 1 await kick_chat_member(message.chat.id, member.user.id, only_search) if mode == "4" and member.user.is_deleted: member_count += 1 await kick_chat_member(message.chat.id, member.user.id, only_search) if mode == "5": member_count += 1 await kick_chat_member(message.chat.id, member.user.id, only_search) if not only_search: await message.edit(f"成功清理了 `{member_count}` 人。") else: await message.edit(f"查找到了 `{member_count}` 人。") except ChatAdminRequired: await message.edit("你好像并不拥有封禁用户权限。") except FloodWait: return await message.edit("处理失败,您已受到 TG 服务器限制。") @listener( command="clean_member", need_admin=True, groups_only=True, description="多种方式清理群成员" ) async def clean_member(client: Client, message: Message): if not await check_self_and_from(message): return await message.edit("您不是群管理员,无法使用此命令") uid = message.from_user.id mode, day = "0", 0 reply = await message.edit( "请选择清理模式:\n\n" "1. 按未上线时间清理\n" "2. 按未发言时间清理(大群慎用)\n" "3. 按发言数清理\n" "4. 清理死号\n" "5. 清理所有人(大群慎用)" ) try: async with client.conversation( message.chat.id, filters=filters.user(uid) ) as conv: await sleep(1) res: Message = await conv.get_response() mode = res.text await res.safe_delete() if mode in ["1", "2"]: await res.safe_delete() await reply.edit("请输入清理天数:") await sleep(1) res = await conv.get_response() day = max(int(res.text), 7) await res.safe_delete() elif mode == "3": await res.safe_delete() await reply.edit("清理发言少于多少条的群成员:") await sleep(1) res = await conv.get_response() day = int(res.text) await res.safe_delete() elif mode == "4": pass elif mode != "5": raise ValueError("清理模式错误") await reply.edit("查找还是清理?") await sleep(1) res = await conv.get_response() only_search = res.text == "查找" await res.safe_delete() except ValueError as e: return await reply.edit(f"{e}") await reply.edit("遍历成员中。。。") await process_clean_member(reply, mode, day, only_search)