code: def by_regex(extractor, regex, key=1):
      
      if _isstring(regex):
          regex = re.compile(regex)
  
      def f(msg):
          text = extractor(msg)
          match = regex.search(text)
          if match:
              index = key if isinstance(key, tuple) else (key,)
              return match.group(*index), (match,)
          else:
              return (None,),  # to distinguish with `None`
      return f
docs: :param extractor:
          a function that takes one argument (the message) and returns a portion
          of message to be interpreted. To extract the text of a chat message,
          use ``lambda msg: msg['text']``.
  
      :type regex: str or regex object
      :param regex: the pattern to look for
  
      :param key: the part of match object to be used as key
  
      :return:
          a key function that returns ``match.group(key)`` as key (where ``match``
          is the match object) and the match object as a positional argument.
          If no match is found, it returns a 1-tuple ``(None,)`` as the key.
          This is to distinguish with the special ``None`` key in routing table.