diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 00000000..4560a56a
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+telepy
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..3071daf2
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..86e90da9
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml
new file mode 100644
index 00000000..922003b8
--- /dev/null
+++ b/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/telepy.iml b/.idea/telepy.iml
new file mode 100644
index 00000000..d0876a78
--- /dev/null
+++ b/.idea/telepy.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TL_schema b/TL_schema
new file mode 100644
index 00000000..ac785680
--- /dev/null
+++ b/TL_schema
@@ -0,0 +1,76 @@
+int ? = Int;
+long ? = Long;
+double ? = Double;
+string ? = String;
+
+vector {t:Type} # [ t ] = Vector t;
+
+int128 4*[ int ] = Int128;
+int256 8*[ int ] = Int256;
+
+resPQ#05162463 nonce:int128 server_nonce:int128 pq:bytes server_public_key_fingerprints:Vector = 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;
+
+rpc_result#f35c6d01 req_msg_id:long result:Object = 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 = 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:Object = Message;
+msg_copy#e06046b2 orig_message:Message = MessageCopy;
+
+gzip_packed#3072cfa1 packed_data:bytes = Object;
+
+msgs_ack#62d6b459 msg_ids:Vector = 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 = MsgResendReq;
+msgs_state_req#da69fb52 msg_ids:Vector = MsgsStateReq;
+msgs_state_info#04deb57d req_msg_id:long info:bytes = MsgsStateInfo;
+msgs_all_info#8cc0d131 msg_ids:Vector info:bytes = 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;
+
+---functions---
+
+req_pq#60469778 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;
+
+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;
\ No newline at end of file
diff --git a/mtproto.py b/mtproto.py
new file mode 100644
index 00000000..69d825cc
--- /dev/null
+++ b/mtproto.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Sep 2 19:26:15 2014
+
+@author: agrigoryev
+"""
+import binascii
+import struct
+
+def sendpacket(socket, data, number):
+ step1 = (len(data)+12).to_bytes(4,'little') + number.to_bytes(4,'little') + data
+ step2 = step1 + binascii.crc32(step1).to_bytes(4,'little')
+ socket.send(step2)
+
+def recvpacket(socket):
+ packet_length_data = socket.recv(4)
+ if len(packet_length_data)>0:
+ packet_length = struct.unpack("=6, Returns a list of primes, 2 <= p < N """
+ correction = N % 6 > 1
+ N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
+ sieve = [True] * (N // 3)
+ sieve[0] = False
+ for i in range(int(N ** .5) // 3 + 1):
+ if sieve[i]:
+ k = (3 * i + 1) | 1
+ sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
+ sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
+ return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]
+
+smallprimeset = set(primesbelow(100000))
+_smallprimeset = 100000
+def isprime(n, precision=7):
+ # http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
+ if n == 1 or n % 2 == 0:
+ return False
+ elif n < 1:
+ raise ValueError("Out of bounds, first argument must be > 0")
+ elif n < _smallprimeset:
+ return n in smallprimeset
+
+
+ d = n - 1
+ s = 0
+ while d % 2 == 0:
+ d //= 2
+ s += 1
+
+ for repeat in range(precision):
+ a = random.randrange(2, n - 2)
+ x = pow(a, d, n)
+
+ if x == 1 or x == n - 1: continue
+
+ for r in range(s - 1):
+ x = pow(x, 2, n)
+ if x == 1: return False
+ if x == n - 1: break
+ else: return False
+
+ return True
+
+# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
+def pollard_brent(n):
+ if n % 2 == 0: return 2
+ if n % 3 == 0: return 3
+
+ y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)
+ g, r, q = 1, 1, 1
+ while g == 1:
+ x = y
+ for i in range(r):
+ y = (pow(y, 2, n) + c) % n
+
+ k = 0
+ while k < r and g==1:
+ ys = y
+ for i in range(min(m, r-k)):
+ y = (pow(y, 2, n) + c) % n
+ q = q * abs(x-y) % n
+ g = gcd(q, n)
+ k += m
+ r *= 2
+ if g == n:
+ while True:
+ ys = (pow(ys, 2, n) + c) % n
+ g = gcd(abs(x - ys), n)
+ if g > 1:
+ break
+
+ return g
+
+smallprimes = primesbelow(10000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
+def primefactors(n, sort=False):
+ factors = []
+
+ limit = int(n ** .5) + 1
+ for checker in smallprimes:
+ if checker > limit: break
+ while n % checker == 0:
+ factors.append(checker)
+ n //= checker
+ limit = int(n ** .5) + 1
+ if checker > limit: break
+
+ if n < 2: return factors
+
+ while n > 1:
+ if isprime(n):
+ factors.append(n)
+ break
+ factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
+ factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
+ n //= factor
+
+ if sort: factors.sort()
+
+ return factors
+
+def factorization(n):
+ factors = {}
+ for p1 in primefactors(n):
+ try:
+ factors[p1] += 1
+ except KeyError:
+ factors[p1] = 1
+ return factors
+
+totients = {}
+def totient(n):
+ if n == 0: return 1
+
+ try: return totients[n]
+ except KeyError: pass
+
+ tot = 1
+ for p, exp in factorization(n).items():
+ tot *= (p - 1) * p ** (exp - 1)
+
+ totients[n] = tot
+ return tot
+
+def gcd(a, b):
+ if a == b: return a
+ while b > 0: a, b = b, a % b
+ return a
+
+def lcm(a, b):
+ return abs(a * b) // gcd(a, b)
+
\ No newline at end of file