From ac79c1ebb7539cec5992b47d223a84a8e32e35b2 Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:02:20 +0300 Subject: [PATCH 1/8] Adding StopPropagation --- tgram/__init__.py | 5 ++++- tgram/errors.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tgram/__init__.py b/tgram/__init__.py index 5b4ea05..240c4e5 100644 --- a/tgram/__init__.py +++ b/tgram/__init__.py @@ -1,4 +1,4 @@ -__all__ = ["types", "TgBot", "handlers", "filters"] +__all__ = ["types", "TgBot", "handlers", "filters", "idle", "StopPropagation"] __version__ = "1.10.7" __author__ = "Zaid" @@ -7,3 +7,6 @@ from . import types, handlers, filters from .tgbot import TgBot +from .sync import idle + +from .errors import StopPropagation diff --git a/tgram/errors.py b/tgram/errors.py index 4216dea..8f579cf 100644 --- a/tgram/errors.py +++ b/tgram/errors.py @@ -1,2 +1,6 @@ class APIException(Exception): pass + + +class StopPropagation(Exception): + pass From 52b75260339f4ca8eec972d01c371e3ad1afd7b9 Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:02:32 +0300 Subject: [PATCH 2/8] wrap idle --- tgram/sync.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tgram/sync.py b/tgram/sync.py index 0393c34..d123c2d 100644 --- a/tgram/sync.py +++ b/tgram/sync.py @@ -4,6 +4,8 @@ import threading import logging +from tgram import utils + logger = logging.getLogger(__name__) @@ -107,3 +109,7 @@ def wrap(source): method ): async_to_sync(source, name) + + +async_to_sync(utils, "idle") +idle = utils.idle From e43186536b04b9877353af2528cd83c2de377f82 Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:02:55 +0300 Subject: [PATCH 3/8] add idle --- tgram/utils.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tgram/utils.py b/tgram/utils.py index 60f80ab..2a77c09 100644 --- a/tgram/utils.py +++ b/tgram/utils.py @@ -2,6 +2,9 @@ import tgram import re import html +import logging +import signal +import asyncio from pathlib import Path from typing import List, Union @@ -9,6 +12,16 @@ from io import BytesIO from .handlers import Handlers +from signal import signal as signal_fn, SIGINT, SIGTERM, SIGABRT + +logger = logging.getLogger(__name__) + +# Signal number to name +signals = { + k: v + for v, k in signal.__dict__.items() + if v.startswith("SIG") and not v.startswith("SIG_") +} API_URL = "https://api.telegram.org/" ALL_UPDATES: List[str] = [ @@ -315,3 +328,22 @@ def recursive(entity_i: int) -> int: last_offset = offset return remove_surrogates(text) + + +async def idle(): + task = None + + def signal_handler(signum, __): + logging.info(f"Stop signal received ({signals[signum]}). Exiting...") + asyncio.get_event_loop().run_in_executor(None, task.cancel) + + for s in (SIGINT, SIGTERM, SIGABRT): + signal_fn(s, signal_handler) + + while True: + task = asyncio.create_task(asyncio.sleep(600)) + + try: + await task + except asyncio.CancelledError: + break From d7710a2aacbdc083c597ebd28faa4807c1ff172b Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:03:12 +0300 Subject: [PATCH 4/8] improve dispatcher --- tgram/tgbot.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tgram/tgbot.py b/tgram/tgbot.py index 4c2b0bb..37b039d 100644 --- a/tgram/tgbot.py +++ b/tgram/tgbot.py @@ -29,7 +29,7 @@ class Dispatcher: - _is_running = False + is_running: bool = None _handlers: List["tgram.handlers.Handler"] = [] _listen_handlers: List["tgram.types.Listener"] = [] @@ -41,10 +41,10 @@ async def run_for_updates(self: "TgBot", skip_updates: bool = True) -> None: self.allowed_updates, 100, ) - self._is_running = True + self.is_running = True self.me = await self.get_me() - while self._is_running: + while self.is_running: try: updates = await self.get_updates( offset=offset, @@ -56,13 +56,24 @@ async def run_for_updates(self: "TgBot", skip_updates: bool = True) -> None: offset = update.update_id + 1 await self._check_update(update) except (asyncio.CancelledError, KeyboardInterrupt): - self._is_running = False + self.is_running = False + except tgram.StopPropagation: + pass except Exception as e: logger.exception(e) session = await self._get_session() await session.close() + async def start(self, skip_updates: bool = True) -> "TgBot": + asyncio.create_task(self.run_for_updates(skip_updates)) + + return self + + async def stop(self) -> Literal[True]: + self.is_running = False + return True + async def _check_cancel(self: "TgBot", callback: Callable, update: Any) -> bool: logger.debug("Checking listener in %s func", callback.__name__) try: From 7533126f7a065ad293d1f5d80c2df8d630b0c51b Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:45:14 +0300 Subject: [PATCH 5/8] replace idle with compose --- tgram/__init__.py | 4 ++-- tgram/sync.py | 4 ++-- tgram/utils.py | 33 +++++---------------------------- 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/tgram/__init__.py b/tgram/__init__.py index 240c4e5..de7d681 100644 --- a/tgram/__init__.py +++ b/tgram/__init__.py @@ -1,4 +1,4 @@ -__all__ = ["types", "TgBot", "handlers", "filters", "idle", "StopPropagation"] +__all__ = ["types", "TgBot", "handlers", "filters", "compose", "StopPropagation"] __version__ = "1.10.7" __author__ = "Zaid" @@ -7,6 +7,6 @@ from . import types, handlers, filters from .tgbot import TgBot -from .sync import idle +from .sync import compose from .errors import StopPropagation diff --git a/tgram/sync.py b/tgram/sync.py index d123c2d..53aaac4 100644 --- a/tgram/sync.py +++ b/tgram/sync.py @@ -111,5 +111,5 @@ def wrap(source): async_to_sync(source, name) -async_to_sync(utils, "idle") -idle = utils.idle +async_to_sync(utils, "compose") +idle = utils.compose diff --git a/tgram/utils.py b/tgram/utils.py index 2a77c09..0ff0368 100644 --- a/tgram/utils.py +++ b/tgram/utils.py @@ -2,8 +2,6 @@ import tgram import re import html -import logging -import signal import asyncio from pathlib import Path @@ -12,16 +10,6 @@ from io import BytesIO from .handlers import Handlers -from signal import signal as signal_fn, SIGINT, SIGTERM, SIGABRT - -logger = logging.getLogger(__name__) - -# Signal number to name -signals = { - k: v - for v, k in signal.__dict__.items() - if v.startswith("SIG") and not v.startswith("SIG_") -} API_URL = "https://api.telegram.org/" ALL_UPDATES: List[str] = [ @@ -330,20 +318,9 @@ def recursive(entity_i: int) -> int: return remove_surrogates(text) -async def idle(): - task = None - - def signal_handler(signum, __): - logging.info(f"Stop signal received ({signals[signum]}). Exiting...") - asyncio.get_event_loop().run_in_executor(None, task.cancel) - - for s in (SIGINT, SIGTERM, SIGABRT): - signal_fn(s, signal_handler) - - while True: - task = asyncio.create_task(asyncio.sleep(600)) +async def compose(bots: List["tgram.TgBot"]): + tasks = [ + asyncio.create_task(bot.run_for_updates()) for bot in bots + ] - try: - await task - except asyncio.CancelledError: - break + return await asyncio.wait(tasks) \ No newline at end of file From 99e67307b250262d3e6cc87d5374c71a0c140384 Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:45:31 +0300 Subject: [PATCH 6/8] remove start method --- tgram/tgbot.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tgram/tgbot.py b/tgram/tgbot.py index 37b039d..0ac2477 100644 --- a/tgram/tgbot.py +++ b/tgram/tgbot.py @@ -65,11 +65,6 @@ async def run_for_updates(self: "TgBot", skip_updates: bool = True) -> None: session = await self._get_session() await session.close() - async def start(self, skip_updates: bool = True) -> "TgBot": - asyncio.create_task(self.run_for_updates(skip_updates)) - - return self - async def stop(self) -> Literal[True]: self.is_running = False return True @@ -237,7 +232,7 @@ async def _send_request(self, method: str, **kwargs) -> Any: ), ) - if not self._is_running: + if not self.is_running: await session.close() response_json = await response.json() From 3362a9ed830337eb1faa6de50c9fe038fc43ed7f Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 22:51:11 +0300 Subject: [PATCH 7/8] rename idle variable --- tgram/sync.py | 2 +- tgram/utils.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tgram/sync.py b/tgram/sync.py index 53aaac4..9b173f1 100644 --- a/tgram/sync.py +++ b/tgram/sync.py @@ -112,4 +112,4 @@ def wrap(source): async_to_sync(utils, "compose") -idle = utils.compose +compose = utils.compose diff --git a/tgram/utils.py b/tgram/utils.py index 0ff0368..c18d5a1 100644 --- a/tgram/utils.py +++ b/tgram/utils.py @@ -319,8 +319,6 @@ def recursive(entity_i: int) -> int: async def compose(bots: List["tgram.TgBot"]): - tasks = [ - asyncio.create_task(bot.run_for_updates()) for bot in bots - ] + tasks = [asyncio.create_task(bot.run_for_updates()) for bot in bots] - return await asyncio.wait(tasks) \ No newline at end of file + return await asyncio.wait(tasks) From 9212a56dba31d028662878750a1cbbc28456a405 Mon Sep 17 00:00:00 2001 From: Zaid Date: Sat, 3 Aug 2024 23:28:25 +0300 Subject: [PATCH 8/8] move to init --- tgram/tgbot.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tgram/tgbot.py b/tgram/tgbot.py index 0ac2477..1084d47 100644 --- a/tgram/tgbot.py +++ b/tgram/tgbot.py @@ -29,10 +29,6 @@ class Dispatcher: - is_running: bool = None - _handlers: List["tgram.handlers.Handler"] = [] - _listen_handlers: List["tgram.types.Listener"] = [] - async def run_for_updates(self: "TgBot", skip_updates: bool = True) -> None: if self.plugins: self.load_plugins() @@ -127,11 +123,6 @@ async def _process_update(self: "TgBot", update: Any, callback: Callable) -> Non class TgBot(TelegramBotMethods, Decorators, Dispatcher): - me: "tgram.types.User" = None - _session: "aiohttp.ClientSession" = None - _api_url: str = None - _custom_types: dict = {} - def __init__( self, bot_token: str, @@ -156,10 +147,18 @@ def __init__( self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handlers") self.loop = asyncio.get_event_loop() + self.is_running: bool = None + self.me: "tgram.types.User" = None + + self._listen_handlers: List["tgram.types.Listener"] = [] + self._handlers: List["tgram.handlers.Handler"] = [] + self._custom_types: dict = {} + self._session: "aiohttp.ClientSession" = None + if not api_url.endswith("/"): api_url += "/" - self._api_url = f"{api_url}bot{bot_token}/" + self._api_url: str = f"{api_url}bot{bot_token}/" def add_handler(self, handler: "tgram.handlers.Handler") -> None: if handler.type == "all":