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.last_update_id = 0
|
||||||
|
|
||||||
self.commands = []
|
self.message_handlers = []
|
||||||
|
|
||||||
def get_update(self):
|
def get_update(self):
|
||||||
"""
|
"""
|
||||||
@ -49,7 +49,7 @@ class TeleBot:
|
|||||||
Registered listeners and applicable message handlers will be notified when a new message arrives.
|
Registered listeners and applicable message handlers will be notified when a new message arrives.
|
||||||
:raises ApiException when a call has failed.
|
: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 = []
|
new_messages = []
|
||||||
for update in updates:
|
for update in updates:
|
||||||
if update['update_id'] > self.last_update_id:
|
if update['update_id'] > self.last_update_id:
|
||||||
@ -66,31 +66,33 @@ class TeleBot:
|
|||||||
t = threading.Thread(target=listener, args=new_messages)
|
t = threading.Thread(target=listener, args=new_messages)
|
||||||
t.start()
|
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.
|
Always get updates.
|
||||||
:param interval: interval secs.
|
:param interval: interval secs.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
self.interval = interval
|
|
||||||
# clear thread.
|
|
||||||
self.__stop_polling = True
|
|
||||||
time.sleep(interval + 1)
|
|
||||||
self.__stop_polling = False
|
self.__stop_polling = False
|
||||||
self.polling_thread = threading.Thread(target=self.__polling, args=())
|
self.polling_thread = threading.Thread(target=self.__polling, args=())
|
||||||
self.polling_thread.daemon = True
|
self.polling_thread.daemon = True
|
||||||
self.polling_thread.start()
|
self.polling_thread.start()
|
||||||
|
|
||||||
def __polling(self):
|
def __polling(self):
|
||||||
print('telegram bot start polling')
|
print('TeleBot: Started polling.')
|
||||||
while not self.__stop_polling:
|
while not self.__stop_polling:
|
||||||
try:
|
try:
|
||||||
self.get_update()
|
self.get_update()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print("TeleBot: Exception occurred. Stopping.")
|
||||||
|
self.__stop_polling = True
|
||||||
print(e)
|
print(e)
|
||||||
time.sleep(self.interval)
|
|
||||||
|
|
||||||
print('telegram bot stop polling')
|
print('TeleBot: Stopped polling.')
|
||||||
|
|
||||||
def stop_polling(self):
|
def stop_polling(self):
|
||||||
self.__stop_polling = True
|
self.__stop_polling = True
|
||||||
@ -109,7 +111,7 @@ class TeleBot:
|
|||||||
:param user_id:
|
:param user_id:
|
||||||
:param offset:
|
:param offset:
|
||||||
:param limit:
|
:param limit:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
result = apihelper.get_user_profile_photos(self.token, user_id, offset, limit)
|
result = apihelper.get_user_profile_photos(self.token, user_id, offset, limit)
|
||||||
return types.UserProfilePhotos.de_json(result)
|
return types.UserProfilePhotos.de_json(result)
|
||||||
@ -122,7 +124,7 @@ class TeleBot:
|
|||||||
:param disable_web_page_preview:
|
:param disable_web_page_preview:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_message(self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
|
return apihelper.send_message(self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
|
||||||
reply_markup)
|
reply_markup)
|
||||||
@ -133,7 +135,7 @@ class TeleBot:
|
|||||||
:param chat_id: which chat to forward
|
:param chat_id: which chat to forward
|
||||||
:param from_chat_id: which chat message from
|
:param from_chat_id: which chat message from
|
||||||
:param message_id: message id
|
:param message_id: message id
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.forward_message(self.token, chat_id, from_chat_id, message_id)
|
return apihelper.forward_message(self.token, chat_id, from_chat_id, message_id)
|
||||||
|
|
||||||
@ -145,7 +147,7 @@ class TeleBot:
|
|||||||
:param caption:
|
:param caption:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_photo(self.token, chat_id, photo, caption, reply_to_message_id, reply_markup)
|
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 data:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_data(self.token, chat_id, data, 'audio', reply_to_message_id, reply_markup)
|
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 data:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_data(self.token, chat_id, data, 'document', reply_to_message_id, reply_markup)
|
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 data:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_data(self.token, chat_id, data, 'sticker', reply_to_message_id, reply_markup)
|
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 data:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_data(self.token, chat_id, data, 'video', reply_to_message_id, reply_markup)
|
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 longitude:
|
||||||
:param reply_to_message_id:
|
:param reply_to_message_id:
|
||||||
:param reply_markup:
|
:param reply_markup:
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_location(self.token, chat_id, latitude, longitude, reply_to_message_id, reply_markup)
|
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
|
The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear
|
||||||
its typing status).
|
its typing status).
|
||||||
:param chat_id:
|
:param chat_id:
|
||||||
:param action: string . typing,upload_photo,record_video,upload_video,record_audio,upload_audio,upload_document,
|
:param action: One of the following strings: 'typing', 'upload_photo', 'record_video', 'upload_video',
|
||||||
find_location.
|
'record_audio', 'upload_audio', 'upload_document', 'find_location'.
|
||||||
:return:
|
:return: API reply.
|
||||||
"""
|
"""
|
||||||
return apihelper.send_chat_action(self.token, chat_id, action)
|
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.
|
Message handler decorator.
|
||||||
This decorator can be used to decorate functions that must handle certain types of messages.
|
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 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 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'].
|
:param content_types: This commands' supported content types. Must be a list. Defaults to ['text'].
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
def decorator(fn):
|
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 fn
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _test_command(command, message):
|
def is_command(text):
|
||||||
if message.content_type not in command[3]:
|
"""
|
||||||
|
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
|
return False
|
||||||
if command[1] is not None and message.content_type == 'text' and re.search(command[1], message.text):
|
if 'commands' in message_handler and message.content_type == 'text':
|
||||||
return True
|
return TeleBot.extract_command(message.text) in message_handler['commands']
|
||||||
if command[2] is not None:
|
if 'regexp' in message_handler and message.content_type == 'text' and re.search(message_handler['regexp'], message.text):
|
||||||
return command[2](message)
|
return False
|
||||||
|
if 'lambda' in message_handler:
|
||||||
|
return message_handler['lambda'](message)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _notify_command_handlers(self, new_messages):
|
def _notify_command_handlers(self, new_messages):
|
||||||
for message in new_messages:
|
for message in new_messages:
|
||||||
for command in self.commands:
|
for message_handler in self.message_handlers:
|
||||||
if self._test_command(command, message):
|
if self._test_message_handler(message_handler, message):
|
||||||
t = threading.Thread(target=command[0], args=(message,))
|
t = threading.Thread(target=message_handler['function'], args=(message,))
|
||||||
t.start()
|
t.start()
|
||||||
break
|
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)
|
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'
|
method_url = r'getUpdates'
|
||||||
if offset is not None:
|
payload = {}
|
||||||
return _make_request(token, method_url, params={'offset': offset})
|
if offset:
|
||||||
else:
|
payload['offset'] = offset
|
||||||
return _make_request(token, method_url)
|
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):
|
def get_user_profile_photos(token, user_id, offset=None, limit=None):
|
||||||
|
Loading…
Reference in New Issue
Block a user