mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Added more aliases, refactor CallbackData factory, added base exceptions classification mechanism
This commit is contained in:
parent
9451a085d1
commit
f022b4441c
18 changed files with 364 additions and 664 deletions
|
|
@ -302,7 +302,7 @@ class Bot(ContextInstanceMixin["Bot"]):
|
|||
:param method:
|
||||
:return:
|
||||
"""
|
||||
return await self.session.make_request(self, method, timeout=request_timeout)
|
||||
return await self.session(self, method, timeout=request_timeout)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from typing import (
|
|||
Optional,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -19,12 +18,12 @@ from aiohttp import BasicAuth, ClientSession, FormData, TCPConnector
|
|||
|
||||
from aiogram.methods import Request, TelegramMethod
|
||||
|
||||
from ...methods.base import TelegramType
|
||||
from .base import UNSET, BaseSession
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from ..bot import Bot
|
||||
|
||||
T = TypeVar("T")
|
||||
_ProxyBasic = Union[str, Tuple[str, BasicAuth]]
|
||||
_ProxyChain = Iterable[_ProxyBasic]
|
||||
_ProxyType = Union[_ProxyChain, _ProxyBasic]
|
||||
|
|
@ -76,6 +75,8 @@ def _prepare_connector(chain_or_plain: _ProxyType) -> Tuple[Type["TCPConnector"]
|
|||
|
||||
class AiohttpSession(BaseSession):
|
||||
def __init__(self, proxy: Optional[_ProxyType] = None):
|
||||
super().__init__()
|
||||
|
||||
self._session: Optional[ClientSession] = None
|
||||
self._connector_type: Type[TCPConnector] = TCPConnector
|
||||
self._connector_init: Dict[str, Any] = {}
|
||||
|
|
@ -86,7 +87,7 @@ class AiohttpSession(BaseSession):
|
|||
try:
|
||||
self._setup_proxy_connector(proxy)
|
||||
except ImportError as exc: # pragma: no cover
|
||||
raise UserWarning(
|
||||
raise RuntimeError(
|
||||
"In order to use aiohttp client for proxy requests, install "
|
||||
"https://pypi.org/project/aiohttp-socks/"
|
||||
) from exc
|
||||
|
|
@ -130,8 +131,8 @@ class AiohttpSession(BaseSession):
|
|||
return form
|
||||
|
||||
async def make_request(
|
||||
self, bot: Bot, call: TelegramMethod[T], timeout: Optional[int] = None
|
||||
) -> T:
|
||||
self, bot: Bot, call: TelegramMethod[TelegramType], timeout: Optional[int] = None
|
||||
) -> TelegramType:
|
||||
session = await self.create_session()
|
||||
|
||||
request = call.build_request(bot)
|
||||
|
|
@ -141,11 +142,10 @@ class AiohttpSession(BaseSession):
|
|||
async with session.post(
|
||||
url, data=form, timeout=self.timeout if timeout is None else timeout
|
||||
) as resp:
|
||||
raw_result = await resp.json(loads=self.json_loads)
|
||||
raw_result = await resp.text()
|
||||
|
||||
response = call.build_response(raw_result)
|
||||
self.raise_for_status(response)
|
||||
return cast(T, response.result)
|
||||
response = self.check_response(method=call, status_code=resp.status, content=raw_result)
|
||||
return cast(TelegramType, response.result)
|
||||
|
||||
async def stream_content(
|
||||
self, url: str, timeout: int, chunk_size: int
|
||||
|
|
|
|||
|
|
@ -3,32 +3,44 @@ from __future__ import annotations
|
|||
import abc
|
||||
import datetime
|
||||
import json
|
||||
from functools import partial
|
||||
from types import TracebackType
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
Awaitable,
|
||||
Callable,
|
||||
ClassVar,
|
||||
List,
|
||||
Optional,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from aiogram.utils.exceptions import TelegramAPIError
|
||||
from aiogram.utils.exceptions.base import TelegramAPIError
|
||||
from aiogram.utils.helper import Default
|
||||
|
||||
from ...methods import Response, TelegramMethod
|
||||
from ...types import UNSET
|
||||
from ...methods.base import TelegramType
|
||||
from ...types import UNSET, TelegramObject
|
||||
from ...utils.exceptions.special import MigrateToChat, RetryAfter
|
||||
from ..errors_middleware import RequestErrorMiddleware
|
||||
from ..telegram import PRODUCTION, TelegramAPIServer
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from ..bot import Bot
|
||||
|
||||
T = TypeVar("T")
|
||||
_JsonLoads = Callable[..., Any]
|
||||
_JsonDumps = Callable[..., str]
|
||||
NextRequestMiddlewareType = Callable[
|
||||
["Bot", TelegramMethod[TelegramObject]], Awaitable[Response[TelegramObject]]
|
||||
]
|
||||
RequestMiddlewareType = Callable[
|
||||
["Bot", TelegramMethod[TelegramType], NextRequestMiddlewareType],
|
||||
Awaitable[Response[TelegramType]],
|
||||
]
|
||||
|
||||
|
||||
class BaseSession(abc.ABC):
|
||||
|
|
@ -43,16 +55,40 @@ class BaseSession(abc.ABC):
|
|||
timeout: Default[float] = Default(fget=lambda self: float(self.__class__.default_timeout))
|
||||
"""Session scope request timeout"""
|
||||
|
||||
@classmethod
|
||||
def raise_for_status(cls, response: Response[T]) -> None:
|
||||
errors_middleware: ClassVar[RequestErrorMiddleware] = RequestErrorMiddleware()
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.middlewares: List[RequestMiddlewareType[TelegramObject]] = [
|
||||
self.errors_middleware,
|
||||
]
|
||||
|
||||
def check_response(
|
||||
self, method: TelegramMethod[TelegramType], status_code: int, content: str
|
||||
) -> Response[TelegramType]:
|
||||
"""
|
||||
Check response status
|
||||
|
||||
:param response: Response instance
|
||||
"""
|
||||
json_data = self.json_loads(content)
|
||||
response = method.build_response(json_data)
|
||||
if response.ok:
|
||||
return
|
||||
raise TelegramAPIError(response.description)
|
||||
return response
|
||||
|
||||
description = cast(str, response.description)
|
||||
if parameters := response.parameters:
|
||||
if parameters.retry_after:
|
||||
raise RetryAfter(
|
||||
method=method, message=description, retry_after=parameters.retry_after
|
||||
)
|
||||
if parameters.migrate_to_chat_id:
|
||||
raise MigrateToChat(
|
||||
method=method,
|
||||
message=description,
|
||||
migrate_to_chat_id=parameters.migrate_to_chat_id,
|
||||
)
|
||||
raise TelegramAPIError(
|
||||
method=method,
|
||||
message=description,
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def close(self) -> None: # pragma: no cover
|
||||
|
|
@ -63,8 +99,8 @@ class BaseSession(abc.ABC):
|
|||
|
||||
@abc.abstractmethod
|
||||
async def make_request(
|
||||
self, bot: Bot, method: TelegramMethod[T], timeout: Optional[int] = UNSET
|
||||
) -> T: # pragma: no cover
|
||||
self, bot: Bot, method: TelegramMethod[TelegramType], timeout: Optional[int] = UNSET
|
||||
) -> TelegramType: # pragma: no cover
|
||||
"""
|
||||
Make request to Telegram Bot API
|
||||
|
||||
|
|
@ -111,6 +147,20 @@ class BaseSession(abc.ABC):
|
|||
return {k: self.clean_json(v) for k, v in value.items() if v is not None}
|
||||
return value
|
||||
|
||||
def middleware(
|
||||
self, middleware: RequestMiddlewareType[TelegramObject]
|
||||
) -> RequestMiddlewareType[TelegramObject]:
|
||||
self.middlewares.append(middleware)
|
||||
return middleware
|
||||
|
||||
async def __call__(
|
||||
self, bot: Bot, method: TelegramMethod[TelegramType], timeout: Optional[int] = UNSET
|
||||
) -> TelegramType:
|
||||
middleware = partial(self.make_request, timeout=timeout)
|
||||
for m in reversed(self.middlewares):
|
||||
middleware = partial(m, make_request=middleware) # type: ignore
|
||||
return await middleware(bot, method)
|
||||
|
||||
async def __aenter__(self) -> BaseSession:
|
||||
return self
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue