【问题标题】:How To Limit Access To A Telegram Bot如何限制对电报机器人的访问
【发布时间】:2016-05-23 22:54:09
【问题描述】:

当我向我的 Telegram Bot 发送消息时,它会毫无问题地响应。

我想限制访问权限,只有我自己可以向它发送消息。

我该怎么做?

【问题讨论】:

    标签: telegram-bot python-telegram-bot


    【解决方案1】:

    按字段过滤消息update.message.from.id

    【讨论】:

      【解决方案2】:

      与您的机器人开始对话,并向其发送消息。这将为包含您对话的消息和聊天 ID 的机器人排队更新。

      要查看最近的更新,请调用 getUpdates 方法。这是通过向 URL https://api.telegram.org/bot$TOKEN/getUpdates 发出 HTTP GET 请求来完成的,其中 $TOKEN 是 BotFather 提供的令牌。比如:

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

      一旦您确定了您的聊天 ID,您就可以在您的机器人中编写一段代码,例如:

      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)
      

      【讨论】:

        【解决方案3】:

        由于此问题与python-telegram-bot有关,因此以下信息与之相关:

        当您向机器人的调度程序添加处理程序时,您可以指定各种预构建的过滤器(在docsgithub 阅读更多信息),或者您可以创建自定义过滤器以过滤传入的更新。

        为了限制特定用户的访问,您需要在初始化处理程序时添加Filters.user(username="@telegramusername"),例如:

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

        此处理程序将仅接受来自用户名为 @username 的用户的 /start 命令。

        您也可以指定用户 ID 而不是用户名,我强烈建议您这样做,因为后者是非常量的,并且可以随着时间的推移而更改。

        【讨论】:

          【解决方案4】:

          update.message.chat_id 过滤对我有用。 要找到您的聊天 ID,请向您的机器人发送消息并浏览到

          https://api.telegram.org/bot$TOKEN/getUpdates
          

          其中$TOKEN 是 BotFather 提供的机器人令牌,如 fdicarlo 的回答中所述,您可以在其中找到 json 结构中的聊天 ID。

          【讨论】:

            【解决方案5】:

            基于python-telegram-bot 代码sn-ps,可以围绕处理程序构建一个简单的包装器:

            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
            

            conf['restricted_ids'] 可能是一个 id 列表,例如[11111111, 22222222].

            所以用法如下所示:

            @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))
            

            更新 |对于函数和方法(DRYpython-telegram-bot version 12 and above

            上面的解决方案不能用于类内部的方法(位置参数改变)。有一段时间,我刚刚为方法创建了一个额外的装饰器。然而,人们总是需要记住何时使用哪种装饰器。

            this solution 之上构建,可以构建以下装饰器类:

            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
            

            然后,正如预期的那样,这适用于函数和方法。它并不完全是 DRY(参见 cmets),但至少是独立的。

            【讨论】:

              猜你喜欢
              • 2020-10-12
              • 2017-10-24
              • 2018-08-08
              • 2017-11-28
              • 2022-12-11
              • 2017-08-18
              • 1970-01-01
              • 2020-10-07
              • 2019-04-08
              相关资源
              最近更新 更多