Merge branch 'master' into asyncio

This commit is contained in:
Lonami Exo 2018-05-02 20:26:05 +02:00
commit 52042d4a1b
24 changed files with 333 additions and 203 deletions

View File

@ -1,9 +1,10 @@
<!--
0. The library is Python 3.x, not Python 2.x.
1. If you're posting an issue, make sure it's a bug in the library, not in your code.
2. If you're posting a question, make sure you have read and tried enough things first.
3. Show as much information as possible, including your failed attempts, and the full console output (to include the whole traceback with line numbers).
4. Good looking issues are a lot more appealing. If you need help check out https://guides.github.com/features/mastering-markdown/.
0. The library is Python >= 3.4, not Python 2.x.
1. If you have a QUESTION, ask it on @TelethonChat (Telegram) or StackOverflow, not here. It will be closed immediatly with no explanation if you post it here.
2. If you have an ISSUE or you are experiencing strange behaviour, make sure you're using the latest version (pip install -U telethon), and post as much information as possible here. Enhancement suggestions are welcome too.
You may also want to watch "How (not) to ask a technical question" over https://youtu.be/53zkBvL4ZB4
If you paste code, please put it between three backticks (`):
```python
code here
```
-->

View File

@ -48,7 +48,7 @@ Basic Usage
# Retrieving messages from a chat
from telethon import utils
async for message in client.get_message_history('username', limit=10):
async for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Listing all the dialogs (conversations you have open)
@ -60,7 +60,7 @@ Basic Usage
# Once you have a message with .media (if message.media)
# you can download it using client.download_media():
messages = await client.get_message_history('username')
messages = await client.get_messages('username')
await client.download_media(messages[0])
**More details**: :ref:`telegram-client`

View File

@ -67,7 +67,7 @@ Many other common methods for quick scripts are also available:
# The utils package has some goodies, like .get_display_name()
from telethon import utils
async for message in client.get_message_history('username', limit=10):
async for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Dialogs are the conversations you have open

View File

@ -288,7 +288,7 @@ use :tl:`GetMessagesViewsRequest`, setting ``increment=True``:
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
# Obtain `msg_ids' through `.get_message_history()` or anyhow. Must be a list.
# Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list.
await client(GetMessagesViewsRequest(
peer=channel,

View File

@ -10,14 +10,13 @@ Extra supported commands are:
* pypi, to generate sdist, bdist_wheel, and push to PyPi
"""
import itertools
import os
import re
# To use a consistent encoding
import shutil
from codecs import open
from sys import argv, version_info
# Always prefer setuptools over distutils
from setuptools import find_packages, setup
@ -44,7 +43,8 @@ ERRORS_IN_JSON = os.path.join(GENERATOR_DIR, 'data', 'errors.json')
ERRORS_IN_DESC = os.path.join(GENERATOR_DIR, 'data', 'error_descriptions')
ERRORS_OUT = os.path.join(LIBRARY_DIR, 'errors', 'rpc_error_list.py')
TLOBJECT_IN_TL = os.path.join(GENERATOR_DIR, 'data', 'scheme.tl')
TLOBJECT_IN_CORE_TL = os.path.join(GENERATOR_DIR, 'data', 'mtproto_api.tl')
TLOBJECT_IN_TL = os.path.join(GENERATOR_DIR, 'data', 'telegram_api.tl')
TLOBJECT_OUT = os.path.join(LIBRARY_DIR, 'tl')
IMPORT_DEPTH = 2
@ -57,7 +57,9 @@ def generate(which):
from telethon_generator.generators import\
generate_errors, generate_tlobjects, generate_docs, clean_tlobjects
tlobjects = list(parse_tl(TLOBJECT_IN_TL, ignore_core=True))
tlobjects = list(itertools.chain(
parse_tl(TLOBJECT_IN_CORE_TL), parse_tl(TLOBJECT_IN_TL)))
errors = list(parse_errors(ERRORS_IN_JSON, ERRORS_IN_DESC))
layer = find_layer(TLOBJECT_IN_TL)

View File

@ -1,4 +1,4 @@
from .common import Raw
from .raw import Raw
from .chataction import ChatAction
from .messagedeleted import MessageDeleted
from .messageedited import MessageEdited

View File

@ -95,7 +95,6 @@ class ChatAction(EventBuilder):
photo (:tl:`Photo`, optional):
The new photo (or ``None`` if it was removed).
user_added (`bool`):
``True`` if the user was added by some other.
@ -111,7 +110,7 @@ class ChatAction(EventBuilder):
created (`bool`, optional):
``True`` if this chat was just created.
new_title (`bool`, optional):
new_title (`str`, optional):
The new title string for the chat, if applicable.
unpin (`bool`):

View File

@ -97,6 +97,7 @@ class EventCommon(abc.ABC):
self._chat = None
self.pattern_match = None
self.original_update = None
self.is_private = isinstance(chat_peer, types.PeerUser)
self.is_group = (
@ -208,17 +209,6 @@ class EventCommon(abc.ABC):
return d
class Raw(EventBuilder):
"""
Represents a raw event. The event is the update itself.
"""
async def resolve(self, client):
pass
def build(self, update):
return update
def name_inner_event(cls):
"""Decorator to rename cls.Event 'Event' as 'cls.Event'"""
if hasattr(cls, 'Event'):

30
telethon/events/raw.py Normal file
View File

@ -0,0 +1,30 @@
from .common import EventBuilder
from .. import utils
class Raw(EventBuilder):
"""
Represents a raw event. The event is the update itself.
Args:
types (`list` | `tuple` | `type`, optional):
The type or types that the :tl:`Update` instance must be.
Equivalent to ``if not isinstance(update, types): return``.
"""
def __init__(self, types=None):
super().__init__()
if not types:
self.types = None
elif not utils.is_list_like(types):
assert isinstance(types, type)
self.types = types
else:
assert all(isinstance(x, type) for x in types)
self.types = tuple(types)
async def resolve(self, client):
pass
def build(self, update):
if not self.types or isinstance(update, self.types):
return update

View File

@ -102,7 +102,9 @@ class TcpClient:
# to none to recreate it on the next iteration
self._socket = None
await asyncio.sleep(timeout)
timeout = min(timeout * 2, MAX_TIMEOUT)
timeout *= 2
if timeout > MAX_TIMEOUT:
raise
else:
raise

View File

@ -67,6 +67,25 @@ class Session(ABC):
"""
raise NotImplementedError
@abstractmethod
def get_update_state(self, entity_id):
"""
Returns the ``UpdateState`` associated with the given `entity_id`.
If the `entity_id` is 0, it should return the ``UpdateState`` for
no specific channel (the "general" state). If no state is known
it should ``return None``.
"""
raise NotImplementedError
@abstractmethod
def set_update_state(self, entity_id, state):
"""
Sets the given ``UpdateState`` for the specified `entity_id`, which
should be 0 if the ``UpdateState`` is the "general" state (and not
for any specific channel).
"""
raise NotImplementedError
@abstractmethod
def close(self):
"""

View File

@ -35,6 +35,7 @@ class MemorySession(Session):
self._files = {}
self._entities = set()
self._update_states = {}
def set_dc(self, dc_id, server_address, port):
self._dc_id = dc_id or 0
@ -57,6 +58,12 @@ class MemorySession(Session):
def auth_key(self, value):
self._auth_key = value
def get_update_state(self, entity_id):
return self._update_states.get(entity_id, None)
def set_update_state(self, entity_id, state):
self._update_states[entity_id] = state
def close(self):
pass

View File

@ -1,9 +1,11 @@
import datetime
import json
import os
import sqlite3
from base64 import b64decode
from os.path import isfile as file_exists
from telethon.tl import types
from .memory import MemorySession, _SentFileType
from .. import utils
from ..crypto import AuthKey
@ -219,6 +221,25 @@ class SQLiteSession(MemorySession):
))
c.close()
def get_update_state(self, entity_id):
c = self._cursor()
row = c.execute('select pts, qts, date, seq from update_state '
'where id = ?', (entity_id,)).fetchone()
c.close()
if row:
pts, qts, date, seq = row
date = datetime.datetime.utcfromtimestamp(date)
return types.updates.State(pts, qts, date, seq, unread_count=0)
def set_update_state(self, entity_id, state):
with self._db_lock:
c = self._cursor()
c.execute('insert or replace into update_state values (?,?,?,?,?)',
(entity_id, state.pts, state.qts,
state.date.timestamp(), state.seq))
c.close()
self.save()
def save(self):
"""Saves the current session object as session_user_id.session"""
self._conn.commit()

View File

@ -265,6 +265,7 @@ class TelegramBareClient:
self._state_loop = None
# TODO Shall we clear the _exported_sessions, or may be reused?
self._first_request = True # On reconnect it will be first again
self.session.set_update_state(0, self.updates.get_update_state(0))
self.session.close()
async def _reconnect(self, new_dc=None):

View File

@ -1089,6 +1089,7 @@ class TelegramClient(TelegramBareClient):
limit=1,
max_id=max_id,
min_id=min_id,
hash=0,
from_id=self.get_input_entity(from_user) if from_user else None
)
else:
@ -1117,6 +1118,7 @@ class TelegramClient(TelegramBareClient):
have = 0
batch_size = min(max(batch_size, 1), 100)
while have < limit:
start = time.time()
# Telegram has a hard limit of 100
request.limit = min(limit - have, batch_size)
r = await self(request)
@ -1163,7 +1165,7 @@ class TelegramClient(TelegramBareClient):
else:
request.max_date = r.messages[-1].date
await asyncio.sleep(wait_time)
await asyncio.sleep(max(wait_time - (time.time() - start), 0))
async def get_messages(self, *args, **kwargs):
"""
@ -2178,7 +2180,7 @@ class TelegramClient(TelegramBareClient):
return result
i += 1
async def download_file(self, input_location, file, part_size_kb=None,
async def download_file(self, input_location, file=None, part_size_kb=None,
file_size=None, progress_callback=None):
"""
Downloads the given input location to a file.
@ -2187,10 +2189,13 @@ class TelegramClient(TelegramBareClient):
input_location (:tl:`InputFileLocation`):
The file location from which the file will be downloaded.
file (`str` | `file`):
file (`str` | `file`, optional):
The output file path, directory, or stream-like object.
If the path exists and is a file, it will be overwritten.
If the file path is ``None``, then the result will be
saved in memory and returned as `bytes`.
part_size_kb (`int`, optional):
Chunk size when downloading files. The larger, the less
requests will be made (up to 512KB maximum).
@ -2221,7 +2226,10 @@ class TelegramClient(TelegramBareClient):
raise ValueError(
'The part size must be evenly divisible by 4096.')
if isinstance(file, str):
in_memory = file is None
if in_memory:
f = io.BytesIO()
elif isinstance(file, str):
# Ensure that we'll be able to download the media
helpers.ensure_parent_dir_exists(file)
f = open(file, 'wb')
@ -2231,6 +2239,7 @@ class TelegramClient(TelegramBareClient):
# The used client will change if FileMigrateError occurs
client = self
cdn_decrypter = None
input_location = utils.get_input_location(input_location)
__log__.info('Downloading file in chunks of %d bytes', part_size)
try:
@ -2264,7 +2273,11 @@ class TelegramClient(TelegramBareClient):
# So there is nothing left to download and write
if not result.bytes:
# Return some extra information, unless it's a CDN file
return getattr(result, 'type', '')
if in_memory:
f.flush()
return f.getvalue()
else:
return getattr(result, 'type', '')
f.write(result.bytes)
__log__.debug('Saved %d more bytes', len(result.bytes))
@ -2279,7 +2292,7 @@ class TelegramClient(TelegramBareClient):
cdn_decrypter.client.disconnect()
except:
pass
if isinstance(file, str):
if isinstance(file, str) or in_memory:
f.close()
# endregion
@ -2317,6 +2330,7 @@ class TelegramClient(TelegramBareClient):
event = builder.build(update)
if event:
event._client = self
event.original_update = update
try:
await callback(event)
except events.StopPropagation:
@ -2576,7 +2590,7 @@ class TelegramClient(TelegramBareClient):
raise ValueError(
'Could not find the input entity for "{}". Please read https://'
'telethon.readthedocs.io/en/latest/extra/basic/entities.html to'
'find out more details.'
' find out more details.'
.format(peer)
)

View File

@ -27,6 +27,10 @@ class UpdateState:
if self.handler:
asyncio.ensure_future(self.handler(update), loop=self._loop)
def get_update_state(self, entity_id):
"""Gets the updates.State corresponding to the given entity or 0."""
return self._state
def process(self, update):
"""Processes an update object. This method is normally called by
the library itself.

View File

@ -25,7 +25,8 @@ from .tl.types import (
InputPhotoEmpty, FileLocation, ChatPhotoEmpty, UserProfilePhotoEmpty,
FileLocationUnavailable, InputMediaUploadedDocument, ChannelFull,
InputMediaUploadedPhoto, DocumentAttributeFilename, photos,
TopPeer, InputNotifyPeer, InputMessageID
TopPeer, InputNotifyPeer, InputMessageID, InputFileLocation,
InputDocumentFileLocation, PhotoSizeEmpty, InputDialogPeer
)
from .tl.types.contacts import ResolvedPeer
@ -181,6 +182,24 @@ def get_input_user(entity):
_raise_cast_fail(entity, 'InputUser')
def get_input_dialog(dialog):
"""Similar to :meth:`get_input_peer`, but for dialogs"""
try:
if dialog.SUBCLASS_OF_ID == 0xa21c9795: # crc32(b'InputDialogPeer')
return dialog
if dialog.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
return InputDialogPeer(dialog)
except AttributeError:
_raise_cast_fail(dialog, 'InputDialogPeer')
try:
return InputDialogPeer(get_input_peer(dialog))
except TypeError:
pass
_raise_cast_fail(dialog, 'InputDialogPeer')
def get_input_document(document):
"""Similar to :meth:`get_input_peer`, but for documents"""
try:
@ -352,6 +371,39 @@ def get_input_message(message):
_raise_cast_fail(message, 'InputMedia')
def get_input_location(location):
"""Similar to :meth:`get_input_peer`, but for input messages."""
try:
if location.SUBCLASS_OF_ID == 0x1523d462:
return location # crc32(b'InputFileLocation'):
except AttributeError:
_raise_cast_fail(location, 'InputFileLocation')
if isinstance(location, Message):
location = location.media
if isinstance(location, MessageMediaDocument):
location = location.document
elif isinstance(location, MessageMediaPhoto):
location = location.photo
if isinstance(location, Document):
return InputDocumentFileLocation(
location.id, location.access_hash, location.version)
elif isinstance(location, Photo):
try:
location = next(x for x in reversed(location.sizes)
if not isinstance(x, PhotoSizeEmpty)).location
except StopIteration:
pass
if isinstance(location, (FileLocation, FileLocationUnavailable)):
return InputFileLocation(
location.volume_id, location.local_id, location.secret)
_raise_cast_fail(location, 'InputFileLocation')
def is_image(file):
"""
Returns ``True`` if the file extension looks like an image file to Telegram.

View File

@ -207,7 +207,7 @@ class InteractiveTelegramClient(TelegramClient):
# History
elif msg == '!h':
# First retrieve the messages and some information
messages = self.get_message_history(entity, limit=10)
messages = self.get_messages(entity, limit=10)
# Iterate over all (in reverse order so the latest appear
# the last in the console) and print them with format:
@ -216,7 +216,7 @@ class InteractiveTelegramClient(TelegramClient):
# Note that the .sender attribute is only there for
# convenience, the API returns it differently. But
# this shouldn't concern us. See the documentation
# for .get_message_history() for more information.
# for .iter_messages() for more information.
name = get_display_name(msg.sender)
# Format the message content

View File

@ -0,0 +1,90 @@
//int ? = Int;
//long ? = Long;
//double ? = Double;
//string ? = String;
dummyHttpWait = HttpWait;
//vector {t:Type} # [ t ] = Vector t;
//int128 4*[ int ] = Int128;
//int256 8*[ int ] = Int256;
resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector<long> = ResPQ;
p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data;
p_q_inner_data_temp#3c6a84d4 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data;
server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params;
server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;
server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data;
client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data;
dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;
bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner;
//rpc_result#f35c6d01 req_msg_id:long result:string = RpcResult;
rpc_error#2144ca19 error_code:int error_message:string = RpcError;
rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;
future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt;
future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts;
pong#347773c5 msg_id:long ping_id:long = Pong;
destroy_session_ok#e22045fc session_id:long = DestroySessionRes;
destroy_session_none#62d350c9 session_id:long = DestroySessionRes;
new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = NewSession;
//msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;
//message msg_id:long seqno:int bytes:int body:string = Message;
//msg_copy#e06046b2 orig_message:Message = MessageCopy;
gzip_packed#3072cfa1 packed_data:string = Object;
msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;
bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;
msg_resend_req#7d861a08 msg_ids:Vector<long> = MsgResendReq;
msgs_state_req#da69fb52 msg_ids:Vector<long> = MsgsStateReq;
msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
msgs_all_info#8cc0d131 msg_ids:Vector<long> info:string = MsgsAllInfo;
msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
rsa_public_key n:string e:string = RSAPublicKey;
---functions---
req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;
req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params;
set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
get_future_salts#b921bd04 num:int = FutureSalts;
ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
destroy_session#e7512126 session_id:long = DestroySessionRes;
http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
//test.useGzipPacked = GzipPacked;
//test.useServerDhInnerData = Server_DH_inner_data;
//test.useNewSessionCreated = NewSession;
//test.useMsgsAck = MsgsAck;
//test.useBadMsgNotification = BadMsgNotification;
//test.useOther key:rsa_public_key p_q_data:P_Q_inner_data dh_data:client_DH_inner_data = RpcError;

View File

@ -1,147 +1,29 @@
// Core types (no need to gen)
//int ? = Int;
//long ? = Long;
//double ? = Double;
//string ? = String;
//bytes = Bytes;
//true#3fedd339 = True;
//boolFalse#bc799737 = Bool;
//boolTrue#997275b5 = Bool;
//vector#1cb5c415 {t:Type} # [ t ] = Vector t;
///////////////////////////////
/////////////////// Layer cons
///////////////////////////////
//invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
//invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;
//invokeWithLayer1#53835315 query:!X = X;
//invokeWithLayer2#289dd1f6 query:!X = X;
//invokeWithLayer3#b7475268 query:!X = X;
//invokeWithLayer4#dea0d430 query:!X = X;
//invokeWithLayer5#417a57ae query:!X = X;
//invokeWithLayer6#3a64d54d query:!X = X;
//invokeWithLayer7#a5be56d3 query:!X = X;
//invokeWithLayer8#e9abd9fd query:!X = X;
//invokeWithLayer9#76715a63 query:!X = X;
//invokeWithLayer10#39620c41 query:!X = X;
//invokeWithLayer11#a6b88fdf query:!X = X;
//invokeWithLayer12#dda60d3c query:!X = X;
//invokeWithLayer13#427c8ea2 query:!X = X;
//invokeWithLayer14#2b9b08fa query:!X = X;
//invokeWithLayer15#b4418b64 query:!X = X;
//invokeWithLayer16#cf5f0987 query:!X = X;
//invokeWithLayer17#50858a19 query:!X = X;
//invokeWithLayer18#1c900537 query:!X = X;
//invokeWithLayer#da9b0d0d layer:int query:!X = X; // after 18 layer
///////////////////////////////
/// Authorization key creation
///////////////////////////////
resPQ#05162463 nonce:int128 server_nonce:int128 pq:bytes server_public_key_fingerprints:Vector<long> = ResPQ;
p_q_inner_data#83c95aec pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data;
server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params;
server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params;
server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:bytes g_a:bytes server_time:int = Server_DH_inner_data;
client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:bytes = Client_DH_Inner_Data;
dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;
destroy_auth_key_ok#f660e1d4 = DestroyAuthKeyRes;
destroy_auth_key_none#0a9f2259 = DestroyAuthKeyRes;
destroy_auth_key_fail#ea109b13 = DestroyAuthKeyRes;
---functions---
// Deprecated since somewhere around February of 2018
// See https://core.telegram.org/mtproto/auth_key
req_pq#60469778 nonce:int128 = ResPQ;
req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;
req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:bytes = Server_DH_Params;
set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer;
destroy_auth_key#d1435160 = DestroyAuthKeyRes;
///////////////////////////////
////////////// System messages
///////////////////////////////
---types---
msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;
bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;
msgs_state_req#da69fb52 msg_ids:Vector<long> = MsgsStateReq;
msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
msgs_all_info#8cc0d131 msg_ids:Vector<long> info:string = MsgsAllInfo;
msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
msg_resend_req#7d861a08 msg_ids:Vector<long> = MsgResendReq;
//rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult; // parsed manually
rpc_error#2144ca19 error_code:int error_message:string = RpcError;
rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;
future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt;
future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts;
pong#347773c5 msg_id:long ping_id:long = Pong;
destroy_session_ok#e22045fc session_id:long = DestroySessionRes;
destroy_session_none#62d350c9 session_id:long = DestroySessionRes;
new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = NewSession;
//message msg_id:long seqno:int bytes:int body:Object = Message; // parsed manually
//msg_container#73f1f8dc messages:vector<message> = MessageContainer; // parsed manually
//msg_copy#e06046b2 orig_message:Message = MessageCopy; // parsed manually, not used - use msg_container
//gzip_packed#3072cfa1 packed_data:string = Object; // parsed manually
http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
error#c4b9f9bb code:int text:string = Error;
ipPort ipv4:int port:int = IpPort;
help.configSimple#d997c3c5 date:int expires:int dc_id:int ip_port_list:Vector<ipPort> = help.ConfigSimple;
---functions---
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
get_future_salts#b921bd04 num:int = FutureSalts;
ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
destroy_session#e7512126 session_id:long = DestroySessionRes;
contest.saveDeveloperInfo#9a5f6e95 vk_id:int name:string phone_number:string age:int city:string = Bool;
///////////////////////////////
///////// Main application API
///////////////////////////////
test.useError = Error;
test.useConfigSimple = help.ConfigSimple;
---types---
boolFalse#bc799737 = Bool;
boolTrue#997275b5 = Bool;
true#3fedd339 = True;
vector#1cb5c415 {t:Type} # [ t ] = Vector t;
error#c4b9f9bb code:int text:string = Error;
null#56730bcc = Null;
inputPeerEmpty#7f3b18ea = InputPeer;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerChat#179be863 chat_id:int = InputPeer;
@ -273,6 +155,7 @@ messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAct
messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
messageActionBotAllowed#abe9affe domain:string = MessageAction;
dialog#e4def5db flags:# pinned:flags.2?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
@ -425,8 +308,8 @@ updateRecentStickers#9a422c20 = Update;
updateConfig#a229dd06 = Update;
updatePtsChanged#3354678f = Update;
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
updateDialogPinned#d711a2cc flags:# pinned:flags.0?true peer:Peer = Update;
updatePinnedDialogs#d8caf68d flags:# order:flags.0?Vector<Peer> = Update;
updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update;
updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector<DialogPeer> = Update;
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
@ -460,11 +343,11 @@ photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> =
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#ea52fe5a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes cdn_file_hashes:Vector<CdnFileHash> = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int = DcOption;
config#9c840964 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector<DisabledFeature> = Config;
config#86b5778e flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
@ -569,8 +452,6 @@ stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
messages.allStickersNotModified#e86602c3 = messages.AllStickers;
messages.allStickers#edfd405f hash:int sets:Vector<StickerSet> = messages.AllStickers;
disabledFeature#ae636f24 feature:string description:string = DisabledFeature;
messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;
contactLinkUnknown#5f4f9247 = ContactLink;
@ -608,7 +489,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
stickerSet#cd303b41 flags:# installed:flags.0?true archived:flags.1?true official:flags.2?true masks:flags.3?true id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
stickerSet#5585a139 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
@ -645,6 +526,8 @@ messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity;
messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
messageEntityMentionName#352dca58 offset:int length:int user_id:int = MessageEntity;
inputMessageEntityMentionName#208e68c9 offset:int length:int user_id:InputUser = MessageEntity;
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
@ -695,7 +578,7 @@ inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:s
inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineResult#2cbbe15a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult;
@ -706,7 +589,7 @@ botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:f
botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineResult#9bebaeb9 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb_url:flags.4?string content_url:flags.5?string content_type:flags.5?string w:flags.6?int h:flags.6?int duration:flags.7?int send_message:BotInlineMessage = BotInlineResult;
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;
@ -755,7 +638,7 @@ messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers;
messages.featuredStickers#f89d88e5 hash:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
messages.recentStickers#5ce20970 hash:int stickers:Vector<Document> = messages.RecentStickers;
messages.recentStickers#22f3afb3 hash:int packs:Vector<StickerPack> stickers:Vector<Document> dates:Vector<int> = messages.RecentStickers;
messages.archivedStickers#4fcba9c8 count:int sets:Vector<StickerSetCovered> = messages.ArchivedStickers;
@ -837,6 +720,7 @@ paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string e
paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;
webDocument#c61acbd8 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> dc_id:int = WebDocument;
webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
@ -925,8 +809,6 @@ channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?tru
popularContact#5ce14175 client_id:long importers:int = PopularContact;
cdnFileHash#77eec38f offset:int limit:int hash:bytes = CdnFileHash;
messages.favedStickersNotModified#9e8fa6d3 = messages.FavedStickers;
messages.favedStickers#f37f2f16 hash:int packs:Vector<StickerPack> stickers:Vector<Document> = messages.FavedStickers;
@ -948,6 +830,15 @@ inputMessageID#a676a322 id:int = InputMessage;
inputMessageReplyTo#bad88395 id:int = InputMessage;
inputMessagePinned#86872538 = InputMessage;
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -974,7 +865,7 @@ auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentC
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
account.registerDevice#1389cc token_type:int token:string app_sandbox:Bool other_uids:Vector<int> = Bool;
account.registerDevice#5cbea590 token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
@ -1027,7 +918,7 @@ contacts.resetSaved#879537f1 = Bool;
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.search#39e9ea0 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true peer:InputPeer max_id:int = messages.AffectedHistory;
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
@ -1039,6 +930,7 @@ messages.forwardMessages#708e0195 flags:# silent:flags.5?true background:flags.6
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.hideReportSpam#a8f1709b peer:InputPeer = Bool;
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
messages.report#bd82b658 peer:InputPeer id:Vector<int> reason:ReportReason = Bool;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
messages.getFullChat#3b831c66 chat_id:int = messages.ChatFull;
messages.editChatTitle#dc452855 chat_id:int title:string = Updates;
@ -1058,7 +950,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool;
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
messages.getStickers#ae22e045 emoticon:string hash:string = messages.Stickers;
messages.getStickers#85cb5182 flags:# exclude_featured:flags.0?true emoticon:string hash:string = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
@ -1086,7 +978,7 @@ messages.editMessage#5d1b8dd flags:# no_webpage:flags.1?true stop_geo_live:flags
messages.editInlineBotMessage#b0e08243 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Bool;
messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
messages.getPeerDialogs#2d9776b9 peers:Vector<InputPeer> = messages.PeerDialogs;
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
messages.getAllDrafts#6a3f8d65 = Updates;
messages.getFeaturedStickers#2dacca4f hash:int = messages.FeaturedStickers;
@ -1104,8 +996,8 @@ messages.getInlineGameHighScores#f635e1b id:InputBotInlineMessageID user_id:Inpu
messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = messages.Chats;
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
messages.toggleDialogPin#3289be6a flags:# pinned:flags.0?true peer:InputPeer = Bool;
messages.reorderPinnedDialogs#959ff644 flags:# force:flags.0?true order:Vector<InputPeer> = Bool;
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
@ -1115,9 +1007,10 @@ messages.getFavedStickers#21ce0b0e hash:int = messages.FavedStickers;
messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory;
messages.getRecentLocations#249431e2 peer:InputPeer limit:int = messages.Messages;
messages.getRecentLocations#bbc45b09 peer:InputPeer limit:int hash:int = messages.Messages;
messages.sendMultiMedia#2095512f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#c2b7d08b flags:# exclude_featured:flags.0?true q:string hash:int = messages.FoundStickerSets;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1133,8 +1026,9 @@ upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
upload.reuploadCdnFile#1af91c09 file_token:bytes request_token:bytes = Vector<CdnFileHash>;
upload.getCdnFileHashes#f715c87b file_token:bytes offset:int = Vector<CdnFileHash>;
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector<FileHash>;
upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector<FileHash>;
upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<FileHash>;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
@ -1210,4 +1104,4 @@ langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangP
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
// LAYER 75
// LAYER 76

View File

@ -1,13 +1,15 @@
from telethon_generator.parsers import parse_errors, parse_tl, find_layer
from telethon_generator.generators import\
generate_errors, generate_tlobjects, generate_docs
import itertools
ERRORS_INPUT_JSON = 'data/errors.json'
ERRORS_INPUT_DESC = 'data/error_descriptions'
ERRORS_OUTPUT = '../telethon/errors/rpc_error_list.py'
TLOBJECT_INPUT_TL = 'data/scheme.tl'
TLOBJECT_INPUT_CORE_TL = 'data/mtproto_api.tl'
TLOBJECT_INPUT_TL = 'data/telegram_api.tl'
TLOBJECT_OUTPUT = '../telethon/tl'
DOCS_INPUT_RES = 'data/html'
@ -15,7 +17,9 @@ DOCS_OUTPUT = '../docs'
if __name__ == '__main__':
tlobjects = list(parse_tl(TLOBJECT_INPUT_TL, ignore_core=True))
tlobjects = list(itertools.chain(
parse_tl(TLOBJECT_INPUT_CORE_TL), parse_tl(TLOBJECT_INPUT_TL)))
errors = list(parse_errors(ERRORS_INPUT_JSON, ERRORS_INPUT_DESC))
layer = find_layer(TLOBJECT_INPUT_TL)

View File

@ -439,9 +439,9 @@ def _write_html_pages(tlobjects, errors, layer, input_res, output_dir):
# List all the methods which take this type as input
docs.write_title('Methods accepting this type as input', level=3)
other_methods = sorted(
(t for t in tlobjects
if any(t == a.type for a in t.args) and t.is_function),
key=lambda t: t.name
(u for u in tlobjects
if any(a.type == t for a in u.args) and u.is_function),
key=lambda u: u.name
)
if not other_methods:
docs.write_text(
@ -464,10 +464,9 @@ def _write_html_pages(tlobjects, errors, layer, input_res, output_dir):
# List every other type which has this type as a member
docs.write_title('Other types containing this type', level=3)
other_types = sorted(
(t for t in tlobjects
if any(t == a.type for a in t.args)
and not t.is_function
), key=lambda t: t.name
(u for u in tlobjects
if any(a.type == t for a in u.args) and not u.is_function),
key=lambda u: u.name
)
if not other_types:

View File

@ -17,6 +17,7 @@ AUTO_CASTS = {
'InputPeer': 'utils.get_input_peer(await client.get_input_entity({}))',
'InputChannel': 'utils.get_input_channel(await client.get_input_entity({}))',
'InputUser': 'utils.get_input_user(await client.get_input_entity({}))',
'InputDialogPeer': 'utils.get_input_dialog(await client.get_input_entity({}))',
'InputMedia': 'utils.get_input_media({})',
'InputPhoto': 'utils.get_input_photo({})',
'InputMessage': 'utils.get_input_message({})'

View File

@ -34,7 +34,7 @@ class HigherLevelTests(unittest.TestCase):
progress_callback=lambda c, t:
print('test_cdn_download:uploading {:.2%}...'.format(c/t))
)
msg = (await client.get_message_history(me))[1][0]
msg = (await client.get_messages(me))[0]
out = BytesIO()
await client.download_media(msg, out)