This commit is contained in:
Dobromir Popov
2024-10-28 16:57:19 +02:00
parent 800cbede4d
commit 885eb523f6
6 changed files with 482 additions and 136 deletions

View File

@ -11,7 +11,7 @@ from config import TELEGRAM_BOT_TOKEN, DEVELOPER_CHAT_ID, BOT_NAME
import asyncio
from typing import Callable, Any
from typing import Callable, Any, Union, Coroutine
import time
import logging
from logging.handlers import RotatingFileHandler
@ -111,7 +111,11 @@ def safe_get_property(info, property_name, default='Unknown'):
value = info.get(property_name, default)
return str(value) if value is not None else str(default)
async def async_safe_call(func: Callable, *args: Any, **kwargs: Any) -> Any:
async def async_safe_call(
func: Union[Callable, Coroutine, None],
*args: Any,
**kwargs: Any
) -> Any:
"""
Safely call a function that might be synchronous, asynchronous, or a coroutine object.
@ -123,18 +127,30 @@ async def async_safe_call(func: Callable, *args: Any, **kwargs: Any) -> Any:
if func is None:
return None
if callable(func):
if asyncio.iscoroutinefunction(func):
return await func(*args, **kwargs)
try:
if asyncio.iscoroutine(func):
# If func is already a coroutine object, just await it
return await func
elif callable(func):
if asyncio.iscoroutinefunction(func):
# If func is an async function, call it with args and await
return await func(*args, **kwargs)
else:
# If func is a regular function, just call it
return func(*args, **kwargs)
else:
return func(*args, **kwargs)
elif asyncio.iscoroutine(func):
# If func is already a coroutine object, just await it
return await func
else:
logging.warning(f"Expected a callable or coroutine, but got {type(func)}: {func}")
logging.warning(f"Expected a callable or coroutine, but got {type(func)}: {func}")
return None
except RuntimeError as e:
if "cannot reuse already awaited coroutine" in str(e):
logging.error(f"Attempted to reuse an already awaited coroutine: {func}")
else:
logging.error(f"Runtime error in async_safe_call: {e}")
return None
except Exception as e:
logging.error(f"Error in async_safe_call: {type(e).__name__}: {e}")
return None
# Create a global instance of TelegramUtils
telegram_utils = TelegramUtils()