From 7c8c65560ed80c52fcb77e2d5dbe559060657a30 Mon Sep 17 00:00:00 2001 From: Lonami Date: Sun, 4 Sep 2016 12:42:11 +0200 Subject: [PATCH] Refactored imports --- api/__init__.py | 0 crypto/__init__.py | 4 ++ crypto/auth_key.py | 5 +-- crypto/rsa.py | 4 +- network/__init__.py | 6 +++ network/authenticator.py | 13 ++---- network/mtproto_plain_sender.py | 3 +- network/mtproto_sender.py | 15 ++++--- network/tcp_message.py | 3 +- network/tcp_transport.py | 3 +- parser/__init__.py | 2 + parser/tl_parser.py | 2 +- tl/__init__.py | 5 +++ tl/session.py | 2 +- tl/telegram_client.py | 70 +++++++++++++++------------------ tl_generator.py | 18 ++++++--- unit_test.py | 22 ++++++----- utils/__init__.py | 3 ++ utils/binary_reader.py | 2 +- utils/helpers.py | 2 +- 20 files changed, 98 insertions(+), 86 deletions(-) delete mode 100644 api/__init__.py diff --git a/api/__init__.py b/api/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/crypto/__init__.py b/crypto/__init__.py index e69de29b..785e48a6 100644 --- a/crypto/__init__.py +++ b/crypto/__init__.py @@ -0,0 +1,4 @@ +from .aes import AES +from .rsa import RSA, RSAServerKey +from .auth_key import AuthKey +from .factorizator import Factorizator diff --git a/crypto/auth_key.py b/crypto/auth_key.py index 2f17652d..0d548cba 100755 --- a/crypto/auth_key.py +++ b/crypto/auth_key.py @@ -1,8 +1,7 @@ # This file is based on TLSharp # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/MTProto/Crypto/AuthKey.cs -import utils.helpers as utils -from utils.binary_writer import BinaryWriter -from utils.binary_reader import BinaryReader +import utils +from utils import BinaryWriter, BinaryReader class AuthKey: diff --git a/crypto/rsa.py b/crypto/rsa.py index 23962a94..1578764c 100755 --- a/crypto/rsa.py +++ b/crypto/rsa.py @@ -1,7 +1,7 @@ # This file is based on TLSharp # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/MTProto/Crypto/RSA.cs -from utils.binary_writer import BinaryWriter -import utils.helpers as utils +import utils +from utils import BinaryWriter class RSAServerKey: diff --git a/network/__init__.py b/network/__init__.py index e69de29b..ea02bd9a 100755 --- a/network/__init__.py +++ b/network/__init__.py @@ -0,0 +1,6 @@ +from .mtproto_plain_sender import MtProtoPlainSender +from .tcp_client import TcpClient +from .tcp_message import TcpMessage +from .authenticator import do_authentication +from .mtproto_sender import MtProtoSender +from .tcp_transport import TcpTransport diff --git a/network/authenticator.py b/network/authenticator.py index ea41f693..14bcfce0 100755 --- a/network/authenticator.py +++ b/network/authenticator.py @@ -5,15 +5,10 @@ # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs import time - -import utils.helpers as utils -from crypto.aes import AES -from crypto.auth_key import AuthKey -from crypto.factorizator import Factorizator -from crypto.rsa import RSA -from network.mtproto_plain_sender import MtProtoPlainSender -from utils.binary_reader import BinaryReader -from utils.binary_writer import BinaryWriter +import utils +from utils import BinaryWriter, BinaryReader +from crypto import AES, AuthKey, Factorizator, RSA +from network import MtProtoPlainSender def do_authentication(transport): diff --git a/network/mtproto_plain_sender.py b/network/mtproto_plain_sender.py index e95dfd60..743bd987 100755 --- a/network/mtproto_plain_sender.py +++ b/network/mtproto_plain_sender.py @@ -1,8 +1,7 @@ # This file is based on TLSharp # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/Network/MtProtoPlainSender.cs import time -from utils.binary_writer import BinaryWriter -from utils.binary_reader import BinaryReader +from utils import BinaryWriter, BinaryReader class MtProtoPlainSender: diff --git a/network/mtproto_sender.py b/network/mtproto_sender.py index 0ecb68e2..ea456ed7 100755 --- a/network/mtproto_sender.py +++ b/network/mtproto_sender.py @@ -4,11 +4,10 @@ import re import zlib from time import sleep -from crypto.aes import AES -from utils.binary_writer import BinaryWriter -from utils.binary_reader import BinaryReader -from tl.types.msgs_ack import MsgsAck -import utils.helpers as helpers +import utils +from crypto import AES +from utils import BinaryWriter, BinaryReader +from tl.types import MsgsAck class MtProtoSender: @@ -74,9 +73,9 @@ class MtProtoSender: writer.write_int(len(packet)) writer.write(packet) - msg_key = helpers.calc_msg_key(writer.get_bytes()) + msg_key = utils.calc_msg_key(writer.get_bytes()) - key, iv = helpers.calc_key(self.session.auth_key.key, msg_key, True) + key, iv = utils.calc_key(self.session.auth_key.key, msg_key, True) cipher_text = AES.encrypt_ige(writer.get_bytes(), key, iv) # And then finally send the packet @@ -101,7 +100,7 @@ class MtProtoSender: remote_auth_key_id = reader.read_long() msg_key = reader.read(16) - key, iv = helpers.calc_key(self.session.auth_key.data, msg_key, False) + key, iv = utils.calc_key(self.session.auth_key.data, msg_key, False) plain_text = AES.decrypt_ige(reader.read(len(body) - reader.tell_position()), key, iv) with BinaryReader(plain_text) as plain_text_reader: diff --git a/network/tcp_message.py b/network/tcp_message.py index 6872a528..ab71c17e 100755 --- a/network/tcp_message.py +++ b/network/tcp_message.py @@ -2,8 +2,7 @@ # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/Network/TcpMessage.cs from zlib import crc32 -from utils.binary_writer import BinaryWriter -from utils.binary_reader import BinaryReader +from utils import BinaryWriter, BinaryReader class TcpMessage: diff --git a/network/tcp_transport.py b/network/tcp_transport.py index bd4e28fa..4a3a0027 100755 --- a/network/tcp_transport.py +++ b/network/tcp_transport.py @@ -1,8 +1,7 @@ # This file is based on TLSharp # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/Network/TcpTransport.cs from zlib import crc32 -from network.tcp_message import TcpMessage -from network.tcp_client import TcpClient +from network import TcpMessage, TcpClient class TcpTransport: diff --git a/parser/__init__.py b/parser/__init__.py index e69de29b..d29930ed 100755 --- a/parser/__init__.py +++ b/parser/__init__.py @@ -0,0 +1,2 @@ +from .source_builder import SourceBuilder +from .tl_parser import TLParser, TLObject diff --git a/parser/tl_parser.py b/parser/tl_parser.py index 1e37d688..694a0d92 100755 --- a/parser/tl_parser.py +++ b/parser/tl_parser.py @@ -1,5 +1,5 @@ import re -from tl.tlobject import TLObject +from tl import TLObject class TLParser: diff --git a/tl/__init__.py b/tl/__init__.py index e69de29b..3d8d20ad 100755 --- a/tl/__init__.py +++ b/tl/__init__.py @@ -0,0 +1,5 @@ +from .all_tlobjects import tlobjects +from .session import Session +from .mtproto_request import MTProtoRequest +from .telegram_client import TelegramClient +from .tlobject import TLObject, TLArg diff --git a/tl/session.py b/tl/session.py index a1925100..66713dc1 100755 --- a/tl/session.py +++ b/tl/session.py @@ -3,7 +3,7 @@ from os.path import isfile as file_exists import time import pickle -import utils.helpers as utils +import utils class Session: diff --git a/tl/telegram_client.py b/tl/telegram_client.py index a02b05d6..91f425b1 100644 --- a/tl/telegram_client.py +++ b/tl/telegram_client.py @@ -1,29 +1,25 @@ # This file is based on TLSharp # https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/TelegramClient.cs -from network.mtproto_sender import MtProtoSender -from network.tcp_transport import TcpTransport -import network.authenticator as authenticator -from tl.session import Session -import utils.helpers as utils -import platform import re +import platform -from tl.functions.invoke_with_layer import InvokeWithLayer -from tl.functions.init_connection import InitConnection -from tl.functions.help.get_config import GetConfig -from tl.functions.auth.check_phone import CheckPhone -from tl.functions.auth.send_code import SendCode -from tl.functions.auth.sign_in import SignIn -from tl.functions.contacts.get_contacts import GetContacts -from tl.types.input_peer_user import InputPeerUser -from tl.functions.messages.send_message import SendMessage +import utils +import network.authenticator +from network import MtProtoSender, TcpTransport + +from tl import Session +from tl.types import InputPeerUser +from tl.functions import InvokeWithLayerRequest, InitConnectionRequest +from tl.functions.help import GetConfigRequest +from tl.functions.auth import CheckPhoneRequest, SendCodeRequest, SignInRequest +from tl.functions.contacts import GetContactsRequest +from tl.functions.messages import SendMessageRequest class TelegramClient: - def __init__(self, session_user_id, layer, api_id=None, api_hash=None): if api_id is None or api_hash is None: - raise PermissionError('Your API ID or Hash are invalid. Make sure to obtain yours in http://my.telegram.org') + raise PermissionError('Your API ID or Hash are invalid. Please read "Requirements" on README.md') self.api_id = api_id self.api_hash = api_hash @@ -32,23 +28,26 @@ class TelegramClient: self.session = Session.try_load_or_create_new(session_user_id) self.transport = TcpTransport(self.session.server_address, self.session.port) + + # These will be set later self.dc_options = None + self.sender = None # TODO Should this be async? def connect(self, reconnect=False): - if self.session.auth_key is None or reconnect: - self.session.auth_key, self.session.time_offset= authenticator.do_authentication(self.transport) + if not self.session.auth_key or reconnect: + self.session.auth_key, self.session.time_offset = network.authenticator.do_authentication(self.transport) self.sender = MtProtoSender(self.transport, self.session) if not reconnect: - request = InvokeWithLayer(layer=self.layer, - query=InitConnection(api_id=self.api_id, - device_model=platform.node(), - system_version=platform.system(), - app_version='0.1', - lang_code='en', - query=GetConfig())) + request = InvokeWithLayerRequest(layer=self.layer, + query=InitConnectionRequest(api_id=self.api_id, + device_model=platform.node(), + system_version=platform.system(), + app_version='0.1', + lang_code='en', + query=GetConfigRequest())) self.sender.send(request) self.sender.receive(request) @@ -77,22 +76,15 @@ class TelegramClient: def is_phone_registered(self, phone_number): assert self.sender is not None, 'Not connected!' - request = CheckPhone(phone_number) + request = CheckPhoneRequest(phone_number) self.sender.send(request) self.sender.receive(request) # Result is an Auth.CheckedPhone return request.result.phone_registered - def send_code_request(self, phone_number, destination='code'): - if destination == 'code': - destination = 5 - elif destination == 'sms': - destination = 0 - else: - raise ValueError('Destination must be either "code" or "sms"') - - request = SendCode(phone_number, self.api_id, self.api_hash) + def send_code_request(self, phone_number): + request = SendCodeRequest(phone_number, self.api_id, self.api_hash) completed = False while not completed: try: @@ -109,7 +101,7 @@ class TelegramClient: return request.result.phone_code_hash def make_auth(self, phone_number, phone_code_hash, code): - request = SignIn(phone_number, phone_code_hash, code) + request = SignInRequest(phone_number, phone_code_hash, code) self.sender.send(request) self.sender.receive(request) @@ -120,14 +112,14 @@ class TelegramClient: return self.session.user def import_contacts(self, phone_code_hash): - request = GetContacts(phone_code_hash) + request = GetContactsRequest(phone_code_hash) self.sender.send(request) self.sender.receive(request) return request.result.contacts, request.result.users def send_message(self, user, message): peer = InputPeerUser(user.id, user.access_hash) - request = SendMessage(peer, message, utils.generate_random_long()) + request = SendMessageRequest(peer, message, utils.generate_random_long()) self.sender.send(request) self.sender.send(request) diff --git a/tl_generator.py b/tl_generator.py index 1d23e3ca..94217ee9 100755 --- a/tl_generator.py +++ b/tl_generator.py @@ -2,8 +2,8 @@ import os import re import shutil -from parser.tl_parser import TLParser -from parser.source_builder import SourceBuilder +from parser import TLParser +from parser import SourceBuilder def tlobjects_exist(): @@ -43,10 +43,12 @@ def generate_tlobjects(scheme_file): os.makedirs(out_dir, exist_ok=True) - # Also create __init__.py + # Also add this object to __init__.py, so we can import the whole packet at once init_py = os.path.join(out_dir, '__init__.py') - if not os.path.isfile(init_py): - open(init_py, 'a').close() + with open(init_py, 'a', encoding='utf-8') as file: + with SourceBuilder(file) as builder: + builder.writeln('from {} import {}'.format( + get_full_file_name(tlobject), get_class_name(tlobject))) # Create the file for this TLObject filename = os.path.join(out_dir, get_file_name(tlobject, add_extension=True)) @@ -165,7 +167,11 @@ def get_class_name(tlobject): # Courtesy of http://stackoverflow.com/a/31531797/4759433 # Also, '_' could be replaced for ' ', then use .title(), and then remove ' ' result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), tlobject.name) - return result[:1].upper() + result[1:].replace('_', '') # Replace again to fully ensure! + result = result[:1].upper() + result[1:].replace('_', '') # Replace again to fully ensure! + # If it's a function, let it end with "Request" to identify them more easily + if tlobject.is_function: + result += 'Request' + return result def get_full_file_name(tlobject): diff --git a/unit_test.py b/unit_test.py index afcd23f9..4d359daf 100755 --- a/unit_test.py +++ b/unit_test.py @@ -2,15 +2,19 @@ import random import socket import threading import unittest +import os +import platform -import utils.helpers as utils -from crypto.aes import AES -from crypto.factorizator import Factorizator -from network.authenticator import do_authentication -from network.tcp_client import TcpClient -from network.tcp_transport import TcpTransport -from utils.binary_reader import BinaryReader -from utils.binary_writer import BinaryWriter +import utils +import network.authenticator + +from crypto import AES, Factorizator +from network import TcpTransport, TcpClient, MtProtoSender +from utils import BinaryWriter, BinaryReader + +from tl import Session +from tl.functions import InvokeWithLayerRequest, InitConnectionRequest +from tl.functions.help import GetConfigRequest host = 'localhost' port = random.randint(50000, 60000) # Arbitrary non-privileged port @@ -218,7 +222,7 @@ class UnitTest(unittest.TestCase): @staticmethod def test_authenticator(): transport = TcpTransport('149.154.167.91', 443) - auth_key, time_offset = do_authentication(transport) + network.authenticator.do_authentication(transport) transport.dispose() if __name__ == '__main__': diff --git a/utils/__init__.py b/utils/__init__.py index e69de29b..15d693f4 100755 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -0,0 +1,3 @@ +from .binary_writer import BinaryWriter +from .binary_reader import BinaryReader +from .helpers import * diff --git a/utils/binary_reader.py b/utils/binary_reader.py index a9a1f30b..7518abe4 100755 --- a/utils/binary_reader.py +++ b/utils/binary_reader.py @@ -1,5 +1,5 @@ from io import BytesIO, BufferedReader -from tl.all_tlobjects import tlobjects +from tl import tlobjects from struct import unpack import inspect import os diff --git a/utils/helpers.py b/utils/helpers.py index 67940e58..bdc331bb 100755 --- a/utils/helpers.py +++ b/utils/helpers.py @@ -1,5 +1,5 @@ import os -from utils.binary_writer import BinaryWriter +from utils import BinaryWriter import hashlib