Skip to content

Commit

Permalink
Work towards dialogs and drafts
Browse files Browse the repository at this point in the history
  • Loading branch information
Lonami committed Oct 19, 2023
1 parent 864d5cd commit b8b9836
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 87 deletions.
23 changes: 23 additions & 0 deletions client/doc/concepts/messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,29 @@ To send a message with formatted text, use the ``markdown`` or ``html`` paramete
When sending files, the format is appended to the name of the ``caption`` parameter, either ``caption_markdown`` or ``caption_html``.


Link previews
^^^^^^^^^^^^^

Link previews are treated as a type of media automatically generated by Telegram.
This means you cannot have both a link preview and other media in the same message.

The ``link_preview`` parameter indicates whether link previews are *allowed* to be present.
If Telegram is unable to generate a link preview for any of the links, there won't be a link preview.

By default, link previews are not enabled.
This is done to prevent sending things you did not explicitly intend to send.
Unlike the official clients, which do not have a GUI to "enable" the preview, you can easily enable them from code.

Telegram will attempt to generate a preview for all links contained in the message in order.
You can use this to your advantage, and hide a link to a photo in the first space or invisible character like ``'\u2063'``.
Note that avid users *will* be able to find out the link. It is not secret!

Link previews of photos won't show under the photos of the chat,
but it requires a server hosting the image, a public address, and Telegram to be able to generate a preview.

To regenerate a preview, send the corresponding link to `@WebpageBot <https://t.me/WebpageBot>`_.


Message identifiers
-------------------

Expand Down
67 changes: 57 additions & 10 deletions client/src/telethon/_impl/client/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
set_banned_rights,
set_default_rights,
)
from .dialogs import delete_dialog, get_dialogs, get_drafts
from .dialogs import delete_dialog, edit_draft, get_dialogs, get_drafts
from .files import (
download,
get_file_bytes,
Expand Down Expand Up @@ -499,7 +499,7 @@ async def edit_message(
text: Optional[str] = None,
markdown: Optional[str] = None,
html: Optional[str] = None,
link_preview: Optional[bool] = None,
link_preview: bool = False,
) -> Message:
"""
Edit a message.
Expand Down Expand Up @@ -1247,6 +1247,7 @@ async def send_file(
title: Optional[str] = None,
performer: Optional[str] = None,
emoji: Optional[str] = None,
emoji_sticker: Optional[str] = None,
width: Optional[int] = None,
height: Optional[int] = None,
round: bool = False,
Expand Down Expand Up @@ -1396,6 +1397,7 @@ async def send_file(
title=title,
performer=performer,
emoji=emoji,
emoji_sticker=emoji_sticker,
width=width,
height=height,
round=round,
Expand Down Expand Up @@ -1425,14 +1427,7 @@ async def send_message(
:param text: See :ref:`formatting`.
:param markdown: See :ref:`formatting`.
:param html: See :ref:`formatting`.
:param link_preview:
Whether the link preview is allowed.
Setting this to :data:`True` does not guarantee a preview.
Telegram must be able to generate a preview from the first link in the message text.
To regenerate the preview, send the link to `@WebpageBot <https://t.me/WebpageBot>`_.
:param link_preview: See :ref:`formatting`.
:param reply_to:
The message identifier of the message to reply to.
Expand Down Expand Up @@ -1578,6 +1573,58 @@ def set_banned_rights(self, chat: ChatLike, user: ChatLike) -> None:
def set_default_rights(self, chat: ChatLike, user: ChatLike) -> None:
set_default_rights(self, chat, user)

async def edit_draft(
self,
chat: ChatLike,
text: Optional[str] = None,
*,
markdown: Optional[str] = None,
html: Optional[str] = None,
link_preview: bool = False,
reply_to: Optional[int] = None,
) -> Draft:
"""
Set a draft message in a chat.
This can also be used to clear the draft by setting the text to an empty string ``""``.
:param chat:
The :term:`chat` where the draft will be saved to.
:param text: See :ref:`formatting`.
:param markdown: See :ref:`formatting`.
:param html: See :ref:`formatting`.
:param link_preview: See :ref:`formatting`.
:param reply_to:
The message identifier of the message to reply to.
:return: The created draft.
.. 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_draft(
self,
chat,
text,
markdown=markdown,
html=html,
link_preview=link_preview,
reply_to=reply_to,
)

def set_handler_filter(
self,
handler: Callable[[Event], Awaitable[Any]],
Expand Down
57 changes: 53 additions & 4 deletions client/src/telethon/_impl/client/client/dialogs.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import annotations

from typing import TYPE_CHECKING
import time
from typing import TYPE_CHECKING, Optional

from ...tl import functions, types
from ..types import AsyncList, ChatLike, Dialog, Draft
from ..utils import build_chat_map
from ..utils import build_chat_map, build_msg_map
from .messages import parse_message

if TYPE_CHECKING:
from .client import Client
Expand Down Expand Up @@ -40,8 +42,11 @@ async def _fetch_next(self) -> None:
assert isinstance(result, (types.messages.Dialogs, types.messages.DialogsSlice))

chat_map = build_chat_map(result.users, result.chats)
msg_map = build_msg_map(self._client, result.messages, chat_map)

self._buffer.extend(Dialog._from_raw(d, chat_map) for d in result.dialogs)
self._buffer.extend(
Dialog._from_raw(self._client, d, chat_map, msg_map) for d in result.dialogs
)


def get_dialogs(self: Client) -> AsyncList[Dialog]:
Expand Down Expand Up @@ -93,7 +98,7 @@ async def _fetch_next(self) -> None:
chat_map = build_chat_map(result.users, result.chats)

self._buffer.extend(
Draft._from_raw(u, chat_map)
Draft._from_raw_update(self._client, u, chat_map)
for u in result.updates
if isinstance(u, types.UpdateDraftMessage)
)
Expand All @@ -104,3 +109,47 @@ async def _fetch_next(self) -> None:

def get_drafts(self: Client) -> AsyncList[Draft]:
return DraftList(self)


async def edit_draft(
self: Client,
chat: ChatLike,
text: Optional[str] = None,
*,
markdown: Optional[str] = None,
html: Optional[str] = None,
link_preview: bool = False,
reply_to: Optional[int] = None,
) -> Draft:
packed = await self._resolve_to_packed(chat)
peer = (await self._resolve_to_packed(chat))._to_input_peer()
message, entities = parse_message(
text=text, markdown=markdown, html=html, allow_empty=False
)
assert isinstance(message, str)

result = await self(
functions.messages.save_draft(
no_webpage=not link_preview,
reply_to_msg_id=reply_to,
top_msg_id=None,
peer=peer,
message=message,
entities=entities,
)
)
assert result

return Draft._from_raw(
client=self,
peer=packed._to_peer(),
top_msg_id=0,
draft=types.DraftMessage(
no_webpage=not link_preview,
reply_to_msg_id=reply_to,
message=message,
entities=entities,
date=int(time.time()),
),
chat_map={},
)
68 changes: 23 additions & 45 deletions client/src/telethon/_impl/client/client/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async def send_message(
*,
markdown: Optional[str] = None,
html: Optional[str] = None,
link_preview: Optional[bool] = None,
link_preview: bool = False,
reply_to: Optional[int] = None,
) -> Message:
packed = await self._resolve_to_packed(chat)
Expand Down Expand Up @@ -99,51 +99,29 @@ async def send_message(
)
)
if isinstance(result, types.UpdateShortSentMessage):
return Message._from_raw(
return Message._from_defaults(
self,
types.Message(
out=result.out,
mentioned=False,
media_unread=False,
silent=False,
post=False,
from_scheduled=False,
legacy=False,
edit_hide=False,
pinned=False,
noforwards=False,
id=result.id,
from_id=types.PeerUser(user_id=self._session.user.id)
if self._session.user
else None,
peer_id=packed._to_peer(),
fwd_from=None,
via_bot_id=None,
reply_to=types.MessageReplyHeader(
reply_to_scheduled=False,
forum_topic=False,
reply_to_msg_id=reply_to,
reply_to_peer_id=None,
reply_to_top_id=None,
)
if reply_to
else None,
date=result.date,
message=message if isinstance(message, str) else (message.text or ""),
media=result.media,
reply_markup=None,
entities=result.entities,
views=None,
forwards=None,
replies=None,
edit_date=None,
post_author=None,
grouped_id=None,
reactions=None,
restriction_reason=None,
ttl_period=result.ttl_period,
),
{},
out=result.out,
id=result.id,
from_id=types.PeerUser(user_id=self._session.user.id)
if self._session.user
else None,
peer_id=packed._to_peer(),
reply_to=types.MessageReplyHeader(
reply_to_scheduled=False,
forum_topic=False,
reply_to_msg_id=reply_to,
reply_to_peer_id=None,
reply_to_top_id=None,
)
if reply_to
else None,
date=result.date,
message=message if isinstance(message, str) else (message.text or ""),
media=result.media,
entities=result.entities,
ttl_period=result.ttl_period,
)
else:
return self._build_message_map(result, peer).with_random_id(random_id)
Expand All @@ -157,7 +135,7 @@ async def edit_message(
text: Optional[str] = None,
markdown: Optional[str] = None,
html: Optional[str] = None,
link_preview: Optional[bool] = None,
link_preview: bool = False,
) -> Message:
peer = (await self._resolve_to_packed(chat))._to_input_peer()
message, entities = parse_message(
Expand Down
2 changes: 1 addition & 1 deletion client/src/telethon/_impl/client/types/chat/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def name(self) -> str:
This property is always present, but may be the empty string.
"""
return self._raw.title
return getattr(self._raw, "title", None) or ""

@property
def username(self) -> Optional[str]:
Expand Down

0 comments on commit b8b9836

Please sign in to comment.