Fix imports

This commit is contained in:
Lonami Exo 2021-09-12 13:27:13 +02:00
parent 28956496fc
commit f222dc167e
62 changed files with 322 additions and 301 deletions

2
.gitignore vendored
View File

@ -20,4 +20,4 @@ __pycache__/
/docs/
# File used to manually test new changes, contains sensitive data
/example.py
/example*.py

View File

@ -49,6 +49,8 @@ The following modules have been moved inside ``_misc``:
* ``statecache.py``
* ``utils.py``
// TODO review telethon/__init__.py isn't exposing more than it should
The TelegramClient is no longer made out of mixins
--------------------------------------------------

View File

@ -1,6 +1,12 @@
# Note: the import order matters
from ._misc import helpers # no dependencies
from . import _tl # no dependencies
from ._misc import utils # depends on helpers and _tl
from ._tl import custom # depends on utils
from ._misc import hints # depends on custom
from ._client.telegramclient import TelegramClient
from .network import connection
from ._tl import custom
from ._network import connection
from ._tl.custom import Button
from . import version, events, utils, errors

View File

@ -5,7 +5,9 @@ import sys
import typing
import warnings
from .. import utils, helpers, errors, password as pwd_mod, _tl
from .._misc import utils, helpers, password as pwd_mod
from .. import errors, _tl
from .._tl import custom
if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient

View File

@ -1,6 +1,7 @@
import typing
from .. import hints, _tl
from .._tl import custom
if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient
@ -13,7 +14,7 @@ async def inline_query(
*,
entity: 'hints.EntityLike' = None,
offset: str = None,
geo_point: '_tl.GeoPoint' = None) -> _tl.custom.InlineResults:
geo_point: '_tl.GeoPoint' = None) -> custom.InlineResults:
bot = await self.get_input_entity(bot)
if entity:
peer = await self.get_input_entity(entity)
@ -28,4 +29,4 @@ async def inline_query(
geo_point=geo_point
))
return _tl.custom.InlineResults(self, result, entity=peer if entity else None)
return custom.InlineResults(self, result, entity=peer if entity else None)

View File

@ -1,6 +1,8 @@
import typing
from .. import utils, hints, _tl
from .._misc import utils, hints
from .. import _tl
from .._tl import custom
def build_reply_markup(
@ -30,7 +32,7 @@ def build_reply_markup(
for row in buttons:
current = []
for button in row:
if isinstance(button, _tl.custom.Button):
if isinstance(button, custom.Button):
if button.resize is not None:
resize = button.resize
if button.single_use is not None:
@ -39,10 +41,10 @@ def build_reply_markup(
selective = button.selective
button = button.button
elif isinstance(button, _tl.custom.MessageButton):
elif isinstance(button, custom.MessageButton):
button = button.button
inline = _tl.custom.Button._is_inline(button)
inline = custom.Button._is_inline(button)
is_inline |= inline
is_normal |= not inline

View File

@ -4,8 +4,9 @@ import itertools
import string
import typing
from .. import helpers, utils, hints, errors, _tl
from ..requestiter import RequestIter
from .. import hints, errors, _tl
from .._misc import helpers, utils, requestiter
from .._tl import custom
if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient
@ -92,7 +93,7 @@ class _ChatAction:
self._action.progress = 100 * round(current / total)
class _ParticipantsIter(RequestIter):
class _ParticipantsIter(requestiter.RequestIter):
async def _init(self, entity, filter, search, aggressive):
if isinstance(filter, type):
if filter in (_tl.ChannelParticipantsBanned,
@ -246,7 +247,7 @@ class _ParticipantsIter(RequestIter):
self.buffer.append(user)
class _AdminLogIter(RequestIter):
class _AdminLogIter(requestiter.RequestIter):
async def _init(
self, entity, admins, search, min_id, max_id,
join, leave, invite, restrict, unrestrict, ban, unban,
@ -301,13 +302,13 @@ class _AdminLogIter(RequestIter):
ev.action.message._finish_init(
self.client, entities, self.entity)
self.buffer.append(_tl.custom.AdminLogEvent(ev, entities))
self.buffer.append(custom.AdminLogEvent(ev, entities))
if len(r.events) < self.request.limit:
return True
class _ProfilePhotoIter(RequestIter):
class _ProfilePhotoIter(requestiter.RequestIter):
async def _init(
self, entity, offset, max_id
):
@ -694,7 +695,7 @@ async def get_permissions(
self: 'TelegramClient',
entity: 'hints.EntityLike',
user: 'hints.EntityLike' = None
) -> 'typing.Optional[_tl.custom.ParticipantPermissions]':
) -> 'typing.Optional[custom.ParticipantPermissions]':
entity = await self.get_entity(entity)
if not user:
@ -715,7 +716,7 @@ async def get_permissions(
entity,
user
))
return _tl.custom.ParticipantPermissions(participant.participant, False)
return custom.ParticipantPermissions(participant.participant, False)
elif helpers._entity_type(entity) == helpers._EntityType.CHAT:
chat = await self(_tl.fn.messages.GetFullChat(
entity
@ -724,7 +725,7 @@ async def get_permissions(
user = await self.get_me(input_peer=True)
for participant in chat.full_chat.participants.participants:
if participant.user_id == user.user_id:
return _tl.custom.ParticipantPermissions(participant, True)
return custom.ParticipantPermissions(participant, True)
raise errors.UserNotParticipantError(None)
raise ValueError('You must pass either a channel or a chat')

View File

@ -3,8 +3,9 @@ import inspect
import itertools
import typing
from .. import helpers, utils, hints, errors, _tl
from ..requestiter import RequestIter
from .. import hints, errors, _tl
from .._misc import helpers, utils, requestiter
from .._tl import custom
_MAX_CHUNK_SIZE = 100
@ -23,7 +24,7 @@ def _dialog_message_key(peer, message_id):
return (peer.channel_id if isinstance(peer, _tl.PeerChannel) else None), message_id
class _DialogsIter(RequestIter):
class _DialogsIter(requestiter.RequestIter):
async def _init(
self, offset_date, offset_id, offset_peer, ignore_pinned, ignore_migrated, folder
):
@ -79,7 +80,7 @@ class _DialogsIter(RequestIter):
# Real world example: https://t.me/TelethonChat/271471
continue
cd = _tl.custom.Dialog(self.client, d, entities, message)
cd = custom.Dialog(self.client, d, entities, message)
if cd.dialog.pts:
self.client._channel_pts[cd.id] = cd.dialog.pts
@ -108,7 +109,7 @@ class _DialogsIter(RequestIter):
self.request.offset_peer = self.buffer[-1].input_entity
class _DraftsIter(RequestIter):
class _DraftsIter(requestiter.RequestIter):
async def _init(self, entities, **kwargs):
if not entities:
r = await self.client(_tl.fn.messages.GetAllDrafts())
@ -127,7 +128,7 @@ class _DraftsIter(RequestIter):
for x in itertools.chain(r.users, r.chats)}
self.buffer.extend(
_tl.custom.Draft(self.client, entities[utils.get_peer_id(d.peer)], d.draft)
custom.Draft(self.client, entities[utils.get_peer_id(d.peer)], d.draft)
for d in items
)

View File

@ -6,10 +6,9 @@ import typing
import inspect
import asyncio
from ..crypto import AES
from .. import utils, helpers, errors, hints, _tl
from ..requestiter import RequestIter
from .._crypto import AES
from .._misc import utils, helpers, requestiter
from .. import errors, hints, _tl
try:
import aiohttp
@ -26,7 +25,7 @@ MAX_CHUNK_SIZE = 512 * 1024
# 2021-01-15, users reported that `errors.TimeoutError` can occur while downloading files.
TIMED_OUT_SLEEP = 1
class _DirectDownloadIter(RequestIter):
class _DirectDownloadIter(requestiter.RequestIter):
async def _init(
self, file, dc_id, offset, stride, chunk_size, request_size, file_size, msg_data
):

View File

@ -3,8 +3,8 @@ import itertools
import typing
import warnings
from .. import helpers, utils, errors, hints, _tl
from ..requestiter import RequestIter
from .. import errors, hints, _tl
from .._misc import helpers, utils, requestiter
_MAX_CHUNK_SIZE = 100
@ -12,7 +12,7 @@ if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient
class _MessagesIter(RequestIter):
class _MessagesIter(requestiter.RequestIter):
"""
Common factor for all requests that need to iterate over messages.
"""
@ -263,7 +263,7 @@ class _MessagesIter(RequestIter):
self.request.offset_rate = getattr(response, 'next_rate', 0)
class _IDsIter(RequestIter):
class _IDsIter(requestiter.RequestIter):
async def _init(self, entity, ids):
self.total = len(ids)
self._ids = list(reversed(ids)) if self.reverse else ids

View File

@ -8,12 +8,10 @@ import time
import typing
from .. import version, helpers, __name__ as __base_name__, _tl
from ..crypto import rsa
from ..entitycache import EntityCache
from ..extensions import markdown
from ..network import MTProtoSender, Connection, ConnectionTcpFull, TcpMTProxy
from .._crypto import rsa
from .._misc import markdown, entitycache, statecache
from .._network import MTProtoSender, Connection, ConnectionTcpFull, TcpMTProxy
from ..sessions import Session, SQLiteSession, MemorySession
from ..statecache import StateCache
DEFAULT_DC_ID = 2
DEFAULT_IPV4_IP = '149.154.167.51'
@ -151,7 +149,7 @@ def init(
# TODO Session should probably return all cached
# info of entities, not just the input versions
self.session = session
self._entity_cache = EntityCache()
self._entity_cache = entitycache.EntityCache()
self.api_id = int(api_id)
self.api_hash = api_hash
@ -259,7 +257,7 @@ def init(
# Update state (for catching up after a disconnection)
# TODO Get state from channels too
self._state_cache = StateCache(
self._state_cache = statecache.StateCache(
self.session.get_update_state(0), self._log)
# Some further state for subclasses

View File

@ -9,7 +9,8 @@ from . import (
telegrambaseclient, updates, uploads, users
)
from .. import helpers, version, _tl
from ..network import ConnectionTcpFull
from .._tl import custom
from .._network import ConnectionTcpFull
from ..events.common import EventBuilder, EventCommon
@ -3390,7 +3391,7 @@ class TelegramClient:
await client.send_file(chat, file, progress_callback=callback)
# Dices, including dart and other future emoji
from telethon.tl import types
from telethon import _tl
await client.send_file(chat, _tl.InputMediaDice(''))
await client.send_file(chat, _tl.InputMediaDice('🎯'))

View File

@ -7,9 +7,11 @@ import re
import typing
from io import BytesIO
from ..crypto import AES
from .._crypto import AES
from .. import utils, helpers, hints, _tl
from .._misc import utils, helpers
from .. import hints, _tl
from .._tl import custom
try:
import PIL
@ -361,7 +363,7 @@ async def upload_file(
if is_big:
return _tl.InputFileBig(file_id, part_count, file_name)
else:
return _tl.custom.InputSizedFile(
return custom.InputSizedFile(
file_id, part_count, file_name, md5=hash_md5, size=file_size
)

View File

@ -4,9 +4,9 @@ import itertools
import time
import typing
from .. import errors, helpers, utils, hints, _tl
from .. import errors, hints, _tl
from .._misc import helpers, utils
from ..errors import MultiError, RPCError
from ..helpers import retry_range
_NOT_A_REQUEST = lambda: TypeError('You can only invoke requests, not types!')
@ -53,7 +53,7 @@ async def call(self: 'TelegramClient', sender, request, ordered=False, flood_sle
last_error = None
self._last_request = time.time()
for attempt in retry_range(self._request_retries):
for attempt in helpers.retry_range(self._request_retries):
try:
future = sender.send(request, ordered=ordered)
if isinstance(future, list):

View File

@ -4,7 +4,7 @@ This module holds the AuthKey class.
import struct
from hashlib import sha1
from ..extensions import BinaryReader
from .._misc import BinaryReader
class AuthKey:

View File

@ -4,7 +4,7 @@ This module holds the CdnDecrypter utility class.
from hashlib import sha256
from .. import _tl
from ..crypto import AESModeCTR
from .._crypto import AESModeCTR
from ..errors import CdnFileTamperedError

View File

@ -1,7 +1,8 @@
import inspect
import itertools
from . import utils, _tl
from .._misc import utils
from .. import _tl
# Which updates have the following fields?
_has_field = {

View File

@ -1,7 +1,9 @@
import datetime
import typing
from . import helpers, _tl
from . import helpers
from .. import _tl
from .._tl import custom
Phone = str
Username = str

View File

@ -6,7 +6,7 @@ since they seem to count as two characters and it's a bit strange.
import re
import warnings
from ..helpers import add_surrogate, del_surrogate, within_surrogate, strip_text
from .helpers import add_surrogate, del_surrogate, within_surrogate, strip_text
from .. import _tl
DEFAULT_DELIMITERS = {

View File

@ -3,9 +3,9 @@ import collections
import io
import struct
from ..tl import TLRequest
from ..tl.core.messagecontainer import MessageContainer
from ..tl.core.tlmessage import TLMessage
from .._tl import TLRequest
from .._tl.core.messagecontainer import MessageContainer
from .._tl.core.tlmessage import TLMessage
class MessagePacker:

View File

@ -1,8 +1,8 @@
import hashlib
import os
from .crypto import factorization
from . import _tl
from .._crypto import factorization
from .. import _tl
def check_prime_and_good_check(prime: int, g: int):

View File

@ -1,6 +1,6 @@
import inspect
from . import _tl
from .. import _tl
# Which updates have the following fields?

View File

@ -19,9 +19,9 @@ from collections import namedtuple
from mimetypes import guess_extension
from types import GeneratorType
from .extensions import markdown, html
from .helpers import add_surrogate, del_surrogate, strip_text
from . import _tl
from . import markdown, html
from .. import _tl
try:
import hachoir
@ -32,26 +32,26 @@ except ImportError:
# Register some of the most common mime-types to avoid any issues.
# See https://github.com/LonamiWebs/Telethon/issues/1096.
mime_tl.add_type('image/png', '.png')
mime_tl.add_type('image/jpeg', '.jpeg')
mime_tl.add_type('image/webp', '.webp')
mime_tl.add_type('image/gif', '.gif')
mime_tl.add_type('image/bmp', '.bmp')
mime_tl.add_type('image/x-tga', '.tga')
mime_tl.add_type('image/tiff', '.tiff')
mime_tl.add_type('image/vnd.adobe.photoshop', '.psd')
mimetypes.add_type('image/png', '.png')
mimetypes.add_type('image/jpeg', '.jpeg')
mimetypes.add_type('image/webp', '.webp')
mimetypes.add_type('image/gif', '.gif')
mimetypes.add_type('image/bmp', '.bmp')
mimetypes.add_type('image/x-tga', '.tga')
mimetypes.add_type('image/tiff', '.tiff')
mimetypes.add_type('image/vnd.adobe.photoshop', '.psd')
mime_tl.add_type('video/mp4', '.mp4')
mime_tl.add_type('video/quicktime', '.mov')
mime_tl.add_type('video/avi', '.avi')
mimetypes.add_type('video/mp4', '.mp4')
mimetypes.add_type('video/quicktime', '.mov')
mimetypes.add_type('video/avi', '.avi')
mime_tl.add_type('audio/mpeg', '.mp3')
mime_tl.add_type('audio/m4a', '.m4a')
mime_tl.add_type('audio/aac', '.aac')
mime_tl.add_type('audio/ogg', '.ogg')
mime_tl.add_type('audio/flac', '.flac')
mimetypes.add_type('audio/mpeg', '.mp3')
mimetypes.add_type('audio/m4a', '.m4a')
mimetypes.add_type('audio/aac', '.aac')
mimetypes.add_type('audio/ogg', '.ogg')
mimetypes.add_type('audio/flac', '.flac')
mime_tl.add_type('application/x-tgsticker', '.tgs')
mimetypes.add_type('application/x-tgsticker', '.tgs')
USERNAME_RE = re.compile(
r'@|(?:https?://)?(?:www\.)?(?:telegram\.(?:me|dog)|t\.me)/(@|joinchat/)?'
@ -675,7 +675,7 @@ def get_attributes(file, *, attributes=None, mime_type=None,
# Note: ``file.name`` works for :tl:`InputFile` and some `IOBase` streams
name = file if isinstance(file, str) else getattr(file, 'name', 'unnamed')
if mime_type is None:
mime_type = mime_tl.guess_type(name)[0]
mime_type = mimetypes.guess_type(name)[0]
attr_dict = {_tl.DocumentAttributeFilename:
_tl.DocumentAttributeFilename(os.path.basename(name))}
@ -881,7 +881,7 @@ def is_audio(file):
return False
else:
file = 'a' + ext
return (mime_tl.guess_type(file)[0] or '').startswith('audio/')
return (mimetypes.guess_type(file)[0] or '').startswith('audio/')
def is_video(file):
@ -895,7 +895,7 @@ def is_video(file):
return False
else:
file = 'a' + ext
return (mime_tl.guess_type(file)[0] or '').startswith('video/')
return (mimetypes.guess_type(file)[0] or '').startswith('video/')
def is_list_like(obj):

View File

@ -7,9 +7,9 @@ import time
from hashlib import sha1
from .. import helpers, _tl
from ..crypto import AES, AuthKey, Factorization, rsa
from .._crypto import AES, AuthKey, Factorization, rsa
from ..errors import SecurityError
from ..extensions import BinaryReader
from .._misc import BinaryReader
async def do_authentication(sender):

View File

@ -9,7 +9,7 @@ from .tcpintermediate import (
RandomizedIntermediatePacketCodec
)
from ...crypto import AESModeCTR
from ..._crypto import AESModeCTR
class MTProxyIO:

View File

@ -3,7 +3,7 @@ import os
from .tcpabridged import AbridgedPacketCodec
from .connection import ObfuscatedConnection
from ...crypto import AESModeCTR
from ..._crypto import AESModeCTR
class ObfuscatedIO:

View File

@ -6,7 +6,7 @@ import struct
from .mtprotostate import MTProtoState
from ..errors import InvalidBufferError
from ..extensions import BinaryReader
from .._misc import BinaryReader
class MTProtoPlainSender:

View File

@ -3,27 +3,20 @@ import collections
import struct
from . import authenticator
from ..extensions.messagepacker import MessagePacker
from .._misc.messagepacker import MessagePacker
from .mtprotoplainsender import MTProtoPlainSender
from .requeststate import RequestState
from .mtprotostate import MTProtoState
from ..tl.tlobject import TLRequest
from .. import helpers, utils
from .._tl.tlobject import TLRequest
from .. import helpers, utils, _tl
from ..errors import (
BadMessageError, InvalidBufferError, SecurityError,
TypeNotFoundError, rpc_message_to_error
)
from ..extensions import BinaryReader
from ..tl.core import RpcResult, MessageContainer, GzipPacked
from ..tl.functions.auth import LogOutRequest
from ..tl.functions import PingRequest, DestroySessionRequest
from ..tl.types import (
MsgsAck, Pong, BadServerSalt, BadMsgNotification, FutureSalts,
MsgNewDetailedInfo, NewSessionCreated, MsgDetailedInfo, MsgsStateReq,
MsgsStateInfo, MsgsAllInfo, MsgResendReq, upload, DestroySessionOk, DestroySessionNone,
)
from ..crypto import AuthKey
from ..helpers import retry_range
from .._misc import BinaryReader
from .._tl.core import RpcResult, MessageContainer, GzipPacked
from .._crypto import AuthKey
from .._misc.helpers import retry_range
class MTProtoSender:
@ -97,19 +90,19 @@ class MTProtoSender:
RpcResult.CONSTRUCTOR_ID: self._handle_rpc_result,
MessageContainer.CONSTRUCTOR_ID: self._handle_container,
GzipPacked.CONSTRUCTOR_ID: self._handle_gzip_packed,
Pong.CONSTRUCTOR_ID: self._handle_pong,
BadServerSalt.CONSTRUCTOR_ID: self._handle_bad_server_salt,
BadMsgNotification.CONSTRUCTOR_ID: self._handle_bad_notification,
MsgDetailedInfo.CONSTRUCTOR_ID: self._handle_detailed_info,
MsgNewDetailedInfo.CONSTRUCTOR_ID: self._handle_new_detailed_info,
NewSessionCreated.CONSTRUCTOR_ID: self._handle_new_session_created,
MsgsAck.CONSTRUCTOR_ID: self._handle_ack,
FutureSalts.CONSTRUCTOR_ID: self._handle_future_salts,
MsgsStateReq.CONSTRUCTOR_ID: self._handle_state_forgotten,
MsgResendReq.CONSTRUCTOR_ID: self._handle_state_forgotten,
MsgsAllInfo.CONSTRUCTOR_ID: self._handle_msg_all,
DestroySessionOk: self._handle_destroy_session,
DestroySessionNone: self._handle_destroy_session,
_tl.Pong.CONSTRUCTOR_ID: self._handle_pong,
_tl.BadServerSalt.CONSTRUCTOR_ID: self._handle_bad_server_salt,
_tl.BadMsgNotification.CONSTRUCTOR_ID: self._handle_bad_notification,
_tl.MsgDetailedInfo.CONSTRUCTOR_ID: self._handle_detailed_info,
_tl.MsgNewDetailedInfo.CONSTRUCTOR_ID: self._handle_new_detailed_info,
_tl.NewSessionCreated.CONSTRUCTOR_ID: self._handle_new_session_created,
_tl.MsgsAck.CONSTRUCTOR_ID: self._handle_ack,
_tl.FutureSalts.CONSTRUCTOR_ID: self._handle_future_salts,
_tl.MsgsStateReq.CONSTRUCTOR_ID: self._handle_state_forgotten,
_tl.MsgResendReq.CONSTRUCTOR_ID: self._handle_state_forgotten,
_tl.MsgsAllInfo.CONSTRUCTOR_ID: self._handle_msg_all,
_tl.DestroySessionOk: self._handle_destroy_session,
_tl.DestroySessionNone: self._handle_destroy_session,
}
# Public API
@ -433,7 +426,7 @@ class MTProtoSender:
# TODO this is ugly, update loop shouldn't worry about this, sender should
if self._ping is None:
self._ping = rnd_id
self.send(PingRequest(rnd_id))
self.send(_tl.fn.Ping(rnd_id))
else:
self._start_reconnect(None)
@ -448,7 +441,7 @@ class MTProtoSender:
"""
while self._user_connected and not self._reconnecting:
if self._pending_ack:
ack = RequestState(MsgsAck(list(self._pending_ack)))
ack = RequestState(_tl.MsgsAck(list(self._pending_ack)))
self._send_queue.append(ack)
self._last_acks.append(ack)
self._pending_ack.clear()
@ -598,7 +591,7 @@ class MTProtoSender:
# which contain the real response right after.
try:
with BinaryReader(rpc_result.body) as reader:
if not isinstance(reader.tgread_object(), upload.File):
if not isinstance(reader.tgread_object(), _tl.upload.File):
raise ValueError('Not an upload.File')
except (TypeNotFoundError, ValueError):
self._log.info('Received response without parent request: %s', rpc_result.body)
@ -607,7 +600,7 @@ class MTProtoSender:
if rpc_result.error:
error = rpc_message_to_error(rpc_result.error, state.request)
self._send_queue.append(
RequestState(MsgsAck([state.msg_id])))
RequestState(_tl.MsgsAck([state.msg_id])))
if not state.future.cancelled():
state.future.set_exception(error)
@ -777,7 +770,7 @@ class MTProtoSender:
self._log.debug('Handling acknowledge for %s', str(ack.msg_ids))
for msg_id in ack.msg_ids:
state = self._pending_state.get(msg_id)
if state and isinstance(state.request, LogOutRequest):
if state and isinstance(state.request, _tl.fn.auth.LogOut):
del self._pending_state[msg_id]
if not state.future.cancelled():
state.future.set_result(True)
@ -802,7 +795,7 @@ class MTProtoSender:
Handles both :tl:`MsgsStateReq` and :tl:`MsgResendReq` by
enqueuing a :tl:`MsgsStateInfo` to be sent at a later point.
"""
self._send_queue.append(RequestState(MsgsStateInfo(
self._send_queue.append(RequestState(_tl.MsgsStateInfo(
req_msg_id=message.msg_id, info=chr(1) * len(message.obj.msg_ids)
)))
@ -817,7 +810,7 @@ class MTProtoSender:
It behaves pretty much like handling an RPC result.
"""
for msg_id, state in self._pending_state.items():
if isinstance(state.request, DestroySessionRequest)\
if isinstance(state.request, _tl.fn.DestroySession)\
and state.request.session_id == message.obj.session_id:
break
else:

View File

@ -3,13 +3,13 @@ import struct
import time
from hashlib import sha256
from ..crypto import AES
from .._crypto import AES
from ..errors import SecurityError, InvalidBufferError
from ..extensions import BinaryReader
from ..tl.core import TLMessage
from ..tl.tlobject import TLRequest
from ..tl.functions import InvokeAfterMsgRequest
from ..tl.core.gzippacked import GzipPacked
from .._misc import BinaryReader
from .._tl.core import TLMessage
from .._tl.tlobject import TLRequest
from .. import _tl
from .._tl.core.gzippacked import GzipPacked
class _OpaqueRequest(TLRequest):
@ -103,7 +103,7 @@ class MTProtoState:
# The `RequestState` stores `bytes(request)`, not the request itself.
# `invokeAfterMsg` wants a `TLRequest` though, hence the wrapping.
body = GzipPacked.gzip_if_smaller(content_related,
bytes(InvokeAfterMsgRequest(after_id, _OpaqueRequest(data))))
bytes(_tl.fn.InvokeAfterMsgRequest(after_id, _OpaqueRequest(data))))
buffer.write(struct.pack('<qii', msg_id, seq_no, len(body)))
buffer.write(body)

View File

@ -1,6 +1,5 @@
from .gzippacked import GzipPacked
from .. import TLObject
from ..types import RpcError
from .. import TLObject, RpcError
class RpcResult(TLObject):

View File

@ -1,5 +1,5 @@
from ...tl import types
from ...utils import get_input_peer
from ... import _tl
from ..._misc.utils import get_input_peer
class AdminLogEvent:

View File

@ -1,5 +1,5 @@
from .. import types
from ... import utils
from ... import _tl
from ..._misc import utils
class Button:

View File

@ -1,7 +1,6 @@
import abc
from ... import errors, utils
from ...tl import types
from ... import errors, utils, _tl
class ChatGetter(abc.ABC):
@ -114,7 +113,7 @@ class ChatGetter(abc.ABC):
Returns `None` if there isn't enough information
(e.g. on `events.MessageDeleted <telethon.events.messagedeleted.MessageDeleted>`).
"""
return isinstance(self._chat_peer, types.PeerUser) if self._chat_peer else None
return isinstance(self._chat_peer, _tl.PeerUser) if self._chat_peer else None
@property
def is_group(self):
@ -128,20 +127,20 @@ class ChatGetter(abc.ABC):
if self._broadcast is None and hasattr(self.chat, 'broadcast'):
self._broadcast = bool(self.chat.broadcast)
if isinstance(self._chat_peer, types.PeerChannel):
if isinstance(self._chat_peer, _tl.PeerChannel):
if self._broadcast is None:
return None
else:
return not self._broadcast
return isinstance(self._chat_peer, types.PeerChat)
return isinstance(self._chat_peer, _tl.PeerChat)
@property
def is_channel(self):
"""`True` if the message was sent on a megagroup or channel."""
# The only case where chat peer could be none is in MessageDeleted,
# however those always have the peer in channels.
return isinstance(self._chat_peer, types.PeerChannel)
return isinstance(self._chat_peer, _tl.PeerChannel)
async def _refetch_chat(self):
"""

View File

@ -1,6 +1,6 @@
from . import Draft
from .. import TLObject, types, functions
from ... import utils
from ... import _tl
from ..._misc import utils
class Dialog:
@ -89,12 +89,12 @@ class Dialog:
self.draft = Draft(client, self.entity, self.dialog.draft)
self.is_user = isinstance(self.entity, types.User)
self.is_user = isinstance(self.entity, _tl.User)
self.is_group = (
isinstance(self.entity, (types.Chat, types.ChatForbidden)) or
(isinstance(self.entity, types.Channel) and self.entity.megagroup)
isinstance(self.entity, (_tl.Chat, _tl.ChatForbidden)) or
(isinstance(self.entity, _tl.Channel) and self.entity.megagroup)
)
self.is_channel = isinstance(self.entity, types.Channel)
self.is_channel = isinstance(self.entity, _tl.Channel)
async def send_message(self, *args, **kwargs):
"""
@ -141,7 +141,7 @@ class Dialog:
dialog.archive(0)
"""
return await self._client(_tl.fn.folders.EditPeerFolders([
types.InputFolderPeer(self.input_entity, folder_id=folder)
_tl.InputFolderPeer(self.input_entity, folder_id=folder)
]))
def to_dict(self):
@ -155,7 +155,7 @@ class Dialog:
}
def __str__(self):
return TLObject.pretty_format(self.to_dict())
return _tl.TLObject.pretty_format(self.to_dict())
def stringify(self):
return TLObject.pretty_format(self.to_dict(), indent=0)
return _tl.TLObject.pretty_format(self.to_dict(), indent=0)

View File

@ -2,8 +2,8 @@ import datetime
from ... import _tl
from ...errors import RPCError
from ...extensions import markdown
from ...utils import get_input_peer, get_peer
from ..._misc import markdown
from ..._misc.utils import get_input_peer, get_peer
class Draft:

View File

@ -1,8 +1,8 @@
import mimetypes
import os
from ... import utils
from ...tl import types
from ..._misc import utils
from ... import _tl
class File:
@ -38,7 +38,7 @@ class File:
"""
The file name of this document.
"""
return self._from_attr(types.DocumentAttributeFilename, 'file_name')
return self._from_attr(_tl.DocumentAttributeFilename, 'file_name')
@property
def ext(self):
@ -49,7 +49,7 @@ class File:
from the file name (if any) will be used.
"""
return (
mimetypes.guess_extension(self.mime_type)
mime_tl.guess_extension(self.mime_type)
or os.path.splitext(self.name or '')[-1]
or None
)
@ -59,9 +59,9 @@ class File:
"""
The mime-type of this file.
"""
if isinstance(self.media, types.Photo):
if isinstance(self.media, _tl.Photo):
return 'image/jpeg'
elif isinstance(self.media, types.Document):
elif isinstance(self.media, _tl.Document):
return self.media.mime_type
@property
@ -69,22 +69,22 @@ class File:
"""
The width in pixels of this media if it's a photo or a video.
"""
if isinstance(self.media, types.Photo):
if isinstance(self.media, _tl.Photo):
return max(getattr(s, 'w', 0) for s in self.media.sizes)
return self._from_attr((
types.DocumentAttributeImageSize, types.DocumentAttributeVideo), 'w')
_tl.DocumentAttributeImageSize, _tl.DocumentAttributeVideo), 'w')
@property
def height(self):
"""
The height in pixels of this media if it's a photo or a video.
"""
if isinstance(self.media, types.Photo):
if isinstance(self.media, _tl.Photo):
return max(getattr(s, 'h', 0) for s in self.media.sizes)
return self._from_attr((
types.DocumentAttributeImageSize, types.DocumentAttributeVideo), 'h')
_tl.DocumentAttributeImageSize, _tl.DocumentAttributeVideo), 'h')
@property
def duration(self):
@ -92,35 +92,35 @@ class File:
The duration in seconds of the audio or video.
"""
return self._from_attr((
types.DocumentAttributeAudio, types.DocumentAttributeVideo), 'duration')
_tl.DocumentAttributeAudio, _tl.DocumentAttributeVideo), 'duration')
@property
def title(self):
"""
The title of the song.
"""
return self._from_attr(types.DocumentAttributeAudio, 'title')
return self._from_attr(_tl.DocumentAttributeAudio, 'title')
@property
def performer(self):
"""
The performer of the song.
"""
return self._from_attr(types.DocumentAttributeAudio, 'performer')
return self._from_attr(_tl.DocumentAttributeAudio, 'performer')
@property
def emoji(self):
"""
A string with all emoji that represent the current sticker.
"""
return self._from_attr(types.DocumentAttributeSticker, 'alt')
return self._from_attr(_tl.DocumentAttributeSticker, 'alt')
@property
def sticker_set(self):
"""
The :tl:`InputStickerSet` to which the sticker file belongs.
"""
return self._from_attr(types.DocumentAttributeSticker, 'stickerset')
return self._from_attr(_tl.DocumentAttributeSticker, 'stickerset')
@property
def size(self):
@ -129,13 +129,13 @@ class File:
For photos, this is the heaviest thumbnail, as it often repressents the largest dimensions.
"""
if isinstance(self.media, types.Photo):
if isinstance(self.media, _tl.Photo):
return max(filter(None, map(utils._photo_size_byte_count, self.media.sizes)), default=None)
elif isinstance(self.media, types.Document):
elif isinstance(self.media, _tl.Document):
return self.media.size
def _from_attr(self, cls, field):
if isinstance(self.media, types.Document):
if isinstance(self.media, _tl.Document):
for attr in self.media.attributes:
if isinstance(attr, cls):
return getattr(attr, field, None)

View File

@ -1,7 +1,6 @@
from .chatgetter import ChatGetter
from .sendergetter import SenderGetter
from ... import utils, helpers
from ...tl import types
from ..._misc import utils, helpers
class Forward(ChatGetter, SenderGetter):

View File

@ -1,7 +1,7 @@
import hashlib
from .. import functions, types
from ... import utils
from ... import _tl
from ..._misc import utils
_TYPE_TO_MIMES = {
'gif': ['image/gif'], # 'video/mp4' too, but that's used for video
@ -126,7 +126,7 @@ class InlineBuilder:
# TODO Does 'article' work always?
# article, photo, gif, mpeg4_gif, video, audio,
# voice, document, location, venue, contact, game
result = types.InputBotInlineResult(
result = _tl.InputBotInlineResult(
id=id or '',
type='article',
send_message=await self._message(
@ -194,15 +194,15 @@ class InlineBuilder:
_, media, _ = await self._client._file_to_media(
file, allow_cache=True, as_image=True
)
if isinstance(media, types.InputPhoto):
if isinstance(media, _tl.InputPhoto):
fh = media
else:
r = await self._client(_tl.fn.messages.UploadMedia(
types.InputPeerSelf(), media=media
_tl.InputPeerSelf(), media=media
))
fh = utils.get_input_photo(r.photo)
result = types.InputBotInlineResultPhoto(
result = _tl.InputBotInlineResultPhoto(
id=id or '',
type='photo',
photo=fh,
@ -314,15 +314,15 @@ class InlineBuilder:
video_note=video_note,
allow_cache=use_cache
)
if isinstance(media, types.InputDocument):
if isinstance(media, _tl.InputDocument):
fh = media
else:
r = await self._client(_tl.fn.messages.UploadMedia(
types.InputPeerSelf(), media=media
_tl.InputPeerSelf(), media=media
))
fh = utils.get_input_document(r.document)
result = types.InputBotInlineResultDocument(
result = _tl.InputBotInlineResultDocument(
id=id or '',
type=type,
document=fh,
@ -361,7 +361,7 @@ class InlineBuilder:
short_name (`str`):
The short name of the game to use.
"""
result = types.InputBotInlineResultGame(
result = _tl.InputBotInlineResultGame(
id=id or '',
short_name=short_name,
send_message=await self._message(
@ -400,31 +400,31 @@ class InlineBuilder:
# "MediaAuto" means it will use whatever media the inline
# result itself has (stickers, photos, or documents), while
# respecting the user's text (caption) and formatting.
return types.InputBotInlineMessageMediaAuto(
return _tl.InputBotInlineMessageMediaAuto(
message=text,
entities=msg_entities,
reply_markup=markup
)
else:
return types.InputBotInlineMessageText(
return _tl.InputBotInlineMessageText(
message=text,
no_webpage=not link_preview,
entities=msg_entities,
reply_markup=markup
)
elif isinstance(geo, (types.InputGeoPoint, types.GeoPoint)):
return types.InputBotInlineMessageMediaGeo(
elif isinstance(geo, (_tl.InputGeoPoint, _tl.GeoPoint)):
return _tl.InputBotInlineMessageMediaGeo(
geo_point=utils.get_input_geo(geo),
period=period,
reply_markup=markup
)
elif isinstance(geo, (types.InputMediaVenue, types.MessageMediaVenue)):
if isinstance(geo, types.InputMediaVenue):
elif isinstance(geo, (_tl.InputMediaVenue, _tl.MessageMediaVenue)):
if isinstance(geo, _tl.InputMediaVenue):
geo_point = geo.geo_point
else:
geo_point = geo.geo
return types.InputBotInlineMessageMediaVenue(
return _tl.InputBotInlineMessageMediaVenue(
geo_point=geo_point,
title=geo.title,
address=geo.address,
@ -434,8 +434,8 @@ class InlineBuilder:
reply_markup=markup
)
elif isinstance(contact, (
types.InputMediaContact, types.MessageMediaContact)):
return types.InputBotInlineMessageMediaContact(
_tl.InputMediaContact, _tl.MessageMediaContact)):
return _tl.InputBotInlineMessageMediaContact(
phone_number=contact.phone_number,
first_name=contact.first_name,
last_name=contact.last_name,
@ -443,7 +443,7 @@ class InlineBuilder:
reply_markup=markup
)
elif game:
return types.InputBotInlineMessageGame(
return _tl.InputBotInlineMessageGame(
reply_markup=markup
)
else:

View File

@ -1,5 +1,5 @@
from .. import types, functions
from ... import utils
from ... import _tl
from ..._misc import utils
class InlineResult:

View File

@ -1,7 +1,7 @@
from ..types import InputFile
from ... import _tl
class InputSizedFile(InputFile):
class InputSizedFile(_tl.InputFile):
"""InputFile class with two extra parameters: md5 (digest) and size"""
def __init__(self, id_, parts, name, md5, size):
super().__init__(id_, parts, name, md5.hexdigest())

View File

@ -5,13 +5,13 @@ from .sendergetter import SenderGetter
from .messagebutton import MessageButton
from .forward import Forward
from .file import File
from .. import TLObject, types, functions, alltlobjects
from ... import utils, errors
from ..._misc import utils
from ... import errors, _tl
# TODO Figure out a way to have the code generator error on missing fields
# Maybe parsing the init function alone if that's possible.
class Message(ChatGetter, SenderGetter, TLObject):
class Message(ChatGetter, SenderGetter, _tl.TLObject):
"""
This custom class aggregates both :tl:`Message` and
:tl:`MessageService` to ease accessing their members.
@ -163,7 +163,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
self, id: int,
# Common to Message and MessageService (mandatory)
peer_id: types.TypePeer = None,
peer_id: _tl.TypePeer = None,
date: Optional[datetime] = None,
# Common to Message and MessageService (flags)
@ -172,19 +172,19 @@ class Message(ChatGetter, SenderGetter, TLObject):
media_unread: Optional[bool] = None,
silent: Optional[bool] = None,
post: Optional[bool] = None,
from_id: Optional[types.TypePeer] = None,
reply_to: Optional[types.TypeMessageReplyHeader] = None,
from_id: Optional[_tl.TypePeer] = None,
reply_to: Optional[_tl.TypeMessageReplyHeader] = None,
ttl_period: Optional[int] = None,
# For Message (mandatory)
message: Optional[str] = None,
# For Message (flags)
fwd_from: Optional[types.TypeMessageFwdHeader] = None,
fwd_from: Optional[_tl.TypeMessageFwdHeader] = None,
via_bot_id: Optional[int] = None,
media: Optional[types.TypeMessageMedia] = None,
reply_markup: Optional[types.TypeReplyMarkup] = None,
entities: Optional[List[types.TypeMessageEntity]] = None,
media: Optional[_tl.TypeMessageMedia] = None,
reply_markup: Optional[_tl.TypeReplyMarkup] = None,
entities: Optional[List[_tl.TypeMessageEntity]] = None,
views: Optional[int] = None,
edit_date: Optional[datetime] = None,
post_author: Optional[str] = None,
@ -193,12 +193,12 @@ class Message(ChatGetter, SenderGetter, TLObject):
legacy: Optional[bool] = None,
edit_hide: Optional[bool] = None,
pinned: Optional[bool] = None,
restriction_reason: Optional[types.TypeRestrictionReason] = None,
restriction_reason: Optional[_tl.TypeRestrictionReason] = None,
forwards: Optional[int] = None,
replies: Optional[types.TypeMessageReplies] = None,
replies: Optional[_tl.TypeMessageReplies] = None,
# For MessageAction (mandatory)
action: Optional[types.TypeMessageAction] = None
action: Optional[_tl.TypeMessageAction] = None
):
# Common properties to messages, then to service (in the order they're defined in the `.tl`)
self.out = bool(out)
@ -217,7 +217,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
self.reply_to = reply_to
self.date = date
self.message = message
self.media = None if isinstance(media, types.MessageMediaEmpty) else media
self.media = None if isinstance(media, _tl.MessageMediaEmpty) else media
self.reply_markup = reply_markup
self.entities = entities
self.views = views
@ -253,7 +253,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
# ...or...
# incoming messages in private conversations no longer have from_id
# (layer 119+), but the sender can only be the chat we're in.
if post or (not out and isinstance(peer_id, types.PeerUser)):
if post or (not out and isinstance(peer_id, _tl.PeerUser)):
sender_id = utils.get_peer_id(peer_id)
# Note that these calls would reset the client
@ -272,7 +272,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
# Make messages sent to ourselves outgoing unless they're forwarded.
# This makes it consistent with official client's appearance.
if self.peer_id == types.PeerUser(client._self_id) and not self.fwd_from:
if self.peer_id == _tl.PeerUser(client._self_id) and not self.fwd_from:
self.out = True
cache = client._entity_cache
@ -294,25 +294,25 @@ class Message(ChatGetter, SenderGetter, TLObject):
self._forward = Forward(self._client, self.fwd_from, entities)
if self.action:
if isinstance(self.action, (types.MessageActionChatAddUser,
types.MessageActionChatCreate)):
if isinstance(self.action, (_tl.MessageActionChatAddUser,
_tl.MessageActionChatCreate)):
self._action_entities = [entities.get(i)
for i in self.action.users]
elif isinstance(self.action, types.MessageActionChatDeleteUser):
elif isinstance(self.action, _tl.MessageActionChatDeleteUser):
self._action_entities = [entities.get(self.action.user_id)]
elif isinstance(self.action, types.MessageActionChatJoinedByLink):
elif isinstance(self.action, _tl.MessageActionChatJoinedByLink):
self._action_entities = [entities.get(self.action.inviter_id)]
elif isinstance(self.action, types.MessageActionChatMigrateTo):
elif isinstance(self.action, _tl.MessageActionChatMigrateTo):
self._action_entities = [entities.get(utils.get_peer_id(
types.PeerChannel(self.action.channel_id)))]
_tl.PeerChannel(self.action.channel_id)))]
elif isinstance(
self.action, types.MessageActionChannelMigrateFrom):
self.action, _tl.MessageActionChannelMigrateFrom):
self._action_entities = [entities.get(utils.get_peer_id(
types.PeerChat(self.action.chat_id)))]
_tl.PeerChat(self.action.chat_id)))]
if self.replies and self.replies.channel_id:
self._linked_chat = entities.get(utils.get_peer_id(
types.PeerChannel(self.replies.channel_id)))
_tl.PeerChannel(self.replies.channel_id)))
# endregion Initialization
@ -435,7 +435,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
if self._buttons_count is None:
if isinstance(self.reply_markup, (
types.ReplyInlineMarkup, types.ReplyKeyboardMarkup)):
_tl.ReplyInlineMarkup, _tl.ReplyKeyboardMarkup)):
self._buttons_count = sum(
len(row.buttons) for row in self.reply_markup.rows)
else:
@ -471,14 +471,14 @@ class Message(ChatGetter, SenderGetter, TLObject):
action is :tl:`MessageActionChatEditPhoto`, or if the message has
a web preview with a photo.
"""
if isinstance(self.media, types.MessageMediaPhoto):
if isinstance(self.media.photo, types.Photo):
if isinstance(self.media, _tl.MessageMediaPhoto):
if isinstance(self.media.photo, _tl.Photo):
return self.media.photo
elif isinstance(self.action, types.MessageActionChatEditPhoto):
elif isinstance(self.action, _tl.MessageActionChatEditPhoto):
return self.action.photo
else:
web = self.web_preview
if web and isinstance(web.photo, types.Photo):
if web and isinstance(web.photo, _tl.Photo):
return web.photo
@property
@ -486,12 +486,12 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`Document` media in this message, if any.
"""
if isinstance(self.media, types.MessageMediaDocument):
if isinstance(self.media.document, types.Document):
if isinstance(self.media, _tl.MessageMediaDocument):
if isinstance(self.media.document, _tl.Document):
return self.media.document
else:
web = self.web_preview
if web and isinstance(web.document, types.Document):
if web and isinstance(web.document, _tl.Document):
return web.document
@property
@ -499,8 +499,8 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`WebPage` media in this message, if any.
"""
if isinstance(self.media, types.MessageMediaWebPage):
if isinstance(self.media.webpage, types.WebPage):
if isinstance(self.media, _tl.MessageMediaWebPage):
if isinstance(self.media.webpage, _tl.WebPage):
return self.media.webpage
@property
@ -508,7 +508,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`Document` media in this message, if it's an audio file.
"""
return self._document_by_attribute(types.DocumentAttributeAudio,
return self._document_by_attribute(_tl.DocumentAttributeAudio,
lambda attr: not attr.voice)
@property
@ -516,7 +516,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`Document` media in this message, if it's a voice note.
"""
return self._document_by_attribute(types.DocumentAttributeAudio,
return self._document_by_attribute(_tl.DocumentAttributeAudio,
lambda attr: attr.voice)
@property
@ -524,14 +524,14 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`Document` media in this message, if it's a video.
"""
return self._document_by_attribute(types.DocumentAttributeVideo)
return self._document_by_attribute(_tl.DocumentAttributeVideo)
@property
def video_note(self):
"""
The :tl:`Document` media in this message, if it's a video note.
"""
return self._document_by_attribute(types.DocumentAttributeVideo,
return self._document_by_attribute(_tl.DocumentAttributeVideo,
lambda attr: attr.round_message)
@property
@ -543,21 +543,21 @@ class Message(ChatGetter, SenderGetter, TLObject):
sound, the so called "animated" media. However, it may be the actual
gif format if the file is too large.
"""
return self._document_by_attribute(types.DocumentAttributeAnimated)
return self._document_by_attribute(_tl.DocumentAttributeAnimated)
@property
def sticker(self):
"""
The :tl:`Document` media in this message, if it's a sticker.
"""
return self._document_by_attribute(types.DocumentAttributeSticker)
return self._document_by_attribute(_tl.DocumentAttributeSticker)
@property
def contact(self):
"""
The :tl:`MessageMediaContact` in this message, if it's a contact.
"""
if isinstance(self.media, types.MessageMediaContact):
if isinstance(self.media, _tl.MessageMediaContact):
return self.media
@property
@ -565,7 +565,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`Game` media in this message, if it's a game.
"""
if isinstance(self.media, types.MessageMediaGame):
if isinstance(self.media, _tl.MessageMediaGame):
return self.media.game
@property
@ -573,9 +573,9 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`GeoPoint` media in this message, if it has a location.
"""
if isinstance(self.media, (types.MessageMediaGeo,
types.MessageMediaGeoLive,
types.MessageMediaVenue)):
if isinstance(self.media, (_tl.MessageMediaGeo,
_tl.MessageMediaGeoLive,
_tl.MessageMediaVenue)):
return self.media.geo
@property
@ -583,7 +583,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`MessageMediaInvoice` in this message, if it's an invoice.
"""
if isinstance(self.media, types.MessageMediaInvoice):
if isinstance(self.media, _tl.MessageMediaInvoice):
return self.media
@property
@ -591,7 +591,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`MessageMediaPoll` in this message, if it's a poll.
"""
if isinstance(self.media, types.MessageMediaPoll):
if isinstance(self.media, _tl.MessageMediaPoll):
return self.media
@property
@ -599,7 +599,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`MessageMediaVenue` in this message, if it's a venue.
"""
if isinstance(self.media, types.MessageMediaVenue):
if isinstance(self.media, _tl.MessageMediaVenue):
return self.media
@property
@ -607,7 +607,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
"""
The :tl:`MessageMediaDice` in this message, if it's a dice roll.
"""
if isinstance(self.media, types.MessageMediaDice):
if isinstance(self.media, _tl.MessageMediaDice):
return self.media
@property
@ -616,7 +616,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
Returns a list of entities that took part in this action.
Possible cases for this are :tl:`MessageActionChatAddUser`,
:tl:`types.MessageActionChatCreate`, :tl:`MessageActionChatDeleteUser`,
:tl:`_tl.MessageActionChatCreate`, :tl:`MessageActionChatDeleteUser`,
:tl:`MessageActionChatJoinedByLink` :tl:`MessageActionChatMigrateTo`
and :tl:`MessageActionChannelMigrateFrom`.
@ -660,7 +660,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
# If the client wasn't set we can't emulate the behaviour correctly,
# so as a best-effort simply return the chat peer.
if self._client and not self.out and self.is_private:
return types.PeerUser(self._client._self_id)
return _tl.PeerUser(self._client._self_id)
return self.peer_id
@ -722,7 +722,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
# However they can access them through replies...
self._reply_message = await self._client.get_messages(
await self.get_input_chat() if self.is_channel else None,
ids=types.InputMessageReplyTo(self.id)
ids=_tl.InputMessageReplyTo(self.id)
)
if not self._reply_message:
# ...unless the current message got deleted.
@ -883,7 +883,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
Clicks the first button or poll option for which the callable
returns `True`. The callable should accept a single
`MessageButton <telethon.tl.custom.messagebutton.MessageButton>`
or `PollAnswer <telethon.tl.types.PollAnswer>` argument.
or `PollAnswer <telethon.tl._tl.PollAnswer>` argument.
If you need to select multiple options in a poll,
pass a list of indices to the ``i`` parameter.
@ -950,7 +950,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
if not chat:
return None
but = types.KeyboardButtonCallback('', data)
but = _tl.KeyboardButtonCallback('', data)
return await MessageButton(self._client, but, chat, None, self.id).click(
share_phone=share_phone, share_geo=share_geo, password=password)
@ -1098,7 +1098,7 @@ class Message(ChatGetter, SenderGetter, TLObject):
Helper methods to set the buttons given the input sender and chat.
"""
if self._client and isinstance(self.reply_markup, (
types.ReplyInlineMarkup, types.ReplyKeyboardMarkup)):
_tl.ReplyInlineMarkup, _tl.ReplyKeyboardMarkup)):
self._buttons = [[
MessageButton(self._client, button, chat, bot, self.id)
for button in row.buttons
@ -1114,12 +1114,12 @@ class Message(ChatGetter, SenderGetter, TLObject):
cannot be found but is needed. Returns `None` if it's not needed.
"""
if self._client and not isinstance(self.reply_markup, (
types.ReplyInlineMarkup, types.ReplyKeyboardMarkup)):
_tl.ReplyInlineMarkup, _tl.ReplyKeyboardMarkup)):
return None
for row in self.reply_markup.rows:
for button in row.buttons:
if isinstance(button, types.KeyboardButtonSwitchInline):
if isinstance(button, _tl.KeyboardButtonSwitchInline):
# no via_bot_id means the bot sent the message itself (#1619)
if button.same_peer or not self.via_bot_id:
bot = self.input_sender

View File

@ -1,5 +1,5 @@
from .. import types, functions
from ... import password as pwd_mod
from ..._misc import password as pwd_mod
from ... import _tl
from ...errors import BotResponseTimeoutError
import webbrowser
import os
@ -46,19 +46,19 @@ class MessageButton:
@property
def data(self):
"""The `bytes` data for :tl:`KeyboardButtonCallback` objects."""
if isinstance(self.button, types.KeyboardButtonCallback):
if isinstance(self.button, _tl.KeyboardButtonCallback):
return self.button.data
@property
def inline_query(self):
"""The query `str` for :tl:`KeyboardButtonSwitchInline` objects."""
if isinstance(self.button, types.KeyboardButtonSwitchInline):
if isinstance(self.button, _tl.KeyboardButtonSwitchInline):
return self.button.query
@property
def url(self):
"""The url `str` for :tl:`KeyboardButtonUrl` objects."""
if isinstance(self.button, types.KeyboardButtonUrl):
if isinstance(self.button, _tl.KeyboardButtonUrl):
return self.button.url
async def click(self, share_phone=None, share_geo=None, *, password=None):
@ -91,10 +91,10 @@ class MessageButton:
this value a lot quickly may not work as expected. You may also pass a
:tl:`InputGeoPoint` if you find the order confusing.
"""
if isinstance(self.button, types.KeyboardButton):
if isinstance(self.button, _tl.KeyboardButton):
return await self._client.send_message(
self._chat, self.button.text, parse_mode=None)
elif isinstance(self.button, types.KeyboardButtonCallback):
elif isinstance(self.button, _tl.KeyboardButtonCallback):
if password is not None:
pwd = await self._client(_tl.fn.account.GetPassword())
password = pwd_mod.compute_check(pwd, password)
@ -107,13 +107,13 @@ class MessageButton:
return await self._client(req)
except BotResponseTimeoutError:
return None
elif isinstance(self.button, types.KeyboardButtonSwitchInline):
elif isinstance(self.button, _tl.KeyboardButtonSwitchInline):
return await self._client(_tl.fn.messages.StartBot(
bot=self._bot, peer=self._chat, start_param=self.button.query
))
elif isinstance(self.button, types.KeyboardButtonUrl):
elif isinstance(self.button, _tl.KeyboardButtonUrl):
return webbrowser.open(self.button.url)
elif isinstance(self.button, types.KeyboardButtonGame):
elif isinstance(self.button, _tl.KeyboardButtonGame):
req = _tl.fn.messages.GetBotCallbackAnswer(
peer=self._chat, msg_id=self._msg_id, game=True
)
@ -121,13 +121,13 @@ class MessageButton:
return await self._client(req)
except BotResponseTimeoutError:
return None
elif isinstance(self.button, types.KeyboardButtonRequestPhone):
elif isinstance(self.button, _tl.KeyboardButtonRequestPhone):
if not share_phone:
raise ValueError('cannot click on phone buttons unless share_phone=True')
if share_phone == True or isinstance(share_phone, str):
me = await self._client.get_me()
share_phone = types.InputMediaContact(
share_phone = _tl.InputMediaContact(
phone_number=me.phone if share_phone == True else share_phone,
first_name=me.first_name or '',
last_name=me.last_name or '',
@ -135,12 +135,12 @@ class MessageButton:
)
return await self._client.send_file(self._chat, share_phone)
elif isinstance(self.button, types.KeyboardButtonRequestGeoLocation):
elif isinstance(self.button, _tl.KeyboardButtonRequestGeoLocation):
if not share_geo:
raise ValueError('cannot click on geo buttons unless share_geo=(longitude, latitude)')
if isinstance(share_geo, (tuple, list)):
long, lat = share_geo
share_geo = types.InputMediaGeoPoint(types.InputGeoPoint(lat=lat, long=long))
share_geo = _tl.InputMediaGeoPoint(_tl.InputGeoPoint(lat=lat, long=long))
return await self._client.send_file(self._chat, share_geo)

View File

@ -1,4 +1,4 @@
from .. import types
from ... import _tl
def _admin_prop(field_name, doc):
@ -85,7 +85,7 @@ class ParticipantPermissions:
Whether the user left the chat.
"""
return isinstance(self.participant, types.ChannelParticipantLeft)
@property
def add_admins(self):
"""
@ -132,7 +132,7 @@ class ParticipantPermissions:
anonymous = property(**_admin_prop('anonymous', """
Whether the administrator will remain anonymous when sending messages.
"""))
manage_call = property(**_admin_prop('manage_call', """
Whether the user will be able to manage group calls.
"""))

View File

@ -2,8 +2,7 @@ import asyncio
import base64
import datetime
from .. import types, functions
from ... import events
from ... import events, _tl
class QRLogin:

View File

@ -1,4 +1,4 @@
from .. import types, alltlobjects
from .. import _tl
from ..custom.message import Message as _Message
class MessageEmpty(_Message, types.MessageEmpty):

View File

@ -3,7 +3,9 @@ import time
import weakref
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
from .._tl import custom
_IGNORE_MAX_SIZE = 100 # len()
_IGNORE_MAX_AGE = 5 # seconds
@ -138,7 +140,7 @@ class Album(EventBuilder):
if len(event.messages) > 1:
return super().filter(event)
class Event(EventCommon, _tl.custom.sendergetter.SenderGetter):
class Event(EventCommon, custom.sendergetter.SenderGetter):
"""
Represents the event of a new album.
@ -158,7 +160,7 @@ class Album(EventBuilder):
super().__init__(chat_peer=chat_peer,
msg_id=message.id, broadcast=bool(message.post))
_tl.custom.sendergetter.SenderGetter.__init__(self, message.sender_id)
custom.sendergetter.SenderGetter.__init__(self, message.sender_id)
self.messages = messages
def _set_client(self, client):

View File

@ -2,7 +2,9 @@ import re
import struct
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
from .._tl import custom
@name_inner_event
@ -121,7 +123,7 @@ class CallbackQuery(EventBuilder):
return self.func(event)
return True
class Event(EventCommon, _tl.custom.sendergetter.SenderGetter):
class Event(EventCommon, custom.sendergetter.SenderGetter):
"""
Represents the event of a new callback query.
@ -139,7 +141,7 @@ class CallbackQuery(EventBuilder):
"""
def __init__(self, query, peer, msg_id):
super().__init__(peer, msg_id=msg_id)
_tl.custom.sendergetter.SenderGetter.__init__(self, query.user_id)
custom.sendergetter.SenderGetter.__init__(self, query.user_id)
self.query = query
self.data_match = None
self.pattern_match = None

View File

@ -1,5 +1,6 @@
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
@name_inner_event

View File

@ -2,7 +2,8 @@ import abc
import asyncio
import warnings
from .. import utils, _tl
from .._misc import utils
from .._tl.custom.chatgetter import ChatGetter
async def _into_id_set(client, chats):

View File

@ -4,7 +4,9 @@ import re
import asyncio
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
from .._tl import custom
@name_inner_event
@ -72,7 +74,7 @@ class InlineQuery(EventBuilder):
return super().filter(event)
class Event(EventCommon, _tl.custom.sendergetter.SenderGetter):
class Event(EventCommon, custom.sendergetter.SenderGetter):
"""
Represents the event of a new callback query.
@ -89,7 +91,7 @@ class InlineQuery(EventBuilder):
"""
def __init__(self, query):
super().__init__(chat_peer=_tl.PeerUser(query.user_id))
_tl.custom.sendergetter.SenderGetter.__init__(self, query.user_id)
custom.sendergetter.SenderGetter.__init__(self, query.user_id)
self.query = query
self.pattern_match = None
self._answered = False

View File

@ -1,5 +1,6 @@
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
@name_inner_event

View File

@ -1,7 +1,8 @@
import re
from .common import EventBuilder, EventCommon, name_inner_event, _into_id_set
from .. import utils, _tl
from .._misc import utils
from .. import _tl
@name_inner_event

View File

@ -1,5 +1,5 @@
from .common import EventBuilder
from .. import utils
from .._misc import utils
class Raw(EventBuilder):

View File

@ -2,7 +2,9 @@ import datetime
import functools
from .common import EventBuilder, EventCommon, name_inner_event
from .. import utils, _tl
from .._misc import utils
from .. import _tl
from .._tl import custom
# TODO Either the properties are poorly named or they should be
@ -63,7 +65,7 @@ class UserUpdate(EventBuilder):
return cls.Event(update.user_id,
typing=update.action)
class Event(EventCommon, _tl.custom.sendergetter.SenderGetter):
class Event(EventCommon, custom.sendergetter.SenderGetter):
"""
Represents the event of a user update
such as gone online, started typing, etc.
@ -85,7 +87,7 @@ class UserUpdate(EventBuilder):
"""
def __init__(self, peer, *, status=None, chat_peer=None, typing=None):
super().__init__(chat_peer or peer)
_tl.custom.sendergetter.SenderGetter.__init__(self, utils.get_peer_id(peer))
custom.sendergetter.SenderGetter.__init__(self, utils.get_peer_id(peer))
self.status = status
self.action = typing

View File

@ -1,7 +1,8 @@
from enum import Enum
from .abstract import Session
from .. import utils, _tl
from .._misc import utils
from .. import _tl
class _SentFileType(Enum):

View File

@ -3,8 +3,9 @@ import os
import time
from .memory import MemorySession, _SentFileType
from .. import utils, _tl
from ..crypto import AuthKey
from .._misc import utils
from .. import _tl
from .._crypto import AuthKey
try:
import sqlite3

View File

@ -4,7 +4,7 @@ import struct
from .abstract import Session
from .memory import MemorySession
from ..crypto import AuthKey
from .._crypto import AuthKey
_STRUCT_PREFORMAT = '>B{}sH256s'

View File

@ -9,7 +9,7 @@ from pathlib import Path
from ..docswriter import DocsWriter
from ..parsers import TLObject, Usability
from ..utils import snake_to_camel_case
from .._misc.utils import snake_to_camel_case
CORE_TYPES = {
'int', 'long', 'int128', 'int256', 'double',

View File

@ -7,7 +7,7 @@ from collections import defaultdict
from zlib import crc32
from ..sourcebuilder import SourceBuilder
from ..utils import snake_to_camel_case
from .._misc.utils import snake_to_camel_case
AUTO_GEN_NOTICE = \
'"""File generated by TLObjects\' generator. All changes will be ERASED"""'

View File

@ -1,7 +1,7 @@
import csv
import re
from ..utils import snake_to_camel_case
from .._misc.utils import snake_to_camel_case
# Core base classes depending on the integer error code
KNOWN_BASE_CLASSES = {

View File

@ -2,7 +2,7 @@ import re
import struct
import zlib
from ...utils import snake_to_camel_case
from ..._misc.utils import snake_to_camel_case
# https://github.com/telegramdesktop/tdesktop/blob/4bf66cb6e93f3965b40084771b595e93d0b11bcd/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py#L57-L62
WHITELISTED_MISMATCHING_IDS = {

View File

@ -1,13 +1,13 @@
import pytest
from telethon.tl import types, functions
from telethon import _tl
def test_nested_invalid_serialization():
large_long = 2**62
request = _tl.fn.account.SetPrivacy(
key=types.InputPrivacyKeyChatInvite(),
rules=[types.InputPrivacyValueDisallowUsers(users=[large_long])]
key=_tl.InputPrivacyKeyChatInvite(),
rules=[_tl.InputPrivacyValueDisallowUsers(users=[large_long])]
)
with pytest.raises(TypeError):
bytes(request)