mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Extended the message_handler decorator.
TeleBot now makes use of the API's getUpdates timeout optional parameter instead of time.sleep. This yields quicker response times.
This commit is contained in:
parent
144fa64604
commit
111ebf5c16
@ -41,7 +41,7 @@ class TeleBot:
|
||||
|
||||
self.last_update_id = 0
|
||||
|
||||
self.commands = []
|
||||
self.message_handlers = []
|
||||
|
||||
def get_update(self):
|
||||
"""
|
||||
@ -49,7 +49,7 @@ class TeleBot:
|
||||
Registered listeners and applicable message handlers will be notified when a new message arrives.
|
||||
:raises ApiException when a call has failed.
|
||||
"""
|
||||
updates = apihelper.get_updates(self.token, offset=(self.last_update_id + 1))
|
||||
updates = apihelper.get_updates(self.token, offset=(self.last_update_id + 1), timeout=20)
|
||||
new_messages = []
|
||||
for update in updates:
|
||||
if update['update_id'] > self.last_update_id:
|
||||
@ -66,31 +66,33 @@ class TeleBot:
|
||||
t = threading.Thread(target=listener, args=new_messages)
|
||||
t.start()
|
||||
|
||||
def polling(self, interval=3):
|
||||
def polling(self):
|
||||
"""
|
||||
This function creates a new Thread that calls an internal __polling function.
|
||||
This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly.
|
||||
|
||||
Do not call this function more than once!
|
||||
|
||||
Always get updates.
|
||||
:param interval: interval secs.
|
||||
:return:
|
||||
"""
|
||||
self.interval = interval
|
||||
# clear thread.
|
||||
self.__stop_polling = True
|
||||
time.sleep(interval + 1)
|
||||
self.__stop_polling = False
|
||||
self.polling_thread = threading.Thread(target=self.__polling, args=())
|
||||
self.polling_thread.daemon = True
|
||||
self.polling_thread.start()
|
||||
|
||||
def __polling(self):
|
||||
print('telegram bot start polling')
|
||||
print('TeleBot: Started polling.')
|
||||
while not self.__stop_polling:
|
||||
try:
|
||||
self.get_update()
|
||||
except Exception as e:
|
||||
print("TeleBot: Exception occurred. Stopping.")
|
||||
self.__stop_polling = True
|
||||
print(e)
|
||||
time.sleep(self.interval)
|
||||
|
||||
print('telegram bot stop polling')
|
||||
print('TeleBot: Stopped polling.')
|
||||
|
||||
def stop_polling(self):
|
||||
self.__stop_polling = True
|
||||
@ -109,7 +111,7 @@ class TeleBot:
|
||||
:param user_id:
|
||||
:param offset:
|
||||
:param limit:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
result = apihelper.get_user_profile_photos(self.token, user_id, offset, limit)
|
||||
return types.UserProfilePhotos.de_json(result)
|
||||
@ -122,7 +124,7 @@ class TeleBot:
|
||||
:param disable_web_page_preview:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_message(self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
|
||||
reply_markup)
|
||||
@ -133,7 +135,7 @@ class TeleBot:
|
||||
:param chat_id: which chat to forward
|
||||
:param from_chat_id: which chat message from
|
||||
:param message_id: message id
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.forward_message(self.token, chat_id, from_chat_id, message_id)
|
||||
|
||||
@ -145,7 +147,7 @@ class TeleBot:
|
||||
:param caption:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_photo(self.token, chat_id, photo, caption, reply_to_message_id, reply_markup)
|
||||
|
||||
@ -157,7 +159,7 @@ class TeleBot:
|
||||
:param data:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_data(self.token, chat_id, data, 'audio', reply_to_message_id, reply_markup)
|
||||
|
||||
@ -168,7 +170,7 @@ class TeleBot:
|
||||
:param data:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_data(self.token, chat_id, data, 'document', reply_to_message_id, reply_markup)
|
||||
|
||||
@ -179,7 +181,7 @@ class TeleBot:
|
||||
:param data:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_data(self.token, chat_id, data, 'sticker', reply_to_message_id, reply_markup)
|
||||
|
||||
@ -190,7 +192,7 @@ class TeleBot:
|
||||
:param data:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_data(self.token, chat_id, data, 'video', reply_to_message_id, reply_markup)
|
||||
|
||||
@ -202,7 +204,7 @@ class TeleBot:
|
||||
:param longitude:
|
||||
:param reply_to_message_id:
|
||||
:param reply_markup:
|
||||
:return:
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_location(self.token, chat_id, latitude, longitude, reply_to_message_id, reply_markup)
|
||||
|
||||
@ -212,13 +214,13 @@ class TeleBot:
|
||||
The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear
|
||||
its typing status).
|
||||
:param chat_id:
|
||||
:param action: string . typing,upload_photo,record_video,upload_video,record_audio,upload_audio,upload_document,
|
||||
find_location.
|
||||
:return:
|
||||
:param action: One of the following strings: 'typing', 'upload_photo', 'record_video', 'upload_video',
|
||||
'record_audio', 'upload_audio', 'upload_document', 'find_location'.
|
||||
:return: API reply.
|
||||
"""
|
||||
return apihelper.send_chat_action(self.token, chat_id, action)
|
||||
|
||||
def message_handler(self, regexp=None, func=None, content_types=['text']):
|
||||
def message_handler(self, commands=None, regexp=None, func=None, content_types=['text']):
|
||||
"""
|
||||
Message handler decorator.
|
||||
This decorator can be used to decorate functions that must handle certain types of messages.
|
||||
@ -246,27 +248,60 @@ class TeleBot:
|
||||
:param regexp: Optional regular expression.
|
||||
:param func: Optional lambda function. The lambda receives the message to test as the first parameter. It must return True if the command should handle the message.
|
||||
:param content_types: This commands' supported content types. Must be a list. Defaults to ['text'].
|
||||
:return:
|
||||
"""
|
||||
def decorator(fn):
|
||||
self.commands.append([fn, regexp, func, content_types])
|
||||
func_dict = {'function': fn, 'content_types': content_types}
|
||||
if regexp:
|
||||
func_dict['regexp'] = regexp if 'text' in content_types else None
|
||||
if func:
|
||||
func_dict['lambda'] = func
|
||||
if commands:
|
||||
func_dict['commands'] = commands if 'text' in content_types else None
|
||||
self.message_handlers.append(func_dict)
|
||||
return fn
|
||||
return decorator
|
||||
|
||||
@staticmethod
|
||||
def _test_command(command, message):
|
||||
if message.content_type not in command[3]:
|
||||
def is_command(text):
|
||||
"""
|
||||
Checks if `text` is a command. Telegram chat commands start with the '/' character.
|
||||
:param text: Text to check.
|
||||
:return: True if `text` is a command, else False.
|
||||
"""
|
||||
return text.startswith('/')
|
||||
|
||||
@staticmethod
|
||||
def extract_command(text):
|
||||
"""
|
||||
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
|
||||
If `text` is not a command, this function returns None.
|
||||
|
||||
Examples:
|
||||
extract_command('/help'): 'help'
|
||||
extract_command('/search black eyed peas'): 'search'
|
||||
extract_command('Good day to you'): None
|
||||
|
||||
:param text: String to extract the command from
|
||||
:return: the command if `text` is a command, else None.
|
||||
"""
|
||||
return text.split()[0][1:] if TeleBot.is_command(text) else None
|
||||
|
||||
@staticmethod
|
||||
def _test_message_handler(message_handler, message):
|
||||
if message.content_type not in message_handler['content_types']:
|
||||
return False
|
||||
if command[1] is not None and message.content_type == 'text' and re.search(command[1], message.text):
|
||||
return True
|
||||
if command[2] is not None:
|
||||
return command[2](message)
|
||||
if 'commands' in message_handler and message.content_type == 'text':
|
||||
return TeleBot.extract_command(message.text) in message_handler['commands']
|
||||
if 'regexp' in message_handler and message.content_type == 'text' and re.search(message_handler['regexp'], message.text):
|
||||
return False
|
||||
if 'lambda' in message_handler:
|
||||
return message_handler['lambda'](message)
|
||||
return False
|
||||
|
||||
def _notify_command_handlers(self, new_messages):
|
||||
for message in new_messages:
|
||||
for command in self.commands:
|
||||
if self._test_command(command, message):
|
||||
t = threading.Thread(target=command[0], args=(message,))
|
||||
for message_handler in self.message_handlers:
|
||||
if self._test_message_handler(message_handler, message):
|
||||
t = threading.Thread(target=message_handler['function'], args=(message,))
|
||||
t.start()
|
||||
break
|
||||
|
@ -56,12 +56,16 @@ def send_message(token, chat_id, text, disable_web_page_preview=None, reply_to_m
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def get_updates(token, offset=None):
|
||||
def get_updates(token, offset=None, limit=None, timeout=None):
|
||||
method_url = r'getUpdates'
|
||||
if offset is not None:
|
||||
return _make_request(token, method_url, params={'offset': offset})
|
||||
else:
|
||||
return _make_request(token, method_url)
|
||||
payload = {}
|
||||
if offset:
|
||||
payload['offset'] = offset
|
||||
if limit:
|
||||
payload['limit'] = limit
|
||||
if timeout:
|
||||
payload['timeout'] = timeout
|
||||
return _make_request(token, method_url, params=payload)
|
||||
|
||||
|
||||
def get_user_profile_photos(token, user_id, offset=None, limit=None):
|
||||
|
Loading…
Reference in New Issue
Block a user