فهرست منبع

Rewrote Captcha module

TheHamkerCat 5 سال پیش
والد
کامیت
430ee044d9
4فایلهای تغییر یافته به همراه128 افزوده شده و 71 حذف شده
  1. 1 0
      .gitignore
  2. BIN
      assets/arial.ttf
  3. 76 71
      wbb/modules/greetings.py
  4. 51 0
      wbb/utils/functions.py

+ 1 - 0
.gitignore

@@ -1,3 +1,4 @@
+*.jpg
 token.py
 *.raw
 images/

BIN
assets/arial.ttf


+ 76 - 71
wbb/modules/greetings.py

@@ -1,22 +1,19 @@
-"""
- Thanks to @dashezup for this idea
- Repo - https://github.com/dashezup/tgbot
-"""
+""" Kang with proper credits or /gbun """
 
 import asyncio
 from wbb import app, WELCOME_DELAY_KICK_SEC
 from wbb.modules.admin import member_permissions
 from wbb.utils.errors import capture_err
 from wbb.utils.filter_groups import welcome_captcha_group
+from wbb.utils.functions import generate_captcha
 from wbb.utils.dbfunctions import (
-        is_gbanned_user, is_captcha_on, captcha_on, captcha_off
-        )
+    is_gbanned_user, is_captcha_on, captcha_on, captcha_off
+)
 from pyrogram.types import (
-        Message, InlineKeyboardMarkup,
-        InlineKeyboardButton, ChatPermissions, User
-         )
+    Message, InlineKeyboardMarkup,
+    InlineKeyboardButton, ChatPermissions, User
+)
 from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant, ChatAdminRequired
-from pyrogram import emoji
 from pyrogram import filters
 from random import shuffle
 from datetime import datetime
@@ -25,47 +22,65 @@ __MODULE__ = "Captcha"
 __HELP__ = "/captcha [ON|OFF] - Enable/Disable Captcha."
 
 
+answers_dicc = []
+
+
 @app.on_message(filters.new_chat_members, group=welcome_captcha_group)
 @capture_err
 async def welcome(_, message: Message):
+    global answers_dicc
     """Mute new member and send message with button"""
     if not await is_captcha_on(message.chat.id):
         return
     for member in message.new_chat_members:
         try:
-            if await is_gbanned_user(member.id):
-                await message.chat.kick_member(member.id)
-                continue
+            # if await is_gbanned_user(member.id):
+            #    await message.chat.kick_member(member.id)
+            #    continue
             if member.is_bot:
                 continue  # ignore bots
-            text = (f"Welcome, {(member.mention())}\nAre you human?\n"
-                    f"Click on the button which include this emoji {emoji.CHECK_MARK_BUTTON}.'")
             await message.chat.restrict_member(member.id, ChatPermissions())
+            text = (f"Welcome, {(member.mention())} Are you human?\n"
+                    f"Solve this captcha in {WELCOME_DELAY_KICK_SEC} seconds or you'll be kicked.")
         except ChatAdminRequired:
-            continue
-
-        keyboard = [
-            InlineKeyboardButton(
-                f"{emoji.BRAIN}",
-                callback_data=f"pressed_button {emoji.BRAIN} {member.id}"
-            ),
-            InlineKeyboardButton(
-                f"{emoji.CHECK_MARK_BUTTON}",
-                callback_data=f"pressed_button {emoji.CHECK_MARK_BUTTON} {member.id}"
-            ),
-            InlineKeyboardButton(
-                f"{emoji.CROSS_MARK}",
-                callback_data=f"pressed_button {emoji.CROSS_MARK} {member.id}"
-            ),
-            InlineKeyboardButton(
-                f"{emoji.ROBOT}",
-                callback_data=f"pressed_button {emoji.ROBOT} {member.id}"
+            break
+        captcha = generate_captcha()
+        captcha_image = captcha[0]
+        captcha_answer = captcha[1]
+        wrong_answers = captcha[2]
+        correct_button = InlineKeyboardButton(
+            f"{captcha_answer}",
+            callback_data=f"pressed_button {captcha_answer} {member.id}"
+        )
+        temp_keyboard_1 = [correct_button]
+        temp_keyboard_2 = []
+        for i in range(3):
+            temp_keyboard_1.append(
+                InlineKeyboardButton(
+                    f"{wrong_answers[i]}",
+                    callback_data=f"pressed_button {wrong_answers[i]} {member.id}"
+                )
+            )
+        for i in range(3, 7):
+            temp_keyboard_2.append(
+                InlineKeyboardButton(
+                    f"{wrong_answers[i]}",
+                    callback_data=f"pressed_button {wrong_answers[i]} {member.id}"
+                )
             )
-        ]
+        shuffle(temp_keyboard_1)
+        keyboard = [temp_keyboard_1, temp_keyboard_2]
         shuffle(keyboard)
-        keyboard = InlineKeyboardMarkup([keyboard])
-        button_message = await message.reply(
-            text,
+        verification_data = {
+            "user_id": member.id,
+            "answer": captcha_answer,
+            "keyboard": keyboard
+        }
+        keyboard = InlineKeyboardMarkup(keyboard)
+        answers_dicc.append(verification_data)
+        button_message = await message.reply_photo(
+            photo=captcha_image,
+            caption=text,
             reply_markup=keyboard,
             quote=True
         )
@@ -75,47 +90,42 @@ async def welcome(_, message: Message):
 
 
 @app.on_callback_query(filters.regex("pressed_button"))
-async def callback_query_welcome_button(client, callback_query):
-    """After the new member presses the button, set his permissions to
-    chat permissions, delete button message and join message
+async def callback_query_welcome_button(_, callback_query):
+    """After the new member presses the correct button,
+    set his permissions to chat permissions,
+    delete button message and join message.
     """
+    global answers_dicc
     data = callback_query.data
     pending_user = await app.get_users(int(data.split(None, 2)[2]))
     pressed_user_id = callback_query.from_user.id
     pending_user_id = pending_user.id
     button_message = callback_query.message
     answer = data.split(None, 2)[1]
+    if len(answers_dicc) != 0:
+        for i in answers_dicc:
+            if i['user_id'] == pending_user_id:
+                correct_answer = i['answer']
+                keyboard = i['keyboard']
     if pending_user_id == pressed_user_id:
-        if answer != emoji.CHECK_MARK_BUTTON:
+        if answer != correct_answer:
             await callback_query.answer("Yeah, It's Wrong.")
-            keyboard = [
-                InlineKeyboardButton(
-                    f"{emoji.BRAIN}",
-                    callback_data=f"pressed_button {emoji.BRAIN} {pending_user_id}"
-                ),
-                InlineKeyboardButton(
-                    f"{emoji.CHECK_MARK_BUTTON}",
-                    callback_data=f"pressed_button {emoji.CHECK_MARK_BUTTON} {pending_user_id}"
-                ),
-                InlineKeyboardButton(
-                    f"{emoji.CROSS_MARK}",
-                    callback_data=f"pressed_button {emoji.CROSS_MARK} {pending_user_id}"
-                ),
-                InlineKeyboardButton(
-                    f"{emoji.ROBOT}",
-                    callback_data=f"pressed_button {emoji.ROBOT} {pending_user_id}"
-                )
-            ]
+            shuffle(keyboard[0])
+            shuffle(keyboard[1])
             shuffle(keyboard)
-            keyboard = InlineKeyboardMarkup([keyboard])
+            keyboard = InlineKeyboardMarkup(keyboard)
             await button_message.edit(
-                text=button_message.text,
+                text=button_message.caption.markdown,
                 reply_markup=keyboard
             )
             return
         await callback_query.answer("Captcha passed successfully!")
         await button_message.chat.unban_member(pending_user_id)
         await button_message.delete()
+        if len(answers_dicc) != 0:
+            for ii in answers_dicc:
+                if ii['user_id'] == pending_user_id:
+                    answers_dicc.remove(ii)
         return
     else:
         await callback_query.answer("This is not for you")
@@ -126,25 +136,20 @@ async def kick_restricted_after_delay(delay, button_message: Message, user: User
     """If the new member is still restricted after the delay, delete
     button message and join message and then kick him
     """
+    global answers_dicc
     await asyncio.sleep(delay)
     join_message = button_message.reply_to_message
     group_chat = button_message.chat
     user_id = user.id
     await join_message.delete()
     await button_message.delete()
+    if len(answers_dicc) != 0:
+        for i in answers_dicc:
+            if i['user_id'] == user_id:
+                answers_dicc.remove(i)
     await _ban_restricted_user_until_date(group_chat, user_id, duration=delay)
 
 
-@app.on_message(filters.left_chat_member)
-@capture_err
-async def left_chat_member(_, message: Message):
-    """When a restricted member left the chat, ban him for a while"""
-    group_chat = message.chat
-    user_id = message.left_chat_member.id
-    await _ban_restricted_user_until_date(group_chat, user_id,
-                                          duration=WELCOME_DELAY_KICK_SEC)
-
-
 async def _ban_restricted_user_until_date(group_chat,
                                           user_id: int,
                                           duration: int):

+ 51 - 0
wbb/utils/functions.py

@@ -0,0 +1,51 @@
+from PIL import Image, ImageDraw, ImageFont, ImageFilter
+from random import randint
+
+
+def generate_captcha():
+    # Generate one letter
+    def gen_letter():
+        return chr(randint(65, 90))
+    
+    def rndColor():
+        return (randint(64, 255), randint(64, 255), randint(64, 255))
+    def rndColor2():
+        return (randint(32, 127), randint(32, 127), randint(32, 127))
+    
+    # Generate a 4 letter word
+    def gen_wrong_answer():
+        word = ""
+        for _ in range(4):
+            word += gen_letter()
+        return word 
+
+    # Generate 7 wrong captcha answers
+    wrong_answers = []
+    for _ in range(7):
+        wrong_answers.append(gen_wrong_answer())
+    
+    width = 120 * 4
+    height = 120
+    correct_answer = ""
+    font = ImageFont.truetype("assets/arial.ttf", 90)
+    file = "assets/captcha.jpg"
+    image = Image.new('RGB', (width, height), (255, 255, 255))
+    draw = ImageDraw.Draw(image)
+    
+    # Draw random points on image
+    for x in range(width):
+        for y in range(height):
+            draw.point((x, y), fill=rndColor())
+
+    for t in range(4):
+        letter = gen_letter()
+        correct_answer += letter
+        draw.text(
+                (120 * t + 32, 3),
+                letter,
+                font=font,
+                fill=rndColor2()
+                )
+    image = image.filter(ImageFilter.BLUR)
+    image.save(file, 'jpeg')
+    return [file, correct_answer, wrong_answers]