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?
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.
To stop receiving messages from the Telegram Bot, you can either type “Stop Bot” or “Delete Chat”.
No, you can't.
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.
Filter messages by field update.message.from.id
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With