An easy to use an (hopefully useful) captcha solution for pyTelegramBotAPI

Overview

pyTelegramBotCAPTCHA

An easy to use and (hopefully useful) image CAPTCHA soltion for pyTelegramBotAPI.

PyPi Package Version Supported Python versions


Installation:

pip install pyTelegramBotCAPTCHA

Do not forget to update the package from time to time by calling
pip install pyTelegramBotCAPTCHA --upgrade


Description:

Do you have problems with userbots that spam your groups or add your group members to other chats? Then this package can help you to protect your groups and members! It's very easy to integrate into your existing bot and also easy to customize the CAPTCHA image with your own fonts.
You can also choose between digits and hexdigits for your CAPTCHA generation.
Note: You should have basic knowledge about the pyTelegramBotAPI
Example1 Example2


Writing a CAPTCHA bot:

Import TeleBot and the CapchaManager:

from telebot import TeleBot
from pyTelegramBotCAPTCHA import CaptchaManager

Initialize the bot and the captcha_manager:

CaptchaManager requires the user_id of your TeleBot instance! You get it with bot.get_me().id
You can add the following optional parameters:

  • default_language (str) the default language to use if not set in captcha_manager.send_random_captcha(...). Default is "en". Currently supported "en", "ru" and "de"
  • default_timeout (float) the default timeout to use if not set in captcha_manager.send_random_captcha(...). Default is None but we will use a default_timeout of 90 seconds for our CAPTCHAs.
  • fonts (list) the fonts to use instead of the builtin ones (must be a list of .ttf file paths). You can choose as many fonts as you like, but keep in mind that all the fonts are loaded into your memory, so use a lot but not to many.
bot = TeleBot("TOKEN")
captcha_manager = CaptchaManager(bot.get_me().id, default_timeout=90)

Note: Make sure to actually replace TOKEN with your own API token


Add a message handler for new chat members:

We need a message handler to restrict the new member and sending a CAPTCHA to solve when a new user joins the group.
captcha_manager.restrict_chat_member() requires your TeleBot instance, the chat_id and the user_id. It disables all permissions of a chat member.
captcha_manager.send_random_captcha() requires your TeleBot instance, the Chat object and the User object. It sends a new CAPTCHA in the chat.
You can add the following optional parameters:

  • language (str) the language to use for this CAPTCHA
  • add_noise (bool) add noise to the CAPTCHA image
  • only_digits (bool) only use ditgits instead of hexdigits for the CAPTCHA code
  • timeout (float) to set a timeout for the CAPTCHA in seconds.
# Message handler for new chat members
@bot.message_handler(content_types=["new_chat_members"])
def new_member(message):
  # get the new chat members
  for user in message.new_chat_members:

    # Restrict the new chat member
    captcha_manager.restrict_chat_member(bot, message.chat.id, user.id)

    # send random CAPTCHA
    captcha_manager.send_random_captcha(bot, message.chat, user)

Note: Service messages about non-bot users joining the chat will be soon removed from large groups. We recommend using the “chat_member” update as a replacement.


Add a callback query handler:

We need a callback query handler, to handle the users input when he presses a CAPTCHA button.
captcha_manager.update_captcha() requires your TeleBot instance and the CallbackQuery object as parameters.
It automatically returns if callback was not from a CAPTCHA or from the wrong user.
If the wrong user pressed a button he gets an callback query answer denying his input.
If the submit button is pressed the CAPTCHA is automatically checked and your corresponding CAPTCHA handler function is called. The timeout is also canceled if submit is pressed.

# Callback query handler
@bot.callback_query_handler(func=lambda callback:True)
def on_callback(callback):
  # update the CAPTCHA
  captcha_manager.update_captcha(bot, callback)

Add CAPTCHA handler functions:

This works just like you know it from message handlers from the pyTelegramBotAPI.
A Captcha object will be passed to your functions.
The Captcha object has the following attributes:

  • message_id (int) the message id of the CAPTCHA message
  • user (User) the user that must solve the CAPTCHA
  • chat (Chat) the chat
  • users_code (str) the code entered by the user
  • correct_code (str) the correct code to solve the CAPTCHA
  • language (str) the language of the CAPTCHA text
  • created_at (float) the timestemp when the CAPTCHA was created
  • previous_tries (int) the number of tries the user made
  • incorrect_digits (int) the number of digits that dont match
  • solved (bool) has the user solved the CAPTCHA? it does not matter if he solved it correct

Lets add our first CAPTCHA handler that handles correct solved CAPTCHAs. captcha_manager.unrestrict_chat_member() requires your TeleBot instance, the chat_id and the user_id. It removes all restictions of a chat member.
captcha_manager.delete_captcha() requires your TeleBot instance and the Captcha object. It removes the CAPTCHA from the chat and your memory

# Handler for correct solved CAPTCHAs
@captcha_manager.on_captcha_correct
def on_correct(captcha):
  bot.send_message(captcha.chat.id, "Congrats! You solved the CAPTCHA!")
  # We unrestrict the chat member because he solved the CAPTCHA correct.
  captcha_manager.unrestrict_chat_member(bot, captcha.chat.id, captcha.user.id)
  # Delete the CAPTCHA
  captcha_manager.delete_captcha(bot, captcha)

Lets add a handler that handles wrong solved CAPTCHAs.
We use the Captcha attributes incorrect_digits and previous_tries to give the user a second try if only one digit was incorrect.
captcha_manager.refresh_captcha() requires your TeleBot instance and the Captcha object. It generates a new code image.
You can add the following optional parameters:

  • add_noise (bool) add noise to the CAPTCHA image
  • only_digits (bool) only use ditgits instead of hexdigits for the CAPTCHA code
  • timeout (float) set new timeout because the previous is canceled. If not set it will captcha_manager.default_timeout (if set).
# Handler for wrong solved CAPTCHAs
@captcha_manager.on_captcha_not_correct
def on_not_correct(captcha):
  # Check if only one dicit was incorrect and the user only did one try
  if (captcha.incorrect_digits == 1 and captcha.previous_tries < 2):
    # Refresh the CAPTCHA
    captcha_manager.refresh_captcha(bot, captcha)
  else:
    # We ban the chat member because he failed solving the CAPTCHA.
    bot.kick_chat_member(captcha.chat.id, captcha.user.id)
    bot.send_message(captcha.chat.id, f"{captcha.user.first_name} failed solving the CAPTCHA and was banned!")
    # Delete the CAPTCHA
    captcha_manager.delete_captcha(bot, captcha)

Now lets add a handler that handles timed out CAPTCHAs

# Handler for timed out CAPTCHAS
@captcha_manager.on_captcha_timeout
def on_timeout(captcha):
  # We ban the chat member because he did not solve the CAPTCHA.
  bot.kick_chat_member(captcha.chat.id, captcha.user.id)
  bot.send_message(captcha.chat.id, f"{captcha.user.first_name} did not solve the CAPTCHA and was banned!")
  # Delete the CAPTCHA
  captcha_manager.delete_captcha(bot, captcha)

The finished CAPTCHA bot

Now we only have to add the line bot.polling()at the end of our script and we have a finished CAPTCHA bot that looks like this:

from telebot import TeleBot
from pyTelegramBotCAPTCHA import CaptchaManager
                                                                    
bot = TeleBot("TOKEN")
captcha_manager = CaptchaManager(bot.get_me().id)

# Message handler for new chat members
@bot.message_handler(content_types=["new_chat_members"])
def new_member(message):
  new_user_id = message.json.get("new_chat_member").get("id")
  new_user = bot.get_chat_member(message.chat.id, new_user_id).user
  captcha_manager.restrict_chat_member(bot, message.chat.id, new_user.id)
  captcha_manager.send_random_captcha(bot, message.chat, new_user)
                                                                    
# Callback query handler
@bot.callback_query_handler(func=lambda callback:True)
def on_callback(callback):
  captcha_manager.update_captcha(bot, callback)
                                                                    
# Handler for correct solved CAPTCHAs
@captcha_manager.on_captcha_correct
def on_correct(captcha):
  bot.send_message(captcha.chat.id, "Congrats! You solved the CAPTCHA!")
  captcha_manager.unrestrict_chat_member(bot, captcha.chat.id, captcha.user.id)
  captcha_manager.delete_captcha(bot, captcha)

# Handler for wrong solved CAPTCHAs
@captcha_manager.on_captcha_not_correct
def on_not_correct(captcha):
  if (captcha.incorrect_digits == 1 and captcha.previous_tries < 2):
    captcha_manager.refresh_captcha(bot, captcha)
  else:
    bot.kick_chat_member(captcha.chat.id, captcha.user.id)
    bot.send_message(captcha.chat.id, f"{captcha.user.first_name} failed solving the CAPTCHA and was banned!")
    captcha_manager.delete_captcha(bot, captcha)
  
# Handler for timed out CAPTCHAS
@captcha_manager.on_captcha_timeout
def on_timeout(captcha):
  bot.kick_chat_member(captcha.chat.id, captcha.user.id)
  bot.send_message(captcha.chat.id, f"{captcha.user.first_name} did not solve the CAPTCHA and was banned!")
  captcha_manager.delete_captcha(bot, captcha)
  
bot.polling()
Comments
  • Issues with CustomLanguage parameters 'your_code' and 'try_again'

    Issues with CustomLanguage parameters 'your_code' and 'try_again'

    Let's take the following setup:

    languages = CustomLanguage() languages.text = "text" languages.try_again = "again" languages.wrong_user = "wrong" languages.too_short = "short" languages.your_code = "code"

    'try_again' is actually not shown when it should. You keep seeing 'text' on both a wrong attempt and a manual user refresh.

    'your_code' is also not shown when it should. You always see the default "Your Code:", and 'your_code' does show up but only on a wrong attempt or a manual user refresh (it is not visible on the initial captcha). However, "Your Code:" is still visible up to this point, so you actually see two lines, one time the default one, and one time the new custom one.

    bug 
    opened by tinderboxmedia 5
  • Inconsistency: A captcha reload on an incorrect submit has default values

    Inconsistency: A captcha reload on an incorrect submit has default values

    If an individual fails to solve the captcha and if another attempt is allowed, the captcha will refresh but it will override variables such as timeout, digits_only and add_noice. This feels like an inconsistency in the logic as a refresh should give a new captcha but with all the user declared variables and values. If the function is declared to not add_noice or to be digits_only, a refresh should not change this behaviour, unless declared otherwise.

    To fix this inconsistency the captcha refresh should either follow the user declared variables and values, or one should be able to allow this override to happen or not.

    enhancement 
    opened by tinderboxmedia 5
  • No timeout anymore when user has made a wrong attempt

    No timeout anymore when user has made a wrong attempt

    There seems to be an error where there is no timeout event anymore when a user made a wrong attempt, it also seems to not work anymore when a user manually refreshed the CAPTCHA. It still happens though when a user is still on the initial CAPTCHA. I tried this with the default timeout of 90, and a custom timeout. Note that max_incorrect_to_auto_reload has been set to 1, so a timeout should still happen.

    bug 
    opened by tinderboxmedia 4
  • Suggestion: Be able to declare the digits and hex-digits used in the captcha outside of the module

    Suggestion: Be able to declare the digits and hex-digits used in the captcha outside of the module

    Currently the only way to change the digits and hex-digits used in the captcha is to change variables inside of the module. The suggestion would be to be able to declare which digits or letters can be used, but still in a set of 10 (the 2 by 5 input markup grid), or a set of 16 (the 4x4 input markup grid).

    The main reason for this suggestion is that some fonts do have characters that could potentially look to similar. For example: 8 and B, or 1 and 7. Be able to declare a custom set of 10 or 16 characters, the captchas could become more user friendly but still bot proof.

    opened by tinderboxmedia 4
  • Suggestion: Be able to declare the length of the captcha

    Suggestion: Be able to declare the length of the captcha

    Currently the length of the captcha showed is defaulted and hardcoded to be 8 characters long. The suggestion would be to be able to declare the length of the captcha, so that it can display less or even more characters that need to be solved.

    enhancement 
    opened by tinderboxmedia 4
  • KeyZenD returns a 404. Fallback to 'Default' might be needed.

    KeyZenD returns a 404. Fallback to 'Default' might be needed.

    Seems like the KeyZenD CAPTCHA can't be found anymore: https://tyt.xyeta.ml/captcha.png

    This page returns an 404, and the CAPTCHA can't be found. Maybe it would be smart to add some sort of fallback that turns the option back to 'default' as currently this would break the entire thing?

    opened by tinderboxmedia 3
  • Issue: Adding 1+ users to the channel will only trigger 1 captcha

    Issue: Adding 1+ users to the channel will only trigger 1 captcha

    After some more stress testing it seems to be the case that if someone invites or adds more than 1 user (the option to mass invite your contacts to a channel for example) to the channel where the bot is active, it will only create 1 captcha. Only one user has to complete the captcha, the other users are already 'in' (so to speak).

    opened by tinderboxmedia 3
  • ERROR: TypeError: 'float' object cannot be interpreted as an integer

    ERROR: TypeError: 'float' object cannot be interpreted as an integer

    I try init a new bot with

    from telebot import TeleBot
    from pyTelegramBotCAPTCHA import CaptchaManager
                                                                        
    bot = TeleBot("MY_TOKEN")
    captcha_manager = CaptchaManager(bot.get_me().id)
    
    # Message handler for new chat members
    @bot.message_handler(content_types=["new_chat_members"])
    def new_member(message):
      for new_user in message.new_chat_members:
        captcha_manager.restrict_chat_member(bot, message.chat.id, new_user.id)
        captcha_manager.send_new_captcha(bot, message.chat, new_user)
                                                                        
    # Callback query handler
    @bot.callback_query_handler(func=lambda callback:True)
    def on_callback(callback):
      captcha_manager.update_captcha(bot, callback)
                                                                        
    # Handler for correct solved CAPTCHAs
    @captcha_manager.on_captcha_correct
    def on_correct(captcha):
      bot.send_message(captcha.chat.id, "Congrats! You solved the CAPTCHA!")
      captcha_manager.unrestrict_chat_member(bot, captcha.chat.id, captcha.user.id)
      captcha_manager.delete_captcha(bot, captcha)
    
    # Handler for wrong solved CAPTCHAs
    @captcha_manager.on_captcha_not_correct
    def on_not_correct(captcha):
      if (captcha.incorrect_digits == 1 and captcha.previous_tries < 2):
        captcha_manager.refresh_captcha(bot, captcha)
      else:
        bot.kick_chat_member(captcha.chat.id, captcha.user.id)
        bot.send_message(captcha.chat.id, f"{captcha.user.first_name} failed solving the CAPTCHA and was banned!")
        captcha_manager.delete_captcha(bot, captcha)
    
    # Handler for timed out CAPTCHAS
    @captcha_manager.on_captcha_timeout
    def on_timeout(captcha):
      bot.kick_chat_member(captcha.chat.id, captcha.user.id)
      bot.send_message(captcha.chat.id, f"{captcha.user.first_name} did not solve the CAPTCHA and was banned!")
      captcha_manager.delete_captcha(bot, captcha)
      
    bot.polling()
    

    And i take a error:

    Traceback (most recent call last):
      File "/Users/olivmath/repo/lunes/bot-telegram-cruzeiro/olivmath.py", line 43, in <module>
        bot.polling()
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/telebot/__init__.py", line 660, in polling
        self.__threaded_polling(non_stop, interval, timeout, long_polling_timeout, allowed_updates)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/telebot/__init__.py", line 722, in __threaded_polling
        raise e
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/telebot/__init__.py", line 682, in __threaded_polling
        self.worker_pool.raise_exceptions()
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/telebot/util.py", line 135, in raise_exceptions
        raise self.exception_info
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/telebot/util.py", line 87, in run
        task(*args, **kwargs)
      File "/Users/olivmath/repo/lunes/bot-telegram-cruzeiro/olivmath.py", line 12, in new_member
        captcha_manager.send_new_captcha(bot, message.chat, new_user)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/pyTelegramBotCAPTCHA/telebot_captcha.py", line 553, in send_new_captcha
        captcha = Captcha(bot, chat, user, options)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/pyTelegramBotCAPTCHA/telebot_captcha.py", line 345, in __init__
        self.correct_code, self.image = _random_codeimage(self.options)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/pyTelegramBotCAPTCHA/telebot_captcha.py", line 865, in _random_codeimage
        image = image.generate_image(code)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/captcha/image.py", line 228, in generate_image
        im = self.create_captcha_image(chars, color, background)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/captcha/image.py", line 212, in create_captcha_image
        mask = im.convert('L').point(table)
      File "/Users/olivmath/Library/Caches/pypoetry/virtualenvs/bot-telegram-cruzeiro-rcJnbm2r-py3.10/lib/python3.10/site-packages/PIL/Image.py", line 1680, in point
        return self._new(self.im.point(lut, mode))
    TypeError: 'float' object cannot be interpreted as an integer
    
    opened by olivmath 2
  • Refresh button

    Refresh button

    Hi there,

    Great work - loving your captcha bot! I had one idea that would be great to implement. A Refresh button in case the captcha is really hard / barley readable.

    Keep it up!

    enhancement good first issue 
    opened by fabston 2
  • Issue: Adding the code_length argument to send_random_captcha will throw a TypeError.

    Issue: Adding the code_length argument to send_random_captcha will throw a TypeError.

    For example, trying initialize the captcha using captcha_manager.send_random_captcha(bot, message.chat, new_user, timeout=60, code_length=4, language="en") will result in TypeError: send_random_captcha() got an unexpected keyword argument 'code_length'

    However, following the documentation this should be possible.

    opened by tinderboxmedia 2
  • Issue: If a captcha is not properly removed after kicking a user, it will throw a KeyError when trying to interact with it again

    Issue: If a captcha is not properly removed after kicking a user, it will throw a KeyError when trying to interact with it again

    While interacting with a captcha button (update_captcha), it should first be checked if that captcha session is still 'available' or not. It not being 'available' can be due to that the captcha message was not deleted properly after kicking a user and that user did not solve it, or that the file that holds that captcha session is somehow removed.

    Right now it will throw a KeyError if the session can't be found, but if we can check if that captcha session is not available anymore, we could just remove the captcha instead (whoever presses it) and clean up.

    opened by tinderboxmedia 2
Releases(1.1.4)
Rest API Written In Python To Classify NSFW Images.

✨ NSFW Classifier API ✨ Rest API Written In Python To Classify NSFW Images. Fastest Solution If you don't want to selfhost it, there's already an inst

Akshay Rajput 23 Dec 30, 2022
a Deep Learning Framework for Text

DeLFT DeLFT (Deep Learning Framework for Text) is a Keras and TensorFlow framework for text processing, focusing on sequence labelling (e.g. named ent

Patrice Lopez 350 Dec 19, 2022
A pure pytorch implemented ocr project including text detection and recognition

ocr.pytorch A pure pytorch implemented ocr project. Text detection is based CTPN and text recognition is based CRNN. More detection and recognition me

coura 444 Dec 30, 2022
This tool will help you convert your text to handwriting xD

So your teacher asked you to upload written assignments? Hate writing assigments? This tool will help you convert your text to handwriting xD

Saurabh Daware 4.2k Jan 07, 2023
When Age-Invariant Face Recognition Meets Face Age Synthesis: A Multi-Task Learning Framework (CVPR 2021 oral)

MTLFace This repository contains the PyTorch implementation and the dataset of the paper: When Age-Invariant Face Recognition Meets Face Age Synthesis

Hzzone 120 Jan 05, 2023
chineseocr/table_line 表格线检测模型pytorch版

table_line_pytorch chineseocr/table_detct 表格线检测模型table_line pytorch版 原项目github: https://github.com/chineseocr/table-detect 1、模型转换 下载原项目table_detect模型文

1 Oct 21, 2021
With the virtual keyboard, you can write on the real time images by combining the thumb and index fingers on the letter you want.

Virtual Keyboard With the virtual keyboard, you can write on the real time images by combining the thumb and index fingers on the letter you want. At

Güldeniz Bektaş 5 Jan 23, 2022
Deskewing images with slanted content

skew_correction De-skewing images with slanted content by finding the deviation using Canny Edge Detection. To Run: In python 3.6, from deskew import

13 Aug 27, 2022
A webcam-based 3x3x3 rubik's cube solver written in Python 3 and OpenCV.

Qbr Qbr, pronounced as Cuber, is a webcam-based 3x3x3 rubik's cube solver written in Python 3 and OpenCV. 🌈 Accurate color detection 🔍 Accurate 3x3x

Kim 金可明 502 Dec 29, 2022
A version of nrsc5-gui that merges the interface developed by cmnybo with the architecture developed by zefie in order to start a new baseline that is not heavily dependent upon Python processing.

NRSC5-DUI is a graphical interface for nrsc5. It makes it easy to play your favorite FM HD radio stations using an RTL-SDR dongle. It will also displa

61 Dec 22, 2022
Contextual speed detection for python

Speed Prediction using Optical Flow and 2D CNN About the challenge: Comma.AI Speed Challenge This challenge was developed by Comma.AI to predict the s

Mahimana Bhatt 2 Dec 16, 2021
🔎 Like Chardet. 🚀 Package for encoding & language detection. Charset detection.

Charset Detection, for Everyone 👋 The Real First Universal Charset Detector A library that helps you read text from an unknown charset encoding. Moti

TAHRI Ahmed R. 332 Dec 31, 2022
Automatically fishes for you while you are afk :)

Dank-memer-afk-script A simple and quick way to make easy money in Dank Memer! How to use Open a discord channel which has the Dank Memer bot enabled.

Pranav Doshi 9 Nov 11, 2022
STEFANN: Scene Text Editor using Font Adaptive Neural Network

STEFANN: Scene Text Editor using Font Adaptive Neural Network @ The IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR) 2020.

Prasun Roy 208 Dec 11, 2022
Handwriting Recognition System based on a deep Convolutional Recurrent Neural Network architecture

Handwriting Recognition System This repository is the Tensorflow implementation of the Handwriting Recognition System described in Handwriting Recogni

Edgard Chammas 346 Jan 07, 2023
A curated list of awesome synthetic data for text location and recognition

awesome-SynthText A curated list of awesome synthetic data for text location and recognition and OCR datasets. Text location SynthText SynthText_Chine

Tianzhong 283 Jan 05, 2023
Usando o Amazon Textract como OCR para Extração de Dados no DynamoDB

dio-live-textract2 Repositório de código para o live coding do dia 05/10/2021 sobre extração de dados estruturados e gravação em banco de dados a part

hugoportela 0 Jan 19, 2022
Text Detection from images using OpenCV

EAST Detector for Text Detection OpenCV’s EAST(Efficient and Accurate Scene Text Detection ) text detector is a deep learning model, based on a novel

Abhishek Singh 88 Oct 20, 2022
📷 Face Recognition using Haar-Cascade Classifier, OpenCV, and Python

Face-Recognition-System Face Recognition using Haar-Cascade Classifier, OpenCV and Python. This project is based on face detection and face recognitio

1 Jan 10, 2022