Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Limit Access To A Telegram Bot

When I send a message to my Telegram Bot, it responses with no problems.

I wanna limit the access such that me and only me can send message to it.

How can I do that?

like image 770
E.B Avatar asked Feb 12 '16 17:02

E.B


People also ask

Can we make a telegram BOT private?

With Telegram bots are not private. Everybody can find them. The difference is that a certain communication channel with the bot can be made private. This is a group with the bot that you and the bot are members of.

How do I block bots without blocking Telegram?

To stop receiving messages from the Telegram Bot, you can either type “Stop Bot” or “Delete Chat”.

Can a telegram BOT block a specific user?

No, you can't.


4 Answers

As this question is related to python-telegram-bot, information below is related to it:

When you add handlers to your bot's dispatcher, you can specify various pre-built filters (read more at docs, github) or you can create custom ones in order to filter incoming updates.

To limit access to a specific user, you need to add Filters.user(username="@telegramusername") when initializing handler, e.g.:

dispatcher.add_handler(CommandHandler("start", text_callback, Filters.user(username="@username")))

This handler will accept /start command only from user with username @username.

You can also specify user-id instead of username, which I would highly recommend, as latter is non-constant and can be changed over time.

like image 142
gyunter Avatar answered Oct 23 '22 19:10

gyunter


Filter messages by field update.message.from.id

like image 37
ihoru Avatar answered Oct 23 '22 20:10

ihoru


Based on the python-telegram-bot code snippets, one can build a simple wrapper around the handler:

def restricted(func):
    """Restrict usage of func to allowed users only and replies if necessary"""
    @wraps(func)
    def wrapped(bot, update, *args, **kwargs):
        user_id = update.effective_user.id
        if user_id not in conf['restricted_ids']:
            print("WARNING: Unauthorized access denied for {}.".format(user_id))
            update.message.reply_text('User disallowed.')
            return  # quit function
        return func(bot, update, *args, **kwargs)
    return wrapped

where conf['restricted_ids'] might be an id list, e.g. [11111111, 22222222].

So the usage would look like this:

@restricted
def bot_start(bot, update):
    """Send a message when the command /start is issued"""
    update.message.reply_text('Hi! This is {} speaking.'.format(bot.username))

Update | for functions and methods (DRY, python-telegram-bot version 12 and above)

The solution above cannot be used on methods inside classes (positional arguments change). For a while, I had just created an additional decorator for methods. However one would always need to keep in mind which decorator to use when.

Building on top of this solution, the following decorator class can be built:

class restricted(object):
    """
    Decorator class used to restrict usage of commands.
    Sends a "disallowed" reply if necessary. Works on functions and methods.
    """
    def __init__(self, func):
        self._func = func
        self._obj = None
        self._wrapped = None

    def __call__(self, *args, **kwargs):
        if not self._wrapped:
            if self._obj:
                self._wrapped = self._wrap_method(self._func)
                self._wrapped = partial(self._wrapped, self._obj)
            else:
                self._wrapped = self._wrap_function(self._func)
        return self._wrapped(*args, **kwargs)

    def __get__(self, obj, type_=None):
        self._obj = obj
        return self

    def _wrap_method(self, method): # Wrapper called in case of a method
        @wraps(method)
        def inner(self, *args, **kwargs): # `self` is the *inner* class' `self` here
            user_id = args[0].effective_user.id # args[0]: update
            if user_id not in cfg.RESTRICTED_IDS:
                print(f'Unauthorized access denied on {method.__name__} ' \
                    f'for {user_id} : {args[0].message.chat.username}.')
                args[0].message.reply_text('User disallowed.')
                return None # quit handling command
            return method(self, *args, **kwargs)
        return inner

    def _wrap_function(self, function): # Wrapper called in case of a function
        @wraps(function)
        def inner(*args, **kwargs): # `self` would be the *restricted* class' `self` here
            user_id = args[0].effective_user.id # args[0]: update
            if user_id not in cfg.RESTRICTED_IDS:
                print(f'Unauthorized access denied on {function.__name__} ' \
                    f'for {user_id} : {args[0].message.chat.username}.')
                args[0].message.reply_text('User disallowed.')
                return None # quit handling command
            return function(*args, **kwargs)
        return inner

This works then, as expected, on functions and methods. It's not entirely DRY (cf. comments), but at least self-contained.

like image 9
Pronex Avatar answered Oct 23 '22 19:10

Pronex


Start a conversation with your bot, and send it a message. This will queue up an updates for the bot containing the message and the chat ID for your conversation.

To view recent updates, you call the getUpdates method. This is done by making a HTTP GET request to the URL https://api.telegram.org/bot$TOKEN/getUpdates Where $TOKEN is the token provided by the BotFather. Something like:

"chat":{
        "id":12345,
        "first_name":"Bob",
        "last_name":"Jones",
        "username":"bjones",
        "type":"private"},
      "date":1452933785,
      "text":"Hi there, bot!"}}]}

Once you determined your chat id you can write a piece of code in your bot like:

id_a = [111111,2222222,3333333,4444444,5555555]

    def handle(msg):
        chat_id = msg['chat']['id']
        command = msg['text']
        sender = msg['from']['id']
     if sender in id_a:
    [...]
     else:
           bot.sendMessage(chat_id, 'Forbidden access!')
           bot.sendMessage(chat_id, sender)
like image 4
fdicarlo Avatar answered Oct 23 '22 18:10

fdicarlo