How to add the user ban function by id in Telegram bot?

Ie so that I could enter /ban userid and this user could no longer write to the bot.

    1 answer 1

    The user in any case will be able to write to the bot, but it’s up to us to decide whether to answer it or not.

    There are 2 ways to do this, the first with the help of a decorator, who will check whether our user is banned:

     from telebot import TeleBot from functools import wraps bot = TeleBot('<token>') banned_users = [] def is_not_banned(func): @wraps(func) def decorator(message): if message.from_user.id not in banned_users: return func(message) return decorator @bot.message_handler(commands=['ban']) def ban_user(message): message_args = message.text.split() if len(message_args) == 2: banned_users.append(int(message_args[1])) bot.reply_to(message, text='OK') else: bot.reply_to(message, text='Wrong format') @bot.message_handler() @is_not_banned def foo(message): bot.reply_to(message, text='Hey!') 

    How it works:

    • The bot receives an update and calls our handler.
    • Instead of the original handler, we already have a decorator function that has locked the original handler.
    • When the bot calls it, it checks if our user is banned, if not - calls the original handler, otherwise it does nothing.

    This method has its drawback, we process the updates of banned users.

    This can be avoided by overriding the get_updates method:

     from telebot import TeleBot from telebot import apihelper from telebot import types class MyTeleBot(TeleBot): def get_updates(self, *args, **kwargs): json_updates = apihelper.get_updates(self.token, *args, **kwargs) ret = [] for ju in json_updates: if ju['message']['from']['id'] in banned_users: self.last_update_id = ju['update_id'] else: ret.append(types.Update.de_json(ju)) return ret 

    Now create an instance of our class:

     bot = MyTeleBot('<token>') 

    Then we can write our handlers without any decorators, the ban_user function remains unchanged.

    Well, do not forget to start polling:

     if __name__ == '__main__': bot.infinity_polling() 

    How it works:

    • We have the following call chain for polling
      • infinity_polling > polling > __threaded_polling > __retrieve_updates > get_updates > process_new_updates
    • Before calling process_new_updates we "cut off" all unnecessary updates, thus our handler does not even work.

    How do we "cut off" updates?

    You probably noticed this test in our class:

     if ju['message']['from']['id'] in banned_users: self.last_update_id = ju['update_id'] 

    The fact is that if you do not do self.last_update_id = ju['update_id'] , our top bot will get stuck on the latest update, which we want to skip.

    Actually this is what process_new_updates does:

     if update.update_id > self.last_update_id: self.last_update_id = update.update_id 

    Instead of the banned_users array, banned_users advisable to take a database.