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)
This is a passport scanning web service to help you scan, identify and validate your passport created with a simple and flexible design and ready to be integrated right into your system!

Passport-Recogniton-System This is a passport scanning web service to help you scan, identify and validate your passport created with a simple and fle

Mo'men Ashraf Muhamed 7 Jan 04, 2023
Deep Learning Chinese Word Segment

引用 本项目模型BiLSTM+CRF参考论文:http://www.aclweb.org/anthology/N16-1030 ,IDCNN+CRF参考论文:https://arxiv.org/abs/1702.02098 构建 安装好bazel代码构建工具,安装好tensorflow(目前本项目需

2.1k Dec 23, 2022
Hiiii this is the Spanish for Linux and win 10 and in the near future the english version of PortScan my new tool on which you can see what ports are Open only with the IP adress.

PortScanner-by-IIT PortScanner es una herramienta programada en Python3. Como su nombre indica esta herramienta escanea los primeros 150 puertos de re

5 Sep 19, 2022
Erosion and dialation using structure element in OpenCV python

Erosion and dialation using structure element in OpenCV python

Tamzid hasan 2 Nov 11, 2021
零样本学习测评基准,中文版

ZeroCLUE 零样本学习测评基准,中文版 零样本学习是AI识别方法之一。 简单来说就是识别从未见过的数据类别,即训练的分类器不仅仅能够识别出训练集中已有的数据类别, 还可以对于来自未见过的类别的数据进行区分。 这是一个很有用的功能,使得计算机能够具有知识迁移的能力,并无需任何训练数据, 很符合现

CLUE benchmark 27 Dec 10, 2022
This is a GUI for scrapping PDFs with the help of optical character recognition making easier than ever to scrape PDFs.

pdf-scraper-with-ocr With this tool I am aiming to facilitate the work of those who need to scrape PDFs either by hand or using tools that doesn't imp

Jacobo José Guijarro Villalba 75 Oct 21, 2022
Web interface for browsing arXiv papers

Currently, arxivbox considers only major computer vision and machine learning conferences

Ankan Kumar Bhunia 12 Sep 11, 2022
An expandable and scalable OCR pipeline

Overview Nidaba is the central controller for the entire OGL OCR pipeline. It oversees and automates the process of converting raw images into citable

81 Jan 04, 2023
Deep learning based page layout analysis

Deep Learning Based Page Layout Analyze This is a Python implementaion of page layout analyze tool. The goal of page layout analyze is to segment page

186 Dec 29, 2022
Official code for :rocket: Unsupervised Change Detection of Extreme Events Using ML On-Board :rocket:

RaVAEn The RaVÆn system We introduce the RaVÆn system, a lightweight, unsupervised approach for change detection in satellite data based on Variationa

SpaceML 35 Jan 05, 2023
Satoshi is a discord bot template in python using discord.py that allow you to track some live crypto prices with your own discord bot.

Satoshi ~ DiscordCryptoBot Satoshi is a simple python discord bot using discord.py that allow you to track your favorites cryptos prices with your own

Théo 2 Sep 15, 2022
Face_mosaic - Mosaic blur processing is applied to multiple faces appearing in the video

動機 face_recognitionを使用して得られる顔座標は長方形であり、この座標をそのまま用いてぼかし処理を行った場合得られる画像は醜い。 それに対してモ

Yoshitsugu Kesamaru 6 Feb 03, 2022
The official code for the ICCV-2021 paper "Speech Drives Templates: Co-Speech Gesture Synthesis with Learned Templates".

SpeechDrivesTemplates The official repo for the ICCV-2021 paper "Speech Drives Templates: Co-Speech Gesture Synthesis with Learned Templates". [arxiv

Qian Shenhan 53 Dec 23, 2022
An interactive document scanner built in Python using OpenCV

The scanner takes a poorly scanned image, finds the corners of the document, applies the perspective transformation to get a top-down view of the document, sharpens the image, and applies an adaptive

Kushal Shingote 1 Feb 12, 2022
This is a GUI program which consist of 4 OpenCV projects

Tkinter-OpenCV Project Using Tkinter, Opencv, Mediapipe This is a python GUI program using Tkinter which consist of 4 OpenCV projects 1. Finger Counte

Arya Bagde 3 Feb 22, 2022
Run tesseract with the tesserocr bindings with @OCR-D's interfaces

ocrd_tesserocr Crop, deskew, segment into regions / tables / lines / words, or recognize with tesserocr Introduction This package offers OCR-D complia

OCR-D 38 Oct 14, 2022
Localization of thoracic abnormalities model based on VinBigData (top 1%)

Repository contains the code for 2nd place solution of VinBigData Chest X-ray Abnormalities Detection competition. The goal of competition was to auto

33 May 24, 2022
A bot that plays TFT using OCR. Keeps track of bench, board, items, and plays the user defined team comp.

NOTES: To ensure best results, make sure you are running this on a computer that has decent specs. 1920x1080 fullscreen is required in League, game mu

francis 125 Dec 30, 2022
computer vision, image processing and machine learning on the web browser or node.

Image processing and Machine learning labs   computer vision, image processing and machine learning on the web browser or node note Fast Fourier Trans

ryohei tanaka 487 Nov 11, 2022
Repository of conference publications and source code for first-/ second-authored papers published at NeurIPS, ICML, and ICLR.

Repository of conference publications and source code for first-/ second-authored papers published at NeurIPS, ICML, and ICLR.

Daniel Jarrett 26 Jun 17, 2021