mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-01-24 16:24:15 +03:00
Document most methods and classes
This commit is contained in:
parent
569ff3d372
commit
604d95a807
|
@ -11,6 +11,9 @@ Glossary
|
||||||
|
|
||||||
.. seealso:: The :doc:`../concepts/chats` concept.
|
.. seealso:: The :doc:`../concepts/chats` concept.
|
||||||
|
|
||||||
|
yourself
|
||||||
|
The logged-in account, whether that represents a bot or a user with a phone number.
|
||||||
|
|
||||||
Raw API
|
Raw API
|
||||||
Functions and types under ``telethon._tl`` that enable access to all of Telegram's API.
|
Functions and types under ``telethon._tl`` that enable access to all of Telegram's API.
|
||||||
|
|
||||||
|
|
|
@ -128,11 +128,8 @@ async def sign_in(
|
||||||
|
|
||||||
|
|
||||||
async def interactive_login(self: Client) -> User:
|
async def interactive_login(self: Client) -> User:
|
||||||
try:
|
if me := await self.get_me():
|
||||||
return await self.get_me()
|
return me
|
||||||
except RpcError as e:
|
|
||||||
if e.code != 401:
|
|
||||||
raise
|
|
||||||
|
|
||||||
phone_or_token = ""
|
phone_or_token = ""
|
||||||
while not re.match(r"\+?[\s()]*\d", phone_or_token):
|
while not re.match(r"\+?[\s()]*\d", phone_or_token):
|
||||||
|
|
|
@ -11,6 +11,10 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class InlineResults(metaclass=NoPublicConstructor):
|
class InlineResults(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
:final:
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
client: Client,
|
client: Client,
|
||||||
|
@ -119,7 +123,7 @@ class InlineResult(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
|
|
||||||
async def inline_query(
|
async def inline_query(
|
||||||
self: Client, bot: ChatLike, query: str, *, chat: Optional[ChatLike] = None
|
self: Client, bot: ChatLike, query: str = "", *, chat: Optional[ChatLike] = None
|
||||||
) -> AsyncIterator[InlineResult]:
|
) -> AsyncIterator[InlineResult]:
|
||||||
packed_bot = await self._resolve_to_packed(bot)
|
packed_bot = await self._resolve_to_packed(bot)
|
||||||
packed_chat = await self._resolve_to_packed(chat) if chat else None
|
packed_chat = await self._resolve_to_packed(chat) if chat else None
|
||||||
|
|
|
@ -107,6 +107,59 @@ T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
"""
|
||||||
|
A client capable of connecting to Telegram and sending requests.
|
||||||
|
|
||||||
|
This is the "entry point" of the library.
|
||||||
|
|
||||||
|
This class can be used as an asynchronous context manager to automatically :meth:`connect` and :meth:`disconnect`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async with Client(session, api_id, api_hash) as client:
|
||||||
|
... # automatically connect()-ed
|
||||||
|
|
||||||
|
... # after exiting the block, disconnect() was automatically called
|
||||||
|
|
||||||
|
:param session:
|
||||||
|
A name or path to a ``.session`` file, or a different storage.
|
||||||
|
|
||||||
|
:param api_id:
|
||||||
|
The API ID. See :doc:`/basic/signing-in` to learn how to obtain it.
|
||||||
|
|
||||||
|
:param api_hash:
|
||||||
|
The API hash. See :doc:`/basic/signing-in` to learn how to obtain it.
|
||||||
|
|
||||||
|
:param device_model:
|
||||||
|
Device model.
|
||||||
|
|
||||||
|
:param system_version:
|
||||||
|
System version.
|
||||||
|
|
||||||
|
:param app_version:
|
||||||
|
Application version.
|
||||||
|
|
||||||
|
:param system_lang_code:
|
||||||
|
ISO 639-1 language code of the system's language.
|
||||||
|
|
||||||
|
:param lang_code:
|
||||||
|
ISO 639-1 language code of the application's language.
|
||||||
|
|
||||||
|
:param catch_up:
|
||||||
|
Whether to "catch up" on updates that occured while the client was not connected.
|
||||||
|
|
||||||
|
:param server_addr:
|
||||||
|
Override the server address ``'ip:port'`` pair to connect to.
|
||||||
|
Useful to connect to one of Telegram's test servers.
|
||||||
|
|
||||||
|
:param flood_sleep_threshold:
|
||||||
|
Maximum amount of time, in seconds, to automatically sleep before retrying a request.
|
||||||
|
This sleeping occurs when ``FLOOD_WAIT`` :class:`~telethon.RpcError` is raised by Telegram.
|
||||||
|
|
||||||
|
:param update_queue_limit:
|
||||||
|
Maximum amount of updates to keep in memory before dropping them.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
session: Optional[Union[str, Path, Storage]],
|
session: Optional[Union[str, Path, Storage]],
|
||||||
|
@ -152,17 +205,114 @@ class Client:
|
||||||
event_cls: Type[Event],
|
event_cls: Type[Event],
|
||||||
filter: Optional[Filter] = None,
|
filter: Optional[Filter] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Register a callable to be invoked when the provided event type occurs.
|
||||||
|
|
||||||
|
:param handler:
|
||||||
|
The callable to invoke when an event occurs.
|
||||||
|
This is often just a function object.
|
||||||
|
|
||||||
|
:param event_cls:
|
||||||
|
The event type to bind to the handler.
|
||||||
|
When Telegram sends an update corresponding to this type,
|
||||||
|
*handler* is called with an instance of this event type as the only argument.
|
||||||
|
|
||||||
|
:param filter:
|
||||||
|
Filter function to call with the event before calling *handler*.
|
||||||
|
If it returns `False`, *handler* will not be called.
|
||||||
|
See the :mod:`~telethon.events.filters` module to learn more.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def my_print_handler(event):
|
||||||
|
print(event.chat.full_name, event.text)
|
||||||
|
|
||||||
|
# Register a handler to be called on new messages
|
||||||
|
client.add_event_handler(my_print_handler, events.NewMessage)
|
||||||
|
|
||||||
|
# Register a handler to be called on new messages if they contain "hello" or "/start"
|
||||||
|
from telethon.events import filters
|
||||||
|
|
||||||
|
client.add_event_handler(
|
||||||
|
my_print_handler,
|
||||||
|
events.NewMessage,
|
||||||
|
filters.Any(filters.Text(r'hello'), filters.Command('/start')),
|
||||||
|
)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`on`, used to register handlers with the decorator syntax.
|
||||||
|
"""
|
||||||
add_event_handler(self, handler, event_cls, filter)
|
add_event_handler(self, handler, event_cls, filter)
|
||||||
|
|
||||||
async def bot_sign_in(self, token: str) -> User:
|
async def bot_sign_in(self, token: str) -> User:
|
||||||
|
"""
|
||||||
|
Sign in to a bot account.
|
||||||
|
|
||||||
|
:param token:
|
||||||
|
The bot token obtained from `@BotFather <https://t.me/BotFather>`_.
|
||||||
|
It's a string composed of digits, a colon, and characters from the base-64 alphabet.
|
||||||
|
|
||||||
|
:return: The bot user corresponding to :term:`yourself`.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await client.bot_sign_in('12345:abc67DEF89ghi')
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`request_login_code`, used to sign in as a user instead.
|
||||||
|
"""
|
||||||
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: Union[str, bytes]
|
self, token: PasswordToken, password: Union[str, bytes]
|
||||||
) -> User:
|
) -> User:
|
||||||
|
"""
|
||||||
|
Check the two-factor-authentication (2FA) password.
|
||||||
|
If it is correct, completes the login.
|
||||||
|
|
||||||
|
:param token:
|
||||||
|
The return value from :meth:`sign_in`.
|
||||||
|
|
||||||
|
:param password:
|
||||||
|
The 2FA password.
|
||||||
|
|
||||||
|
:return: The user corresponding to :term:`yourself`.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon.types import PasswordToken
|
||||||
|
|
||||||
|
login_token = await client.request_login_code('+1 23 456')
|
||||||
|
password_token = await client.sign_in(login_token, input('code: '))
|
||||||
|
assert isinstance(password_token, PasswordToken)
|
||||||
|
|
||||||
|
user = await client.check_password(password_token, '1-L0V3+T3l3th0n')
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`request_login_code` and :meth:`sign_in`
|
||||||
|
"""
|
||||||
return await check_password(self, token, password)
|
return await check_password(self, token, password)
|
||||||
|
|
||||||
async def connect(self) -> None:
|
async def connect(self) -> None:
|
||||||
|
"""
|
||||||
|
Connect to the Telegram servers.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await client.connect()
|
||||||
|
# success!
|
||||||
|
"""
|
||||||
await connect(self)
|
await connect(self)
|
||||||
|
|
||||||
async def delete_dialog(self) -> None:
|
async def delete_dialog(self) -> None:
|
||||||
|
@ -171,17 +321,84 @@ class Client:
|
||||||
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.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the messages are.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When deleting messages from private conversations or small groups,
|
||||||
|
this parameter is ignored. This means the *message_ids* may delete
|
||||||
|
messages in different chats.
|
||||||
|
|
||||||
|
:param message_ids:
|
||||||
|
The list of message identifiers to delete.
|
||||||
|
|
||||||
|
:param revoke:
|
||||||
|
When set to :data:`True`, the message will be deleted for everyone that is part of *chat*.
|
||||||
|
Otherwise, the message will only be deleted for :term:`yourself`.
|
||||||
|
|
||||||
|
:return: The amount of messages that were deleted.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Delete two messages from chat for yourself
|
||||||
|
await client.delete_messages(
|
||||||
|
chat,
|
||||||
|
[187481, 187482],
|
||||||
|
revoke=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Message.delete`
|
||||||
|
"""
|
||||||
return await delete_messages(self, chat, message_ids, revoke=revoke)
|
return await delete_messages(self, chat, message_ids, revoke=revoke)
|
||||||
|
|
||||||
async def disconnect(self) -> None:
|
async def disconnect(self) -> None:
|
||||||
|
"""
|
||||||
|
Disconnect from the Telegram servers.
|
||||||
|
|
||||||
|
This call will only fail if saving the :term:`session` fails.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await client.disconnect()
|
||||||
|
# success!
|
||||||
|
"""
|
||||||
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.
|
Download a file.
|
||||||
|
|
||||||
This is simply a more convenient method to `iter_download`,
|
:param media:
|
||||||
as it will handle dealing with the file chunks and writes by itself.
|
The media to download.
|
||||||
|
This will often come from :attr:`telethon.types.Message.file`.
|
||||||
|
|
||||||
|
:param file:
|
||||||
|
The output file path or :term:`file-like object`.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
if photo := message.photo:
|
||||||
|
await client.download(photo, 'picture.jpg')
|
||||||
|
|
||||||
|
if video := message.video:
|
||||||
|
with open('video.mp4, 'wb') as file:
|
||||||
|
await client.download(video, file)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`iter_download`, for fine-grained control over the download.
|
||||||
"""
|
"""
|
||||||
await download(self, media, file)
|
await download(self, media, file)
|
||||||
|
|
||||||
|
@ -195,6 +412,33 @@ class Client:
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: Optional[bool] = None,
|
link_preview: Optional[bool] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
|
"""
|
||||||
|
Edit a message.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message to edit is.
|
||||||
|
|
||||||
|
:param message_id:
|
||||||
|
The identifier of the message to edit.
|
||||||
|
|
||||||
|
The rest of parameters behave the same as they do in `send_message` or `send_file`.
|
||||||
|
|
||||||
|
:return: The edited message.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Edit message to have text without formatting
|
||||||
|
await client.edit_message(chat, msg_id, text='New text')
|
||||||
|
|
||||||
|
# Remove the link preview without changing the text
|
||||||
|
await client.edit_message(chat, msg_id, link_preview=False)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Message.edit`
|
||||||
|
"""
|
||||||
return await edit_message(
|
return await edit_message(
|
||||||
self,
|
self,
|
||||||
chat,
|
chat,
|
||||||
|
@ -208,9 +452,50 @@ 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.
|
||||||
|
|
||||||
|
:param target:
|
||||||
|
The :term:`chat` where the messages will be forwarded to.
|
||||||
|
|
||||||
|
:param message_ids:
|
||||||
|
The list of message identifiers to forward.
|
||||||
|
|
||||||
|
:param source:
|
||||||
|
The source :term:`chat` where the messages to forward exist.
|
||||||
|
|
||||||
|
:return: The forwarded messages.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Forward two messages from chat to the destination
|
||||||
|
await client.forward_messages(
|
||||||
|
destination,
|
||||||
|
[187481, 187482],
|
||||||
|
chat,
|
||||||
|
)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`telethon.types.Message.forward_to`
|
||||||
|
"""
|
||||||
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]:
|
async def get_contacts(self) -> AsyncList[User]:
|
||||||
|
"""
|
||||||
|
Get the users in your contact list.
|
||||||
|
|
||||||
|
:return: Your contacts.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async for user in client.get_contacts():
|
||||||
|
print(user.full_name, user.id)
|
||||||
|
"""
|
||||||
return await get_contacts(self)
|
return await get_contacts(self)
|
||||||
|
|
||||||
def get_dialogs(self) -> None:
|
def get_dialogs(self) -> None:
|
||||||
|
@ -219,9 +504,51 @@ class Client:
|
||||||
def get_handler_filter(
|
def get_handler_filter(
|
||||||
self, handler: Callable[[Event], Awaitable[Any]]
|
self, handler: Callable[[Event], Awaitable[Any]]
|
||||||
) -> Optional[Filter]:
|
) -> Optional[Filter]:
|
||||||
|
"""
|
||||||
|
Get the filter associated to the given event handler.
|
||||||
|
|
||||||
|
:param handler:
|
||||||
|
The callable that was previously added as an event handler.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
The filter, if *handler* was actually registered and had a filter.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon.events import filters
|
||||||
|
|
||||||
|
# Get the current filter...
|
||||||
|
filt = client.get_handler_filter(my_handler)
|
||||||
|
|
||||||
|
# ...and "append" a new filter that also must match.
|
||||||
|
client.set_handler_filter(my_handler, filters.All(filt, filt.Text(r'test')))
|
||||||
|
"""
|
||||||
return get_handler_filter(self, handler)
|
return get_handler_filter(self, handler)
|
||||||
|
|
||||||
async def get_me(self) -> User:
|
async def get_me(self) -> Optional[User]:
|
||||||
|
"""
|
||||||
|
Get information about :term:`yourself`.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
The user associated with the logged-in account, or :data:`None` if the client is not authorized.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
me = await client.get_me()
|
||||||
|
assert me is not None, "not logged in!"
|
||||||
|
|
||||||
|
if me.bot:
|
||||||
|
print('I am a bot')
|
||||||
|
|
||||||
|
print('My name is', me.full_name)
|
||||||
|
|
||||||
|
if me.phone:
|
||||||
|
print('My phone number is', me.phone)
|
||||||
|
"""
|
||||||
return await get_me(self)
|
return await get_me(self)
|
||||||
|
|
||||||
def get_messages(
|
def get_messages(
|
||||||
|
@ -232,6 +559,40 @@ class Client:
|
||||||
offset_id: Optional[int] = None,
|
offset_id: Optional[int] = None,
|
||||||
offset_date: Optional[datetime.datetime] = None,
|
offset_date: Optional[datetime.datetime] = None,
|
||||||
) -> AsyncList[Message]:
|
) -> AsyncList[Message]:
|
||||||
|
"""
|
||||||
|
Get the message history from a :term:`chat`.
|
||||||
|
|
||||||
|
Edit a message.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message to edit is.
|
||||||
|
|
||||||
|
:param limit:
|
||||||
|
How many messages to fetch at most.
|
||||||
|
|
||||||
|
:param offset_id:
|
||||||
|
Start getting messages with an identifier lower than this one.
|
||||||
|
This means only messages older than the message with ``id = offset_id`` will be fetched.
|
||||||
|
|
||||||
|
:param offset_date:
|
||||||
|
Start getting messages with a date lower than this one.
|
||||||
|
This means only messages sent before *offset_date* will be fetched.
|
||||||
|
|
||||||
|
:return: The message history.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get the last message in a chat
|
||||||
|
last_message = (await client.get_messages(chat, 1))[0]
|
||||||
|
|
||||||
|
# Print all messages before 2023 as HTML
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
async for message in client.get_messages(chat, offset_date=datetime(2023, 1, 1)):
|
||||||
|
print(message.sender.full_name, ':', message.html_text)
|
||||||
|
"""
|
||||||
return get_messages(
|
return get_messages(
|
||||||
self, chat, limit, offset_id=offset_id, offset_date=offset_date
|
self, chat, limit, offset_id=offset_id, offset_date=offset_date
|
||||||
)
|
)
|
||||||
|
@ -245,14 +606,70 @@ class Client:
|
||||||
get_participants(self)
|
get_participants(self)
|
||||||
|
|
||||||
async def inline_query(
|
async def inline_query(
|
||||||
self, bot: ChatLike, query: str, *, chat: Optional[ChatLike] = None
|
self, bot: ChatLike, query: str = "", *, chat: Optional[ChatLike] = None
|
||||||
) -> AsyncIterator[InlineResult]:
|
) -> AsyncIterator[InlineResult]:
|
||||||
|
"""
|
||||||
|
Perform a *@bot inline query*.
|
||||||
|
|
||||||
|
It's known as inline because clients with a GUI display the results *inline*,
|
||||||
|
after typing on the message input textbox, without sending any message.
|
||||||
|
|
||||||
|
:param bot:
|
||||||
|
The bot to sent the query string to.
|
||||||
|
|
||||||
|
:param query:
|
||||||
|
The query string to send to the bot.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
Where the query is being made and will be sent.
|
||||||
|
Some bots display different results based on the type of chat.
|
||||||
|
|
||||||
|
:return: The query results returned by the bot.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
# This is equivalent to typing "@bot songs" in an official client
|
||||||
|
async for result in client.inline_query(bot, 'songs'):
|
||||||
|
if 'keyword' in result.title:
|
||||||
|
await result.send(chat)
|
||||||
|
break
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
if i == 10:
|
||||||
|
break # did not find 'keyword' in the first few results
|
||||||
|
"""
|
||||||
return await inline_query(self, bot, query, chat=chat)
|
return await inline_query(self, bot, query, chat=chat)
|
||||||
|
|
||||||
async def interactive_login(self) -> User:
|
async def interactive_login(self) -> User:
|
||||||
|
"""
|
||||||
|
Begin an interactive login if needed.
|
||||||
|
If the account was already logged-in, this method simply returns :term:`yourself`.
|
||||||
|
|
||||||
|
:return: The user corresponding to :term:`yourself`.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
me = await client.interactive_login()
|
||||||
|
print('Logged in as:', me.full_name)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
In-depth explanation for :doc:`/basic/signing-in`.
|
||||||
|
"""
|
||||||
return await interactive_login(self)
|
return await interactive_login(self)
|
||||||
|
|
||||||
async def is_authorized(self) -> bool:
|
async def is_authorized(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check whether the client instance is authorized (i.e. logged-in).
|
||||||
|
|
||||||
|
:return: :data:`True` if the client instance has signed-in.
|
||||||
|
"""
|
||||||
return await is_authorized(self)
|
return await is_authorized(self)
|
||||||
|
|
||||||
async def iter_download(self) -> None:
|
async def iter_download(self) -> None:
|
||||||
|
@ -263,18 +680,137 @@ class Client:
|
||||||
) -> Callable[
|
) -> Callable[
|
||||||
[Callable[[Event], Awaitable[Any]]], Callable[[Event], Awaitable[Any]]
|
[Callable[[Event], Awaitable[Any]]], Callable[[Event], Awaitable[Any]]
|
||||||
]:
|
]:
|
||||||
|
"""
|
||||||
|
Register the decorated function to be invoked when the provided event type occurs.
|
||||||
|
|
||||||
|
:param event_cls:
|
||||||
|
The event type to bind to the handler.
|
||||||
|
When Telegram sends an update corresponding to this type,
|
||||||
|
the decorated function is called with an instance of this event type as the only argument.
|
||||||
|
|
||||||
|
:param filter:
|
||||||
|
Filter function to call with the event before calling *handler*.
|
||||||
|
If it returns `False`, *handler* will not be called.
|
||||||
|
See the :mod:`~telethon.events.filters` module to learn more.
|
||||||
|
|
||||||
|
:return: The decorator.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Register a handler to be called on new messages
|
||||||
|
@client.on(events.NewMessage)
|
||||||
|
async def my_print_handler(event):
|
||||||
|
print(event.chat.full_name, event.text)
|
||||||
|
|
||||||
|
# Register a handler to be called on new messages if they contain "hello" or "/start"
|
||||||
|
from telethon.events.filters import Any, Text, Command
|
||||||
|
|
||||||
|
@client.on(events.NewMessage, Any(Text(r'hello'), Command('/start')))
|
||||||
|
async def my_other_print_handler(event):
|
||||||
|
print(event.chat.full_name, event.text)
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`add_event_handler`, used to register existing functions as event handlers.
|
||||||
|
"""
|
||||||
return on(self, event_cls, filter)
|
return on(self, event_cls, filter)
|
||||||
|
|
||||||
async def pin_message(self, chat: ChatLike, message_id: int) -> Message:
|
async def pin_message(self, chat: ChatLike, message_id: int) -> Message:
|
||||||
|
"""
|
||||||
|
Pin a message to be at the top.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message to pin is.
|
||||||
|
|
||||||
|
:param message_id:
|
||||||
|
The identifier of the message to pin.
|
||||||
|
|
||||||
|
:return: The service message announcing the pin.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Pin a message, then delete the service message
|
||||||
|
message = await client.pin_message(chat, 187481)
|
||||||
|
await message.delete()
|
||||||
|
"""
|
||||||
return await pin_message(self, chat, message_id)
|
return await pin_message(self, chat, message_id)
|
||||||
|
|
||||||
def remove_event_handler(self, handler: Callable[[Event], Awaitable[Any]]) -> None:
|
def remove_event_handler(self, handler: Callable[[Event], Awaitable[Any]]) -> None:
|
||||||
|
"""
|
||||||
|
Remove the handler as a function to be called when events occur.
|
||||||
|
This is simply the opposite of :meth:`add_event_handler`.
|
||||||
|
Does nothing if the handler was not actually registered.
|
||||||
|
|
||||||
|
:param handler:
|
||||||
|
The callable to stop invoking when events occur.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Register a handler that removes itself when it receives 'stop'
|
||||||
|
@client.on(events.NewMessage)
|
||||||
|
async def my_handler(event):
|
||||||
|
if 'stop' in event.text:
|
||||||
|
client.remove_event_handler(my_handler)
|
||||||
|
else:
|
||||||
|
print('still going!')
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`add_event_handler`, used to register existing functions as event handlers.
|
||||||
|
"""
|
||||||
remove_event_handler(self, handler)
|
remove_event_handler(self, handler)
|
||||||
|
|
||||||
async def request_login_code(self, phone: str) -> LoginToken:
|
async def request_login_code(self, phone: str) -> LoginToken:
|
||||||
|
"""
|
||||||
|
Request Telegram to send a login code to the provided phone number.
|
||||||
|
This is simply the opposite of :meth:`add_event_handler`.
|
||||||
|
Does nothing if the handler was not actually registered.
|
||||||
|
|
||||||
|
:param phone:
|
||||||
|
The phone number string, in international format.
|
||||||
|
The plus-sign ``+`` can be kept in the string.
|
||||||
|
|
||||||
|
:return: Information about the sent code.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
login_token = await client.request_login_code('+1 23 456...')
|
||||||
|
print(login_token.timeout, 'seconds before code expires')
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`sign_in`, to complete the login procedure.
|
||||||
|
"""
|
||||||
return await request_login_code(self, phone)
|
return await request_login_code(self, phone)
|
||||||
|
|
||||||
async def resolve_to_packed(self, chat: ChatLike) -> PackedChat:
|
async def resolve_to_packed(self, chat: ChatLike) -> PackedChat:
|
||||||
|
"""
|
||||||
|
Resolve a :term:`chat` and return a compact, reusable reference to it.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` to resolve.
|
||||||
|
|
||||||
|
:return: An efficient, reusable version of the input.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
friend = await client.resolve_to_packed('@cat')
|
||||||
|
# Now you can use `friend` to get or send messages, files...
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
In-depth explanation for :doc:`/concepts/chats`.
|
||||||
|
"""
|
||||||
return await resolve_to_packed(self, chat)
|
return await resolve_to_packed(self, chat)
|
||||||
|
|
||||||
async def resolve_username(self) -> Chat:
|
async def resolve_username(self) -> Chat:
|
||||||
|
@ -291,6 +827,30 @@ class Client:
|
||||||
offset_id: Optional[int] = None,
|
offset_id: Optional[int] = None,
|
||||||
offset_date: Optional[datetime.datetime] = None,
|
offset_date: Optional[datetime.datetime] = None,
|
||||||
) -> AsyncList[Message]:
|
) -> AsyncList[Message]:
|
||||||
|
"""
|
||||||
|
Perform a global message search.
|
||||||
|
This is used to search messages in no particular chat (i.e. everywhere possible).
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message to edit is.
|
||||||
|
|
||||||
|
:param limit:
|
||||||
|
How many messages to fetch at most.
|
||||||
|
|
||||||
|
:param query:
|
||||||
|
Text query to use for fuzzy matching messages.
|
||||||
|
The rules for how "fuzzy" works are an implementation detail of the server.
|
||||||
|
|
||||||
|
:param offset_id:
|
||||||
|
Start getting messages with an identifier lower than this one.
|
||||||
|
This means only messages older than the message with ``id = offset_id`` will be fetched.
|
||||||
|
|
||||||
|
:param offset_date:
|
||||||
|
Start getting messages with a date lower than this one.
|
||||||
|
This means only messages sent before *offset_date* will be fetched.
|
||||||
|
|
||||||
|
:return: The found messages.
|
||||||
|
"""
|
||||||
return search_all_messages(
|
return search_all_messages(
|
||||||
self, limit, query=query, offset_id=offset_id, offset_date=offset_date
|
self, limit, query=query, offset_id=offset_id, offset_date=offset_date
|
||||||
)
|
)
|
||||||
|
@ -304,6 +864,29 @@ class Client:
|
||||||
offset_id: Optional[int] = None,
|
offset_id: Optional[int] = None,
|
||||||
offset_date: Optional[datetime.datetime] = None,
|
offset_date: Optional[datetime.datetime] = None,
|
||||||
) -> AsyncList[Message]:
|
) -> AsyncList[Message]:
|
||||||
|
"""
|
||||||
|
Search messages in a chat.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where messages will be searched.
|
||||||
|
|
||||||
|
:param limit:
|
||||||
|
How many messages to fetch at most.
|
||||||
|
|
||||||
|
:param query:
|
||||||
|
Text query to use for fuzzy matching messages.
|
||||||
|
The rules for how "fuzzy" works are an implementation detail of the server.
|
||||||
|
|
||||||
|
:param offset_id:
|
||||||
|
Start getting messages with an identifier lower than this one.
|
||||||
|
This means only messages older than the message with ``id = offset_id`` will be fetched.
|
||||||
|
|
||||||
|
:param offset_date:
|
||||||
|
Start getting messages with a date lower than this one.
|
||||||
|
This means only messages sent before *offset_date* will be fetched.
|
||||||
|
|
||||||
|
:return: The found messages.
|
||||||
|
"""
|
||||||
return search_messages(
|
return search_messages(
|
||||||
self, chat, limit, query=query, offset_id=offset_id, offset_date=offset_date
|
self, chat, limit, query=query, offset_id=offset_id, offset_date=offset_date
|
||||||
)
|
)
|
||||||
|
@ -325,8 +908,16 @@ class Client:
|
||||||
"""
|
"""
|
||||||
Send an audio file.
|
Send an audio file.
|
||||||
|
|
||||||
Unlike `send_file`, this method will attempt to guess the values for
|
Unlike :meth:`send_file`, this method will attempt to guess the values for
|
||||||
duration, title and performer if they are not provided.
|
duration, title and performer if they are not provided.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message will be sent to.
|
||||||
|
|
||||||
|
:param path:
|
||||||
|
A local file path or :class:`~telethon.types.File` to send.
|
||||||
|
|
||||||
|
The rest of parameters behave the same as they do in :meth:`send_file`.
|
||||||
"""
|
"""
|
||||||
return await send_audio(
|
return await send_audio(
|
||||||
self,
|
self,
|
||||||
|
@ -372,15 +963,32 @@ class Client:
|
||||||
"""
|
"""
|
||||||
Send any type of file with any amount of attributes.
|
Send any type of file with any amount of attributes.
|
||||||
|
|
||||||
This method will not attempt to guess any of the file metadata such as
|
This method will *not* attempt to guess any of the file metadata such as width, duration, title, etc.
|
||||||
width, duration, title, etc. If you want to let the library attempt to
|
If you want to let the library attempt to guess the file metadata, use the type-specific methods to send media:
|
||||||
guess the file metadata, use the type-specific methods to send media:
|
|
||||||
`send_photo`, `send_audio` or `send_file`.
|
`send_photo`, `send_audio` or `send_file`.
|
||||||
|
|
||||||
Unlike `send_photo`, image files will be sent as documents by default.
|
Unlike `send_photo`, image files will be sent as documents by default.
|
||||||
|
|
||||||
The parameters are used to construct a `File`. See the documentation
|
:param chat:
|
||||||
for `File.new` to learn what they do and when they are in effect.
|
The :term:`chat` where the message will be sent to.
|
||||||
|
|
||||||
|
:param path:
|
||||||
|
A local file path or :class:`~telethon.types.File` to send.
|
||||||
|
|
||||||
|
:param caption:
|
||||||
|
Caption text to display under the media, with no formatting.
|
||||||
|
|
||||||
|
:param caption_markdown:
|
||||||
|
Caption text to display under the media, parsed as markdown.
|
||||||
|
|
||||||
|
:param caption_html:
|
||||||
|
Caption text to display under the media, parsed as HTML.
|
||||||
|
|
||||||
|
The rest of parameters are passed to :meth:`telethon.types.File.new`
|
||||||
|
if *path* isn't a :class:`~telethon.types.File`.
|
||||||
|
See the documentation of :meth:`~telethon.types.File.new` to learn what they do.
|
||||||
|
|
||||||
|
Note that only one *caption* parameter can be provided.
|
||||||
"""
|
"""
|
||||||
return await send_file(
|
return await send_file(
|
||||||
self,
|
self,
|
||||||
|
@ -418,6 +1026,23 @@ class Client:
|
||||||
html: Optional[str] = None,
|
html: Optional[str] = None,
|
||||||
link_preview: Optional[bool] = None,
|
link_preview: Optional[bool] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
|
"""
|
||||||
|
Send a message.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message will be sent to.
|
||||||
|
|
||||||
|
:param text:
|
||||||
|
Message text, with no formatting.
|
||||||
|
|
||||||
|
:param text_markdown:
|
||||||
|
Message text, parsed as markdown.
|
||||||
|
|
||||||
|
:param text_html:
|
||||||
|
Message text, parsed as HTML.
|
||||||
|
|
||||||
|
Note that exactly one *text* parameter must be provided.
|
||||||
|
"""
|
||||||
return await send_message(
|
return await send_message(
|
||||||
self,
|
self,
|
||||||
chat,
|
chat,
|
||||||
|
@ -443,16 +1068,20 @@ class Client:
|
||||||
"""
|
"""
|
||||||
Send a photo file.
|
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.
|
By default, the server will be allowed to `compress` the image.
|
||||||
Only compressed images can be displayed as photos in applications.
|
Only compressed images can be displayed as photos in applications.
|
||||||
Images that cannot be compressed will be sent as file documents,
|
If *compress* is set to :data:`False`, the image will be sent as a file document.
|
||||||
with a thumbnail if possible.
|
|
||||||
|
|
||||||
Unlike `send_file`, this method will attempt to guess the values for
|
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.
|
width and height if they are not provided.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message will be sent to.
|
||||||
|
|
||||||
|
:param path:
|
||||||
|
A local file path or :class:`~telethon.types.File` to send.
|
||||||
|
|
||||||
|
The rest of parameters behave the same as they do in :meth:`send_file`.
|
||||||
"""
|
"""
|
||||||
return await send_photo(
|
return await send_photo(
|
||||||
self,
|
self,
|
||||||
|
@ -487,6 +1116,14 @@ class Client:
|
||||||
|
|
||||||
Unlike `send_file`, this method will attempt to guess the values for
|
Unlike `send_file`, this method will attempt to guess the values for
|
||||||
duration, width and height if they are not provided.
|
duration, width and height if they are not provided.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message will be sent to.
|
||||||
|
|
||||||
|
:param path:
|
||||||
|
A local file path or :class:`~telethon.types.File` to send.
|
||||||
|
|
||||||
|
The rest of parameters behave the same as they do in :meth:`send_file`.
|
||||||
"""
|
"""
|
||||||
return await send_video(
|
return await send_video(
|
||||||
self,
|
self,
|
||||||
|
@ -508,17 +1145,89 @@ class Client:
|
||||||
handler: Callable[[Event], Awaitable[Any]],
|
handler: Callable[[Event], Awaitable[Any]],
|
||||||
filter: Optional[Filter] = None,
|
filter: Optional[Filter] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Set the filter to use for the given event handler.
|
||||||
|
|
||||||
|
:param handler:
|
||||||
|
The callable that was previously added as an event handler.
|
||||||
|
|
||||||
|
:param filter:
|
||||||
|
The filter to use for *handler*, or :data:`None` to remove the old filter.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon.events import filters
|
||||||
|
|
||||||
|
# Change the filter to handle '/stop'
|
||||||
|
client.set_handler_filter(my_handler, filters.Command('/stop'))
|
||||||
|
|
||||||
|
# Remove the filter
|
||||||
|
client.set_handler_filter(my_handler, None)
|
||||||
|
"""
|
||||||
set_handler_filter(self, handler, filter)
|
set_handler_filter(self, handler, filter)
|
||||||
|
|
||||||
async def sign_in(self, token: LoginToken, code: str) -> Union[User, PasswordToken]:
|
async def sign_in(self, token: LoginToken, code: str) -> Union[User, PasswordToken]:
|
||||||
|
"""
|
||||||
|
Sign in to a user account.
|
||||||
|
|
||||||
|
:param token:
|
||||||
|
The login token returned from :meth:`request_login_code`.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
The user corresponding to :term:`yourself`, or a password token if the account has 2FA enabled.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from telethon.types import PasswordToken
|
||||||
|
|
||||||
|
login_token = await client.request_login_code('+1 23 456')
|
||||||
|
user_or_token = await client.sign_in(login_token, input('code: '))
|
||||||
|
|
||||||
|
if isinstance(password_token, PasswordToken):
|
||||||
|
user = await client.check_password(password_token, '1-L0V3+T3l3th0n')
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:meth:`check_password`, the next step if the account has 2FA enabled.
|
||||||
|
"""
|
||||||
return await sign_in(self, token, code)
|
return await sign_in(self, token, code)
|
||||||
|
|
||||||
async def sign_out(self) -> None:
|
async def sign_out(self) -> None:
|
||||||
|
"""
|
||||||
|
Sign out, revoking the authorization of the current :term:`session`.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await client.sign_out() # turn off the lights
|
||||||
|
await client.disconnect() # shut the door
|
||||||
|
"""
|
||||||
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: Union[int, Literal["all"]]
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Unpin one or all messages from the top.
|
||||||
|
|
||||||
|
:param chat:
|
||||||
|
The :term:`chat` where the message pinned message is.
|
||||||
|
|
||||||
|
:param message_id:
|
||||||
|
The identifier of the message to unpin, or ``'all'`` to unpin them all.
|
||||||
|
|
||||||
|
.. rubric:: Example
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Unpin all messages
|
||||||
|
await client.unpin_message(chat, 'all')
|
||||||
|
"""
|
||||||
await unpin_message(self, chat, message_id)
|
await unpin_message(self, chat, message_id)
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
|
@ -39,6 +39,12 @@ def default_system_version() -> str:
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Config:
|
class Config:
|
||||||
|
"""
|
||||||
|
Configuration used by the :class:`telethon.Client`.
|
||||||
|
|
||||||
|
See the parameters of :class:`~telethon.Client` for an explanation of the fields.
|
||||||
|
"""
|
||||||
|
|
||||||
session: Session
|
session: Session
|
||||||
api_id: int
|
api_id: int
|
||||||
api_hash: str
|
api_hash: str
|
||||||
|
|
|
@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||||
from .client import Client
|
from .client import Client
|
||||||
|
|
||||||
|
|
||||||
async def get_me(self: Client) -> User:
|
async def get_me(self: Client) -> Optional[User]:
|
||||||
self
|
self
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class Event(metaclass=NoPublicConstructor):
|
class Event(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
The base type of all events.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
|
|
|
@ -6,7 +6,7 @@ from .common import Filter
|
||||||
|
|
||||||
class Any:
|
class Any:
|
||||||
"""
|
"""
|
||||||
Combine multiple filters, returning `True` if any of the filters pass.
|
Combine multiple filters, returning :data:`True` if any of the filters pass.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_filters",)
|
__slots__ = ("_filters",)
|
||||||
|
@ -27,7 +27,7 @@ class Any:
|
||||||
|
|
||||||
class All:
|
class All:
|
||||||
"""
|
"""
|
||||||
Combine multiple filters, returning `True` if all of the filters pass.
|
Combine multiple filters, returning :data:`True` if all of the filters pass.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_filters",)
|
__slots__ = ("_filters",)
|
||||||
|
@ -48,8 +48,7 @@ class All:
|
||||||
|
|
||||||
class Not:
|
class Not:
|
||||||
"""
|
"""
|
||||||
Negate the output of a single filter, returning `True` if the nested
|
Negate the output of a single filter, returning :data:`True` if the nested filter does *not* pass.
|
||||||
filter does *not* pass.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_filter",)
|
__slots__ = ("_filter",)
|
||||||
|
|
|
@ -7,7 +7,7 @@ Filter = Callable[[Event], bool]
|
||||||
|
|
||||||
class Chats:
|
class Chats:
|
||||||
"""
|
"""
|
||||||
Filter by `event.chat.id`.
|
Filter by ``event.chat.id``, if the event has a chat.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_chats",)
|
__slots__ = ("_chats",)
|
||||||
|
@ -31,7 +31,7 @@ class Chats:
|
||||||
|
|
||||||
class Senders:
|
class Senders:
|
||||||
"""
|
"""
|
||||||
Filter by `event.sender.id`.
|
Filter by ``event.sender.id``, if the event has a sender.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("_senders",)
|
__slots__ = ("_senders",)
|
||||||
|
|
|
@ -6,10 +6,10 @@ from ..event import Event
|
||||||
|
|
||||||
class Text:
|
class Text:
|
||||||
"""
|
"""
|
||||||
Filter by `event.text` using a *regular expression* pattern.
|
Filter by ``event.text`` using a *regular expression* pattern.
|
||||||
|
|
||||||
The pattern is searched on the text anywhere, not matched at the start.
|
The pattern is searched on the text anywhere, not matched at the start.
|
||||||
Use the `'^'` anchor if you want to match the text from the start.
|
Use the ``'^'`` anchor if you want to match the text from the start.
|
||||||
|
|
||||||
The match, if any, is discarded. If you need to access captured groups,
|
The match, if any, is discarded. If you need to access captured groups,
|
||||||
you need to manually perform the check inside the handler instead.
|
you need to manually perform the check inside the handler instead.
|
||||||
|
@ -27,12 +27,12 @@ class Text:
|
||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
"""
|
"""
|
||||||
Filter by `event.text` to make sure the first word matches the command or
|
Filter by ``event.text`` to make sure the first word matches the command or
|
||||||
the command + '@' + username, using the username of the logged-in account.
|
the command + '@' + username, using the username of the logged-in account.
|
||||||
|
|
||||||
For example, if the logged-in account has an username of "bot", then the
|
For example, if the logged-in account has an username of "bot", then the
|
||||||
filter `Command('/help')` will match both "/help" and "/help@bot", but not
|
filter ``Command('/help')`` will match both ``"/help"`` and ``"/help@bot"``, but not
|
||||||
"/list" or "/help@other".
|
``"/list"`` or ``"/help@other"``.
|
||||||
|
|
||||||
Note that the leading forward-slash is not automatically added,
|
Note that the leading forward-slash is not automatically added,
|
||||||
which allows for using a different prefix or no prefix at all.
|
which allows for using a different prefix or no prefix at all.
|
||||||
|
@ -49,11 +49,11 @@ class Command:
|
||||||
|
|
||||||
class Incoming:
|
class Incoming:
|
||||||
"""
|
"""
|
||||||
Filter by `event.incoming`, that is, messages sent from others to the
|
Filter by ``event.incoming``, that is, messages sent from others to the
|
||||||
logged-in account.
|
logged-in account.
|
||||||
|
|
||||||
This is not a reliable way to check that the update was not produced by
|
This is not a reliable way to check that the update was not produced by
|
||||||
the logged-in account.
|
the logged-in account in broadcast channels.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
@ -64,11 +64,11 @@ class Incoming:
|
||||||
|
|
||||||
class Outgoing:
|
class Outgoing:
|
||||||
"""
|
"""
|
||||||
Filter by `event.outgoing`, that is, messages sent from others to the
|
Filter by ``event.outgoing``, that is, messages sent from others to the
|
||||||
logged-in account.
|
logged-in account.
|
||||||
|
|
||||||
This is not a reliable way to check that the update was not produced by
|
This is not a reliable way to check that the update was not produced by
|
||||||
the logged-in account.
|
the logged-in account in broadcast channels.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
@ -79,7 +79,7 @@ class Outgoing:
|
||||||
|
|
||||||
class Forward:
|
class Forward:
|
||||||
"""
|
"""
|
||||||
Filter by `event.forward`.
|
Filter by ``event.forward``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
@ -90,7 +90,7 @@ class Forward:
|
||||||
|
|
||||||
class Reply:
|
class Reply:
|
||||||
"""
|
"""
|
||||||
Filter by `event.reply`.
|
Filter by ``event.reply``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
|
@ -15,6 +15,16 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class NewMessage(Event, Message):
|
class NewMessage(Event, Message):
|
||||||
|
"""
|
||||||
|
Occurs when a new message is sent or received.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Messages sent with the :class:`~telethon.Client` are also caught,
|
||||||
|
so be careful not to enter infinite loops!
|
||||||
|
This is true for all event types, including edits.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
if isinstance(update, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
if isinstance(update, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
||||||
|
@ -29,18 +39,30 @@ class NewMessage(Event, Message):
|
||||||
|
|
||||||
|
|
||||||
class MessageEdited(Event):
|
class MessageEdited(Event):
|
||||||
|
"""
|
||||||
|
Occurs when a new message is sent or received.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class MessageDeleted(Event):
|
class MessageDeleted(Event):
|
||||||
|
"""
|
||||||
|
Occurs when one or more messages are deleted.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class MessageRead(Event):
|
class MessageRead(Event):
|
||||||
|
"""
|
||||||
|
Occurs both when your messages are read by others, and when you read messages.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
|
@ -10,12 +10,24 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class CallbackQuery(Event):
|
class CallbackQuery(Event):
|
||||||
|
"""
|
||||||
|
Occurs when an inline button was pressed.
|
||||||
|
|
||||||
|
Only bot accounts can receive this event.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class InlineQuery(Event):
|
class InlineQuery(Event):
|
||||||
|
"""
|
||||||
|
Occurs when users type ``@bot query`` in their chat box.
|
||||||
|
|
||||||
|
Only bot accounts can receive this event.
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
def _try_from_update(cls, client: Client, update: abcs.Update) -> Optional[Self]:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
|
@ -21,6 +21,7 @@ class AsyncList(abc.ABC, Generic[T]):
|
||||||
The `len()` of the asynchronous list will be the "total count" reported
|
The `len()` of the asynchronous list will be the "total count" reported
|
||||||
by the server. It does not necessarily reflect how many items will
|
by the server. It does not necessarily reflect how many items will
|
||||||
actually be returned. This count can change as more items are fetched.
|
actually be returned. This count can change as more items are fetched.
|
||||||
|
Note that this method cannot be awaited.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|
|
@ -6,6 +6,10 @@ from ..meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class Channel(metaclass=NoPublicConstructor):
|
class Channel(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
A broadcast channel.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw",)
|
__slots__ = ("_raw",)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -45,6 +49,10 @@ class Channel(metaclass=NoPublicConstructor):
|
||||||
def title(self) -> str:
|
def title(self) -> str:
|
||||||
return getattr(self._raw, "title", None) or ""
|
return getattr(self._raw, "title", None) or ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_name(self) -> str:
|
||||||
|
return self.title
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def username(self) -> Optional[str]:
|
def username(self) -> Optional[str]:
|
||||||
return getattr(self._raw, "username", None)
|
return getattr(self._raw, "username", None)
|
||||||
|
|
|
@ -6,6 +6,10 @@ from ..meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class Group(metaclass=NoPublicConstructor):
|
class Group(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
A small group or supergroup.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw",)
|
__slots__ = ("_raw",)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -49,6 +53,10 @@ class Group(metaclass=NoPublicConstructor):
|
||||||
def title(self) -> str:
|
def title(self) -> str:
|
||||||
return getattr(self._raw, "title", None) or ""
|
return getattr(self._raw, "title", None) or ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_name(self) -> str:
|
||||||
|
return self.title
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def username(self) -> Optional[str]:
|
def username(self) -> Optional[str]:
|
||||||
return getattr(self._raw, "username", None)
|
return getattr(self._raw, "username", None)
|
||||||
|
|
|
@ -6,6 +6,10 @@ from ..meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class RestrictionReason(metaclass=NoPublicConstructor):
|
class RestrictionReason(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
A restriction reason for :class:`telethon.types.User`.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw",)
|
__slots__ = ("_raw",)
|
||||||
|
|
||||||
def __init__(self, raw: types.RestrictionReason) -> None:
|
def __init__(self, raw: types.RestrictionReason) -> None:
|
||||||
|
@ -30,6 +34,10 @@ class RestrictionReason(metaclass=NoPublicConstructor):
|
||||||
|
|
||||||
|
|
||||||
class User(metaclass=NoPublicConstructor):
|
class User(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
A user, representing either a bot account or an account created with a phone number.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw",)
|
__slots__ = ("_raw",)
|
||||||
|
|
||||||
def __init__(self, raw: types.User) -> None:
|
def __init__(self, raw: types.User) -> None:
|
||||||
|
|
|
@ -34,8 +34,8 @@ MediaLike = object
|
||||||
|
|
||||||
class InFileLike(Protocol):
|
class InFileLike(Protocol):
|
||||||
"""
|
"""
|
||||||
[File-like object](https://docs.python.org/3/glossary.html#term-file-like-object)
|
A :term:`file-like object` used for input only.
|
||||||
used for input only, where the `read` method can be `async`.
|
The :meth:`read` method can be :keyword:`async`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def read(self, n: int) -> Union[bytes, Coroutine[Any, Any, bytes]]:
|
def read(self, n: int) -> Union[bytes, Coroutine[Any, Any, bytes]]:
|
||||||
|
@ -44,8 +44,8 @@ class InFileLike(Protocol):
|
||||||
|
|
||||||
class OutFileLike(Protocol):
|
class OutFileLike(Protocol):
|
||||||
"""
|
"""
|
||||||
[File-like object](https://docs.python.org/3/glossary.html#term-file-like-object)
|
A :term:`file-like object` used for output only.
|
||||||
used for output only, where the `write` method can be `async`.
|
The :meth:`write` method can be :keyword:`async`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def write(self, data: bytes) -> Union[Any, Coroutine[Any, Any, Any]]:
|
def write(self, data: bytes) -> Union[Any, Coroutine[Any, Any, Any]]:
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
from typing import Self
|
from typing import Optional, Self
|
||||||
|
|
||||||
from ...tl import types
|
from ...tl import types
|
||||||
from .meta import NoPublicConstructor
|
from .meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class LoginToken(metaclass=NoPublicConstructor):
|
class LoginToken(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
Result of requesting a login code via :meth:`telethon.Client.request_login_code`.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_code", "_phone")
|
__slots__ = ("_code", "_phone")
|
||||||
|
|
||||||
def __init__(self, code: types.auth.SentCode, phone: str) -> None:
|
def __init__(self, code: types.auth.SentCode, phone: str) -> None:
|
||||||
|
@ -14,3 +18,7 @@ class LoginToken(metaclass=NoPublicConstructor):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _new(cls, code: types.auth.SentCode, phone: str) -> Self:
|
def _new(cls, code: types.auth.SentCode, phone: str) -> Self:
|
||||||
return cls._create(code, phone)
|
return cls._create(code, phone)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timeout(self) -> Optional[int]:
|
||||||
|
return self._code.timeout
|
||||||
|
|
|
@ -8,6 +8,10 @@ from .meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class Message(metaclass=NoPublicConstructor):
|
class Message(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
A sent message.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_raw",)
|
__slots__ = ("_raw",)
|
||||||
|
|
||||||
def __init__(self, message: abcs.Message) -> None:
|
def __init__(self, message: abcs.Message) -> None:
|
||||||
|
@ -28,6 +32,14 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
def text(self) -> Optional[str]:
|
def text(self) -> Optional[str]:
|
||||||
return getattr(self._raw, "message", None)
|
return getattr(self._raw, "message", None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def html_text(self) -> Optional[str]:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def markdown_text(self) -> Optional[str]:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def date(self) -> Optional[datetime.datetime]:
|
def date(self) -> Optional[datetime.datetime]:
|
||||||
date = getattr(self._raw, "date", None)
|
date = getattr(self._raw, "date", None)
|
||||||
|
@ -80,3 +92,16 @@ class Message(metaclass=NoPublicConstructor):
|
||||||
)
|
)
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def file(self) -> Optional[File]:
|
||||||
|
return self._file()
|
||||||
|
|
||||||
|
async def delete(self) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
async def edit(self) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
async def forward_to(self) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
|
@ -5,6 +5,10 @@ from .meta import NoPublicConstructor
|
||||||
|
|
||||||
|
|
||||||
class PasswordToken(metaclass=NoPublicConstructor):
|
class PasswordToken(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
Result of attempting to :meth:`~telethon.Client.sign_in` to a 2FA-protected account.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("_password",)
|
__slots__ = ("_password",)
|
||||||
|
|
||||||
def __init__(self, password: types.account.Password) -> None:
|
def __init__(self, password: types.account.Password) -> None:
|
||||||
|
|
|
@ -9,6 +9,17 @@ MsgId = NewType("MsgId", int)
|
||||||
|
|
||||||
|
|
||||||
class RpcError(ValueError):
|
class RpcError(ValueError):
|
||||||
|
"""
|
||||||
|
A Remote Procedure Call Error.
|
||||||
|
|
||||||
|
Only occurs when the answer to a request sent to Telegram is not the expected result.
|
||||||
|
The library will never construct instances of this error by itself.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:doc:`/concepts/errors`
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|
|
@ -6,6 +6,10 @@ from ...tl import abcs, types
|
||||||
|
|
||||||
|
|
||||||
class PackedType(Enum):
|
class PackedType(Enum):
|
||||||
|
"""
|
||||||
|
The type of a :class:`PackedChat`.
|
||||||
|
"""
|
||||||
|
|
||||||
# bits: zero, has-access-hash, channel, broadcast, group, chat, user, bot
|
# bits: zero, has-access-hash, channel, broadcast, group, chat, user, bot
|
||||||
USER = 0b0000_0010
|
USER = 0b0000_0010
|
||||||
BOT = 0b0000_0011
|
BOT = 0b0000_0011
|
||||||
|
@ -16,6 +20,16 @@ class PackedType(Enum):
|
||||||
|
|
||||||
|
|
||||||
class PackedChat:
|
class PackedChat:
|
||||||
|
"""
|
||||||
|
A compact representation of a :term:`chat`.
|
||||||
|
|
||||||
|
You can reuse it as many times as you want.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:doc:`/concepts/chats`
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("ty", "id", "access_hash")
|
__slots__ = ("ty", "id", "access_hash")
|
||||||
|
|
||||||
def __init__(self, ty: PackedType, id: int, access_hash: Optional[int]) -> None:
|
def __init__(self, ty: PackedType, id: int, access_hash: Optional[int]) -> None:
|
||||||
|
|
|
@ -3,6 +3,14 @@ from typing import Any, Dict, List, Optional, Self
|
||||||
|
|
||||||
|
|
||||||
class DataCenter:
|
class DataCenter:
|
||||||
|
"""
|
||||||
|
Data-center information.
|
||||||
|
|
||||||
|
:var id: The DC identifier.
|
||||||
|
:var addr: The server address of the DC, in ``'ip:port'`` format.
|
||||||
|
:var auth: Authentication key to encrypt communication with.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("id", "addr", "auth")
|
__slots__ = ("id", "addr", "auth")
|
||||||
|
|
||||||
def __init__(self, *, id: int, addr: str, auth: Optional[bytes]) -> None:
|
def __init__(self, *, id: int, addr: str, auth: Optional[bytes]) -> None:
|
||||||
|
@ -12,6 +20,14 @@ class DataCenter:
|
||||||
|
|
||||||
|
|
||||||
class User:
|
class User:
|
||||||
|
"""
|
||||||
|
Information about the logged-in user.
|
||||||
|
|
||||||
|
:var id: User identifier.
|
||||||
|
:var dc: Data-center identifier of the user's "home" DC.
|
||||||
|
:var bot: :data:`True` if the user is from a bot account.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("id", "dc", "bot")
|
__slots__ = ("id", "dc", "bot")
|
||||||
|
|
||||||
def __init__(self, *, id: int, dc: int, bot: bool) -> None:
|
def __init__(self, *, id: int, dc: int, bot: bool) -> None:
|
||||||
|
@ -21,6 +37,13 @@ class User:
|
||||||
|
|
||||||
|
|
||||||
class ChannelState:
|
class ChannelState:
|
||||||
|
"""
|
||||||
|
Update state for a channel.
|
||||||
|
|
||||||
|
:var id: The channel identifier.
|
||||||
|
:var pts: The channel's partial sequence number.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = ("id", "pts")
|
__slots__ = ("id", "pts")
|
||||||
|
|
||||||
def __init__(self, *, id: int, pts: int) -> None:
|
def __init__(self, *, id: int, pts: int) -> None:
|
||||||
|
@ -29,6 +52,16 @@ class ChannelState:
|
||||||
|
|
||||||
|
|
||||||
class UpdateState:
|
class UpdateState:
|
||||||
|
"""
|
||||||
|
Update state for an account.
|
||||||
|
|
||||||
|
:var pts: The primary partial sequence number.
|
||||||
|
:var qts: The secondary partial sequence number.
|
||||||
|
:var date: Date of the latest update sequence.
|
||||||
|
:var seq: The sequence number.
|
||||||
|
:var channels: Update state for channels.
|
||||||
|
"""
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
"pts",
|
"pts",
|
||||||
"qts",
|
"qts",
|
||||||
|
@ -55,9 +88,9 @@ class UpdateState:
|
||||||
|
|
||||||
class Session:
|
class Session:
|
||||||
"""
|
"""
|
||||||
A Telethon session.
|
A Telethon :term:`session`.
|
||||||
|
|
||||||
A `Session` instance contains the required information to login into your
|
A session instance contains the required information to login into your
|
||||||
Telegram account. **Never** give the saved session file to anyone else or
|
Telegram account. **Never** give the saved session file to anyone else or
|
||||||
make it public.
|
make it public.
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ class SqliteSession(Storage):
|
||||||
|
|
||||||
SQLite is a reliable way to persist data to disk and offers file locking.
|
SQLite is a reliable way to persist data to disk and offers file locking.
|
||||||
|
|
||||||
Paths without extension will have '.session' appended to them.
|
Paths without extension will have ``'.session'`` appended to them.
|
||||||
This is by convention, and to make it harder to commit session files to
|
This is by convention, and to make it harder to commit session files to
|
||||||
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: Union[str, Path]):
|
||||||
|
|
|
@ -5,6 +5,10 @@ from ..session import Session
|
||||||
|
|
||||||
|
|
||||||
class Storage(abc.ABC):
|
class Storage(abc.ABC):
|
||||||
|
"""
|
||||||
|
Interface declaring the required methods of a :term:`session` storage.
|
||||||
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
async def load(self) -> Optional[Session]:
|
async def load(self) -> Optional[Session]:
|
||||||
"""
|
"""
|
||||||
|
@ -27,4 +31,6 @@ class Storage(abc.ABC):
|
||||||
Delete the saved `Session`.
|
Delete the saved `Session`.
|
||||||
|
|
||||||
This method is called by the library post `log_out`.
|
This method is called by the library post `log_out`.
|
||||||
|
|
||||||
|
Note that both :meth:`load` and :meth:`save` may still be called after.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
"""
|
||||||
|
Filters are functions that accept a single parameter, an :class:`~telethon.events.Event` instance, and return a :class:`bool`.
|
||||||
|
|
||||||
|
When the return value is :data:`True`, the associated :mod:`~telethon.events` handler will be invoked.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The :doc:`/concepts/updates` concept to learn to combine filters or define your own.
|
||||||
|
"""
|
||||||
from .._impl.client.events.filters import (
|
from .._impl.client.events.filters import (
|
||||||
All,
|
All,
|
||||||
Any,
|
Any,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from ._impl.client.client import Config, InlineResult, InlineResults
|
from ._impl.client.client import Config, InlineResult
|
||||||
from ._impl.client.types import (
|
from ._impl.client.types import (
|
||||||
AsyncList,
|
AsyncList,
|
||||||
Channel,
|
Channel,
|
||||||
|
@ -20,7 +20,6 @@ from ._impl.session import PackedChat, PackedType
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Config",
|
"Config",
|
||||||
"InlineResult",
|
"InlineResult",
|
||||||
"InlineResults",
|
|
||||||
"AsyncList",
|
"AsyncList",
|
||||||
"Channel",
|
"Channel",
|
||||||
"Chat",
|
"Chat",
|
||||||
|
|
|
@ -18,7 +18,7 @@ def main() -> None:
|
||||||
run("isort", ".", "-c", "--profile", "black", "--gitignore")
|
run("isort", ".", "-c", "--profile", "black", "--gitignore")
|
||||||
or run("black", ".", "--check", "--extend-exclude", BLACK_IGNORE)
|
or run("black", ".", "--check", "--extend-exclude", BLACK_IGNORE)
|
||||||
or run("mypy", "--strict", ".")
|
or run("mypy", "--strict", ".")
|
||||||
or run("sphinx", "-nW", "client/doc", tmp_dir)
|
or run("sphinx", "-M", "dummy", "client/doc", tmp_dir, "-n", "-W")
|
||||||
or run("pytest", ".", "-m", "not net")
|
or run("pytest", ".", "-m", "not net")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user