import asyncio import logging log = logging.getLogger(__name__) async def _await(aw): return await aw async def gather_results(*aws) -> list: """Run awaitables in parallel and return results (exceptions included, never raised). aiogram's bot-method objects (call.answer(), message.edit_text(), ...) are awaitable but are unhashable pydantic models, and asyncio.gather() puts its arguments in a dict -> TypeError "unhashable type". Wrapping each one in a coroutine avoids that. """ return await asyncio.gather(*(_await(a) for a in aws), return_exceptions=True) async def gather_safe(*aws) -> None: """Parallel Telegram calls; failures are logged, not raised.""" for res in await gather_results(*aws): if isinstance(res, Exception): log.info("Parallel call failed: %r", res)