This commit is contained in:
Hackintosh 5 2021-12-13 09:19:19 +00:00
parent 8de375323e
commit 1d4bd39307
8 changed files with 121 additions and 48 deletions

View File

@ -8,6 +8,7 @@ import asyncio
from .._crypto import AES
from .._misc import utils, helpers, requestiter, tlobject, hints
from ..types._custom import Message
from .. import errors, _tl
try:
@ -267,7 +268,8 @@ async def download_media(
msg_data = None
# TODO This won't work for messageService
if isinstance(message, _tl.Message):
# TODO Handle _tl.Message
if isinstance(message, Message):
date = message.date
media = message.media
msg_data = (message.input_chat, message.id) if message.input_chat else None

View File

@ -489,7 +489,7 @@ async def send_message(
request = _tl.fn.messages.SendMessage(
peer=entity,
message=message._text,
entities=formatting_entities,
entities=message._fmt_entities,
no_webpage=not link_preview,
reply_to_msg_id=utils.get_message_id(reply_to),
clear_draft=clear_draft,
@ -508,7 +508,7 @@ async def send_message(
date=result.date,
out=result.out,
media=result.media,
entities=result.entities,
entities=result._fmt_entities,
reply_markup=request.reply_markup,
ttl_period=result.ttl_period
), {}, entity)
@ -579,35 +579,88 @@ async def forward_messages(
async def edit_message(
self: 'TelegramClient',
entity: 'typing.Union[hints.EntityLike, _tl.Message]',
message: 'hints.MessageLike' = None,
message_id: 'hints.MessageLike' = None,
text: str = None,
*,
parse_mode: str = (),
attributes: 'typing.Sequence[_tl.TypeDocumentAttribute]' = None,
formatting_entities: typing.Optional[typing.List[_tl.TypeMessageEntity]] = None,
link_preview: bool = True,
file: 'hints.FileLike' = None,
thumb: 'hints.FileLike' = None,
force_document: bool = False,
buttons: 'hints.MarkupLike' = None,
# - Message contents
# Formatting
markdown: str = None,
html: str = None,
formatting_entities: list = None,
link_preview: bool = (),
# Media
file: typing.Optional[hints.FileLike] = None,
file_name: str = None,
mime_type: str = None,
thumb: str = False,
force_file: bool = False,
file_size: int = None,
# Media attributes
duration: int = None,
width: int = None,
height: int = None,
title: str = None,
performer: str = None,
supports_streaming: bool = False,
schedule: 'hints.DateLike' = None
video_note: bool = False,
voice_note: bool = False,
waveform: bytes = None,
# Additional parametrization
buttons: list = None,
ttl: int = None,
# - Send options
schedule: 'hints.DateLike' = None,
) -> '_tl.Message':
if formatting_entities is None:
text, formatting_entities = await self._parse_message_text(text, parse_mode)
file_handle, media, image = await self._file_to_media(file,
supports_streaming=supports_streaming,
if isinstance(text, str) or text is None:
message = InputMessage(
text=text,
markdown=markdown,
html=html,
formatting_entities=formatting_entities,
link_preview=link_preview,
file=file,
file_name=file_name,
mime_type=mime_type,
thumb=thumb,
attributes=attributes,
force_document=force_document)
force_file=force_file,
file_size=file_size,
duration=duration,
width=width,
height=height,
title=title,
performer=performer,
supports_streaming=supports_streaming,
video_note=video_note,
voice_note=voice_note,
waveform=waveform,
silent=False,
buttons=buttons,
ttl=ttl,
)
elif isinstance(text, _custom.Message):
# TODO accept this as the first and only parameter
message = message._as_input()
elif not isinstance(text, InputMessage):
raise TypeError(f'text must be either str, Message or InputMessage, but got: {text!r}')
if message._file:
# TODO Properly implement allow_cache to reuse the sha256 of the file
# i.e. `None` was used
# TODO album
if message._file._should_upload_thumb():
message._file._set_uploaded_thumb(await self.upload_file(message._file._thumb))
if message._file._should_upload_file():
message._file._set_uploaded_file(await self.upload_file(message._file._file))
if isinstance(message, _tl.InputBotInlineMessageID):
request = _tl.fn.messages.EditInlineBotMessage(
id=message,
message=text,
id=message_id,
message=message._text,
no_webpage=not link_preview,
entities=formatting_entities,
media=media,
entities=message._fmt_entities,
media=message._file._media,
reply_markup=_custom.button.build_reply_markup(buttons)
)
# Invoke `messages.editInlineBotMessage` from the right datacenter.
@ -622,17 +675,13 @@ async def edit_message(
else:
return await self(request)
entity = await self.get_input_entity(entity)
message_id = utils.get_message_id(message_id)
request = _tl.fn.messages.EditMessage(
peer=entity,
id=utils.get_message_id(message),
message=text,
no_webpage=not link_preview,
entities=formatting_entities,
media=media,
reply_markup=_custom.button.build_reply_markup(buttons),
schedule_date=schedule
entity, message_id, no_webpage=not link_preview, message=message._text,
media=message._file._media if message._file else None, reply_markup=message._reply_markup, entities=message._fmt_entities, schedule_date=schedule
)
msg = self._get_response_message(request, await self(request), entity)
return msg

View File

@ -7,7 +7,7 @@ import typing
from ..errors._custom import MultiError
from ..errors._rpcbase import RpcError, ServerError, FloodError, InvalidDcError, UnauthorizedError
from .._misc import helpers, utils, hints
from .._sessions.types import Entity
from .._sessions.types import Entity, get_peer_canonical_entity_type
from .. import errors, _tl
_NOT_A_REQUEST = lambda: TypeError('You can only invoke requests, not types!')
@ -235,8 +235,10 @@ async def get_input_entity(
# Next in priority is having a peer (or its ID) cached in-memory
try:
# 0x2d45687 == crc32(b'Peer')
if isinstance(peer, int) or peer.SUBCLASS_OF_ID == 0x2d45687:
return self._entity_cache[peer]
# TODO: FIXME: This logic is incorrect - Peers are unhashable and the cache should be sorted by Entity.ty
# if isinstance(peer, int) or peer.SUBCLASS_OF_ID == 0x2d45687:
# return self._entity_cache[peer]
pass
except (AttributeError, KeyError):
pass
@ -250,13 +252,14 @@ async def get_input_entity(
except TypeError:
pass
else:
entity = await self.session.get_entity(None, peer_id)
entity_type = get_peer_canonical_entity_type(peer)
entity = await self.session.get_entity(entity_type, peer_id)
if entity:
if entity.ty in (Entity.USER, Entity.BOT):
if entity_type == Entity.USER:
return _tl.InputPeerUser(entity.id, entity.access_hash)
elif entity.ty in (Entity.GROUP):
elif entity_type == Entity.GROUP:
return _tl.InputPeerChat(peer.chat_id)
elif entity.ty in (Entity.CHANNEL, Entity.MEGAGROUP, Entity.GIGAGROUP):
elif entity_type == Entity.CHANNEL:
return _tl.InputPeerChannel(entity.id, entity.access_hash)
# Only network left to try

View File

@ -7,14 +7,12 @@ from ..types import _custom
Phone = str
Username = str
PeerID = int
Entity = typing.Union[_tl.User, _tl.Chat, _tl.Channel]
FullEntity = typing.Union[_tl.UserFull, _tl.messages.ChatFull, _tl.ChatFull, _tl.ChannelFull]
EntityLike = typing.Union[
Phone,
Username,
PeerID,
_tl.TypePeer,
_tl.TypeInputPeer,
Entity,

View File

@ -1,4 +1,4 @@
from .types import DataCenter, ChannelState, SessionState, Entity
from .types import DataCenter, ChannelState, SessionState, Entity, get_entity_type_group
from .abstract import Session
from .._misc import utils, tlobject
from .. import _tl
@ -34,11 +34,11 @@ class MemorySession(Session):
return list(self.channel_states.values())
async def insert_entities(self, entities: List[Entity]):
self.entities.update((e.id, (e.ty, e.access_hash)) for e in entities)
self.entities.update(((get_peer_canonical_entity_type(e.ty), e.id), e.access_hash) for e in entities)
async def get_entity(self, ty: Optional[int], id: int) -> Optional[Entity]:
async def get_entity(self, ty: int, id: int) -> Optional[Entity]:
try:
ty, access_hash = self.entities[id]
access_hash = self.entities[get_peer_canonical_entity_type(ty), id]
return Entity(ty, id, access_hash)
except KeyError:
return None

View File

@ -1,4 +1,6 @@
from typing import Optional, Tuple
from typing import Optional, Tuple, Union
from .. import _tl
from .._misc import hints, utils
class DataCenter:
@ -155,3 +157,21 @@ def get_entity_type_group(ty: int, *, _mapping={
except KeyError:
ty = chr(ty) if isinstance(ty, int) else ty
raise ValueError(f'entity type {ty!r} is not valid')
def get_peer_canonical_entity_type(peer: Union[
_tl.TypePeer,
_tl.TypeInputPeer,
hints.Entity,
hints.FullEntity,
], *, _mapping={
_tl.PeerUser: Entity.USER,
_tl.PeerChat: Entity.GROUP,
_tl.PeerChannel: Entity.CHANNEL,
}) -> int:
peer = utils.get_peer(peer)
try:
return _mapping[type(peer)]
except KeyError:
# Safe to log full peer since only contains the ID
raise ValueError(f'Unexpected peer {peer!r}')

View File

@ -90,8 +90,9 @@ class InputFile:
elif isinstance(thumb, (_tl.InputFile, _tl.InputFileBig)):
self._uploaded_thumb = (thumb, time.time())
else:
elif thumb:
raise TypeError(f'thumb must be a file to upload, but got: {thumb!r}')
# else: it's falsey, ignore it
# document parameters (only if it's our file, i.e. there's no media ready yet)
if self._media:

View File

@ -160,7 +160,7 @@ class Message(ChatGetter, SenderGetter):
except AttributeError:
return None
return None if media.CONSTRUCTOR_ID == 0x3ded6320 else media
return None if media is None or media.CONSTRUCTOR_ID == 0x3ded6320 else media
@media.setter
def media(self, value):