1
0
mirror of https://github.com/eternnoir/pyTelegramBotAPI.git synced 2023-08-10 21:12:57 +03:00

Fixed a bug, made improvements in reload system

Didn't test that much, there is still some stuff to do
This commit is contained in:
coder2020official
2022-09-30 23:22:21 +04:00
parent d3080b6d4e
commit eb576d83fb
4 changed files with 72 additions and 43 deletions

View File

@@ -880,10 +880,27 @@ class TeleBot:
for listener in self.update_listener: for listener in self.update_listener:
self._exec_task(listener, new_messages) self._exec_task(listener, new_messages)
def _setup_change_detector(self):
try:
from watchdog.observers import Observer
from telebot.ext.reloader import EventHandler
except ImportError:
raise ImportError(
'Please install watchdog and psutil before using restart_on_change option.'
)
self.event_handler = EventHandler()
path = path_to_watch if path_to_watch else None
if path is None:
path = sys.argv[1] if len(sys.argv) > 1 else '.' # current directory
self.observer = Observer()
self.observer.schedule(self.event_handler, path, recursive=True)
self.observer.start()
def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, long_polling_timeout: Optional[int]=20, def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, long_polling_timeout: Optional[int]=20,
logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None, logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None,
restart_on_change: Optional[bool]=False, *args, **kwargs): restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None, *args, **kwargs):
""" """
Wrap polling with infinite loop and exception handling to avoid bot stops polling. Wrap polling with infinite loop and exception handling to avoid bot stops polling.
@@ -912,11 +929,18 @@ class TeleBot:
:param restart_on_change: Restart a file on file(s) change. Defaults to False :param restart_on_change: Restart a file on file(s) change. Defaults to False
:type restart_on_change: :obj:`bool` :type restart_on_change: :obj:`bool`
:param path_to_watch: Path to watch for changes. Defaults to current directory
:type path_to_watch: :obj:`str`
:return: :return:
""" """
if skip_pending: if skip_pending:
self.__skip_updates() self.__skip_updates()
if restart_on_change:
self._setup_change_detector(path_to_watch)
restart_on_change = False
while not self.__stop_polling.is_set(): while not self.__stop_polling.is_set():
try: try:
self.polling(non_stop=True, timeout=timeout, long_polling_timeout=long_polling_timeout, self.polling(non_stop=True, timeout=timeout, long_polling_timeout=long_polling_timeout,
@@ -938,7 +962,7 @@ class TeleBot:
def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=False, interval: Optional[int]=0, def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=False, interval: Optional[int]=0,
timeout: Optional[int]=20, long_polling_timeout: Optional[int]=20, timeout: Optional[int]=20, long_polling_timeout: Optional[int]=20,
logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None, logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None,
none_stop: Optional[bool]=None, restart_on_change: Optional[bool]=False): none_stop: Optional[bool]=None, restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None):
""" """
This function creates a new Thread that calls an internal __retrieve_updates function. This function creates a new Thread that calls an internal __retrieve_updates function.
This allows the bot to retrieve Updates automatically and notify listeners and message handlers accordingly. This allows the bot to retrieve Updates automatically and notify listeners and message handlers accordingly.
@@ -984,6 +1008,9 @@ class TeleBot:
:param restart_on_change: Restart a file on file(s) change. Defaults to False :param restart_on_change: Restart a file on file(s) change. Defaults to False
:type restart_on_change: :obj:`bool` :type restart_on_change: :obj:`bool`
:param path_to_watch: Path to watch for changes. Defaults to None
:type path_to_watch: :obj:`str`
:return: :return:
""" """
@@ -995,19 +1022,7 @@ class TeleBot:
self.__skip_updates() self.__skip_updates()
if restart_on_change: if restart_on_change:
try: self._setup_change_detector(path_to_watch)
from watchdog.observers import Observer
from telebot.ext.reloader import EventHandler
except ImportError:
raise ImportError(
'Please install watchdog and psutil before using restart_on_change option.'
)
event_handler = EventHandler()
path = sys.argv[1] if len(sys.argv) > 1 else '.'
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
logger.info('Starting your bot with username: [@%s]', self.user.username) logger.info('Starting your bot with username: [@%s]', self.user.username)

View File

@@ -5,6 +5,7 @@ import logging
import re import re
import traceback import traceback
from typing import Any, Awaitable, Callable, List, Optional, Union from typing import Any, Awaitable, Callable, List, Optional, Union
import sys
# this imports are used to avoid circular import error # this imports are used to avoid circular import error
import telebot.util import telebot.util
@@ -213,9 +214,27 @@ class AsyncTeleBot:
json_updates = await asyncio_helper.get_updates(self.token, offset, limit, timeout, allowed_updates, request_timeout) json_updates = await asyncio_helper.get_updates(self.token, offset, limit, timeout, allowed_updates, request_timeout)
return [types.Update.de_json(ju) for ju in json_updates] return [types.Update.de_json(ju) for ju in json_updates]
def _setup_change_detector(self, path_to_watch: str) -> None:
try:
from watchdog.observers import Observer
from telebot.ext.reloader import EventHandler
except ImportError:
raise ImportError(
'Please install watchdog and psutil before using restart_on_change option.'
)
self.event_handler = EventHandler()
path = path_to_watch if path_to_watch else None
if path is None:
path = sys.argv[1] if len(sys.argv) > 1 else '.' # current directory
self.observer = Observer()
self.observer.schedule(self.event_handler, path, recursive=True)
self.observer.start()
async def polling(self, non_stop: bool=False, skip_pending=False, interval: int=0, timeout: int=20, async def polling(self, non_stop: bool=False, skip_pending=False, interval: int=0, timeout: int=20,
request_timeout: Optional[int]=None, allowed_updates: Optional[List[str]]=None, request_timeout: Optional[int]=None, allowed_updates: Optional[List[str]]=None,
none_stop: Optional[bool]=None, restart_on_change: Optional[bool]=False): none_stop: Optional[bool]=None, restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None):
""" """
Runs bot in long-polling mode in a main loop. Runs bot in long-polling mode in a main loop.
This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly. This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly.
@@ -259,6 +278,9 @@ class AsyncTeleBot:
:param restart_on_change: Restart a file on file(s) change. Defaults to False :param restart_on_change: Restart a file on file(s) change. Defaults to False
:type restart_on_change: :obj:`bool` :type restart_on_change: :obj:`bool`
:param path_to_watch: Path to watch for changes. Defaults to current directory
:type path_to_watch: :obj:`str`
:return: :return:
""" """
@@ -268,11 +290,15 @@ class AsyncTeleBot:
if skip_pending: if skip_pending:
await self.skip_updates() await self.skip_updates()
await self._process_polling(non_stop, interval, timeout, request_timeout, allowed_updates, restart_on_change)
if restart_on_change:
self._setup_change_detector(path_to_watch)
await self._process_polling(non_stop, interval, timeout, request_timeout, allowed_updates)
async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, request_timeout: Optional[int]=None, async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, request_timeout: Optional[int]=None,
logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None, logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None,
restart_on_change: Optional[bool]=False, *args, **kwargs): restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None, *args, **kwargs):
""" """
Wrap polling with infinite loop and exception handling to avoid bot stops polling. Wrap polling with infinite loop and exception handling to avoid bot stops polling.
@@ -302,15 +328,24 @@ class AsyncTeleBot:
:param restart_on_change: Restart a file on file(s) change. Defaults to False :param restart_on_change: Restart a file on file(s) change. Defaults to False
:type restart_on_change: :obj:`bool` :type restart_on_change: :obj:`bool`
:param path_to_watch: Path to watch for changes. Defaults to current directory
:type path_to_watch: :obj:`str`
:return: None :return: None
""" """
if skip_pending: if skip_pending:
await self.skip_updates() await self.skip_updates()
self._polling = True self._polling = True
if restart_on_change:
restart_on_change = False
self._setup_change_detector(path_to_watch)
while self._polling: while self._polling:
try: try:
await self._process_polling(non_stop=False, timeout=timeout, request_timeout=request_timeout, await self._process_polling(non_stop=False, timeout=timeout, request_timeout=request_timeout,
allowed_updates=allowed_updates, restart_on_change=restart_on_change, *args, **kwargs) allowed_updates=allowed_updates, *args, **kwargs)
except Exception as e: except Exception as e:
if logger_level and logger_level >= logging.ERROR: if logger_level and logger_level >= logging.ERROR:
logger.error("Infinity polling exception: %s", str(e)) logger.error("Infinity polling exception: %s", str(e))
@@ -324,7 +359,7 @@ class AsyncTeleBot:
logger.error("Break infinity polling") logger.error("Break infinity polling")
async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20, async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20,
request_timeout: int=None, allowed_updates: Optional[List[str]]=None, restart_on_change: Optional[bool]=False): request_timeout: int=None, allowed_updates: Optional[List[str]]=None):
""" """
Function to process polling. Function to process polling.
@@ -341,30 +376,11 @@ class AsyncTeleBot:
Please note that this parameter doesn't affect updates created before the call to the get_updates, Please note that this parameter doesn't affect updates created before the call to the get_updates,
so unwanted updates may be received for a short period of time. so unwanted updates may be received for a short period of time.
:param restart_on_change: Restart a file on file(s) change. Defaults to False
:type restart_on_change: :obj:`bool`
:return: :return:
""" """
self._user = await self.get_me() self._user = await self.get_me()
if restart_on_change:
try:
from watchdog.observers import Observer
from telebot.ext.reloader import EventHandler
except ImportError:
raise ImportError(
'Please install watchdog and psutil before using restart_on_change option.'
)
event_handler = EventHandler()
path = sys.argv[1] if len(sys.argv) > 1 else '.'
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
logger.info('Starting your bot with username: [@%s]', self.user.username) logger.info('Starting your bot with username: [@%s]', self.user.username)

View File

@@ -71,7 +71,7 @@ async def _process_request(token, url, method='get', params=None, files=None, **
else: else:
# let's check for timeout in params # let's check for timeout in params
request_timeout = params.pop('timeout', None) request_timeout = params.pop('timeout', None) if params else None
# we will apply default request_timeout if there is no timeout in params # we will apply default request_timeout if there is no timeout in params
# otherwise, we will use timeout parameter applied for payload. # otherwise, we will use timeout parameter applied for payload.

View File

@@ -8,11 +8,9 @@ import logging
logger = logging.getLogger('TeleBot') logger = logging.getLogger('TeleBot')
class EventHandler(FileSystemEventHandler): class EventHandler(FileSystemEventHandler):
def on_any_event(self, event: FileSystemEvent): def on_any_event(self, event: FileSystemEvent):
logger.info('* Detected changes in: %s , reloading', (event.src_path)) logger.info('* Detected changes in: %s, reloading', (event.src_path))
restart_file() restart_file()
def restart_file(): def restart_file():