Begin preparing client for documentation

This commit is contained in:
Lonami Exo 2023-09-13 19:00:47 +02:00
parent 80fefca2e9
commit e36c35c805
8 changed files with 165 additions and 15 deletions

View File

@ -1,6 +1,7 @@
from ._impl import tl as _tl from ._impl import tl as _tl
from ._impl.client import Client, Config from ._impl.client import Client, Config
from ._impl.mtproto import RpcError
from ._impl.session import Session from ._impl.session import Session
from .version import __version__ from .version import __version__
__all__ = ["_tl", "Client", "Config", "Session"] __all__ = ["_tl", "Client", "Config", "RpcError", "Session"]

View File

@ -33,6 +33,7 @@ from ..events import Event
from ..events.filters import Filter from ..events.filters import Filter
from ..types import ( from ..types import (
AsyncList, AsyncList,
Chat,
ChatLike, ChatLike,
File, File,
InFileLike, InFileLike,
@ -46,6 +47,7 @@ from ..types import (
from .auth import ( from .auth import (
bot_sign_in, bot_sign_in,
check_password, check_password,
interactive_login,
is_authorized, is_authorized,
request_login_code, request_login_code,
sign_in, sign_in,
@ -92,7 +94,13 @@ from .updates import (
remove_event_handler, remove_event_handler,
set_handler_filter, set_handler_filter,
) )
from .users import get_me, input_to_peer, resolve_to_packed from .users import (
get_contacts,
get_me,
input_to_peer,
resolve_to_packed,
resolve_username,
)
Return = TypeVar("Return") Return = TypeVar("Return")
T = TypeVar("T") T = TypeVar("T")
@ -169,6 +177,12 @@ class Client:
await disconnect(self) await disconnect(self)
async def download(self, media: MediaLike, file: OutFileLike) -> None: async def download(self, media: MediaLike, file: OutFileLike) -> None:
"""
Download a file.
This is simply a more convenient method to `iter_download`,
as it will handle dealing with the file chunks and writes by itself.
"""
await download(self, media, file) await download(self, media, file)
async def edit_message( async def edit_message(
@ -196,6 +210,9 @@ class Client:
) -> List[Message]: ) -> List[Message]:
return await forward_messages(self, target, message_ids, source) return await forward_messages(self, target, message_ids, source)
async def get_contacts(self) -> AsyncList[User]:
return await get_contacts(self)
def get_dialogs(self) -> None: def get_dialogs(self) -> None:
get_dialogs(self) get_dialogs(self)
@ -232,6 +249,9 @@ class Client:
) -> AsyncIterator[InlineResult]: ) -> AsyncIterator[InlineResult]:
return await inline_query(self, bot, query, chat=chat) return await inline_query(self, bot, query, chat=chat)
async def interactive_login(self) -> User:
return await interactive_login(self)
async def is_authorized(self) -> bool: async def is_authorized(self) -> bool:
return await is_authorized(self) return await is_authorized(self)
@ -257,6 +277,9 @@ class Client:
async def resolve_to_packed(self, chat: ChatLike) -> PackedChat: async def resolve_to_packed(self, chat: ChatLike) -> PackedChat:
return await resolve_to_packed(self, chat) return await resolve_to_packed(self, chat)
async def resolve_username(self) -> Chat:
return await resolve_username(self)
async def run_until_disconnected(self) -> None: async def run_until_disconnected(self) -> None:
await run_until_disconnected(self) await run_until_disconnected(self)
@ -299,6 +322,12 @@ class Client:
title: Optional[str] = None, title: Optional[str] = None,
performer: Optional[str] = None, performer: Optional[str] = None,
) -> Message: ) -> Message:
"""
Send an audio file.
Unlike `send_file`, this method will attempt to guess the values for
duration, title and performer if they are not provided.
"""
return await send_audio( return await send_audio(
self, self,
chat, chat,
@ -340,6 +369,19 @@ class Client:
caption_markdown: Optional[str] = None, caption_markdown: Optional[str] = None,
caption_html: Optional[str] = None, caption_html: Optional[str] = None,
) -> Message: ) -> Message:
"""
Send any type of file with any amount of attributes.
This method will not attempt to guess any of the file metadata such as
width, duration, title, etc. If you want to let the library attempt to
guess the file metadata, use the type-specific methods to send media:
`send_photo`, `send_audio` or `send_file`.
Unlike `send_photo`, image files will be sent as documents by default.
The parameters are used to construct a `File`. See the documentation
for `File.new` to learn what they do and when they are in effect.
"""
return await send_file( return await send_file(
self, self,
chat, chat,
@ -398,6 +440,20 @@ class Client:
width: Optional[int] = None, width: Optional[int] = None,
height: Optional[int] = None, height: Optional[int] = None,
) -> Message: ) -> Message:
"""
Send a photo file.
Exactly one of path, url or file must be specified.
A `File` can also be used as the second parameter.
By default, the server will be allowed to `compress` the image.
Only compressed images can be displayed as photos in applications.
Images that cannot be compressed will be sent as file documents,
with a thumbnail if possible.
Unlike `send_file`, this method will attempt to guess the values for
width and height if they are not provided and the can't be compressed.
"""
return await send_photo( return await send_photo(
self, self,
chat, chat,
@ -426,6 +482,12 @@ class Client:
round: bool = False, round: bool = False,
supports_streaming: bool = False, supports_streaming: bool = False,
) -> Message: ) -> Message:
"""
Send a video file.
Unlike `send_file`, this method will attempt to guess the values for
duration, width and height if they are not provided.
"""
return await send_video( return await send_video(
self, self,
chat, chat,

View File

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Optional
from ...session import PackedChat, PackedType from ...session import PackedChat, PackedType
from ...tl import abcs, types from ...tl import abcs, types
from ..types import Channel, ChatLike, Group, User from ..types import AsyncList, Channel, Chat, ChatLike, Group, User
if TYPE_CHECKING: if TYPE_CHECKING:
from .client import Client from .client import Client
@ -15,6 +15,16 @@ async def get_me(self: Client) -> User:
raise NotImplementedError raise NotImplementedError
async def get_contacts(self: Client) -> AsyncList[User]:
self
raise NotImplementedError
async def resolve_username(self: Client) -> Chat:
self
raise NotImplementedError
async def resolve_to_packed(self: Client, chat: ChatLike) -> PackedChat: async def resolve_to_packed(self: Client, chat: ChatLike) -> PackedChat:
if isinstance(chat, (User, Group, Channel)): if isinstance(chat, (User, Group, Channel)):
packed = chat.pack() packed = chat.pack()

View File

@ -1,12 +1,11 @@
from typing import Union from typing import Union
from ....session import PackedChat from ....session import PackedChat
from ....tl import abcs
from .channel import Channel from .channel import Channel
from .group import Group from .group import Group
from .user import RestrictionReason, User from .user import RestrictionReason, User
Chat = Union[Channel, Group, User] Chat = Union[Channel, Group, User]
ChatLike = Union[Chat, PackedChat, int, str, abcs.InputPeer] ChatLike = Union[Chat, PackedChat, int, str]
__all__ = ["Chat", "ChatLike", "Channel", "Group", "RestrictionReason", "User"] __all__ = ["Chat", "ChatLike", "Channel", "Group", "RestrictionReason", "User"]

View File

@ -41,6 +41,10 @@ class Message(metaclass=NoPublicConstructor):
def chat(self) -> Chat: def chat(self) -> Chat:
raise NotImplementedError raise NotImplementedError
@property
def sender(self) -> Chat:
raise NotImplementedError
def _file(self) -> Optional[File]: def _file(self) -> Optional[File]:
return ( return (
File._try_from_raw(self._raw.media) File._try_from_raw(self._raw.media)

View File

@ -20,10 +20,22 @@ class RpcError(ValueError):
append_value = f" ({value})" if value else None append_value = f" ({value})" if value else None
super().__init__(f"rpc error {code}: {name}{append_value}") super().__init__(f"rpc error {code}: {name}{append_value}")
self.code = code self._code = code
self.name = name self._name = name
self.value = value self._value = value
self.caused_by = caused_by self._caused_by = caused_by
@property
def code(self) -> int:
return self._code
@property
def name(self) -> str:
return self._name
@property
def value(self) -> Optional[int]:
return self._value
@classmethod @classmethod
def from_mtproto_error(cls, error: GeneratedRpcError) -> Self: def from_mtproto_error(cls, error: GeneratedRpcError) -> Self:
@ -49,9 +61,9 @@ class RpcError(ValueError):
if not isinstance(other, self.__class__): if not isinstance(other, self.__class__):
return NotImplemented return NotImplemented
return ( return (
self.code == other.code self._code == other._code
and self.name == other.name and self._name == other._name
and self.value == other.value and self._value == other._value
) )
@ -64,13 +76,17 @@ class BadMessage(ValueError):
) -> None: ) -> None:
super().__init__(f"bad msg: {code}") super().__init__(f"bad msg: {code}")
self.code = code self._code = code
self.caused_by = caused_by self._caused_by = caused_by
@property
def code(self) -> int:
return self._code
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
if not isinstance(other, self.__class__): if not isinstance(other, self.__class__):
return NotImplemented return NotImplemented
return self.code == other.code return self._code == other._code
RpcResult = bytes | RpcError | BadMessage RpcResult = bytes | RpcError | BadMessage

View File

@ -0,0 +1,21 @@
from ._impl.session import (
ChannelState,
DataCenter,
MemorySession,
Session,
SqliteSession,
Storage,
UpdateState,
User,
)
__all__ = [
"ChannelState",
"DataCenter",
"MemorySession",
"Session",
"SqliteSession",
"Storage",
"UpdateState",
"User",
]

View File

@ -0,0 +1,37 @@
from ._impl.client.types import (
AsyncList,
Channel,
Chat,
ChatLike,
File,
Group,
InFileLike,
LoginToken,
MediaLike,
Message,
NoPublicConstructor,
OutFileLike,
PasswordToken,
RestrictionReason,
User,
)
from ._impl.session import PackedChat
__all__ = [
"AsyncList",
"Channel",
"Chat",
"ChatLike",
"File",
"Group",
"InFileLike",
"LoginToken",
"MediaLike",
"Message",
"NoPublicConstructor",
"OutFileLike",
"PasswordToken",
"RestrictionReason",
"User",
"PackedChat",
]