Преглед на файлове

feat: manual approval (#237)

* Added: manual approval

* fix: remove redundant int()

---------

Co-authored-by: Akshay Rajput <thehamkercat@gmail.com>
SI_NN_ER_LS преди 2 години
родител
ревизия
8f3a9902e4
променени са 1 файла, в които са добавени 163 реда и са изтрити 55 реда
  1. 163 55
      wbb/modules/autoapprove.py

+ 163 - 55
wbb/modules/autoapprove.py

@@ -1,47 +1,89 @@
+"""
+MIT License
+
+Copyright (c) 2023 SI_NN_ER_LS 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from wbb import app, SUDOERS
+from wbb import db
 from pyrogram import filters
+from pyrogram.enums import ChatMembersFilter
 from pyrogram.types import (
-    CallbackQuery,
-    Chat,
-    ChatJoinRequest,
     InlineKeyboardButton,
     InlineKeyboardMarkup,
+    CallbackQuery,
     Message,
+    Chat,
+    ChatJoinRequest,
 )
-
-from wbb import SUDOERS, app, db
+from wbb.modules.greetings import handle_new_member, send_welcome_message
+from wbb.core.keyboard import ikb
 from wbb.core.decorators.permissions import adminsOnly
 from wbb.modules.admin import member_permissions
-from wbb.modules.greetings import handle_new_member
 
 approvaldb = db.autoapprove
 
-# For /help menu
 __MODULE__ = "Autoapprove"
 __HELP__ = """
 command: /autoapprove
 
-This module helps to automatically accept chat join request send by a user through invitation link of your group"""
+This module helps to automatically accept chat join request send by a user through invitation link of your group
+
+**Modes:**
+¤ Automatic - Automatically accepts chat join request.
+
+¤ Manual - A message will be send to the chat by tagging the admins. The admins can accept or decline the requests.
+
+Use: /clear_pending Command to remove all pending user ID from DB. This will allow the user to send request again.
+"""
 
 
 @app.on_message(filters.command("autoapprove") & filters.group)
 @adminsOnly("can_change_info")
 async def approval_command(client, message):
     chat_id = message.chat.id
-    if (await approvaldb.count_documents({"chat_id": chat_id})) > 0:
-        keyboard_OFF = InlineKeyboardMarkup(
-            [[InlineKeyboardButton("Turn OFF", callback_data="approval_off")]]
-        )
+    chat = await approvaldb.find_one({"chat_id": chat_id})
+    if chat:
+        mode = chat.get("mode", "")
+        if not mode:
+            mode = "automatic"
+            await approvaldb.update_one(
+                {"chat_id": chat_id},
+                {"$set": {"mode": mode}},
+                upsert=True,
+                   )
+        if mode == "automatic":
+            switch = "manual"
+        else:
+            switch = "automatic"
+        buttons = {"Turn OFF": "approval_off", f"{(mode.upper())}": f"approval_{switch}"}
+        keyboard = ikb(buttons, 1)
         await message.reply(
-            "**Autoapproval for this chat: Enabled.**",
-            reply_markup=keyboard_OFF,
+            "**Autoapproval for this chat: Enabled.**", reply_markup=keyboard
         )
     else:
-        keyboard_ON = InlineKeyboardMarkup(
-            [[InlineKeyboardButton("Turn ON", callback_data="approval_on")]]
-        )
+        buttons = {"Turn ON": "approval_on"}
+        keyboard = ikb(buttons, 1)
         await message.reply(
-            "**Autoapproval for this chat: Disabled.**",
-            reply_markup=keyboard_ON,
+            "**Autoapproval for this chat: Disabled.**", reply_markup=keyboard
         )
 
 
@@ -49,7 +91,6 @@ async def approval_command(client, message):
 async def approval_cb(client, cb):
     chat_id = cb.message.chat.id
     from_user = cb.from_user
-
     permissions = await member_permissions(chat_id, from_user.id)
     permission = "can_restrict_members"
     if permission not in permissions:
@@ -58,49 +99,116 @@ async def approval_cb(client, cb):
                 f"You don't have the required permission.\n Permission: {permission}",
                 show_alert=True,
             )
-
     command_parts = cb.data.split("_", 1)
     option = command_parts[1]
-
-    if option == "on":
-        if await approvaldb.count_documents({"chat_id": chat_id}) == 0:
-            approvaldb.insert_one({"chat_id": chat_id})
-            keyboard_off = InlineKeyboardMarkup(
-                [
-                    [
-                        InlineKeyboardButton(
-                            "Turn OFF", callback_data="approval_off"
-                        )
-                    ]
-                ]
-            )
-            await cb.edit_message_text(
-                "**Autoapproval for this chat: Enabled.**",
-                reply_markup=keyboard_off,
-            )
-    elif option == "off":
+    if option == "off":
         if await approvaldb.count_documents({"chat_id": chat_id}) > 0:
             approvaldb.delete_one({"chat_id": chat_id})
-            keyboard_on = InlineKeyboardMarkup(
-                [
-                    [
-                        InlineKeyboardButton(
-                            "Turn ON", callback_data="approval_on"
-                        )
-                    ]
-                ]
+            buttons = {"Turn ON": "approval_on"}
+            keyboard = ikb(buttons, 1)
+            return await cb.edit_message_text(
+                "**Autoapproval for this chat: Disabled.**", reply_markup=keyboard
             )
-            await cb.edit_message_text(
-                "**Autoapproval for this chat: Disabled.**",
-                reply_markup=keyboard_on,
-            )
-    return await cb.answer()
+    if option == "on":
+        switch = "manual"
+        mode = "automatic"
+    if option == "automatic":
+        switch = "manual"
+        mode = option
+    if option == "manual":
+        switch = "automatic"
+        mode = option
+    await approvaldb.update_one(
+        {"chat_id": chat_id},
+        {"$set": {"mode": mode}},
+        upsert=True,
+    )
+    chat = await approvaldb.find_one({"chat_id": chat_id})
+    mode = chat["mode"].upper()
+    buttons = {"Turn OFF": "approval_off", f"{mode}": f"approval_{switch}"}
+    keyboard = ikb(buttons, 1)
+    await cb.edit_message_text(
+        "**Autoapproval for this chat: Enabled.**", reply_markup=keyboard
+    )
+
+
+@app.on_message(filters.command("clear_pending") & filters.group)
+@adminsOnly("can_restrict_members")
+async def clear_pending_command(client, message):
+    chat_id = message.chat.id
+    result = await approvaldb.update_one(
+        {"chat_id": chat_id},
+        {"$set": {"pending_users": []}},
+    )
+    if result.modified_count > 0:
+        await message.reply_text("Cleared pending users.")
+    else:
+        await message.reply_text("No pending users to clear.")
 
 
 @app.on_chat_join_request(filters.group)
 async def accept(client, message: ChatJoinRequest):
     chat = message.chat
     user = message.from_user
-    if (await approvaldb.count_documents({"chat_id": chat.id})) > 0:
-        await app.approve_chat_join_request(chat_id=chat.id, user_id=user.id)
-        await handle_new_member(message, user, chat)
+    chat_id = await approvaldb.find_one({"chat_id": chat.id})
+    if chat_id:
+        mode = chat_id["mode"]
+        if mode == "automatic":
+            await app.approve_chat_join_request(chat_id=chat.id, user_id=user.id)
+            return await handle_new_member(message, user, chat_id)
+        if mode == "manual":
+            is_user_in_pending = await approvaldb.count_documents(
+                {"chat_id": chat.id, "pending_users": int(user.id)}
+            )
+            if is_user_in_pending == 0:
+                await approvaldb.update_one(
+                    {"chat_id": chat.id},
+                    {"$addToSet": {"pending_users": int(user.id)}},
+                    upsert=True,
+                )
+                buttons = {
+                    "accept": f"manual_approve_{user.id}",
+                    "Decline": f"manual_decline_{user.id}",
+                }
+                keyboard = ikb(buttons, int(2))
+                text = f"**User: {user.mention} has send a request to join our  group. Any admins can accept or decline it.**"
+                admin_data = [
+                    i
+                    async for i in app.get_chat_members(
+                        chat_id=message.chat.id, filter=ChatMembersFilter.ADMINISTRATORS
+                    )
+                ]
+                for admin in admin_data:
+                    if admin.user.is_bot or admin.user.is_deleted:
+                        continue
+                    text += f"[\u2063](tg://user?id={admin.user.id})"
+                return await app.send_message(chat.id, text, reply_markup=keyboard)
+
+
+@app.on_callback_query(filters.regex("manual_(.*)"))
+async def manual(app, cb):
+    chat = cb.message.chat
+    from_user = cb.from_user
+    permissions = await member_permissions(chat.id, from_user.id)
+    permission = "can_restrict_members"
+    if permission not in permissions:
+        if from_user.id not in SUDOERS:
+            return await cb.answer(
+                f"You don't have the required permission.\n Permission: {permission}",
+                show_alert=True,
+            )
+    datas = cb.data.split("_", 1)[1]
+    data = datas.split("_", 1)
+    dis = data[0]
+    id = data[1]
+    if dis == "approve":
+        await app.approve_chat_join_request(chat_id=chat.id, user_id=id)
+        # No need to verify user as admin is the one who accept the request
+        await send_welcome_message(chat, id, True)
+    if dis == "decline":
+        await app.decline_chat_join_request(chat_id=chat.id, user_id=id)
+    await approvaldb.update_one(
+        {"chat_id": chat.id},
+        {"$pull": {"pending_users": int(id)}},
+    )
+    return await cb.message.delete()