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/ /docs/
# File used to manually test new changes, contains sensitive data # 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`` * ``statecache.py``
* ``utils.py`` * ``utils.py``
// TODO review telethon/__init__.py isn't exposing more than it should
The TelegramClient is no longer made out of mixins 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 ._client.telegramclient import TelegramClient
from .network import connection from ._network import connection
from ._tl import custom
from ._tl.custom import Button from ._tl.custom import Button
from . import version, events, utils, errors from . import version, events, utils, errors

View File

@ -5,7 +5,9 @@ import sys
import typing import typing
import warnings 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: if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient from .telegramclient import TelegramClient

View File

@ -1,6 +1,7 @@
import typing import typing
from .. import hints, _tl from .. import hints, _tl
from .._tl import custom
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient from .telegramclient import TelegramClient
@ -13,7 +14,7 @@ async def inline_query(
*, *,
entity: 'hints.EntityLike' = None, entity: 'hints.EntityLike' = None,
offset: str = 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) bot = await self.get_input_entity(bot)
if entity: if entity:
peer = await self.get_input_entity(entity) peer = await self.get_input_entity(entity)
@ -28,4 +29,4 @@ async def inline_query(
geo_point=geo_point 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 import typing
from .. import utils, hints, _tl from .._misc import utils, hints
from .. import _tl
from .._tl import custom
def build_reply_markup( def build_reply_markup(
@ -30,7 +32,7 @@ def build_reply_markup(
for row in buttons: for row in buttons:
current = [] current = []
for button in row: for button in row:
if isinstance(button, _tl.custom.Button): if isinstance(button, custom.Button):
if button.resize is not None: if button.resize is not None:
resize = button.resize resize = button.resize
if button.single_use is not None: if button.single_use is not None:
@ -39,10 +41,10 @@ def build_reply_markup(
selective = button.selective selective = button.selective
button = button.button button = button.button
elif isinstance(button, _tl.custom.MessageButton): elif isinstance(button, custom.MessageButton):
button = button.button button = button.button
inline = _tl.custom.Button._is_inline(button) inline = custom.Button._is_inline(button)
is_inline |= inline is_inline |= inline
is_normal |= not inline is_normal |= not inline

View File

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

View File

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

View File

@ -6,10 +6,9 @@ import typing
import inspect import inspect
import asyncio import asyncio
from ..crypto import AES from .._crypto import AES
from .._misc import utils, helpers, requestiter
from .. import utils, helpers, errors, hints, _tl from .. import errors, hints, _tl
from ..requestiter import RequestIter
try: try:
import aiohttp import aiohttp
@ -26,7 +25,7 @@ MAX_CHUNK_SIZE = 512 * 1024
# 2021-01-15, users reported that `errors.TimeoutError` can occur while downloading files. # 2021-01-15, users reported that `errors.TimeoutError` can occur while downloading files.
TIMED_OUT_SLEEP = 1 TIMED_OUT_SLEEP = 1
class _DirectDownloadIter(RequestIter): class _DirectDownloadIter(requestiter.RequestIter):
async def _init( async def _init(
self, file, dc_id, offset, stride, chunk_size, request_size, file_size, msg_data 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 typing
import warnings import warnings
from .. import helpers, utils, errors, hints, _tl from .. import errors, hints, _tl
from ..requestiter import RequestIter from .._misc import helpers, utils, requestiter
_MAX_CHUNK_SIZE = 100 _MAX_CHUNK_SIZE = 100
@ -12,7 +12,7 @@ if typing.TYPE_CHECKING:
from .telegramclient import TelegramClient from .telegramclient import TelegramClient
class _MessagesIter(RequestIter): class _MessagesIter(requestiter.RequestIter):
""" """
Common factor for all requests that need to iterate over messages. 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) self.request.offset_rate = getattr(response, 'next_rate', 0)
class _IDsIter(RequestIter): class _IDsIter(requestiter.RequestIter):
async def _init(self, entity, ids): async def _init(self, entity, ids):
self.total = len(ids) self.total = len(ids)
self._ids = list(reversed(ids)) if self.reverse else ids self._ids = list(reversed(ids)) if self.reverse else ids

View File

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

View File

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

View File

@ -7,9 +7,11 @@ import re
import typing import typing
from io import BytesIO 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: try:
import PIL import PIL
@ -361,7 +363,7 @@ async def upload_file(
if is_big: if is_big:
return _tl.InputFileBig(file_id, part_count, file_name) return _tl.InputFileBig(file_id, part_count, file_name)
else: else:
return _tl.custom.InputSizedFile( return custom.InputSizedFile(
file_id, part_count, file_name, md5=hash_md5, size=file_size file_id, part_count, file_name, md5=hash_md5, size=file_size
) )

View File

@ -4,9 +4,9 @@ import itertools
import time import time
import typing 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 ..errors import MultiError, RPCError
from ..helpers import retry_range
_NOT_A_REQUEST = lambda: TypeError('You can only invoke requests, not types!') _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 last_error = None
self._last_request = time.time() self._last_request = time.time()
for attempt in retry_range(self._request_retries): for attempt in helpers.retry_range(self._request_retries):
try: try:
future = sender.send(request, ordered=ordered) future = sender.send(request, ordered=ordered)
if isinstance(future, list): if isinstance(future, list):

View File

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

View File

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

View File

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

View File

@ -1,7 +1,9 @@
import datetime import datetime
import typing import typing
from . import helpers, _tl from . import helpers
from .. import _tl
from .._tl import custom
Phone = str Phone = str
Username = 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 re
import warnings 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 from .. import _tl
DEFAULT_DELIMITERS = { DEFAULT_DELIMITERS = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
from . import Draft from . import Draft
from .. import TLObject, types, functions from ... import _tl
from ... import utils from ..._misc import utils
class Dialog: class Dialog:
@ -89,12 +89,12 @@ class Dialog:
self.draft = Draft(client, self.entity, self.dialog.draft) 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 = ( self.is_group = (
isinstance(self.entity, (types.Chat, types.ChatForbidden)) or isinstance(self.entity, (_tl.Chat, _tl.ChatForbidden)) or
(isinstance(self.entity, types.Channel) and self.entity.megagroup) (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): async def send_message(self, *args, **kwargs):
""" """
@ -141,7 +141,7 @@ class Dialog:
dialog.archive(0) dialog.archive(0)
""" """
return await self._client(_tl.fn.folders.EditPeerFolders([ 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): def to_dict(self):
@ -155,7 +155,7 @@ class Dialog:
} }
def __str__(self): def __str__(self):
return TLObject.pretty_format(self.to_dict()) return _tl.TLObject.pretty_format(self.to_dict())
def stringify(self): 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 ... import _tl
from ...errors import RPCError from ...errors import RPCError
from ...extensions import markdown from ..._misc import markdown
from ...utils import get_input_peer, get_peer from ..._misc.utils import get_input_peer, get_peer
class Draft: class Draft:

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
from .. import types, functions from ... import _tl
from ... import utils from ..._misc import utils
class InlineResult: 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""" """InputFile class with two extra parameters: md5 (digest) and size"""
def __init__(self, id_, parts, name, md5, size): def __init__(self, id_, parts, name, md5, size):
super().__init__(id_, parts, name, md5.hexdigest()) super().__init__(id_, parts, name, md5.hexdigest())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
import re import re
from .common import EventBuilder, EventCommon, name_inner_event, _into_id_set 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 @name_inner_event

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import csv import csv
import re 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 # Core base classes depending on the integer error code
KNOWN_BASE_CLASSES = { KNOWN_BASE_CLASSES = {

View File

@ -2,7 +2,7 @@ import re
import struct import struct
import zlib 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 # https://github.com/telegramdesktop/tdesktop/blob/4bf66cb6e93f3965b40084771b595e93d0b11bcd/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py#L57-L62
WHITELISTED_MISMATCHING_IDS = { WHITELISTED_MISMATCHING_IDS = {

View File

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