mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-10 19:46:36 +03:00
Use modern typehint syntax
This commit is contained in:
parent
9afe2f853d
commit
8267f5d590
|
@ -2,7 +2,8 @@ import datetime
|
||||||
import io
|
import io
|
||||||
import struct
|
import struct
|
||||||
import timeit
|
import timeit
|
||||||
from typing import Any, Iterator
|
from collections.abc import Iterator
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from .data_codegen import DATA, Obj
|
from .data_codegen import DATA, Obj
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from setuptools import build_meta as _orig
|
from setuptools import build_meta as _orig
|
||||||
from setuptools.build_meta import * # noqa: F403 # pyright: ignore [reportWildcardImportFromLibrary]
|
from setuptools.build_meta import * # noqa: F403 # pyright: ignore [reportWildcardImportFromLibrary]
|
||||||
|
@ -39,7 +39,7 @@ def gen_types_if_needed() -> None:
|
||||||
|
|
||||||
def build_wheel( # type: ignore [no-redef]
|
def build_wheel( # type: ignore [no-redef]
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
gen_types_if_needed()
|
gen_types_if_needed()
|
||||||
|
@ -47,7 +47,7 @@ def build_wheel( # type: ignore [no-redef]
|
||||||
|
|
||||||
|
|
||||||
def build_sdist( # type: ignore [no-redef]
|
def build_sdist( # type: ignore [no-redef]
|
||||||
sdist_directory: str, config_settings: Optional[Dict[Any, Any]] = None
|
sdist_directory: str, config_settings: Optional[dict[Any, Any]] = None
|
||||||
) -> str:
|
) -> str:
|
||||||
gen_types_if_needed()
|
gen_types_if_needed()
|
||||||
return _orig.build_sdist(sdist_directory, config_settings)
|
return _orig.build_sdist(sdist_directory, config_settings)
|
||||||
|
@ -55,7 +55,7 @@ def build_sdist( # type: ignore [no-redef]
|
||||||
|
|
||||||
def build_editable( # type: ignore [no-redef]
|
def build_editable( # type: ignore [no-redef]
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
gen_types_if_needed()
|
gen_types_if_needed()
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import getpass
|
import getpass
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Optional, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ...crypto import two_factor_auth
|
from ...crypto import two_factor_auth
|
||||||
from ...mtproto import RpcError
|
from ...mtproto import RpcError
|
||||||
|
@ -115,9 +115,7 @@ async def request_login_code(self: Client, phone: str) -> LoginToken:
|
||||||
return LoginToken._new(result, phone)
|
return LoginToken._new(result, phone)
|
||||||
|
|
||||||
|
|
||||||
async def sign_in(
|
async def sign_in(self: Client, token: LoginToken, code: str) -> User | PasswordToken:
|
||||||
self: Client, token: LoginToken, code: str
|
|
||||||
) -> Union[User, PasswordToken]:
|
|
||||||
try:
|
try:
|
||||||
result = await self(
|
result = await self(
|
||||||
functions.auth.sign_in(
|
functions.auth.sign_in(
|
||||||
|
@ -213,7 +211,7 @@ async def get_password_information(client: Client) -> PasswordToken:
|
||||||
|
|
||||||
|
|
||||||
async def check_password(
|
async def check_password(
|
||||||
self: Client, token: PasswordToken, password: Union[str, bytes]
|
self: Client, token: PasswordToken, password: str | bytes
|
||||||
) -> User:
|
) -> User:
|
||||||
algo = token._password.current_algo
|
algo = token._password.current_algo
|
||||||
if not isinstance(
|
if not isinstance(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, AsyncIterator, List, Optional, Self
|
from collections.abc import AsyncIterator
|
||||||
|
from typing import TYPE_CHECKING, Optional, Self
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from ..types import ChatLike, InlineResult, NoPublicConstructor
|
from ..types import ChatLike, InlineResult, NoPublicConstructor
|
||||||
|
@ -22,7 +23,7 @@ class InlineResults(metaclass=NoPublicConstructor):
|
||||||
self._query = query
|
self._query = query
|
||||||
self._peer = chat or types.InputPeerEmpty()
|
self._peer = chat or types.InputPeerEmpty()
|
||||||
self._offset: Optional[str] = ""
|
self._offset: Optional[str] = ""
|
||||||
self._buffer: List[InlineResult] = []
|
self._buffer: list[InlineResult] = []
|
||||||
self._done = False
|
self._done = False
|
||||||
|
|
||||||
def __aiter__(self) -> Self:
|
def __aiter__(self) -> Self:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Optional, Sequence, Set
|
from typing import TYPE_CHECKING, Optional, Sequence
|
||||||
|
|
||||||
from ...session import PackedChat
|
from ...session import PackedChat
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
|
@ -32,7 +32,7 @@ class ParticipantList(AsyncList[Participant]):
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
self._packed: Optional[PackedChat] = None
|
self._packed: Optional[PackedChat] = None
|
||||||
self._offset = 0
|
self._offset = 0
|
||||||
self._seen: Set[int] = set()
|
self._seen: set[int] = set()
|
||||||
|
|
||||||
async def _fetch_next(self) -> None:
|
async def _fetch_next(self) -> None:
|
||||||
if self._packed is None:
|
if self._packed is None:
|
||||||
|
|
|
@ -1,24 +1,10 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
from collections.abc import AsyncIterator, Awaitable, Callable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import (
|
from typing import Any, Literal, Optional, Self, Sequence, Type, TypeVar
|
||||||
Any,
|
|
||||||
AsyncIterator,
|
|
||||||
Awaitable,
|
|
||||||
Callable,
|
|
||||||
Dict,
|
|
||||||
List,
|
|
||||||
Literal,
|
|
||||||
Optional,
|
|
||||||
Self,
|
|
||||||
Sequence,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ....version import __version__ as default_version
|
from ....version import __version__ as default_version
|
||||||
from ...mtsender import Connector, Sender
|
from ...mtsender import Connector, Sender
|
||||||
|
@ -215,7 +201,7 @@ class Client:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
session: Optional[Union[str, Path, Storage]],
|
session: Optional[str | Path | Storage],
|
||||||
api_id: int,
|
api_id: int,
|
||||||
api_hash: Optional[str] = None,
|
api_hash: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
|
@ -253,9 +239,9 @@ class Client:
|
||||||
lang_code=lang_code or "en",
|
lang_code=lang_code or "en",
|
||||||
catch_up=catch_up or False,
|
catch_up=catch_up or False,
|
||||||
datacenter=datacenter,
|
datacenter=datacenter,
|
||||||
flood_sleep_threshold=60
|
flood_sleep_threshold=(
|
||||||
if flood_sleep_threshold is None
|
60 if flood_sleep_threshold is None else flood_sleep_threshold
|
||||||
else flood_sleep_threshold,
|
),
|
||||||
update_queue_limit=update_queue_limit,
|
update_queue_limit=update_queue_limit,
|
||||||
base_logger=base_logger,
|
base_logger=base_logger,
|
||||||
connector=connector or (lambda ip, port: asyncio.open_connection(ip, port)),
|
connector=connector or (lambda ip, port: asyncio.open_connection(ip, port)),
|
||||||
|
@ -267,11 +253,11 @@ class Client:
|
||||||
self._chat_hashes = ChatHashCache(None)
|
self._chat_hashes = ChatHashCache(None)
|
||||||
self._last_update_limit_warn: Optional[float] = None
|
self._last_update_limit_warn: Optional[float] = None
|
||||||
self._updates: asyncio.Queue[
|
self._updates: asyncio.Queue[
|
||||||
Tuple[abcs.Update, Dict[int, Chat]]
|
tuple[abcs.Update, dict[int, Chat]]
|
||||||
] = asyncio.Queue(maxsize=self._config.update_queue_limit or 0)
|
] = asyncio.Queue(maxsize=self._config.update_queue_limit or 0)
|
||||||
self._dispatcher: Optional[asyncio.Task[None]] = None
|
self._dispatcher: Optional[asyncio.Task[None]] = None
|
||||||
self._handlers: Dict[
|
self._handlers: dict[
|
||||||
Type[Event], List[Tuple[Callable[[Any], Awaitable[Any]], Optional[Filter]]]
|
Type[Event], list[tuple[Callable[[Any], Awaitable[Any]], Optional[Filter]]]
|
||||||
] = {}
|
] = {}
|
||||||
self._check_all_handlers = check_all_handlers
|
self._check_all_handlers = check_all_handlers
|
||||||
|
|
||||||
|
@ -356,9 +342,7 @@ class Client:
|
||||||
"""
|
"""
|
||||||
return await bot_sign_in(self, token)
|
return await bot_sign_in(self, token)
|
||||||
|
|
||||||
async def check_password(
|
async def check_password(self, token: PasswordToken, password: str | bytes) -> User:
|
||||||
self, token: PasswordToken, password: Union[str, bytes]
|
|
||||||
) -> User:
|
|
||||||
"""
|
"""
|
||||||
Check the two-factor-authentication (2FA) password.
|
Check the two-factor-authentication (2FA) password.
|
||||||
If it is correct, completes the login.
|
If it is correct, completes the login.
|
||||||
|
@ -428,7 +412,7 @@ class Client:
|
||||||
await delete_dialog(self, chat)
|
await delete_dialog(self, chat)
|
||||||
|
|
||||||
async def delete_messages(
|
async def delete_messages(
|
||||||
self, chat: ChatLike, message_ids: List[int], *, revoke: bool = True
|
self, chat: ChatLike, message_ids: list[int], *, revoke: bool = True
|
||||||
) -> int:
|
) -> int:
|
||||||
"""
|
"""
|
||||||
Delete messages.
|
Delete messages.
|
||||||
|
@ -484,7 +468,7 @@ class Client:
|
||||||
"""
|
"""
|
||||||
await disconnect(self)
|
await disconnect(self)
|
||||||
|
|
||||||
async def download(self, media: File, file: Union[str, Path, OutFileLike]) -> None:
|
async def download(self, media: File, file: str | Path | OutFileLike) -> None:
|
||||||
"""
|
"""
|
||||||
Download a file.
|
Download a file.
|
||||||
|
|
||||||
|
@ -585,7 +569,7 @@ class Client:
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Edit a message.
|
Edit a message.
|
||||||
|
@ -633,8 +617,8 @@ class Client:
|
||||||
)
|
)
|
||||||
|
|
||||||
async def forward_messages(
|
async def forward_messages(
|
||||||
self, target: ChatLike, message_ids: List[int], source: ChatLike
|
self, target: ChatLike, message_ids: list[int], source: ChatLike
|
||||||
) -> List[Message]:
|
) -> list[Message]:
|
||||||
"""
|
"""
|
||||||
Forward messages from one :term:`chat` to another.
|
Forward messages from one :term:`chat` to another.
|
||||||
|
|
||||||
|
@ -691,8 +675,8 @@ class Client:
|
||||||
return get_admin_log(self, chat)
|
return get_admin_log(self, chat)
|
||||||
|
|
||||||
async def get_chats(
|
async def get_chats(
|
||||||
self, chats: Union[List[ChatLike], Tuple[ChatLike, ...]]
|
self, chats: list[ChatLike] | tuple[ChatLike, ...]
|
||||||
) -> List[Chat]:
|
) -> list[Chat]:
|
||||||
"""
|
"""
|
||||||
Get the latest basic information about the given chats.
|
Get the latest basic information about the given chats.
|
||||||
|
|
||||||
|
@ -907,7 +891,7 @@ class Client:
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_messages_with_ids(
|
def get_messages_with_ids(
|
||||||
self, chat: ChatLike, message_ids: List[int]
|
self, chat: ChatLike, message_ids: list[int]
|
||||||
) -> AsyncList[Message]:
|
) -> AsyncList[Message]:
|
||||||
"""
|
"""
|
||||||
Get the full message objects from the corresponding message identifiers.
|
Get the full message objects from the corresponding message identifiers.
|
||||||
|
@ -1160,7 +1144,7 @@ class Client:
|
||||||
return prepare_album(self)
|
return prepare_album(self)
|
||||||
|
|
||||||
async def read_message(
|
async def read_message(
|
||||||
self, chat: ChatLike, message_id: Union[int, Literal["all"]]
|
self, chat: ChatLike, message_id: int | Literal["all"]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Mark messages as read.
|
Mark messages as read.
|
||||||
|
@ -1361,7 +1345,7 @@ class Client:
|
||||||
async def send_audio(
|
async def send_audio(
|
||||||
self,
|
self,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
mime_type: Optional[str] = None,
|
mime_type: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
|
@ -1374,7 +1358,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send an audio file.
|
Send an audio file.
|
||||||
|
@ -1424,7 +1408,7 @@ class Client:
|
||||||
async def send_file(
|
async def send_file(
|
||||||
self,
|
self,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -1446,7 +1430,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send any type of file with any amount of attributes.
|
Send any type of file with any amount of attributes.
|
||||||
|
@ -1606,13 +1590,13 @@ class Client:
|
||||||
async def send_message(
|
async def send_message(
|
||||||
self,
|
self,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
text: Optional[Union[str, Message]] = None,
|
text: Optional[str | Message] = None,
|
||||||
*,
|
*,
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a message.
|
Send a message.
|
||||||
|
@ -1653,7 +1637,7 @@ class Client:
|
||||||
async def send_photo(
|
async def send_photo(
|
||||||
self,
|
self,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -1665,7 +1649,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a photo file.
|
Send a photo file.
|
||||||
|
@ -1717,7 +1701,7 @@ class Client:
|
||||||
async def send_video(
|
async def send_video(
|
||||||
self,
|
self,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -1732,7 +1716,7 @@ class Client:
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Send a video file.
|
Send a video file.
|
||||||
|
@ -1947,7 +1931,7 @@ class Client:
|
||||||
"""
|
"""
|
||||||
await set_participant_restrictions(self, chat, user, restrictions, until=until)
|
await set_participant_restrictions(self, chat, user, restrictions, until=until)
|
||||||
|
|
||||||
async def sign_in(self, token: LoginToken, code: str) -> Union[User, PasswordToken]:
|
async def sign_in(self, token: LoginToken, code: str) -> User | PasswordToken:
|
||||||
"""
|
"""
|
||||||
Sign in to a user account.
|
Sign in to a user account.
|
||||||
|
|
||||||
|
@ -1993,7 +1977,7 @@ class Client:
|
||||||
await sign_out(self)
|
await sign_out(self)
|
||||||
|
|
||||||
async def unpin_message(
|
async def unpin_message(
|
||||||
self, chat: ChatLike, message_id: Union[int, Literal["all"]]
|
self, chat: ChatLike, message_id: int | Literal["all"]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Unpin one or all messages from the top.
|
Unpin one or all messages from the top.
|
||||||
|
@ -2041,8 +2025,8 @@ class Client:
|
||||||
return input_to_peer(self, input)
|
return input_to_peer(self, input)
|
||||||
|
|
||||||
async def _upload(
|
async def _upload(
|
||||||
self, fd: Union[str, Path, InFileLike], size: Optional[int], name: Optional[str]
|
self, fd: str | Path | InFileLike, size: Optional[int], name: Optional[str]
|
||||||
) -> Tuple[abcs.InputFile, str]:
|
) -> tuple[abcs.InputFile, str]:
|
||||||
return await upload(self, fd, size, name)
|
return await upload(self, fd, size, name)
|
||||||
|
|
||||||
async def __call__(self, request: Request[Return]) -> Return:
|
async def __call__(self, request: Request[Return]) -> Return:
|
||||||
|
|
|
@ -4,7 +4,7 @@ import hashlib
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from inspect import isawaitable
|
from inspect import isawaitable
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from ..types import (
|
from ..types import (
|
||||||
|
@ -45,7 +45,7 @@ def prepare_album(self: Client) -> AlbumBuilder:
|
||||||
async def send_photo(
|
async def send_photo(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -57,7 +57,7 @@ async def send_photo(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -65,9 +65,11 @@ async def send_photo(
|
||||||
file,
|
file,
|
||||||
size=size,
|
size=size,
|
||||||
name=name,
|
name=name,
|
||||||
mime_type="image/jpeg" # specific mime doesn't matter, only that it's image
|
mime_type=(
|
||||||
if compress
|
"image/jpeg" # specific mime doesn't matter, only that it's image
|
||||||
else mime_type,
|
if compress
|
||||||
|
else mime_type
|
||||||
|
),
|
||||||
compress=compress,
|
compress=compress,
|
||||||
width=width,
|
width=width,
|
||||||
height=height,
|
height=height,
|
||||||
|
@ -82,7 +84,7 @@ async def send_photo(
|
||||||
async def send_audio(
|
async def send_audio(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
mime_type: Optional[str] = None,
|
mime_type: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
|
@ -95,7 +97,7 @@ async def send_audio(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -119,7 +121,7 @@ async def send_audio(
|
||||||
async def send_video(
|
async def send_video(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -134,7 +136,7 @@ async def send_video(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -160,7 +162,7 @@ async def send_video(
|
||||||
async def send_file(
|
async def send_file(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
file: Union[str, Path, InFileLike, File],
|
file: str | Path | InFileLike | File,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -182,7 +184,7 @@ async def send_file(
|
||||||
caption_markdown: Optional[str] = None,
|
caption_markdown: Optional[str] = None,
|
||||||
caption_html: Optional[str] = None,
|
caption_html: Optional[str] = None,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
message, entities = parse_message(
|
message, entities = parse_message(
|
||||||
text=caption, markdown=caption_markdown, html=caption_html, allow_empty=True
|
text=caption, markdown=caption_markdown, html=caption_html, allow_empty=True
|
||||||
|
@ -237,7 +239,7 @@ async def send_file(
|
||||||
|
|
||||||
# Only bother to calculate attributes when sending documents.
|
# Only bother to calculate attributes when sending documents.
|
||||||
else:
|
else:
|
||||||
attributes: List[abcs.DocumentAttribute] = []
|
attributes: list[abcs.DocumentAttribute] = []
|
||||||
attributes.append(types.DocumentAttributeFilename(file_name=name))
|
attributes.append(types.DocumentAttributeFilename(file_name=name))
|
||||||
|
|
||||||
if mime_type.startswith("image/"):
|
if mime_type.startswith("image/"):
|
||||||
|
@ -290,9 +292,9 @@ async def do_send_file(
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
input_media: abcs.InputMedia,
|
input_media: abcs.InputMedia,
|
||||||
message: str,
|
message: str,
|
||||||
entities: Optional[List[abcs.MessageEntity]],
|
entities: Optional[list[abcs.MessageEntity]],
|
||||||
reply_to: Optional[int],
|
reply_to: Optional[int],
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]],
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]],
|
||||||
) -> Message:
|
) -> Message:
|
||||||
peer = (await client._resolve_to_packed(chat))._to_input_peer()
|
peer = (await client._resolve_to_packed(chat))._to_input_peer()
|
||||||
random_id = generate_random_id()
|
random_id = generate_random_id()
|
||||||
|
@ -305,11 +307,11 @@ async def do_send_file(
|
||||||
noforwards=False,
|
noforwards=False,
|
||||||
update_stickersets_order=False,
|
update_stickersets_order=False,
|
||||||
peer=peer,
|
peer=peer,
|
||||||
reply_to=types.InputReplyToMessage(
|
reply_to=(
|
||||||
reply_to_msg_id=reply_to, top_msg_id=None
|
types.InputReplyToMessage(reply_to_msg_id=reply_to, top_msg_id=None)
|
||||||
)
|
if reply_to
|
||||||
if reply_to
|
else None
|
||||||
else None,
|
),
|
||||||
media=input_media,
|
media=input_media,
|
||||||
message=message,
|
message=message,
|
||||||
random_id=random_id,
|
random_id=random_id,
|
||||||
|
@ -325,10 +327,10 @@ async def do_send_file(
|
||||||
|
|
||||||
async def upload(
|
async def upload(
|
||||||
client: Client,
|
client: Client,
|
||||||
file: Union[str, Path, InFileLike],
|
file: str | Path | InFileLike,
|
||||||
size: Optional[int],
|
size: Optional[int],
|
||||||
name: Optional[str],
|
name: Optional[str],
|
||||||
) -> Tuple[abcs.InputFile, str]:
|
) -> tuple[abcs.InputFile, str]:
|
||||||
# Paths are opened and closed by us. Anything else is *only* read, not closed.
|
# Paths are opened and closed by us. Anything else is *only* read, not closed.
|
||||||
if isinstance(file, (str, Path)):
|
if isinstance(file, (str, Path)):
|
||||||
path = Path(file) if isinstance(file, str) else file
|
path = Path(file) if isinstance(file, str) else file
|
||||||
|
@ -360,7 +362,7 @@ async def do_upload(
|
||||||
part = 0
|
part = 0
|
||||||
total_parts = (size + MAX_CHUNK_SIZE - 1) // MAX_CHUNK_SIZE
|
total_parts = (size + MAX_CHUNK_SIZE - 1) // MAX_CHUNK_SIZE
|
||||||
buffer = bytearray()
|
buffer = bytearray()
|
||||||
to_store: Union[bytearray, bytes] = b""
|
to_store: bytearray | bytes = b""
|
||||||
hash_md5 = hashlib.md5()
|
hash_md5 = hashlib.md5()
|
||||||
is_big = size > BIG_FILE_SIZE
|
is_big = size > BIG_FILE_SIZE
|
||||||
|
|
||||||
|
@ -454,9 +456,7 @@ def get_file_bytes(self: Client, media: File) -> AsyncList[bytes]:
|
||||||
return FileBytesList(self, media)
|
return FileBytesList(self, media)
|
||||||
|
|
||||||
|
|
||||||
async def download(
|
async def download(self: Client, media: File, file: str | Path | OutFileLike) -> None:
|
||||||
self: Client, media: File, file: Union[str, Path, OutFileLike]
|
|
||||||
) -> None:
|
|
||||||
fd = OutWrapper(file)
|
fd = OutWrapper(file)
|
||||||
try:
|
try:
|
||||||
async for chunk in get_file_bytes(self, media):
|
async for chunk in get_file_bytes(self, media):
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Self, Union
|
from typing import TYPE_CHECKING, Literal, Optional, Self
|
||||||
|
|
||||||
from ...session import PackedChat
|
from ...session import PackedChat
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
|
@ -17,13 +17,13 @@ if TYPE_CHECKING:
|
||||||
async def send_message(
|
async def send_message(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
text: Optional[Union[str, Message]] = None,
|
text: Optional[str | Message] = None,
|
||||||
*,
|
*,
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
reply_to: Optional[int] = None,
|
reply_to: Optional[int] = None,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
packed = await self._resolve_to_packed(chat)
|
packed = await self._resolve_to_packed(chat)
|
||||||
peer = packed._to_input_peer()
|
peer = packed._to_input_peer()
|
||||||
|
@ -121,7 +121,7 @@ async def edit_message(
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[Union[List[btns.Button], List[List[btns.Button]]]] = None,
|
buttons: Optional[list[btns.Button] | list[list[btns.Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
||||||
message, entities = parse_message(
|
message, entities = parse_message(
|
||||||
|
@ -145,7 +145,7 @@ async def edit_message(
|
||||||
|
|
||||||
|
|
||||||
async def delete_messages(
|
async def delete_messages(
|
||||||
self: Client, chat: ChatLike, message_ids: List[int], *, revoke: bool = True
|
self: Client, chat: ChatLike, message_ids: list[int], *, revoke: bool = True
|
||||||
) -> int:
|
) -> int:
|
||||||
packed_chat = await self._resolve_to_packed(chat)
|
packed_chat = await self._resolve_to_packed(chat)
|
||||||
if packed_chat.is_channel():
|
if packed_chat.is_channel():
|
||||||
|
@ -163,8 +163,8 @@ async def delete_messages(
|
||||||
|
|
||||||
|
|
||||||
async def forward_messages(
|
async def forward_messages(
|
||||||
self: Client, target: ChatLike, message_ids: List[int], source: ChatLike
|
self: Client, target: ChatLike, message_ids: list[int], source: ChatLike
|
||||||
) -> List[Message]:
|
) -> list[Message]:
|
||||||
to_peer = (await self._resolve_to_packed(target))._to_input_peer()
|
to_peer = (await self._resolve_to_packed(target))._to_input_peer()
|
||||||
from_peer = (await self._resolve_to_packed(source))._to_input_peer()
|
from_peer = (await self._resolve_to_packed(source))._to_input_peer()
|
||||||
random_ids = [generate_random_id() for _ in message_ids]
|
random_ids = [generate_random_id() for _ in message_ids]
|
||||||
|
@ -198,7 +198,7 @@ class MessageList(AsyncList[Message]):
|
||||||
|
|
||||||
def _extend_buffer(
|
def _extend_buffer(
|
||||||
self, client: Client, messages: abcs.messages.Messages
|
self, client: Client, messages: abcs.messages.Messages
|
||||||
) -> Dict[int, Chat]:
|
) -> dict[int, Chat]:
|
||||||
if isinstance(messages, types.messages.MessagesNotModified):
|
if isinstance(messages, types.messages.MessagesNotModified):
|
||||||
self._total = messages.count
|
self._total = messages.count
|
||||||
return {}
|
return {}
|
||||||
|
@ -224,7 +224,7 @@ class MessageList(AsyncList[Message]):
|
||||||
|
|
||||||
def _last_non_empty_message(
|
def _last_non_empty_message(
|
||||||
self,
|
self,
|
||||||
) -> Union[types.Message, types.MessageService, types.MessageEmpty]:
|
) -> types.Message | types.MessageService | types.MessageEmpty:
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
m._raw
|
m._raw
|
||||||
|
@ -318,13 +318,13 @@ class CherryPickedList(MessageList):
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
ids: List[int],
|
ids: list[int],
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._client = client
|
self._client = client
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
self._packed: Optional[PackedChat] = None
|
self._packed: Optional[PackedChat] = None
|
||||||
self._ids: List[abcs.InputMessage] = [types.InputMessageId(id=id) for id in ids]
|
self._ids: list[abcs.InputMessage] = [types.InputMessageId(id=id) for id in ids]
|
||||||
|
|
||||||
async def _fetch_next(self) -> None:
|
async def _fetch_next(self) -> None:
|
||||||
if not self._ids:
|
if not self._ids:
|
||||||
|
@ -350,7 +350,7 @@ class CherryPickedList(MessageList):
|
||||||
def get_messages_with_ids(
|
def get_messages_with_ids(
|
||||||
self: Client,
|
self: Client,
|
||||||
chat: ChatLike,
|
chat: ChatLike,
|
||||||
message_ids: List[int],
|
message_ids: list[int],
|
||||||
) -> AsyncList[Message]:
|
) -> AsyncList[Message]:
|
||||||
return CherryPickedList(self, chat, message_ids)
|
return CherryPickedList(self, chat, message_ids)
|
||||||
|
|
||||||
|
@ -509,7 +509,7 @@ async def pin_message(self: Client, chat: ChatLike, message_id: int) -> Message:
|
||||||
|
|
||||||
|
|
||||||
async def unpin_message(
|
async def unpin_message(
|
||||||
self: Client, chat: ChatLike, message_id: Union[int, Literal["all"]]
|
self: Client, chat: ChatLike, message_id: int | Literal["all"]
|
||||||
) -> None:
|
) -> None:
|
||||||
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
||||||
if message_id == "all":
|
if message_id == "all":
|
||||||
|
@ -528,7 +528,7 @@ async def unpin_message(
|
||||||
|
|
||||||
|
|
||||||
async def read_message(
|
async def read_message(
|
||||||
self: Client, chat: ChatLike, message_id: Union[int, Literal["all"]]
|
self: Client, chat: ChatLike, message_id: int | Literal["all"]
|
||||||
) -> None:
|
) -> None:
|
||||||
packed = await self._resolve_to_packed(chat)
|
packed = await self._resolve_to_packed(chat)
|
||||||
if message_id == "all":
|
if message_id == "all":
|
||||||
|
@ -555,8 +555,8 @@ class MessageMap:
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
peer: Optional[abcs.InputPeer],
|
peer: Optional[abcs.InputPeer],
|
||||||
random_id_to_id: Dict[int, int],
|
random_id_to_id: dict[int, int],
|
||||||
id_to_message: Dict[int, Message],
|
id_to_message: dict[int, Message],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._client = client
|
self._client = client
|
||||||
self._peer = peer
|
self._peer = peer
|
||||||
|
@ -599,8 +599,8 @@ def build_message_map(
|
||||||
else:
|
else:
|
||||||
return MessageMap(client, peer, {}, {})
|
return MessageMap(client, peer, {}, {})
|
||||||
|
|
||||||
random_id_to_id: Dict[int, int] = {}
|
random_id_to_id: dict[int, int] = {}
|
||||||
id_to_message: Dict[int, Message] = {}
|
id_to_message: dict[int, Message] = {}
|
||||||
for update in updates:
|
for update in updates:
|
||||||
if isinstance(update, types.UpdateMessageId):
|
if isinstance(update, types.UpdateMessageId):
|
||||||
random_id_to_id[update.random_id] = update.id
|
random_id_to_id[update.random_id] = update.id
|
||||||
|
|
|
@ -6,7 +6,7 @@ import logging
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, TypeVar
|
from typing import TYPE_CHECKING, Optional, TypeVar
|
||||||
|
|
||||||
from ....version import __version__
|
from ....version import __version__
|
||||||
from ...mtproto import BadStatus, Full, RpcError
|
from ...mtproto import BadStatus, Full, RpcError
|
||||||
|
@ -75,10 +75,10 @@ def as_concrete_dc_option(opt: abcs.DcOption) -> types.DcOption:
|
||||||
|
|
||||||
async def connect_sender(
|
async def connect_sender(
|
||||||
config: Config,
|
config: Config,
|
||||||
known_dcs: List[DataCenter],
|
known_dcs: list[DataCenter],
|
||||||
dc: DataCenter,
|
dc: DataCenter,
|
||||||
force_auth_gen: bool = False,
|
force_auth_gen: bool = False,
|
||||||
) -> Tuple[Sender, List[DataCenter]]:
|
) -> tuple[Sender, list[DataCenter]]:
|
||||||
# Only the ID of the input DC may be known.
|
# Only the ID of the input DC may be known.
|
||||||
# Find the corresponding address and authentication key if needed.
|
# Find the corresponding address and authentication key if needed.
|
||||||
addr = dc.ipv4_addr or next(
|
addr = dc.ipv4_addr or next(
|
||||||
|
@ -143,7 +143,7 @@ async def connect_sender(
|
||||||
]
|
]
|
||||||
dc_options.sort(key=lambda opt: opt.static, reverse=True)
|
dc_options.sort(key=lambda opt: opt.static, reverse=True)
|
||||||
|
|
||||||
latest_dcs: Dict[int, DataCenter] = {}
|
latest_dcs: dict[int, DataCenter] = {}
|
||||||
for opt in dc_options:
|
for opt in dc_options:
|
||||||
dc = latest_dcs.setdefault(opt.id, DataCenter(id=opt.id))
|
dc = latest_dcs.setdefault(opt.id, DataCenter(id=opt.id))
|
||||||
if opt.ipv6:
|
if opt.ipv6:
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import (
|
from collections.abc import Awaitable, Callable
|
||||||
TYPE_CHECKING,
|
from typing import TYPE_CHECKING, Any, Optional, Sequence, Type, TypeVar
|
||||||
Any,
|
|
||||||
Awaitable,
|
|
||||||
Callable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Sequence,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ...session import Gap
|
from ...session import Gap
|
||||||
from ...tl import abcs
|
from ...tl import abcs
|
||||||
|
@ -81,7 +72,7 @@ def set_handler_filter(
|
||||||
handlers[i] = (h, filter)
|
handlers[i] = (h, filter)
|
||||||
|
|
||||||
|
|
||||||
def process_socket_updates(client: Client, all_updates: List[abcs.Updates]) -> None:
|
def process_socket_updates(client: Client, all_updates: list[abcs.Updates]) -> None:
|
||||||
if not all_updates:
|
if not all_updates:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -103,7 +94,7 @@ def process_socket_updates(client: Client, all_updates: List[abcs.Updates]) -> N
|
||||||
|
|
||||||
def extend_update_queue(
|
def extend_update_queue(
|
||||||
client: Client,
|
client: Client,
|
||||||
updates: List[abcs.Update],
|
updates: list[abcs.Update],
|
||||||
users: Sequence[abcs.User],
|
users: Sequence[abcs.User],
|
||||||
chats: Sequence[abcs.Chat],
|
chats: Sequence[abcs.Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ...mtproto import RpcError
|
from ...mtproto import RpcError
|
||||||
from ...session import PackedChat, PackedType
|
from ...session import PackedChat, PackedType
|
||||||
|
@ -75,12 +75,12 @@ async def resolve_username(self: Client, username: str) -> Chat:
|
||||||
|
|
||||||
|
|
||||||
async def get_chats(
|
async def get_chats(
|
||||||
self: Client, chats: Union[List[ChatLike], Tuple[ChatLike, ...]]
|
self: Client, chats: list[ChatLike] | tuple[ChatLike, ...]
|
||||||
) -> List[Chat]:
|
) -> list[Chat]:
|
||||||
packed_chats: List[PackedChat] = []
|
packed_chats: list[PackedChat] = []
|
||||||
input_users: List[types.InputUser] = []
|
input_users: list[types.InputUser] = []
|
||||||
input_chats: List[int] = []
|
input_chats: list[int] = []
|
||||||
input_channels: List[types.InputChannel] = []
|
input_channels: list[types.InputChannel] = []
|
||||||
|
|
||||||
for chat in chats:
|
for chat in chats:
|
||||||
packed = await resolve_to_packed(self, chat)
|
packed = await resolve_to_packed(self, chat)
|
||||||
|
@ -121,7 +121,7 @@ async def get_chats(
|
||||||
|
|
||||||
|
|
||||||
async def resolve_to_packed(
|
async def resolve_to_packed(
|
||||||
client: Client, chat: Union[ChatLike, abcs.InputPeer, abcs.Peer]
|
client: Client, chat: ChatLike | abcs.InputPeer | abcs.Peer
|
||||||
) -> PackedChat:
|
) -> PackedChat:
|
||||||
if isinstance(chat, PackedChat):
|
if isinstance(chat, PackedChat):
|
||||||
return chat
|
return chat
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Tuple, Type
|
from typing import Type
|
||||||
|
|
||||||
from ..mtproto import RpcError
|
from ..mtproto import RpcError
|
||||||
|
|
||||||
|
@ -20,14 +20,14 @@ def pretty_name(name: str) -> str:
|
||||||
return "".join(map(str.title, name.split("_")))
|
return "".join(map(str.title, name.split("_")))
|
||||||
|
|
||||||
|
|
||||||
def from_code(code: int, *, _cache: Dict[int, Type[RpcError]] = {}) -> Type[RpcError]:
|
def from_code(code: int, *, _cache: dict[int, Type[RpcError]] = {}) -> Type[RpcError]:
|
||||||
code = canonicalize_code(code)
|
code = canonicalize_code(code)
|
||||||
if code not in _cache:
|
if code not in _cache:
|
||||||
_cache[code] = type(f"Code{code}", (RpcError,), {})
|
_cache[code] = type(f"Code{code}", (RpcError,), {})
|
||||||
return _cache[code]
|
return _cache[code]
|
||||||
|
|
||||||
|
|
||||||
def from_name(name: str, *, _cache: Dict[str, Type[RpcError]] = {}) -> Type[RpcError]:
|
def from_name(name: str, *, _cache: dict[str, Type[RpcError]] = {}) -> Type[RpcError]:
|
||||||
name = canonicalize_name(name)
|
name = canonicalize_name(name)
|
||||||
if name not in _cache:
|
if name not in _cache:
|
||||||
_cache[name] = type(pretty_name(name), (RpcError,), {})
|
_cache[name] = type(pretty_name(name), (RpcError,), {})
|
||||||
|
@ -35,7 +35,7 @@ def from_name(name: str, *, _cache: Dict[str, Type[RpcError]] = {}) -> Type[RpcE
|
||||||
|
|
||||||
|
|
||||||
def adapt_rpc(
|
def adapt_rpc(
|
||||||
error: RpcError, *, _cache: Dict[Tuple[int, str], Type[RpcError]] = {}
|
error: RpcError, *, _cache: dict[tuple[int, str], Type[RpcError]] = {}
|
||||||
) -> RpcError:
|
) -> RpcError:
|
||||||
code = canonicalize_code(error.code)
|
code = canonicalize_code(error.code)
|
||||||
name = canonicalize_name(error.name)
|
name = canonicalize_name(error.name)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self
|
from typing import TYPE_CHECKING, Optional, Self
|
||||||
|
|
||||||
from ...tl import abcs
|
from ...tl import abcs
|
||||||
from ..types import Chat, NoPublicConstructor
|
from ..types import Chat, NoPublicConstructor
|
||||||
|
@ -25,7 +25,7 @@ class Event(metaclass=NoPublicConstructor):
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import abc
|
import abc
|
||||||
import typing
|
import typing
|
||||||
from typing import Callable, Tuple, TypeAlias
|
from collections.abc import Callable
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
from ..event import Event
|
from ..event import Event
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ class Any(Combinable):
|
||||||
self._filters = (filter1, filter2, *filters)
|
self._filters = (filter1, filter2, *filters)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def filters(self) -> Tuple[Filter, ...]:
|
def filters(self) -> tuple[Filter, ...]:
|
||||||
"""
|
"""
|
||||||
The filters being checked, in order.
|
The filters being checked, in order.
|
||||||
"""
|
"""
|
||||||
|
@ -114,7 +115,7 @@ class All(Combinable):
|
||||||
self._filters = (filter1, filter2, *filters)
|
self._filters = (filter1, filter2, *filters)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def filters(self) -> Tuple[Filter, ...]:
|
def filters(self) -> tuple[Filter, ...]:
|
||||||
"""
|
"""
|
||||||
The filters being checked, in order.
|
The filters being checked, in order.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Sequence, Set, Type, Union
|
from typing import Sequence, Type
|
||||||
|
|
||||||
from ...types import Channel, Group, User
|
from ...types import Channel, Group, User
|
||||||
from ..event import Event
|
from ..event import Event
|
||||||
|
@ -18,7 +18,7 @@ class Chats(Combinable):
|
||||||
self._chats = set(chat_ids)
|
self._chats = set(chat_ids)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def chat_ids(self) -> Set[int]:
|
def chat_ids(self) -> set[int]:
|
||||||
"""
|
"""
|
||||||
A copy of the set of chat identifiers this filter is filtering on.
|
A copy of the set of chat identifiers this filter is filtering on.
|
||||||
"""
|
"""
|
||||||
|
@ -43,7 +43,7 @@ class Senders(Combinable):
|
||||||
self._senders = set(sender_ids)
|
self._senders = set(sender_ids)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sender_ids(self) -> Set[int]:
|
def sender_ids(self) -> set[int]:
|
||||||
"""
|
"""
|
||||||
A copy of the set of sender identifiers this filter is filtering on.
|
A copy of the set of sender identifiers this filter is filtering on.
|
||||||
"""
|
"""
|
||||||
|
@ -79,12 +79,12 @@ class ChatType(Combinable):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
type: Type[Union[User, Group, Channel]],
|
type: Type[User | Group | Channel],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._type = type
|
self._type = type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> Type[Union[User, Group, Channel]]:
|
def type(self) -> Type[User | Group | Channel]:
|
||||||
"""
|
"""
|
||||||
The chat type this filter is filtering on.
|
The chat type this filter is filtering on.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Literal, Optional, Tuple, Union
|
from typing import TYPE_CHECKING, Literal, Optional
|
||||||
|
|
||||||
from ..event import Event
|
from ..event import Event
|
||||||
from .combinators import Combinable
|
from .combinators import Combinable
|
||||||
|
@ -28,7 +28,7 @@ class Text(Combinable):
|
||||||
|
|
||||||
__slots__ = ("_pattern",)
|
__slots__ = ("_pattern",)
|
||||||
|
|
||||||
def __init__(self, regexp: Union[str, re.Pattern[str]]) -> None:
|
def __init__(self, regexp: str | re.Pattern[str]) -> None:
|
||||||
self._pattern = re.compile(regexp) if isinstance(regexp, str) else regexp
|
self._pattern = re.compile(regexp) if isinstance(regexp, str) else regexp
|
||||||
|
|
||||||
def __call__(self, event: Event) -> bool:
|
def __call__(self, event: Event) -> bool:
|
||||||
|
@ -164,7 +164,7 @@ class Media(Combinable):
|
||||||
@property
|
@property
|
||||||
def types(
|
def types(
|
||||||
self,
|
self,
|
||||||
) -> Tuple[Literal["photo", "audio", "video"], ...]:
|
) -> tuple[Literal["photo", "audio", "video"], ...]:
|
||||||
"""
|
"""
|
||||||
The media types being checked.
|
The media types being checked.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self, Sequence, Union
|
from typing import TYPE_CHECKING, Optional, Self, Sequence
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from ..types import Chat, Message, expand_peer, peer_id
|
from ..types import Chat, Message, expand_peer, peer_id
|
||||||
|
@ -25,7 +25,7 @@ class NewMessage(Event, Message):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(update, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
if isinstance(update, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
||||||
if isinstance(update.message, types.Message):
|
if isinstance(update.message, types.Message):
|
||||||
|
@ -47,7 +47,7 @@ class MessageEdited(Event, Message):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
update, (types.UpdateEditMessage, types.UpdateEditChannelMessage)
|
update, (types.UpdateEditMessage, types.UpdateEditChannelMessage)
|
||||||
|
@ -75,7 +75,7 @@ class MessageDeleted(Event):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(update, types.UpdateDeleteMessages):
|
if isinstance(update, types.UpdateDeleteMessages):
|
||||||
return cls._create(update.messages, None)
|
return cls._create(update.messages, None)
|
||||||
|
@ -109,13 +109,13 @@ class MessageRead(Event):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
update: Union[
|
update: (
|
||||||
types.UpdateReadHistoryInbox,
|
types.UpdateReadHistoryInbox
|
||||||
types.UpdateReadHistoryOutbox,
|
| types.UpdateReadHistoryOutbox
|
||||||
types.UpdateReadChannelInbox,
|
| types.UpdateReadChannelInbox
|
||||||
types.UpdateReadChannelOutbox,
|
| types.UpdateReadChannelOutbox
|
||||||
],
|
),
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._client = client
|
self._client = client
|
||||||
self._raw = update
|
self._raw = update
|
||||||
|
@ -123,7 +123,7 @@ class MessageRead(Event):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
update,
|
update,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self
|
from typing import TYPE_CHECKING, Optional, Self
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from ..client.messages import CherryPickedList
|
from ..client.messages import CherryPickedList
|
||||||
|
@ -23,7 +23,7 @@ class ButtonCallback(Event):
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
update: types.UpdateBotCallbackQuery,
|
update: types.UpdateBotCallbackQuery,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
):
|
):
|
||||||
self._client = client
|
self._client = client
|
||||||
self._raw = update
|
self._raw = update
|
||||||
|
@ -31,7 +31,7 @@ class ButtonCallback(Event):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(update, types.UpdateBotCallbackQuery) and update.data is not None:
|
if isinstance(update, types.UpdateBotCallbackQuery) and update.data is not None:
|
||||||
return cls._create(client, update, chat_map)
|
return cls._create(client, update, chat_map)
|
||||||
|
@ -105,7 +105,7 @@ class InlineQuery(Event):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(
|
def _try_from_update(
|
||||||
cls, client: Client, update: abcs.Update, chat_map: Dict[int, Chat]
|
cls, client: Client, update: abcs.Update, chat_map: dict[int, Chat]
|
||||||
) -> Optional[Self]:
|
) -> Optional[Self]:
|
||||||
if isinstance(update, types.UpdateBotInlineQuery):
|
if isinstance(update, types.UpdateBotInlineQuery):
|
||||||
return cls._create(update)
|
return cls._create(update)
|
||||||
|
|
|
@ -1,19 +1,8 @@
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from collections.abc import Callable, Iterable
|
||||||
from html import escape
|
from html import escape
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
from typing import (
|
from typing import Any, Optional, Type, cast
|
||||||
Any,
|
|
||||||
Callable,
|
|
||||||
Deque,
|
|
||||||
Dict,
|
|
||||||
Iterable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
Union,
|
|
||||||
cast,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ...tl.abcs import MessageEntity
|
from ...tl.abcs import MessageEntity
|
||||||
from ...tl.types import (
|
from ...tl.types import (
|
||||||
|
@ -37,12 +26,12 @@ class HTMLToTelegramParser(HTMLParser):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.text = ""
|
self.text = ""
|
||||||
self.entities: List[MessageEntity] = []
|
self.entities: list[MessageEntity] = []
|
||||||
self._building_entities: Dict[str, MessageEntity] = {}
|
self._building_entities: dict[str, MessageEntity] = {}
|
||||||
self._open_tags: Deque[str] = deque()
|
self._open_tags: deque[str] = deque()
|
||||||
self._open_tags_meta: Deque[Optional[str]] = deque()
|
self._open_tags_meta: deque[Optional[str]] = deque()
|
||||||
|
|
||||||
def handle_starttag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None:
|
def handle_starttag(self, tag: str, attrs: list[tuple[str, Optional[str]]]) -> None:
|
||||||
self._open_tags.appendleft(tag)
|
self._open_tags.appendleft(tag)
|
||||||
self._open_tags_meta.appendleft(None)
|
self._open_tags_meta.appendleft(None)
|
||||||
|
|
||||||
|
@ -128,7 +117,7 @@ class HTMLToTelegramParser(HTMLParser):
|
||||||
self.entities.append(entity)
|
self.entities.append(entity)
|
||||||
|
|
||||||
|
|
||||||
def parse(html: str) -> Tuple[str, List[MessageEntity]]:
|
def parse(html: str) -> tuple[str, list[MessageEntity]]:
|
||||||
"""
|
"""
|
||||||
Parses the given HTML message and returns its stripped representation
|
Parses the given HTML message and returns its stripped representation
|
||||||
plus a list of the MessageEntity's that were found.
|
plus a list of the MessageEntity's that were found.
|
||||||
|
@ -144,8 +133,8 @@ def parse(html: str) -> Tuple[str, List[MessageEntity]]:
|
||||||
return del_surrogate(parser.text), parser.entities
|
return del_surrogate(parser.text), parser.entities
|
||||||
|
|
||||||
|
|
||||||
ENTITY_TO_FORMATTER: Dict[
|
ENTITY_TO_FORMATTER: dict[
|
||||||
Type[MessageEntity], Union[Tuple[str, str], Callable[[Any, str], Tuple[str, str]]]
|
Type[MessageEntity], tuple[str, str] | Callable[[Any, str], tuple[str, str]]
|
||||||
] = {
|
] = {
|
||||||
MessageEntityBold: ("<strong>", "</strong>"),
|
MessageEntityBold: ("<strong>", "</strong>"),
|
||||||
MessageEntityItalic: ("<em>", "</em>"),
|
MessageEntityItalic: ("<em>", "</em>"),
|
||||||
|
@ -183,7 +172,7 @@ def unparse(text: str, entities: Iterable[MessageEntity]) -> str:
|
||||||
return escape(text)
|
return escape(text)
|
||||||
|
|
||||||
text = add_surrogate(text)
|
text = add_surrogate(text)
|
||||||
insert_at: List[Tuple[int, str]] = []
|
insert_at: list[tuple[int, str]] = []
|
||||||
for e in entities:
|
for e in entities:
|
||||||
offset, length = getattr(e, "offset", None), getattr(e, "length", None)
|
offset, length = getattr(e, "offset", None), getattr(e, "length", None)
|
||||||
assert isinstance(offset, int) and isinstance(length, int)
|
assert isinstance(offset, int) and isinstance(length, int)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Iterator, List, Tuple, Type
|
from collections.abc import Iterator
|
||||||
|
from typing import Any, Type
|
||||||
|
|
||||||
import markdown_it
|
import markdown_it
|
||||||
import markdown_it.token
|
import markdown_it.token
|
||||||
|
@ -19,7 +20,7 @@ from ...tl.types import (
|
||||||
from .strings import add_surrogate, del_surrogate, within_surrogate
|
from .strings import add_surrogate, del_surrogate, within_surrogate
|
||||||
|
|
||||||
MARKDOWN = markdown_it.MarkdownIt().enable("strikethrough")
|
MARKDOWN = markdown_it.MarkdownIt().enable("strikethrough")
|
||||||
DELIMITERS: Dict[Type[MessageEntity], Tuple[str, str]] = {
|
DELIMITERS: dict[Type[MessageEntity], tuple[str, str]] = {
|
||||||
MessageEntityBlockquote: ("> ", ""),
|
MessageEntityBlockquote: ("> ", ""),
|
||||||
MessageEntityBold: ("**", "**"),
|
MessageEntityBold: ("**", "**"),
|
||||||
MessageEntityCode: ("`", "`"),
|
MessageEntityCode: ("`", "`"),
|
||||||
|
@ -44,7 +45,7 @@ HTML_TO_TYPE = {
|
||||||
|
|
||||||
|
|
||||||
def expand_inline_and_html(
|
def expand_inline_and_html(
|
||||||
tokens: List[markdown_it.token.Token],
|
tokens: list[markdown_it.token.Token],
|
||||||
) -> Iterator[markdown_it.token.Token]:
|
) -> Iterator[markdown_it.token.Token]:
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if token.type == "inline":
|
if token.type == "inline":
|
||||||
|
@ -63,7 +64,7 @@ def expand_inline_and_html(
|
||||||
yield token
|
yield token
|
||||||
|
|
||||||
|
|
||||||
def parse(message: str) -> Tuple[str, List[MessageEntity]]:
|
def parse(message: str) -> tuple[str, list[MessageEntity]]:
|
||||||
"""
|
"""
|
||||||
Parses the given markdown message and returns its stripped representation
|
Parses the given markdown message and returns its stripped representation
|
||||||
plus a list of the MessageEntity's that were found.
|
plus a list of the MessageEntity's that were found.
|
||||||
|
@ -71,7 +72,7 @@ def parse(message: str) -> Tuple[str, List[MessageEntity]]:
|
||||||
if not message:
|
if not message:
|
||||||
return message, []
|
return message, []
|
||||||
|
|
||||||
entities: List[MessageEntity]
|
entities: list[MessageEntity]
|
||||||
token: markdown_it.token.Token
|
token: markdown_it.token.Token
|
||||||
|
|
||||||
def push(ty: Any, **extra: object) -> None:
|
def push(ty: Any, **extra: object) -> None:
|
||||||
|
@ -145,7 +146,7 @@ def parse(message: str) -> Tuple[str, List[MessageEntity]]:
|
||||||
return del_surrogate(message), entities
|
return del_surrogate(message), entities
|
||||||
|
|
||||||
|
|
||||||
def unparse(text: str, entities: List[MessageEntity]) -> str:
|
def unparse(text: str, entities: list[MessageEntity]) -> str:
|
||||||
"""
|
"""
|
||||||
Performs the reverse operation to .parse(), effectively returning
|
Performs the reverse operation to .parse(), effectively returning
|
||||||
markdown-like syntax given a normal text and its MessageEntity's.
|
markdown-like syntax given a normal text and its MessageEntity's.
|
||||||
|
@ -157,7 +158,7 @@ def unparse(text: str, entities: List[MessageEntity]) -> str:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
text = add_surrogate(text)
|
text = add_surrogate(text)
|
||||||
insert_at: List[Tuple[int, str]] = []
|
insert_at: list[tuple[int, str]] = []
|
||||||
for e in entities:
|
for e in entities:
|
||||||
offset, length = getattr(e, "offset", None), getattr(e, "length", None)
|
offset, length = getattr(e, "offset", None), getattr(e, "length", None)
|
||||||
assert isinstance(offset, int) and isinstance(length, int)
|
assert isinstance(offset, int) and isinstance(length, int)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Set
|
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ class AdminRight(Enum):
|
||||||
"""Allows deleting stories in a channel."""
|
"""Allows deleting stories in a channel."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw(cls, rights: abcs.ChatAdminRights) -> Set[AdminRight]:
|
def _from_raw(cls, rights: abcs.ChatAdminRights) -> set[AdminRight]:
|
||||||
assert isinstance(rights, types.ChatAdminRights)
|
assert isinstance(rights, types.ChatAdminRights)
|
||||||
all_rights = (
|
all_rights = (
|
||||||
cls.CHANGE_INFO if rights.change_info else None,
|
cls.CHANGE_INFO if rights.change_info else None,
|
||||||
|
@ -84,7 +83,7 @@ class AdminRight(Enum):
|
||||||
return set(filter(None, iter(all_rights)))
|
return set(filter(None, iter(all_rights)))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _chat_rights(cls) -> Set[AdminRight]:
|
def _chat_rights(cls) -> set[AdminRight]:
|
||||||
return {
|
return {
|
||||||
cls.CHANGE_INFO,
|
cls.CHANGE_INFO,
|
||||||
cls.POST_MESSAGES,
|
cls.POST_MESSAGES,
|
||||||
|
@ -104,7 +103,7 @@ class AdminRight(Enum):
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _set_to_raw(cls, all_rights: Set[AdminRight]) -> types.ChatAdminRights:
|
def _set_to_raw(cls, all_rights: set[AdminRight]) -> types.ChatAdminRights:
|
||||||
return types.ChatAdminRights(
|
return types.ChatAdminRights(
|
||||||
change_info=cls.CHANGE_INFO in all_rights,
|
change_info=cls.CHANGE_INFO in all_rights,
|
||||||
post_messages=cls.POST_MESSAGES in all_rights,
|
post_messages=cls.POST_MESSAGES in all_rights,
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, List, Optional, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from .chat import ChatLike
|
from .chat import ChatLike
|
||||||
|
@ -23,11 +23,11 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
def __init__(self, *, client: Client):
|
def __init__(self, *, client: Client):
|
||||||
self._client = client
|
self._client = client
|
||||||
self._medias: List[types.InputSingleMedia] = []
|
self._medias: list[types.InputSingleMedia] = []
|
||||||
|
|
||||||
async def add_photo(
|
async def add_photo(
|
||||||
self,
|
self,
|
||||||
file: Union[str, Path, InFileLike],
|
file: str | Path | InFileLike,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
caption: Optional[str] = None,
|
caption: Optional[str] = None,
|
||||||
|
@ -90,7 +90,7 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
async def add_video(
|
async def add_video(
|
||||||
self,
|
self,
|
||||||
file: Union[str, Path, InFileLike],
|
file: str | Path | InFileLike,
|
||||||
*,
|
*,
|
||||||
size: Optional[int] = None,
|
size: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
|
@ -141,7 +141,7 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
|
||||||
if mime_type is None:
|
if mime_type is None:
|
||||||
mime_type = "application/octet-stream"
|
mime_type = "application/octet-stream"
|
||||||
|
|
||||||
attributes: List[abcs.DocumentAttribute] = []
|
attributes: list[abcs.DocumentAttribute] = []
|
||||||
attributes.append(types.DocumentAttributeFilename(file_name=name))
|
attributes.append(types.DocumentAttributeFilename(file_name=name))
|
||||||
if duration is not None and width is not None and height is not None:
|
if duration is not None and width is not None and height is not None:
|
||||||
attributes.append(
|
attributes.append(
|
||||||
|
@ -198,7 +198,7 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
async def send(
|
async def send(
|
||||||
self, chat: ChatLike, *, reply_to: Optional[int] = None
|
self, chat: ChatLike, *, reply_to: Optional[int] = None
|
||||||
) -> List[Message]:
|
) -> list[Message]:
|
||||||
"""
|
"""
|
||||||
Send the album.
|
Send the album.
|
||||||
|
|
||||||
|
@ -224,11 +224,13 @@ class AlbumBuilder(metaclass=NoPublicConstructor):
|
||||||
noforwards=False,
|
noforwards=False,
|
||||||
update_stickersets_order=False,
|
update_stickersets_order=False,
|
||||||
peer=peer,
|
peer=peer,
|
||||||
reply_to=types.InputReplyToMessage(
|
reply_to=(
|
||||||
reply_to_msg_id=reply_to, top_msg_id=None
|
types.InputReplyToMessage(
|
||||||
)
|
reply_to_msg_id=reply_to, top_msg_id=None
|
||||||
if reply_to
|
)
|
||||||
else None,
|
if reply_to
|
||||||
|
else None
|
||||||
|
),
|
||||||
multi_media=self._medias,
|
multi_media=self._medias,
|
||||||
schedule_date=None,
|
schedule_date=None,
|
||||||
send_as=None,
|
send_as=None,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import abc
|
import abc
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from typing import Any, Deque, Generator, Generic, List, Self, TypeVar
|
from collections.abc import Generator
|
||||||
|
from typing import Any, Generic, Self, TypeVar
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ class AsyncList(abc.ABC, Generic[T]):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._buffer: Deque[T] = deque()
|
self._buffer: deque[T] = deque()
|
||||||
self._total: int = 0
|
self._total: int = 0
|
||||||
self._done = False
|
self._done = False
|
||||||
|
|
||||||
|
@ -54,14 +55,14 @@ class AsyncList(abc.ABC, Generic[T]):
|
||||||
The `_done` flag should be set if it is known that the end was reached
|
The `_done` flag should be set if it is known that the end was reached
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def _collect(self) -> List[T]:
|
async def _collect(self) -> list[T]:
|
||||||
prev = -1
|
prev = -1
|
||||||
while not self._done and prev != len(self._buffer):
|
while not self._done and prev != len(self._buffer):
|
||||||
prev = len(self._buffer)
|
prev = len(self._buffer)
|
||||||
await self._fetch_next()
|
await self._fetch_next()
|
||||||
return list(self._buffer)
|
return list(self._buffer)
|
||||||
|
|
||||||
def __await__(self) -> Generator[Any, None, List[T]]:
|
def __await__(self) -> Generator[Any, None, list[T]]:
|
||||||
return self._collect().__await__()
|
return self._collect().__await__()
|
||||||
|
|
||||||
def __aiter__(self) -> Self:
|
def __aiter__(self) -> Self:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import weakref
|
import weakref
|
||||||
from typing import TYPE_CHECKING, List, Optional, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
from .button import Button
|
from .button import Button
|
||||||
|
@ -24,7 +24,7 @@ def as_concrete_row(row: abcs.KeyboardButtonRow) -> types.KeyboardButtonRow:
|
||||||
|
|
||||||
|
|
||||||
def build_keyboard(
|
def build_keyboard(
|
||||||
btns: Optional[Union[List[Button], List[List[Button]]]]
|
btns: Optional[list[Button] | list[list[Button]]],
|
||||||
) -> Optional[abcs.ReplyMarkup]:
|
) -> Optional[abcs.ReplyMarkup]:
|
||||||
# list[button] -> list[list[button]]
|
# list[button] -> list[list[button]]
|
||||||
# This does allow for "invalid" inputs (mixing lists and non-lists), but that's acceptable.
|
# This does allow for "invalid" inputs (mixing lists and non-lists), but that's acceptable.
|
||||||
|
@ -37,7 +37,7 @@ def build_keyboard(
|
||||||
if not buttons_lists:
|
if not buttons_lists:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
rows: List[abcs.KeyboardButtonRow] = [
|
rows: list[abcs.KeyboardButtonRow] = [
|
||||||
types.KeyboardButtonRow(buttons=[btn._raw for btn in btns])
|
types.KeyboardButtonRow(buttons=[btn._raw for btn in btns])
|
||||||
for btns in buttons_lists
|
for btns in buttons_lists
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import weakref
|
import weakref
|
||||||
from typing import TYPE_CHECKING, Optional, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ....tl import types
|
from ....tl import types
|
||||||
|
|
||||||
|
@ -9,24 +9,24 @@ if TYPE_CHECKING:
|
||||||
from ..message import Message
|
from ..message import Message
|
||||||
|
|
||||||
|
|
||||||
ButtonTypes = Union[
|
ButtonTypes = (
|
||||||
types.KeyboardButton,
|
types.KeyboardButton
|
||||||
types.KeyboardButtonUrl,
|
| types.KeyboardButtonUrl
|
||||||
types.KeyboardButtonCallback,
|
| types.KeyboardButtonCallback
|
||||||
types.KeyboardButtonRequestPhone,
|
| types.KeyboardButtonRequestPhone
|
||||||
types.KeyboardButtonRequestGeoLocation,
|
| types.KeyboardButtonRequestGeoLocation
|
||||||
types.KeyboardButtonSwitchInline,
|
| types.KeyboardButtonSwitchInline
|
||||||
types.KeyboardButtonGame,
|
| types.KeyboardButtonGame
|
||||||
types.KeyboardButtonBuy,
|
| types.KeyboardButtonBuy
|
||||||
types.KeyboardButtonUrlAuth,
|
| types.KeyboardButtonUrlAuth
|
||||||
types.InputKeyboardButtonUrlAuth,
|
| types.InputKeyboardButtonUrlAuth
|
||||||
types.KeyboardButtonRequestPoll,
|
| types.KeyboardButtonRequestPoll
|
||||||
types.InputKeyboardButtonUserProfile,
|
| types.InputKeyboardButtonUserProfile
|
||||||
types.KeyboardButtonUserProfile,
|
| types.KeyboardButtonUserProfile
|
||||||
types.KeyboardButtonWebView,
|
| types.KeyboardButtonWebView
|
||||||
types.KeyboardButtonSimpleWebView,
|
| types.KeyboardButtonSimpleWebView
|
||||||
types.KeyboardButtonRequestPeer,
|
| types.KeyboardButtonRequestPeer
|
||||||
]
|
)
|
||||||
|
|
||||||
|
|
||||||
class Button:
|
class Button:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
import itertools
|
import itertools
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import TYPE_CHECKING, DefaultDict, Dict, List, Optional, Sequence, Union
|
from typing import TYPE_CHECKING, Optional, Sequence
|
||||||
|
|
||||||
from ....session import PackedChat
|
from ....session import PackedChat
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
|
@ -15,12 +15,12 @@ from .user import User
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ...client.client import Client
|
from ...client.client import Client
|
||||||
|
|
||||||
ChatLike = Union[Chat, PackedChat, int, str]
|
ChatLike = Chat | PackedChat | int | str
|
||||||
|
|
||||||
|
|
||||||
def build_chat_map(
|
def build_chat_map(
|
||||||
client: Client, users: Sequence[abcs.User], chats: Sequence[abcs.Chat]
|
client: Client, users: Sequence[abcs.User], chats: Sequence[abcs.Chat]
|
||||||
) -> Dict[int, Chat]:
|
) -> dict[int, Chat]:
|
||||||
users_iter = (User._from_raw(u) for u in users)
|
users_iter = (User._from_raw(u) for u in users)
|
||||||
chats_iter = (
|
chats_iter = (
|
||||||
(
|
(
|
||||||
|
@ -31,11 +31,11 @@ def build_chat_map(
|
||||||
for c in chats
|
for c in chats
|
||||||
)
|
)
|
||||||
|
|
||||||
result: Dict[int, Chat] = {c.id: c for c in itertools.chain(users_iter, chats_iter)}
|
result: dict[int, Chat] = {c.id: c for c in itertools.chain(users_iter, chats_iter)}
|
||||||
|
|
||||||
if len(result) != len(users) + len(chats):
|
if len(result) != len(users) + len(chats):
|
||||||
# The fabled ID collision between different chat types.
|
# The fabled ID collision between different chat types.
|
||||||
counter: DefaultDict[int, List[Union[abcs.User, abcs.Chat]]] = defaultdict(list)
|
counter: defaultdict[int, list[abcs.User | abcs.Chat]] = defaultdict(list)
|
||||||
for user in users:
|
for user in users:
|
||||||
if (id := getattr(user, "id", None)) is not None:
|
if (id := getattr(user, "id", None)) is not None:
|
||||||
counter[id].append(user)
|
counter[id].append(user)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Optional, Self, Union
|
from typing import Optional, Self
|
||||||
|
|
||||||
from ....session import PackedChat, PackedType
|
from ....session import PackedChat, PackedType
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
|
@ -16,7 +16,7 @@ class Channel(Chat, metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
raw: Union[types.Channel, types.ChannelForbidden],
|
raw: types.Channel | types.ChannelForbidden,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._raw = raw
|
self._raw = raw
|
||||||
|
|
||||||
|
@ -55,9 +55,11 @@ class Channel(Chat, metaclass=NoPublicConstructor):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return PackedChat(
|
return PackedChat(
|
||||||
ty=PackedType.GIGAGROUP
|
ty=(
|
||||||
if getattr(self._raw, "gigagroup", False)
|
PackedType.GIGAGROUP
|
||||||
else PackedType.BROADCAST,
|
if getattr(self._raw, "gigagroup", False)
|
||||||
|
else PackedType.BROADCAST
|
||||||
|
),
|
||||||
id=self._raw.id,
|
id=self._raw.id,
|
||||||
access_hash=self._raw.access_hash,
|
access_hash=self._raw.access_hash,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Optional, Self, Sequence, Union
|
from typing import TYPE_CHECKING, Optional, Self, Sequence
|
||||||
|
|
||||||
from ....session import PackedChat, PackedType
|
from ....session import PackedChat, PackedType
|
||||||
from ....tl import abcs, types
|
from ....tl import abcs, types
|
||||||
|
@ -24,13 +24,13 @@ class Group(Chat, metaclass=NoPublicConstructor):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
chat: Union[
|
chat: (
|
||||||
types.ChatEmpty,
|
types.ChatEmpty
|
||||||
types.Chat,
|
| types.Chat
|
||||||
types.ChatForbidden,
|
| types.ChatForbidden
|
||||||
types.Channel,
|
| types.Channel
|
||||||
types.ChannelForbidden,
|
| types.ChannelForbidden
|
||||||
],
|
),
|
||||||
) -> None:
|
) -> None:
|
||||||
self._client = client
|
self._client = client
|
||||||
self._raw = chat
|
self._raw = chat
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Set
|
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
|
|
||||||
|
@ -85,7 +84,7 @@ class ChatRestriction(Enum):
|
||||||
"""Prevents sending plain text messages with no media to the chat."""
|
"""Prevents sending plain text messages with no media to the chat."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw(cls, rights: abcs.ChatBannedRights) -> Set[ChatRestriction]:
|
def _from_raw(cls, rights: abcs.ChatBannedRights) -> set[ChatRestriction]:
|
||||||
assert isinstance(rights, types.ChatBannedRights)
|
assert isinstance(rights, types.ChatBannedRights)
|
||||||
restrictions = (
|
restrictions = (
|
||||||
cls.VIEW_MESSAGES if rights.view_messages else None,
|
cls.VIEW_MESSAGES if rights.view_messages else None,
|
||||||
|
@ -113,7 +112,7 @@ class ChatRestriction(Enum):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _set_to_raw(
|
def _set_to_raw(
|
||||||
cls, restrictions: Set[ChatRestriction], until_date: int
|
cls, restrictions: set[ChatRestriction], until_date: int
|
||||||
) -> types.ChatBannedRights:
|
) -> types.ChatBannedRights:
|
||||||
return types.ChatBannedRights(
|
return types.ChatBannedRights(
|
||||||
view_messages=cls.VIEW_MESSAGES in restrictions,
|
view_messages=cls.VIEW_MESSAGES in restrictions,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self, Union
|
from typing import TYPE_CHECKING, Optional, Self
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from .chat import Chat, peer_id
|
from .chat import Chat, peer_id
|
||||||
|
@ -26,9 +26,9 @@ class Dialog(metaclass=NoPublicConstructor):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
raw: Union[types.Dialog, types.DialogFolder],
|
raw: types.Dialog | types.DialogFolder,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
msg_map: Dict[int, Message],
|
msg_map: dict[int, Message],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._client = client
|
self._client = client
|
||||||
self._raw = raw
|
self._raw = raw
|
||||||
|
@ -40,8 +40,8 @@ class Dialog(metaclass=NoPublicConstructor):
|
||||||
cls,
|
cls,
|
||||||
client: Client,
|
client: Client,
|
||||||
dialog: abcs.Dialog,
|
dialog: abcs.Dialog,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
msg_map: Dict[int, Message],
|
msg_map: dict[int, Message],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
assert isinstance(dialog, (types.Dialog, types.DialogFolder))
|
assert isinstance(dialog, (types.Dialog, types.DialogFolder))
|
||||||
return cls._create(client, dialog, chat_map, msg_map)
|
return cls._create(client, dialog, chat_map, msg_map)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self
|
from typing import TYPE_CHECKING, Optional, Self
|
||||||
|
|
||||||
from ...session import PackedChat
|
from ...session import PackedChat
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
|
@ -27,7 +27,7 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
peer: abcs.Peer,
|
peer: abcs.Peer,
|
||||||
top_msg_id: Optional[int],
|
top_msg_id: Optional[int],
|
||||||
raw: abcs.DraftMessage,
|
raw: abcs.DraftMessage,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
assert isinstance(raw, (types.DraftMessage, types.DraftMessageEmpty))
|
assert isinstance(raw, (types.DraftMessage, types.DraftMessageEmpty))
|
||||||
self._client = client
|
self._client = client
|
||||||
|
@ -38,7 +38,7 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw_update(
|
def _from_raw_update(
|
||||||
cls, client: Client, draft: types.UpdateDraftMessage, chat_map: Dict[int, Chat]
|
cls, client: Client, draft: types.UpdateDraftMessage, chat_map: dict[int, Chat]
|
||||||
) -> Self:
|
) -> Self:
|
||||||
return cls._create(client, draft.peer, draft.top_msg_id, draft.draft, chat_map)
|
return cls._create(client, draft.peer, draft.top_msg_id, draft.draft, chat_map)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
peer: abcs.Peer,
|
peer: abcs.Peer,
|
||||||
top_msg_id: int,
|
top_msg_id: int,
|
||||||
draft: abcs.DraftMessage,
|
draft: abcs.DraftMessage,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
return cls._create(client, peer, top_msg_id, draft, chat_map)
|
return cls._create(client, peer, top_msg_id, draft, chat_map)
|
||||||
|
|
||||||
|
@ -197,11 +197,11 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
noforwards=False,
|
noforwards=False,
|
||||||
update_stickersets_order=False,
|
update_stickersets_order=False,
|
||||||
peer=peer,
|
peer=peer,
|
||||||
reply_to=types.InputReplyToMessage(
|
reply_to=(
|
||||||
reply_to_msg_id=reply_to, top_msg_id=None
|
types.InputReplyToMessage(reply_to_msg_id=reply_to, top_msg_id=None)
|
||||||
)
|
if reply_to
|
||||||
if reply_to
|
else None
|
||||||
else None,
|
),
|
||||||
message=message,
|
message=message,
|
||||||
random_id=random_id,
|
random_id=random_id,
|
||||||
reply_markup=None,
|
reply_markup=None,
|
||||||
|
@ -216,19 +216,23 @@ class Draft(metaclass=NoPublicConstructor):
|
||||||
{},
|
{},
|
||||||
out=result.out,
|
out=result.out,
|
||||||
id=result.id,
|
id=result.id,
|
||||||
from_id=types.PeerUser(user_id=self._client._session.user.id)
|
from_id=(
|
||||||
if self._client._session.user
|
types.PeerUser(user_id=self._client._session.user.id)
|
||||||
else None,
|
if self._client._session.user
|
||||||
|
else None
|
||||||
|
),
|
||||||
peer_id=packed._to_peer(),
|
peer_id=packed._to_peer(),
|
||||||
reply_to=types.MessageReplyHeader(
|
reply_to=(
|
||||||
reply_to_scheduled=False,
|
types.MessageReplyHeader(
|
||||||
forum_topic=False,
|
reply_to_scheduled=False,
|
||||||
reply_to_msg_id=reply_to,
|
forum_topic=False,
|
||||||
reply_to_peer_id=None,
|
reply_to_msg_id=reply_to,
|
||||||
reply_to_top_id=None,
|
reply_to_peer_id=None,
|
||||||
)
|
reply_to_top_id=None,
|
||||||
if reply_to
|
)
|
||||||
else None,
|
if reply_to
|
||||||
|
else None
|
||||||
|
),
|
||||||
date=result.date,
|
date=result.date,
|
||||||
message=message,
|
message=message,
|
||||||
media=result.media,
|
media=result.media,
|
||||||
|
|
|
@ -2,20 +2,11 @@ from __future__ import annotations
|
||||||
|
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
from collections.abc import Coroutine
|
||||||
from inspect import isawaitable
|
from inspect import isawaitable
|
||||||
from io import BufferedWriter
|
from io import BufferedWriter
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import (
|
from typing import TYPE_CHECKING, Any, Optional, Protocol, Self, Sequence
|
||||||
TYPE_CHECKING,
|
|
||||||
Any,
|
|
||||||
Coroutine,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Protocol,
|
|
||||||
Self,
|
|
||||||
Sequence,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from .meta import NoPublicConstructor
|
from .meta import NoPublicConstructor
|
||||||
|
@ -79,7 +70,7 @@ def photo_size_dimensions(
|
||||||
raise RuntimeError("unexpected case")
|
raise RuntimeError("unexpected case")
|
||||||
|
|
||||||
|
|
||||||
def try_get_url_path(maybe_url: Union[str, Path, InFileLike]) -> Optional[str]:
|
def try_get_url_path(maybe_url: str | Path | InFileLike) -> Optional[str]:
|
||||||
if not isinstance(maybe_url, str):
|
if not isinstance(maybe_url, str):
|
||||||
return None
|
return None
|
||||||
lowercase = maybe_url.lower()
|
lowercase = maybe_url.lower()
|
||||||
|
@ -97,7 +88,7 @@ class InFileLike(Protocol):
|
||||||
It's only used in function parameters.
|
It's only used in function parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def read(self, n: int, /) -> Union[bytes, Coroutine[Any, Any, bytes]]:
|
def read(self, n: int, /) -> bytes | Coroutine[Any, Any, bytes]:
|
||||||
"""
|
"""
|
||||||
Read from the file or buffer.
|
Read from the file or buffer.
|
||||||
|
|
||||||
|
@ -116,7 +107,7 @@ class OutFileLike(Protocol):
|
||||||
It's only used in function parameters.
|
It's only used in function parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def write(self, data: bytes) -> Union[Any, Coroutine[Any, Any, Any]]:
|
def write(self, data: bytes) -> Any | Coroutine[Any, Any, Any]:
|
||||||
"""
|
"""
|
||||||
Write all the data into the file or buffer.
|
Write all the data into the file or buffer.
|
||||||
|
|
||||||
|
@ -128,10 +119,10 @@ class OutFileLike(Protocol):
|
||||||
class OutWrapper:
|
class OutWrapper:
|
||||||
__slots__ = ("_fd", "_owned_fd")
|
__slots__ = ("_fd", "_owned_fd")
|
||||||
|
|
||||||
_fd: Union[OutFileLike, BufferedWriter]
|
_fd: OutFileLike | BufferedWriter
|
||||||
_owned_fd: Optional[BufferedWriter]
|
_owned_fd: Optional[BufferedWriter]
|
||||||
|
|
||||||
def __init__(self, file: Union[str, Path, OutFileLike]):
|
def __init__(self, file: str | Path | OutFileLike):
|
||||||
if isinstance(file, str):
|
if isinstance(file, str):
|
||||||
file = Path(file)
|
file = Path(file)
|
||||||
|
|
||||||
|
@ -173,7 +164,7 @@ class File(metaclass=NoPublicConstructor):
|
||||||
input_media: abcs.InputMedia,
|
input_media: abcs.InputMedia,
|
||||||
thumb: Optional[abcs.PhotoSize],
|
thumb: Optional[abcs.PhotoSize],
|
||||||
thumbs: Optional[Sequence[abcs.PhotoSize]],
|
thumbs: Optional[Sequence[abcs.PhotoSize]],
|
||||||
raw: Optional[Union[abcs.MessageMedia, abcs.Photo, abcs.Document]],
|
raw: Optional[abcs.MessageMedia | abcs.Photo | abcs.Document],
|
||||||
client: Optional[Client],
|
client: Optional[Client],
|
||||||
):
|
):
|
||||||
self._attributes = attributes
|
self._attributes = attributes
|
||||||
|
@ -336,7 +327,7 @@ class File(metaclass=NoPublicConstructor):
|
||||||
return mimetypes.guess_extension(self._mime) or ""
|
return mimetypes.guess_extension(self._mime) or ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def thumbnails(self) -> List[File]:
|
def thumbnails(self) -> list[File]:
|
||||||
"""
|
"""
|
||||||
The file thumbnails.
|
The file thumbnails.
|
||||||
|
|
||||||
|
@ -393,7 +384,7 @@ class File(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def download(self, file: Union[str, Path, OutFileLike]) -> None:
|
async def download(self, file: str | Path | OutFileLike) -> None:
|
||||||
"""
|
"""
|
||||||
Alias for :meth:`telethon.Client.download`.
|
Alias for :meth:`telethon.Client.download`.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Optional, Union
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from ...tl import abcs, functions, types
|
from ...tl import abcs, functions, types
|
||||||
from .chat import ChatLike
|
from .chat import ChatLike
|
||||||
|
@ -22,7 +22,7 @@ class InlineResult(metaclass=NoPublicConstructor):
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
results: types.messages.BotResults,
|
results: types.messages.BotResults,
|
||||||
result: Union[types.BotInlineMediaResult, types.BotInlineResult],
|
result: types.BotInlineMediaResult | types.BotInlineResult,
|
||||||
default_peer: abcs.InputPeer,
|
default_peer: abcs.InputPeer,
|
||||||
):
|
):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
|
@ -2,17 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
from typing import (
|
from typing import TYPE_CHECKING, Any, Optional, Self, Sequence
|
||||||
TYPE_CHECKING,
|
|
||||||
Any,
|
|
||||||
Dict,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Self,
|
|
||||||
Sequence,
|
|
||||||
Tuple,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from ..parsers import (
|
from ..parsers import (
|
||||||
|
@ -68,7 +58,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, client: Client, message: abcs.Message, chat_map: Dict[int, Chat]
|
self, client: Client, message: abcs.Message, chat_map: dict[int, Chat]
|
||||||
) -> None:
|
) -> None:
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
message, (types.Message, types.MessageService, types.MessageEmpty)
|
message, (types.Message, types.MessageService, types.MessageEmpty)
|
||||||
|
@ -79,7 +69,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_raw(
|
def _from_raw(
|
||||||
cls, client: Client, message: abcs.Message, chat_map: Dict[int, Chat]
|
cls, client: Client, message: abcs.Message, chat_map: dict[int, Chat]
|
||||||
) -> Self:
|
) -> Self:
|
||||||
return cls._create(client, message, chat_map)
|
return cls._create(client, message, chat_map)
|
||||||
|
|
||||||
|
@ -87,14 +77,14 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
def _from_defaults(
|
def _from_defaults(
|
||||||
cls,
|
cls,
|
||||||
client: Client,
|
client: Client,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
id: int,
|
id: int,
|
||||||
peer_id: abcs.Peer,
|
peer_id: abcs.Peer,
|
||||||
date: int,
|
date: int,
|
||||||
message: str,
|
message: str,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Self:
|
) -> Self:
|
||||||
default_kwargs: Dict[str, Any] = {
|
default_kwargs: dict[str, Any] = {
|
||||||
"out": False,
|
"out": False,
|
||||||
"mentioned": False,
|
"mentioned": False,
|
||||||
"media_unread": False,
|
"media_unread": False,
|
||||||
|
@ -337,12 +327,12 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
async def respond(
|
async def respond(
|
||||||
self,
|
self,
|
||||||
text: Optional[Union[str, Message]] = None,
|
text: Optional[str | Message] = None,
|
||||||
*,
|
*,
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[Union[List[Button], List[List[Button]]]] = None,
|
buttons: Optional[list[Button] | list[list[Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Alias for :meth:`telethon.Client.send_message`.
|
Alias for :meth:`telethon.Client.send_message`.
|
||||||
|
@ -364,12 +354,12 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
async def reply(
|
async def reply(
|
||||||
self,
|
self,
|
||||||
text: Optional[Union[str, Message]] = None,
|
text: Optional[str | Message] = None,
|
||||||
*,
|
*,
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[Union[List[Button], List[List[Button]]]] = None,
|
buttons: Optional[list[Button] | list[list[Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Alias for :meth:`telethon.Client.send_message` with the ``reply_to`` parameter set to this message.
|
Alias for :meth:`telethon.Client.send_message` with the ``reply_to`` parameter set to this message.
|
||||||
|
@ -404,7 +394,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
markdown: Optional[str] = None,
|
markdown: Optional[str] = None,
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: bool = False,
|
link_preview: bool = False,
|
||||||
buttons: Optional[Union[List[Button], List[List[Button]]]] = None,
|
buttons: Optional[list[Button] | list[list[Button]]] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""
|
"""
|
||||||
Alias for :meth:`telethon.Client.edit_message`.
|
Alias for :meth:`telethon.Client.edit_message`.
|
||||||
|
@ -458,7 +448,7 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def buttons(self) -> Optional[List[List[Button]]]:
|
def buttons(self) -> Optional[list[list[Button]]]:
|
||||||
"""
|
"""
|
||||||
The buttons attached to the message.
|
The buttons attached to the message.
|
||||||
|
|
||||||
|
@ -512,8 +502,8 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
|
|
||||||
def build_msg_map(
|
def build_msg_map(
|
||||||
client: Client, messages: Sequence[abcs.Message], chat_map: Dict[int, Chat]
|
client: Client, messages: Sequence[abcs.Message], chat_map: dict[int, Chat]
|
||||||
) -> Dict[int, Message]:
|
) -> dict[int, Message]:
|
||||||
return {
|
return {
|
||||||
msg.id: msg
|
msg.id: msg
|
||||||
for msg in (Message._from_raw(client, m, chat_map) for m in messages)
|
for msg in (Message._from_raw(client, m, chat_map) for m in messages)
|
||||||
|
@ -526,7 +516,7 @@ def parse_message(
|
||||||
markdown: Optional[str],
|
markdown: Optional[str],
|
||||||
html: Optional[str],
|
html: Optional[str],
|
||||||
allow_empty: bool,
|
allow_empty: bool,
|
||||||
) -> Tuple[str, Optional[List[abcs.MessageEntity]]]:
|
) -> tuple[str, Optional[list[abcs.MessageEntity]]]:
|
||||||
cnt = sum((text is not None, markdown is not None, html is not None))
|
cnt = sum((text is not None, markdown is not None, html is not None))
|
||||||
if cnt != 1:
|
if cnt != 1:
|
||||||
if cnt == 0 and allow_empty:
|
if cnt == 0 and allow_empty:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Dict, Optional, Self, Sequence, Set, Union
|
from typing import TYPE_CHECKING, Optional, Self, Sequence
|
||||||
|
|
||||||
from ...session import PackedChat
|
from ...session import PackedChat
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
|
@ -25,18 +25,18 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
chat: PackedChat,
|
chat: PackedChat,
|
||||||
participant: Union[
|
participant: (
|
||||||
types.ChannelParticipant,
|
types.ChannelParticipant
|
||||||
types.ChannelParticipantSelf,
|
| types.ChannelParticipantSelf
|
||||||
types.ChannelParticipantCreator,
|
| types.ChannelParticipantCreator
|
||||||
types.ChannelParticipantAdmin,
|
| types.ChannelParticipantAdmin
|
||||||
types.ChannelParticipantBanned,
|
| types.ChannelParticipantBanned
|
||||||
types.ChannelParticipantLeft,
|
| types.ChannelParticipantLeft
|
||||||
types.ChatParticipant,
|
| types.ChatParticipant
|
||||||
types.ChatParticipantCreator,
|
| types.ChatParticipantCreator
|
||||||
types.ChatParticipantAdmin,
|
| types.ChatParticipantAdmin
|
||||||
],
|
),
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._client = client
|
self._client = client
|
||||||
self._chat = chat
|
self._chat = chat
|
||||||
|
@ -49,7 +49,7 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
client: Client,
|
client: Client,
|
||||||
chat: PackedChat,
|
chat: PackedChat,
|
||||||
participant: abcs.ChannelParticipant,
|
participant: abcs.ChannelParticipant,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
participant,
|
participant,
|
||||||
|
@ -72,7 +72,7 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
client: Client,
|
client: Client,
|
||||||
chat: PackedChat,
|
chat: PackedChat,
|
||||||
participant: abcs.ChatParticipant,
|
participant: abcs.ChatParticipant,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> Self:
|
) -> Self:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
participant,
|
participant,
|
||||||
|
@ -162,7 +162,7 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def admin_rights(self) -> Optional[Set[AdminRight]]:
|
def admin_rights(self) -> Optional[set[AdminRight]]:
|
||||||
"""
|
"""
|
||||||
The set of administrator rights this participant has been granted, if they are an administrator.
|
The set of administrator rights this participant has been granted, if they are an administrator.
|
||||||
"""
|
"""
|
||||||
|
@ -178,7 +178,7 @@ class Participant(metaclass=NoPublicConstructor):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def restrictions(self) -> Optional[Set[ChatRestriction]]:
|
def restrictions(self) -> Optional[set[ChatRestriction]]:
|
||||||
"""
|
"""
|
||||||
The set of restrictions applied to this participant, if they are banned.
|
The set of restrictions applied to this participant, if they are banned.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from .chat import Chat
|
from .chat import Chat
|
||||||
from .meta import NoPublicConstructor
|
from .meta import NoPublicConstructor
|
||||||
|
@ -17,7 +15,7 @@ class RecentAction(metaclass=NoPublicConstructor):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
event: abcs.ChannelAdminLogEvent,
|
event: abcs.ChannelAdminLogEvent,
|
||||||
chat_map: Dict[int, Chat],
|
chat_map: dict[int, Chat],
|
||||||
) -> None:
|
) -> None:
|
||||||
assert isinstance(event, types.ChannelAdminLogEvent)
|
assert isinstance(event, types.ChannelAdminLogEvent)
|
||||||
self._raw = event
|
self._raw = event
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from math import gcd
|
from math import gcd
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
|
|
||||||
def factorize(pq: int) -> Tuple[int, int]:
|
def factorize(pq: int) -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
Factorize the given number into its two prime factors.
|
Factorize the given number into its two prime factors.
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import struct
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from ..crypto import (
|
from ..crypto import (
|
||||||
RSA_KEYS,
|
RSA_KEYS,
|
||||||
|
@ -67,17 +66,17 @@ class DhGenData:
|
||||||
nonce_number: int
|
nonce_number: int
|
||||||
|
|
||||||
|
|
||||||
def _do_step1(random_bytes: bytes) -> Tuple[bytes, Step1]:
|
def _do_step1(random_bytes: bytes) -> tuple[bytes, Step1]:
|
||||||
assert len(random_bytes) == 16
|
assert len(random_bytes) == 16
|
||||||
nonce = int.from_bytes(random_bytes)
|
nonce = int.from_bytes(random_bytes)
|
||||||
return req_pq_multi(nonce=nonce), Step1(nonce=nonce)
|
return req_pq_multi(nonce=nonce), Step1(nonce=nonce)
|
||||||
|
|
||||||
|
|
||||||
def step1() -> Tuple[bytes, Step1]:
|
def step1() -> tuple[bytes, Step1]:
|
||||||
return _do_step1(os.urandom(16))
|
return _do_step1(os.urandom(16))
|
||||||
|
|
||||||
|
|
||||||
def _do_step2(data: Step1, response: bytes, random_bytes: bytes) -> Tuple[bytes, Step2]:
|
def _do_step2(data: Step1, response: bytes, random_bytes: bytes) -> tuple[bytes, Step2]:
|
||||||
assert len(random_bytes) == 288
|
assert len(random_bytes) == 288
|
||||||
nonce = data.nonce
|
nonce = data.nonce
|
||||||
res_pq = ResPq.from_bytes(response)
|
res_pq = ResPq.from_bytes(response)
|
||||||
|
@ -130,13 +129,13 @@ def _do_step2(data: Step1, response: bytes, random_bytes: bytes) -> Tuple[bytes,
|
||||||
), Step2(nonce=nonce, server_nonce=res_pq.server_nonce, new_nonce=new_nonce)
|
), Step2(nonce=nonce, server_nonce=res_pq.server_nonce, new_nonce=new_nonce)
|
||||||
|
|
||||||
|
|
||||||
def step2(data: Step1, response: bytes) -> Tuple[bytes, Step2]:
|
def step2(data: Step1, response: bytes) -> tuple[bytes, Step2]:
|
||||||
return _do_step2(data, response, os.urandom(288))
|
return _do_step2(data, response, os.urandom(288))
|
||||||
|
|
||||||
|
|
||||||
def _do_step3(
|
def _do_step3(
|
||||||
data: Step2, response: bytes, random_bytes: bytes, now: int
|
data: Step2, response: bytes, random_bytes: bytes, now: int
|
||||||
) -> Tuple[bytes, Step3]:
|
) -> tuple[bytes, Step3]:
|
||||||
assert len(random_bytes) == 272
|
assert len(random_bytes) == 272
|
||||||
|
|
||||||
nonce = data.nonce
|
nonce = data.nonce
|
||||||
|
@ -231,7 +230,7 @@ def _do_step3(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def step3(data: Step2, response: bytes) -> Tuple[bytes, Step3]:
|
def step3(data: Step2, response: bytes) -> tuple[bytes, Step3]:
|
||||||
return _do_step3(data, response, os.urandom(272), int(time.time()))
|
return _do_step3(data, response, os.urandom(272), int(time.time()))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
from typing import List, Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from ...crypto import AuthKey, decrypt_data_v2, encrypt_data_v2
|
from ...crypto import AuthKey, decrypt_data_v2, encrypt_data_v2
|
||||||
from ...tl.core import Reader
|
from ...tl.core import Reader
|
||||||
|
@ -107,12 +107,12 @@ class Encrypted(Mtp):
|
||||||
) -> None:
|
) -> None:
|
||||||
self._auth_key = auth_key
|
self._auth_key = auth_key
|
||||||
self._time_offset: int = time_offset or 0
|
self._time_offset: int = time_offset or 0
|
||||||
self._salts: List[FutureSalt] = [
|
self._salts: list[FutureSalt] = [
|
||||||
FutureSalt(valid_since=0, valid_until=0x7FFFFFFF, salt=first_salt or 0)
|
FutureSalt(valid_since=0, valid_until=0x7FFFFFFF, salt=first_salt or 0)
|
||||||
]
|
]
|
||||||
self._start_salt_time: Optional[Tuple[int, float]] = None
|
self._start_salt_time: Optional[tuple[int, float]] = None
|
||||||
self._compression_threshold = compression_threshold
|
self._compression_threshold = compression_threshold
|
||||||
self._deserialization: List[Deserialization] = []
|
self._deserialization: list[Deserialization] = []
|
||||||
self._buffer = bytearray()
|
self._buffer = bytearray()
|
||||||
self._salt_request_msg_id: Optional[int] = None
|
self._salt_request_msg_id: Optional[int] = None
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ class Encrypted(Mtp):
|
||||||
self._client_id: int
|
self._client_id: int
|
||||||
self._sequence: int
|
self._sequence: int
|
||||||
self._last_msg_id: int
|
self._last_msg_id: int
|
||||||
self._in_pending_ack: List[int] = []
|
self._in_pending_ack: list[int] = []
|
||||||
self._msg_count: int
|
self._msg_count: int
|
||||||
self._reset_session()
|
self._reset_session()
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ class Encrypted(Mtp):
|
||||||
def _get_current_salt(self) -> int:
|
def _get_current_salt(self) -> int:
|
||||||
return self._salts[-1].salt if self._salts else 0
|
return self._salts[-1].salt if self._salts else 0
|
||||||
|
|
||||||
def _finalize_plain(self) -> Optional[Tuple[MsgId, bytes]]:
|
def _finalize_plain(self) -> Optional[tuple[MsgId, bytes]]:
|
||||||
if not self._msg_count:
|
if not self._msg_count:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ class Encrypted(Mtp):
|
||||||
|
|
||||||
return self._serialize_msg(body, True)
|
return self._serialize_msg(body, True)
|
||||||
|
|
||||||
def finalize(self) -> Optional[Tuple[MsgId, bytes]]:
|
def finalize(self) -> Optional[tuple[MsgId, bytes]]:
|
||||||
result = self._finalize_plain()
|
result = self._finalize_plain()
|
||||||
if not result:
|
if not result:
|
||||||
return None
|
return None
|
||||||
|
@ -441,7 +441,7 @@ class Encrypted(Mtp):
|
||||||
|
|
||||||
def deserialize(
|
def deserialize(
|
||||||
self, payload: bytes | bytearray | memoryview
|
self, payload: bytes | bytearray | memoryview
|
||||||
) -> List[Deserialization]:
|
) -> list[Deserialization]:
|
||||||
check_message_buffer(payload)
|
check_message_buffer(payload)
|
||||||
|
|
||||||
plaintext = decrypt_data_v2(payload, self._auth_key)
|
plaintext = decrypt_data_v2(payload, self._auth_key)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import struct
|
import struct
|
||||||
from typing import List, Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from ..utils import check_message_buffer
|
from ..utils import check_message_buffer
|
||||||
from .types import Deserialization, MsgId, Mtp, RpcResult
|
from .types import Deserialization, MsgId, Mtp, RpcResult
|
||||||
|
@ -23,7 +23,7 @@ class Plain(Mtp):
|
||||||
self._buffer += request # message_data
|
self._buffer += request # message_data
|
||||||
return msg_id
|
return msg_id
|
||||||
|
|
||||||
def finalize(self) -> Optional[Tuple[MsgId, bytes]]:
|
def finalize(self) -> Optional[tuple[MsgId, bytes]]:
|
||||||
if not self._buffer:
|
if not self._buffer:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class Plain(Mtp):
|
||||||
|
|
||||||
def deserialize(
|
def deserialize(
|
||||||
self, payload: bytes | bytearray | memoryview
|
self, payload: bytes | bytearray | memoryview
|
||||||
) -> List[Deserialization]:
|
) -> list[Deserialization]:
|
||||||
check_message_buffer(payload)
|
check_message_buffer(payload)
|
||||||
|
|
||||||
auth_key_id, msg_id, length = struct.unpack_from("<qqi", payload)
|
auth_key_id, msg_id, length = struct.unpack_from("<qqi", payload)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import List, NewType, Optional, Self, Tuple
|
from typing import NewType, Optional, Self
|
||||||
|
|
||||||
from ...tl.mtproto.types import RpcError as GeneratedRpcError
|
from ...tl.mtproto.types import RpcError as GeneratedRpcError
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ class Mtp(ABC):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def finalize(self) -> Optional[Tuple[MsgId, bytes]]:
|
def finalize(self) -> Optional[tuple[MsgId, bytes]]:
|
||||||
"""
|
"""
|
||||||
Finalize the buffer of serialized requests.
|
Finalize the buffer of serialized requests.
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ class Mtp(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def deserialize(
|
def deserialize(
|
||||||
self, payload: bytes | bytearray | memoryview
|
self, payload: bytes | bytearray | memoryview
|
||||||
) -> List[Deserialization]:
|
) -> list[Deserialization]:
|
||||||
"""
|
"""
|
||||||
Deserialize incoming buffer payload.
|
Deserialize incoming buffer payload.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Callable
|
from collections.abc import Callable
|
||||||
|
|
||||||
OutFn = Callable[[bytes | bytearray | memoryview], None]
|
OutFn = Callable[[bytes | bytearray | memoryview], None]
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,9 @@ import struct
|
||||||
import time
|
import time
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from asyncio import FIRST_COMPLETED, Event, Future
|
from asyncio import FIRST_COMPLETED, Event, Future
|
||||||
|
from collections.abc import Iterator
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import (
|
from typing import Generic, Optional, Protocol, Self, Type, TypeVar
|
||||||
Generic,
|
|
||||||
Iterator,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Protocol,
|
|
||||||
Self,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
|
||||||
)
|
|
||||||
|
|
||||||
from ..crypto import AuthKey
|
from ..crypto import AuthKey
|
||||||
from ..mtproto import (
|
from ..mtproto import (
|
||||||
|
@ -127,7 +118,7 @@ class Connector(Protocol):
|
||||||
The :doc:`/concepts/datacenters` concept has examples on how to combine proxy libraries with Telethon.
|
The :doc:`/concepts/datacenters` concept has examples on how to combine proxy libraries with Telethon.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def __call__(self, ip: str, port: int) -> Tuple[AsyncReader, AsyncWriter]:
|
async def __call__(self, ip: str, port: int) -> tuple[AsyncReader, AsyncWriter]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +166,7 @@ class Sender:
|
||||||
_transport: Transport
|
_transport: Transport
|
||||||
_mtp: Mtp
|
_mtp: Mtp
|
||||||
_mtp_buffer: bytearray
|
_mtp_buffer: bytearray
|
||||||
_requests: List[Request[object]]
|
_requests: list[Request[object]]
|
||||||
_request_event: Event
|
_request_event: Event
|
||||||
_next_ping: float
|
_next_ping: float
|
||||||
_read_buffer: bytearray
|
_read_buffer: bytearray
|
||||||
|
@ -239,7 +230,7 @@ class Sender:
|
||||||
if rx.done():
|
if rx.done():
|
||||||
return rx.result()
|
return rx.result()
|
||||||
|
|
||||||
async def step(self) -> List[Updates]:
|
async def step(self) -> list[Updates]:
|
||||||
self._try_fill_write()
|
self._try_fill_write()
|
||||||
|
|
||||||
recv_req = asyncio.create_task(self._request_event.wait())
|
recv_req = asyncio.create_task(self._request_event.wait())
|
||||||
|
@ -296,13 +287,13 @@ class Sender:
|
||||||
self._transport.pack(mtp_buffer, self._writer.write)
|
self._transport.pack(mtp_buffer, self._writer.write)
|
||||||
self._write_drain_pending = True
|
self._write_drain_pending = True
|
||||||
|
|
||||||
def _on_net_read(self, read_buffer: bytes) -> List[Updates]:
|
def _on_net_read(self, read_buffer: bytes) -> list[Updates]:
|
||||||
if not read_buffer:
|
if not read_buffer:
|
||||||
raise ConnectionResetError("read 0 bytes")
|
raise ConnectionResetError("read 0 bytes")
|
||||||
|
|
||||||
self._read_buffer += read_buffer
|
self._read_buffer += read_buffer
|
||||||
|
|
||||||
updates: List[Updates] = []
|
updates: list[Updates] = []
|
||||||
while self._read_buffer:
|
while self._read_buffer:
|
||||||
self._mtp_buffer.clear()
|
self._mtp_buffer.clear()
|
||||||
try:
|
try:
|
||||||
|
@ -331,7 +322,7 @@ class Sender:
|
||||||
)
|
)
|
||||||
self._next_ping = asyncio.get_running_loop().time() + PING_DELAY
|
self._next_ping = asyncio.get_running_loop().time() + PING_DELAY
|
||||||
|
|
||||||
def _process_mtp_buffer(self, updates: List[Updates]) -> None:
|
def _process_mtp_buffer(self, updates: list[Updates]) -> None:
|
||||||
results = self._mtp.deserialize(self._mtp_buffer)
|
results = self._mtp.deserialize(self._mtp_buffer)
|
||||||
|
|
||||||
for result in results:
|
for result in results:
|
||||||
|
@ -345,13 +336,13 @@ class Sender:
|
||||||
self._process_bad_message(result)
|
self._process_bad_message(result)
|
||||||
|
|
||||||
def _process_update(
|
def _process_update(
|
||||||
self, updates: List[Updates], update: bytes | bytearray | memoryview
|
self, updates: list[Updates], update: bytes | bytearray | memoryview
|
||||||
) -> None:
|
) -> None:
|
||||||
try:
|
try:
|
||||||
updates.append(Updates.from_bytes(update))
|
updates.append(Updates.from_bytes(update))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
cid = struct.unpack_from("I", update)[0]
|
cid = struct.unpack_from("I", update)[0]
|
||||||
alt_classes: Tuple[Type[Serializable], ...] = (
|
alt_classes: tuple[Type[Serializable], ...] = (
|
||||||
AffectedFoundMessages,
|
AffectedFoundMessages,
|
||||||
AffectedHistory,
|
AffectedHistory,
|
||||||
AffectedMessages,
|
AffectedMessages,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, Dict, Optional, Sequence, Tuple
|
from typing import Any, Optional, Sequence
|
||||||
|
|
||||||
from ...tl import abcs, types
|
from ...tl import abcs, types
|
||||||
from .packed import PackedChat, PackedType
|
from .packed import PackedChat, PackedType
|
||||||
|
@ -7,8 +7,8 @@ from .packed import PackedChat, PackedType
|
||||||
class ChatHashCache:
|
class ChatHashCache:
|
||||||
__slots__ = ("_hash_map", "_self_id", "_self_bot")
|
__slots__ = ("_hash_map", "_self_id", "_self_bot")
|
||||||
|
|
||||||
def __init__(self, self_user: Optional[Tuple[int, bool]]):
|
def __init__(self, self_user: Optional[tuple[int, bool]]):
|
||||||
self._hash_map: Dict[int, Tuple[int, PackedType]] = {}
|
self._hash_map: dict[int, tuple[int, PackedType]] = {}
|
||||||
self._self_id = self_user[0] if self_user else None
|
self._self_id = self_user[0] if self_user else None
|
||||||
self._self_bot = self_user[1] if self_user else False
|
self._self_bot = self_user[1] if self_user else False
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, Literal, Union
|
from typing import Literal
|
||||||
|
|
||||||
from ...tl import abcs
|
from ...tl import abcs
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ NO_UPDATES_TIMEOUT = 15 * 60
|
||||||
|
|
||||||
ENTRY_ACCOUNT: Literal["ACCOUNT"] = "ACCOUNT"
|
ENTRY_ACCOUNT: Literal["ACCOUNT"] = "ACCOUNT"
|
||||||
ENTRY_SECRET: Literal["SECRET"] = "SECRET"
|
ENTRY_SECRET: Literal["SECRET"] = "SECRET"
|
||||||
Entry = Union[Literal["ACCOUNT", "SECRET"], int]
|
Entry = Literal["ACCOUNT", "SECRET"] | int
|
||||||
|
|
||||||
# Python's logging doesn't define a TRACE level. Pick halfway between DEBUG and NOTSET.
|
# Python's logging doesn't define a TRACE level. Pick halfway between DEBUG and NOTSET.
|
||||||
# We don't define a name for this as libraries shouldn't do that though.
|
# We don't define a name for this as libraries shouldn't do that though.
|
||||||
|
@ -64,7 +64,7 @@ class PossibleGap:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
deadline: float,
|
deadline: float,
|
||||||
updates: List[abcs.Update],
|
updates: list[abcs.Update],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.deadline = deadline
|
self.deadline = deadline
|
||||||
self.updates = updates
|
self.updates = updates
|
||||||
|
|
|
@ -2,7 +2,7 @@ import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Dict, List, Optional, Sequence, Set, Tuple
|
from typing import Optional, Sequence
|
||||||
|
|
||||||
from ...tl import Request, abcs, functions, types
|
from ...tl import Request, abcs, functions, types
|
||||||
from ..chat import ChatHashCache
|
from ..chat import ChatHashCache
|
||||||
|
@ -53,11 +53,11 @@ class MessageBox:
|
||||||
base_logger: logging.Logger,
|
base_logger: logging.Logger,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._logger = base_logger.getChild("messagebox")
|
self._logger = base_logger.getChild("messagebox")
|
||||||
self.map: Dict[Entry, State] = {}
|
self.map: dict[Entry, State] = {}
|
||||||
self.date = epoch()
|
self.date = epoch()
|
||||||
self.seq = NO_SEQ
|
self.seq = NO_SEQ
|
||||||
self.possible_gaps: Dict[Entry, PossibleGap] = {}
|
self.possible_gaps: dict[Entry, PossibleGap] = {}
|
||||||
self.getting_diff_for: Set[Entry] = set()
|
self.getting_diff_for: set[Entry] = set()
|
||||||
self.next_deadline: Optional[Entry] = None
|
self.next_deadline: Optional[Entry] = None
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
@ -164,7 +164,7 @@ class MessageBox:
|
||||||
|
|
||||||
return deadline
|
return deadline
|
||||||
|
|
||||||
def reset_deadlines(self, entries: Set[Entry], deadline: float) -> None:
|
def reset_deadlines(self, entries: set[Entry], deadline: float) -> None:
|
||||||
if not entries:
|
if not entries:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -259,8 +259,8 @@ class MessageBox:
|
||||||
self,
|
self,
|
||||||
updates: abcs.Updates,
|
updates: abcs.Updates,
|
||||||
chat_hashes: ChatHashCache,
|
chat_hashes: ChatHashCache,
|
||||||
) -> Tuple[List[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
) -> tuple[list[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
||||||
result: List[abcs.Update] = []
|
result: list[abcs.Update] = []
|
||||||
combined = adapt(updates, chat_hashes)
|
combined = adapt(updates, chat_hashes)
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
@ -290,7 +290,7 @@ class MessageBox:
|
||||||
sorted_updates = list(sorted(combined.updates, key=update_sort_key))
|
sorted_updates = list(sorted(combined.updates, key=update_sort_key))
|
||||||
|
|
||||||
any_pts_applied = False
|
any_pts_applied = False
|
||||||
reset_deadlines_for: Set[Entry] = set()
|
reset_deadlines_for: set[Entry] = set()
|
||||||
for update in sorted_updates:
|
for update in sorted_updates:
|
||||||
entry, applied = self.apply_pts_info(update)
|
entry, applied = self.apply_pts_info(update)
|
||||||
if entry is not None:
|
if entry is not None:
|
||||||
|
@ -341,7 +341,7 @@ class MessageBox:
|
||||||
def apply_pts_info(
|
def apply_pts_info(
|
||||||
self,
|
self,
|
||||||
update: abcs.Update,
|
update: abcs.Update,
|
||||||
) -> Tuple[Optional[Entry], Optional[abcs.Update]]:
|
) -> tuple[Optional[Entry], Optional[abcs.Update]]:
|
||||||
if isinstance(update, types.UpdateChannelTooLong):
|
if isinstance(update, types.UpdateChannelTooLong):
|
||||||
self.try_begin_get_diff(update.channel_id, "received updateChannelTooLong")
|
self.try_begin_get_diff(update.channel_id, "received updateChannelTooLong")
|
||||||
return None, None
|
return None, None
|
||||||
|
@ -438,12 +438,12 @@ class MessageBox:
|
||||||
self,
|
self,
|
||||||
diff: abcs.updates.Difference,
|
diff: abcs.updates.Difference,
|
||||||
chat_hashes: ChatHashCache,
|
chat_hashes: ChatHashCache,
|
||||||
) -> Tuple[List[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
) -> tuple[list[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._trace("applying account difference: %s", diff)
|
self._trace("applying account difference: %s", diff)
|
||||||
|
|
||||||
finish: bool
|
finish: bool
|
||||||
result: Tuple[List[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]
|
result: tuple[list[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]
|
||||||
if isinstance(diff, types.updates.DifferenceEmpty):
|
if isinstance(diff, types.updates.DifferenceEmpty):
|
||||||
finish = True
|
finish = True
|
||||||
self.date = datetime.datetime.fromtimestamp(
|
self.date = datetime.datetime.fromtimestamp(
|
||||||
|
@ -496,7 +496,7 @@ class MessageBox:
|
||||||
self,
|
self,
|
||||||
diff: types.updates.Difference,
|
diff: types.updates.Difference,
|
||||||
chat_hashes: ChatHashCache,
|
chat_hashes: ChatHashCache,
|
||||||
) -> Tuple[List[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
) -> tuple[list[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
||||||
state = diff.state
|
state = diff.state
|
||||||
assert isinstance(state, types.updates.State)
|
assert isinstance(state, types.updates.State)
|
||||||
self.map[ENTRY_ACCOUNT].pts = state.pts
|
self.map[ENTRY_ACCOUNT].pts = state.pts
|
||||||
|
@ -582,7 +582,7 @@ class MessageBox:
|
||||||
channel_id: int,
|
channel_id: int,
|
||||||
diff: abcs.updates.ChannelDifference,
|
diff: abcs.updates.ChannelDifference,
|
||||||
chat_hashes: ChatHashCache,
|
chat_hashes: ChatHashCache,
|
||||||
) -> Tuple[List[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
) -> tuple[list[abcs.Update], Sequence[abcs.User], Sequence[abcs.Chat]]:
|
||||||
entry: Entry = channel_id
|
entry: Entry = channel_id
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._trace("applying channel=%r difference: %s", entry, diff)
|
self._trace("applying channel=%r difference: %s", entry, diff)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import List, Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from ..tl.core.serializable import obj_repr
|
from ..tl.core.serializable import obj_repr
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class DataCenter:
|
||||||
:param auth: See below.
|
:param auth: See below.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__: Tuple[str, ...] = ("id", "ipv4_addr", "ipv6_addr", "auth")
|
__slots__: tuple[str, ...] = ("id", "ipv4_addr", "ipv6_addr", "auth")
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -116,7 +116,7 @@ class UpdateState:
|
||||||
qts: int,
|
qts: int,
|
||||||
date: int,
|
date: int,
|
||||||
seq: int,
|
seq: int,
|
||||||
channels: List[ChannelState],
|
channels: list[ChannelState],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.pts = pts
|
self.pts = pts
|
||||||
"The primary partial sequence number."
|
"The primary partial sequence number."
|
||||||
|
@ -165,7 +165,7 @@ class Session:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
dcs: Optional[List[DataCenter]] = None,
|
dcs: Optional[list[DataCenter]] = None,
|
||||||
user: Optional[User] = None,
|
user: Optional[User] = None,
|
||||||
state: Optional[UpdateState] = None,
|
state: Optional[UpdateState] = None,
|
||||||
):
|
):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Union
|
from typing import Optional
|
||||||
|
|
||||||
from ..session import ChannelState, DataCenter, Session, UpdateState, User
|
from ..session import ChannelState, DataCenter, Session, UpdateState, User
|
||||||
from .storage import Storage
|
from .storage import Storage
|
||||||
|
@ -20,7 +20,7 @@ class SqliteSession(Storage):
|
||||||
an VCS by accident (adding ``*.session`` to ``.gitignore`` will catch them).
|
an VCS by accident (adding ``*.session`` to ``.gitignore`` will catch them).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, file: Union[str, Path]):
|
def __init__(self, file: str | Path):
|
||||||
path = Path(file)
|
path = Path(file)
|
||||||
if not path.suffix:
|
if not path.suffix:
|
||||||
path = path.with_suffix(EXTENSION)
|
path = path.with_suffix(EXTENSION)
|
||||||
|
@ -105,18 +105,22 @@ class SqliteSession(Storage):
|
||||||
DataCenter(id=id, ipv4_addr=ipv4_addr, ipv6_addr=ipv6_addr, auth=auth)
|
DataCenter(id=id, ipv4_addr=ipv4_addr, ipv6_addr=ipv6_addr, auth=auth)
|
||||||
for (id, ipv4_addr, ipv6_addr, auth) in datacenter
|
for (id, ipv4_addr, ipv6_addr, auth) in datacenter
|
||||||
],
|
],
|
||||||
user=User(id=user[0], dc=user[1], bot=bool(user[2]), username=user[3])
|
user=(
|
||||||
if user
|
User(id=user[0], dc=user[1], bot=bool(user[2]), username=user[3])
|
||||||
else None,
|
if user
|
||||||
state=UpdateState(
|
else None
|
||||||
pts=state[0],
|
),
|
||||||
qts=state[1],
|
state=(
|
||||||
date=state[2],
|
UpdateState(
|
||||||
seq=state[3],
|
pts=state[0],
|
||||||
channels=[ChannelState(id=id, pts=pts) for id, pts in channelstate],
|
qts=state[1],
|
||||||
)
|
date=state[2],
|
||||||
if state
|
seq=state[3],
|
||||||
else None,
|
channels=[ChannelState(id=id, pts=pts) for id, pts in channelstate],
|
||||||
|
)
|
||||||
|
if state
|
||||||
|
else None
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import functools
|
import functools
|
||||||
import struct
|
import struct
|
||||||
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Type, TypeVar
|
from collections.abc import Callable
|
||||||
|
from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .serializable import Serializable
|
from .serializable import Serializable
|
||||||
|
@ -96,8 +97,8 @@ def single_deserializer(cls: Type[T]) -> Callable[[bytes], T]:
|
||||||
|
|
||||||
|
|
||||||
@functools.cache
|
@functools.cache
|
||||||
def list_deserializer(cls: Type[T]) -> Callable[[bytes], List[T]]:
|
def list_deserializer(cls: Type[T]) -> Callable[[bytes], list[T]]:
|
||||||
def deserializer(body: bytes) -> List[T]:
|
def deserializer(body: bytes) -> list[T]:
|
||||||
reader = Reader(body)
|
reader = Reader(body)
|
||||||
vec_id, length = reader.read_fmt("<ii", 8)
|
vec_id, length = reader.read_fmt("<ii", 8)
|
||||||
assert vec_id == 0x1CB5C415 and length >= 0
|
assert vec_id == 0x1CB5C415 and length >= 0
|
||||||
|
@ -106,14 +107,14 @@ def list_deserializer(cls: Type[T]) -> Callable[[bytes], List[T]]:
|
||||||
return deserializer
|
return deserializer
|
||||||
|
|
||||||
|
|
||||||
def deserialize_i64_list(body: bytes) -> List[int]:
|
def deserialize_i64_list(body: bytes) -> list[int]:
|
||||||
reader = Reader(body)
|
reader = Reader(body)
|
||||||
vec_id, length = reader.read_fmt("<ii", 8)
|
vec_id, length = reader.read_fmt("<ii", 8)
|
||||||
assert vec_id == 0x1CB5C415 and length >= 0
|
assert vec_id == 0x1CB5C415 and length >= 0
|
||||||
return [*reader.read_fmt(f"<{length}q", length * 8)]
|
return [*reader.read_fmt(f"<{length}q", length * 8)]
|
||||||
|
|
||||||
|
|
||||||
def deserialize_i32_list(body: bytes) -> List[int]:
|
def deserialize_i32_list(body: bytes) -> list[int]:
|
||||||
reader = Reader(body)
|
reader = Reader(body)
|
||||||
vec_id, length = reader.read_fmt("<ii", 8)
|
vec_id, length = reader.read_fmt("<ii", 8)
|
||||||
assert vec_id == 0x1CB5C415 and length >= 0
|
assert vec_id == 0x1CB5C415 and length >= 0
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import struct
|
import struct
|
||||||
from typing import Any, Callable, Generic, Optional, TypeVar
|
from collections.abc import Callable
|
||||||
|
from typing import Any, Generic, Optional, TypeVar
|
||||||
|
|
||||||
Return = TypeVar("Return")
|
Return = TypeVar("Return")
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import abc
|
import abc
|
||||||
import struct
|
import struct
|
||||||
from typing import Protocol, Self, Tuple
|
from typing import Protocol, Self
|
||||||
|
|
||||||
from .reader import Reader
|
from .reader import Reader
|
||||||
|
|
||||||
|
|
||||||
class HasSlots(Protocol):
|
class HasSlots(Protocol):
|
||||||
__slots__: Tuple[str, ...]
|
__slots__: tuple[str, ...]
|
||||||
|
|
||||||
|
|
||||||
def obj_repr(self: HasSlots) -> str:
|
def obj_repr(self: HasSlots) -> str:
|
||||||
|
@ -16,7 +16,7 @@ def obj_repr(self: HasSlots) -> str:
|
||||||
|
|
||||||
|
|
||||||
class Serializable(abc.ABC):
|
class Serializable(abc.ABC):
|
||||||
__slots__: Tuple[str, ...] = ()
|
__slots__: tuple[str, ...] = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import struct
|
import struct
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from telethon._impl.crypto import AuthKey
|
from telethon._impl.crypto import AuthKey
|
||||||
|
@ -49,7 +49,7 @@ def test_rpc_error_parsing() -> None:
|
||||||
PLAIN_REQUEST = b"Hey!"
|
PLAIN_REQUEST = b"Hey!"
|
||||||
|
|
||||||
|
|
||||||
def unwrap_finalize(finalized: Optional[Tuple[MsgId, bytes]]) -> bytes:
|
def unwrap_finalize(finalized: Optional[tuple[MsgId, bytes]]) -> bytes:
|
||||||
assert finalized is not None
|
assert finalized is not None
|
||||||
_, buffer = finalized
|
_, buffer = finalized
|
||||||
return buffer
|
return buffer
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from telethon._impl.mtproto import Abridged
|
from telethon._impl.mtproto import Abridged
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@ class Output(bytearray):
|
||||||
self += data
|
self += data
|
||||||
|
|
||||||
|
|
||||||
def setup_pack(n: int) -> Tuple[Abridged, bytes, Output]:
|
def setup_pack(n: int) -> tuple[Abridged, bytes, Output]:
|
||||||
input = bytes(x & 0xFF for x in range(n))
|
input = bytes(x & 0xFF for x in range(n))
|
||||||
return Abridged(), input, Output()
|
return Abridged(), input, Output()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from telethon._impl.mtproto import Full
|
from telethon._impl.mtproto import Full
|
||||||
|
|
||||||
|
@ -11,12 +9,12 @@ class Output(bytearray):
|
||||||
self += data
|
self += data
|
||||||
|
|
||||||
|
|
||||||
def setup_pack(n: int) -> Tuple[Full, bytes, Output]:
|
def setup_pack(n: int) -> tuple[Full, bytes, Output]:
|
||||||
input = bytes(x & 0xFF for x in range(n))
|
input = bytes(x & 0xFF for x in range(n))
|
||||||
return Full(), input, Output()
|
return Full(), input, Output()
|
||||||
|
|
||||||
|
|
||||||
def setup_unpack(n: int) -> Tuple[bytes, Full, bytes, bytearray]:
|
def setup_unpack(n: int) -> tuple[bytes, Full, bytes, bytearray]:
|
||||||
transport, expected_output, input = setup_pack(n)
|
transport, expected_output, input = setup_pack(n)
|
||||||
transport.pack(expected_output, input)
|
transport.pack(expected_output, input)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
from telethon._impl.mtproto import Intermediate
|
from telethon._impl.mtproto import Intermediate
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@ class Output(bytearray):
|
||||||
self += data
|
self += data
|
||||||
|
|
||||||
|
|
||||||
def setup_pack(n: int) -> Tuple[Intermediate, bytes, Output]:
|
def setup_pack(n: int) -> tuple[Intermediate, bytes, Output]:
|
||||||
input = bytes(x & 0xFF for x in range(n))
|
input = bytes(x & 0xFF for x in range(n))
|
||||||
return Intermediate(), input, Output()
|
return Intermediate(), input, Output()
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import weakref
|
import weakref
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
|
|
||||||
class FakeFs:
|
class FakeFs:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._files: Dict[Path, bytearray] = {}
|
self._files: dict[Path, bytearray] = {}
|
||||||
|
|
||||||
def open(self, path: Path) -> "SourceWriter":
|
def open(self, path: Path) -> "SourceWriter":
|
||||||
return SourceWriter(self, path)
|
return SourceWriter(self, path)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Set
|
|
||||||
|
|
||||||
from ..tl_parser import NormalParameter, ParsedTl
|
from ..tl_parser import NormalParameter, ParsedTl
|
||||||
from .fakefs import FakeFs, SourceWriter
|
from .fakefs import FakeFs, SourceWriter
|
||||||
|
@ -19,7 +18,7 @@ from .serde.serialization import generate_function, generate_write
|
||||||
|
|
||||||
|
|
||||||
def generate_init(
|
def generate_init(
|
||||||
writer: SourceWriter, namespaces: Set[str], classes: Set[str]
|
writer: SourceWriter, namespaces: set[str], classes: set[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
sorted_cls = list(sorted(classes))
|
sorted_cls = list(sorted(classes))
|
||||||
sorted_ns = list(sorted(namespaces))
|
sorted_ns = list(sorted(namespaces))
|
||||||
|
@ -46,14 +45,14 @@ def generate(fs: FakeFs, tl: ParsedTl) -> None:
|
||||||
|
|
||||||
ignored_types = {"true", "boolTrue", "boolFalse"} # also "compiler built-ins"
|
ignored_types = {"true", "boolTrue", "boolFalse"} # also "compiler built-ins"
|
||||||
|
|
||||||
abc_namespaces: Set[str] = set()
|
abc_namespaces: set[str] = set()
|
||||||
type_namespaces: Set[str] = set()
|
type_namespaces: set[str] = set()
|
||||||
function_namespaces: Set[str] = set()
|
function_namespaces: set[str] = set()
|
||||||
|
|
||||||
abc_class_names: Set[str] = set()
|
abc_class_names: set[str] = set()
|
||||||
type_class_names: Set[str] = set()
|
type_class_names: set[str] = set()
|
||||||
function_def_names: Set[str] = set()
|
function_def_names: set[str] = set()
|
||||||
generated_type_names: Set[str] = set()
|
generated_type_names: set[str] = set()
|
||||||
|
|
||||||
for typedef in tl.typedefs:
|
for typedef in tl.typedefs:
|
||||||
if typedef.ty.full_name not in generated_types:
|
if typedef.ty.full_name not in generated_types:
|
||||||
|
@ -193,10 +192,10 @@ def generate(fs: FakeFs, tl: ParsedTl) -> None:
|
||||||
writer.write(
|
writer.write(
|
||||||
"from .core import Serializable, Reader, deserialize_bool, deserialize_i32_list, deserialize_i64_list, deserialize_identity, single_deserializer, list_deserializer"
|
"from .core import Serializable, Reader, deserialize_bool, deserialize_i32_list, deserialize_i64_list, deserialize_identity, single_deserializer, list_deserializer"
|
||||||
)
|
)
|
||||||
writer.write("from typing import cast, Tuple, Type")
|
writer.write("from typing import cast, Type")
|
||||||
writer.write(f"LAYER = {tl.layer!r}")
|
writer.write(f"LAYER = {tl.layer!r}")
|
||||||
writer.write(
|
writer.write(
|
||||||
"TYPE_MAPPING = {t.constructor_id(): t for t in cast(Tuple[Type[Serializable]], ("
|
"TYPE_MAPPING = {t.constructor_id(): t for t in cast(tuple[Type[Serializable]], ("
|
||||||
)
|
)
|
||||||
for name in sorted(generated_type_names):
|
for name in sorted(generated_type_names):
|
||||||
writer.write(f" types.{name},")
|
writer.write(f" types.{name},")
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import re
|
import re
|
||||||
from typing import Iterator, List
|
from collections.abc import Iterator
|
||||||
|
|
||||||
from ....tl_parser import BaseParameter, FlagsParameter, NormalParameter, Type
|
from ....tl_parser import BaseParameter, FlagsParameter, NormalParameter, Type
|
||||||
|
|
||||||
|
|
||||||
def split_words(name: str) -> List[str]:
|
def split_words(name: str) -> list[str]:
|
||||||
return re.findall(
|
return re.findall(
|
||||||
r"""
|
r"""
|
||||||
^$
|
^$
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import struct
|
import struct
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from ....tl_parser import Definition, NormalParameter, Parameter, Type
|
from ....tl_parser import Definition, NormalParameter, Parameter, Type
|
||||||
from ..fakefs import SourceWriter
|
from ..fakefs import SourceWriter
|
||||||
|
@ -14,7 +14,7 @@ SPECIAL_CASED_OBJECT_READS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def reader_read_fmt(ty: Type, constructor_id: int) -> Tuple[str, Optional[str]]:
|
def reader_read_fmt(ty: Type, constructor_id: int) -> tuple[str, Optional[str]]:
|
||||||
if is_trivial(NormalParameter(ty=ty, flag=None)):
|
if is_trivial(NormalParameter(ty=ty, flag=None)):
|
||||||
fmt = trivial_struct_fmt(NormalParameter(ty=ty, flag=None))
|
fmt = trivial_struct_fmt(NormalParameter(ty=ty, flag=None))
|
||||||
size = struct.calcsize(f"<{fmt}")
|
size = struct.calcsize(f"<{fmt}")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import struct
|
import struct
|
||||||
|
from collections.abc import Iterator
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from typing import Iterator
|
|
||||||
|
|
||||||
from ....tl_parser import Definition, FlagsParameter, NormalParameter, Parameter, Type
|
from ....tl_parser import Definition, FlagsParameter, NormalParameter, Parameter, Type
|
||||||
from ..fakefs import SourceWriter
|
from ..fakefs import SourceWriter
|
||||||
|
@ -104,9 +104,11 @@ def generate_write(writer: SourceWriter, defn: Definition) -> None:
|
||||||
for param in group:
|
for param in group:
|
||||||
if isinstance(param.ty, FlagsParameter):
|
if isinstance(param.ty, FlagsParameter):
|
||||||
flags = " | ".join(
|
flags = " | ".join(
|
||||||
f"({1 << p.ty.flag.index} if self.{p.name} else 0)"
|
(
|
||||||
if p.ty.ty.name == "true"
|
f"({1 << p.ty.flag.index} if self.{p.name} else 0)"
|
||||||
else f"(0 if self.{p.name} is None else {1 << p.ty.flag.index})"
|
if p.ty.ty.name == "true"
|
||||||
|
else f"(0 if self.{p.name} is None else {1 << p.ty.flag.index})"
|
||||||
|
)
|
||||||
for p in defn.params
|
for p in defn.params
|
||||||
if isinstance(p.ty, NormalParameter)
|
if isinstance(p.ty, NormalParameter)
|
||||||
and p.ty.flag
|
and p.ty.flag
|
||||||
|
@ -140,9 +142,11 @@ def generate_function(writer: SourceWriter, defn: Definition) -> None:
|
||||||
for param in group:
|
for param in group:
|
||||||
if isinstance(param.ty, FlagsParameter):
|
if isinstance(param.ty, FlagsParameter):
|
||||||
flags = " | ".join(
|
flags = " | ".join(
|
||||||
f"({1 << p.ty.flag.index} if {p.name} else 0)"
|
(
|
||||||
if p.ty.ty.name == "true"
|
f"({1 << p.ty.flag.index} if {p.name} else 0)"
|
||||||
else f"(0 if {p.name} is None else {1 << p.ty.flag.index})"
|
if p.ty.ty.name == "true"
|
||||||
|
else f"(0 if {p.name} is None else {1 << p.ty.flag.index})"
|
||||||
|
)
|
||||||
for p in defn.params
|
for p in defn.params
|
||||||
if isinstance(p.ty, NormalParameter)
|
if isinstance(p.ty, NormalParameter)
|
||||||
and p.ty.flag
|
and p.ty.flag
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Union
|
from typing import Optional
|
||||||
|
|
||||||
from .tl import Definition
|
from .tl import Definition
|
||||||
from .tl_iterator import FunctionDef, TypeDef, iterate
|
from .tl_iterator import FunctionDef, TypeDef, iterate
|
||||||
|
@ -10,13 +10,13 @@ from .tl_iterator import FunctionDef, TypeDef, iterate
|
||||||
@dataclass
|
@dataclass
|
||||||
class ParsedTl:
|
class ParsedTl:
|
||||||
layer: Optional[int]
|
layer: Optional[int]
|
||||||
typedefs: List[Definition]
|
typedefs: list[Definition]
|
||||||
functiondefs: List[Definition]
|
functiondefs: list[Definition]
|
||||||
|
|
||||||
|
|
||||||
def load_tl_file(path: Union[str, Path]) -> ParsedTl:
|
def load_tl_file(path: str | Path) -> ParsedTl:
|
||||||
typedefs: List[TypeDef] = []
|
typedefs: list[TypeDef] = []
|
||||||
functiondefs: List[FunctionDef] = []
|
functiondefs: list[FunctionDef] = []
|
||||||
with open(path, "r", encoding="utf-8") as fd:
|
with open(path, "r", encoding="utf-8") as fd:
|
||||||
contents = fd.read()
|
contents = fd.read()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List, Self, Set
|
from typing import Self
|
||||||
|
|
||||||
from ..utils import infer_id
|
from ..utils import infer_id
|
||||||
from .parameter import Parameter, TypeDefNotImplemented
|
from .parameter import Parameter, TypeDefNotImplemented
|
||||||
|
@ -9,10 +9,10 @@ from .ty import Type
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Definition:
|
class Definition:
|
||||||
namespace: List[str]
|
namespace: list[str]
|
||||||
name: str
|
name: str
|
||||||
id: int
|
id: int
|
||||||
params: List[Parameter]
|
params: list[Parameter]
|
||||||
ty: Type
|
ty: Type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -58,9 +58,9 @@ class Definition:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError("invalid id")
|
raise ValueError("invalid id")
|
||||||
|
|
||||||
type_defs: List[str] = []
|
type_defs: list[str] = []
|
||||||
flag_defs: List[str] = []
|
flag_defs: list[str] = []
|
||||||
params: List[Parameter] = []
|
params: list[Parameter] = []
|
||||||
|
|
||||||
for param_str in middle.split():
|
for param_str in middle.split():
|
||||||
try:
|
try:
|
||||||
|
@ -102,7 +102,7 @@ class Definition:
|
||||||
res += f"{ns}."
|
res += f"{ns}."
|
||||||
res += f"{self.name}#{self.id:x}"
|
res += f"{self.name}#{self.id:x}"
|
||||||
|
|
||||||
def_set: Set[str] = set()
|
def_set: set[str] = set()
|
||||||
for param in self.params:
|
for param in self.params:
|
||||||
if isinstance(param.ty, NormalParameter):
|
if isinstance(param.ty, NormalParameter):
|
||||||
def_set.update(param.ty.ty.find_generic_refs())
|
def_set.update(param.ty.ty.find_generic_refs())
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, Union
|
from typing import Optional
|
||||||
|
|
||||||
from .flag import Flag
|
from .flag import Flag
|
||||||
from .ty import Type
|
from .ty import Type
|
||||||
|
@ -8,7 +10,7 @@ from .ty import Type
|
||||||
|
|
||||||
class BaseParameter(ABC):
|
class BaseParameter(ABC):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_str(ty: str) -> Union["FlagsParameter", "NormalParameter"]:
|
def from_str(ty: str) -> FlagsParameter | NormalParameter:
|
||||||
if not ty:
|
if not ty:
|
||||||
raise ValueError("empty")
|
raise ValueError("empty")
|
||||||
if ty == "#":
|
if ty == "#":
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
from collections.abc import Iterator
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Iterator, List, Optional, Self
|
from typing import Optional, Self
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Type:
|
class Type:
|
||||||
namespace: List[str]
|
namespace: list[str]
|
||||||
name: str
|
name: str
|
||||||
bare: bool
|
bare: bool
|
||||||
generic_ref: bool
|
generic_ref: bool
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from typing import Iterator, Type
|
from collections.abc import Iterator
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
from .tl.definition import Definition
|
from .tl.definition import Definition
|
||||||
from .utils import remove_tl_comments
|
from .utils import remove_tl_comments
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from pytest import mark
|
from pytest import mark
|
||||||
from telethon_generator._impl.codegen.serde.common import (
|
from telethon_generator._impl.codegen.serde.common import (
|
||||||
split_words,
|
split_words,
|
||||||
|
@ -19,7 +17,7 @@ from telethon_generator._impl.codegen.serde.common import (
|
||||||
("fileMp4", ["file", "Mp4"]),
|
("fileMp4", ["file", "Mp4"]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_split_name_words(name: str, expected: List[str]) -> None:
|
def test_split_name_words(name: str, expected: list[str]) -> None:
|
||||||
assert split_words(name) == expected
|
assert split_words(name) == expected
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
from typing import List, Optional
|
from typing import Optional
|
||||||
|
|
||||||
from telethon_generator.codegen import FakeFs, generate
|
from telethon_generator.codegen import FakeFs, generate
|
||||||
from telethon_generator.tl_parser import Definition, ParsedTl, parse_tl_file
|
from telethon_generator.tl_parser import Definition, ParsedTl, parse_tl_file
|
||||||
|
|
||||||
|
|
||||||
def get_definitions(contents: str) -> List[Definition]:
|
def get_definitions(contents: str) -> list[Definition]:
|
||||||
return [defn for defn in parse_tl_file(contents) if not isinstance(defn, Exception)]
|
return [defn for defn in parse_tl_file(contents) if not isinstance(defn, Exception)]
|
||||||
|
|
||||||
|
|
||||||
def gen_py_code(
|
def gen_py_code(
|
||||||
*,
|
*,
|
||||||
typedefs: Optional[List[Definition]] = None,
|
typedefs: Optional[list[Definition]] = None,
|
||||||
functiondefs: Optional[List[Definition]] = None,
|
functiondefs: Optional[list[Definition]] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
fs = FakeFs()
|
fs = FakeFs()
|
||||||
generate(
|
generate(
|
||||||
|
|
|
@ -15,12 +15,11 @@ import ast
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Union
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionMethodsVisitor(ast.NodeVisitor):
|
class FunctionMethodsVisitor(ast.NodeVisitor):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.methods: List[Union[ast.FunctionDef, ast.AsyncFunctionDef]] = []
|
self.methods: list[ast.FunctionDef | ast.AsyncFunctionDef] = []
|
||||||
|
|
||||||
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
||||||
self._try_add_def(node)
|
self._try_add_def(node)
|
||||||
|
@ -28,7 +27,7 @@ class FunctionMethodsVisitor(ast.NodeVisitor):
|
||||||
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
||||||
self._try_add_def(node)
|
self._try_add_def(node)
|
||||||
|
|
||||||
def _try_add_def(self, node: Union[ast.FunctionDef, ast.AsyncFunctionDef]) -> None:
|
def _try_add_def(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None:
|
||||||
match node.args.args:
|
match node.args.args:
|
||||||
case [ast.arg(arg="self", annotation=ast.Name(id="Client")), *_]:
|
case [ast.arg(arg="self", annotation=ast.Name(id="Client")), *_]:
|
||||||
self.methods.append(node)
|
self.methods.append(node)
|
||||||
|
@ -39,7 +38,7 @@ class FunctionMethodsVisitor(ast.NodeVisitor):
|
||||||
class MethodVisitor(ast.NodeVisitor):
|
class MethodVisitor(ast.NodeVisitor):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._in_client = False
|
self._in_client = False
|
||||||
self.method_docs: Dict[str, str] = {}
|
self.method_docs: dict[str, str] = {}
|
||||||
|
|
||||||
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
||||||
if node.name == "Client":
|
if node.name == "Client":
|
||||||
|
@ -55,7 +54,7 @@ class MethodVisitor(ast.NodeVisitor):
|
||||||
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
||||||
self._try_add_doc(node)
|
self._try_add_doc(node)
|
||||||
|
|
||||||
def _try_add_doc(self, node: Union[ast.FunctionDef, ast.AsyncFunctionDef]) -> None:
|
def _try_add_doc(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None:
|
||||||
if not self._in_client:
|
if not self._in_client:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -86,10 +85,10 @@ def main() -> None:
|
||||||
|
|
||||||
m_visitor.visit(ast.parse(contents))
|
m_visitor.visit(ast.parse(contents))
|
||||||
|
|
||||||
class_body: List[ast.stmt] = []
|
class_body: list[ast.stmt] = []
|
||||||
|
|
||||||
for function in sorted(fm_visitor.methods, key=lambda f: f.name):
|
for function in sorted(fm_visitor.methods, key=lambda f: f.name):
|
||||||
function_body: List[ast.stmt] = []
|
function_body: list[ast.stmt] = []
|
||||||
if doc := m_visitor.method_docs.get(function.name):
|
if doc := m_visitor.method_docs.get(function.name):
|
||||||
function.body.append(ast.Expr(value=ast.Constant(value=doc)))
|
function.body.append(ast.Expr(value=ast.Constant(value=doc)))
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,11 @@ import ast
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
|
||||||
|
|
||||||
|
|
||||||
class ImportVisitor(ast.NodeVisitor):
|
class ImportVisitor(ast.NodeVisitor):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.imported_names: List[str] = []
|
self.imported_names: list[str] = []
|
||||||
|
|
||||||
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
||||||
if node.level == 1:
|
if node.level == 1:
|
||||||
|
@ -26,7 +25,7 @@ def main() -> None:
|
||||||
rf"(tl|mtproto){re.escape(os.path.sep)}(abcs|functions|types)"
|
rf"(tl|mtproto){re.escape(os.path.sep)}(abcs|functions|types)"
|
||||||
)
|
)
|
||||||
|
|
||||||
files: List[str] = []
|
files: list[str] = []
|
||||||
for file in impl_root.rglob("__init__.py"):
|
for file in impl_root.rglob("__init__.py"):
|
||||||
file_str = str(file)
|
file_str = str(file)
|
||||||
if autogenerated_re.search(file_str):
|
if autogenerated_re.search(file_str):
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
from typing import List
|
|
||||||
|
|
||||||
class AES:
|
class AES:
|
||||||
def __init__(self, key: bytes) -> None: ...
|
def __init__(self, key: bytes) -> None: ...
|
||||||
def encrypt(self, plaintext: List[int]) -> List[int]: ...
|
def encrypt(self, plaintext: list[int]) -> list[int]: ...
|
||||||
def decrypt(self, ciphertext: List[int]) -> List[int]: ...
|
def decrypt(self, ciphertext: list[int]) -> list[int]: ...
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
def build_wheel(
|
def build_wheel(
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
def build_sdist(
|
def build_sdist(
|
||||||
sdist_directory: str, config_settings: Optional[Dict[Any, Any]] = None
|
sdist_directory: str, config_settings: Optional[dict[Any, Any]] = None
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
def build_editable(
|
def build_editable(
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
class build_meta:
|
class build_meta:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_wheel(
|
def build_wheel(
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_sdist(
|
def build_sdist(
|
||||||
sdist_directory: str, config_settings: Optional[Dict[Any, Any]] = None
|
sdist_directory: str, config_settings: Optional[dict[Any, Any]] = None
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_editable(
|
def build_editable(
|
||||||
wheel_directory: str,
|
wheel_directory: str,
|
||||||
config_settings: Optional[Dict[Any, Any]] = None,
|
config_settings: Optional[dict[Any, Any]] = None,
|
||||||
metadata_directory: Optional[str] = None,
|
metadata_directory: Optional[str] = None,
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
|
|
Loading…
Reference in New Issue
Block a user