2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-09-02 07:15:23 +00:00

Merge branch 'master' into new-api

# Conflicts:
#	pyrogram/client/client.py
This commit is contained in:
Dan
2018-03-26 13:46:48 +02:00
16 changed files with 1096 additions and 860 deletions

View File

@@ -23,7 +23,7 @@ __copyright__ = "Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance
"e" if sys.getfilesystemencoding() == "ascii" else "\xe8"
)
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__version__ = "0.6.2"
__version__ = "0.6.4"
from .api.errors import Error
from .client import ChatAction

File diff suppressed because it is too large Load Diff

View File

@@ -81,7 +81,7 @@ class InputMedia:
width: int = 0,
height: int = 0,
duration: int = 0,
supports_streaming: bool = None):
supports_streaming: bool = True):
self.media = media
self.caption = caption
self.parse_mode = parse_mode

View File

@@ -36,7 +36,7 @@ class Markdown:
CODE_DELIMITER = "`"
PRE_DELIMITER = "```"
MARKDOWN_RE = re.compile(r"```([\w ]*)\n([\w\W]*)(?:\n|)```|\[([^[(]+)\]\(([^])]+)\)|({d})(.+?)\5".format(
MARKDOWN_RE = re.compile(r"```([\w ]*)\n([\w\W]*)(?:\n|)```|\[(.+?)\]\((.+?)\)|({d})(.+?)\5".format(
d="|".join(
["".join(i) for i in [
["\{}".format(j) for j in i]

View File

@@ -54,6 +54,7 @@ class Connection:
def close(self):
self.connection.close()
log.info("Disconnected")
def send(self, data: bytes):
with self.lock:

View File

@@ -20,7 +20,15 @@ import logging
import socket
from collections import namedtuple
import socks
try:
import socks
except ImportError as e:
e.msg = (
"PySocks is missing and Pyrogram can't run without. "
"Please install it using \"pip3 install pysocks\"."
)
raise e
log = logging.getLogger(__name__)

View File

@@ -16,52 +16,33 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
log = logging.getLogger(__name__)
try:
import tgcrypto
except ImportError:
log.warning(
"TgCrypto is missing! "
"Pyrogram will work the same, but at a much slower speed. "
except ImportError as e:
e.msg = (
"TgCrypto is missing and Pyrogram can't run without. "
"Please install it using \"pip3 install tgcrypto\". "
"More info: https://docs.pyrogram.ml/resources/TgCrypto"
)
is_fast = False
import pyaes
else:
log.info("Using TgCrypto")
is_fast = True
raise e
# TODO: Ugly IFs
class AES:
@classmethod
def ige_encrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
if is_fast:
return tgcrypto.ige_encrypt(data, key, iv)
else:
return cls.ige(data, key, iv, True)
return tgcrypto.ige_encrypt(data, key, iv)
@classmethod
def ige_decrypt(cls, data: bytes, key: bytes, iv: bytes) -> bytes:
if is_fast:
return tgcrypto.ige_decrypt(data, key, iv)
else:
return cls.ige(data, key, iv, False)
return tgcrypto.ige_decrypt(data, key, iv)
@staticmethod
def ctr_decrypt(data: bytes, key: bytes, iv: bytes, offset: int) -> bytes:
replace = int.to_bytes(offset // 16, byteorder="big", length=4)
replace = int.to_bytes(offset // 16, 4, "big")
iv = iv[:-4] + replace
if is_fast:
return tgcrypto.ctr_decrypt(data, key, iv)
else:
ctr = pyaes.AESModeOfOperationCTR(key)
ctr._counter._counter = list(iv)
return ctr.decrypt(data)
return tgcrypto.ctr_decrypt(data, key, iv)
@staticmethod
def xor(a: bytes, b: bytes) -> bytes:
@@ -70,23 +51,3 @@ class AES:
len(a),
"big",
)
@classmethod
def ige(cls, data: bytes, key: bytes, iv: bytes, encrypt: bool) -> bytes:
cipher = pyaes.AES(key)
iv_1 = iv[:16]
iv_2 = iv[16:]
data = [data[i: i + 16] for i in range(0, len(data), 16)]
if encrypt:
for i, chunk in enumerate(data):
iv_1 = data[i] = cls.xor(cipher.encrypt(cls.xor(chunk, iv_1)), iv_2)
iv_2 = chunk
else:
for i, chunk in enumerate(data):
iv_2 = data[i] = cls.xor(cipher.decrypt(cls.xor(chunk, iv_2)), iv_1)
iv_1 = chunk
return b"".join(data)

View File

@@ -61,7 +61,7 @@ class Session:
INITIAL_SALT = 0x616e67656c696361
NET_WORKERS = 1
WAIT_TIMEOUT = 10
WAIT_TIMEOUT = 30
MAX_RETRIES = 5
ACKS_THRESHOLD = 8
PING_INTERVAL = 5
@@ -122,8 +122,6 @@ class Session:
self.is_connected = Event()
def start(self):
terms = None
while True:
try:
self.connection.connect()
@@ -141,7 +139,7 @@ class Session:
self.next_salt_thread.start()
if not self.is_cdn:
terms = self._send(
self._send(
functions.InvokeWithLayer(
layer,
functions.InitConnection(
@@ -150,10 +148,10 @@ class Session:
self.SYSTEM_VERSION,
self.APP_VERSION,
"en", "", "en",
functions.help.GetTermsOfService(),
functions.help.GetConfig(),
)
)
).text
)
self.ping_thread = Thread(target=self.ping, name="PingThread")
self.ping_thread.start()
@@ -168,8 +166,6 @@ class Session:
log.debug("Session started")
return terms
def stop(self):
self.is_connected.clear()
@@ -190,6 +186,9 @@ class Session:
for i in range(self.NET_WORKERS):
self.recv_queue.put(None)
for i in self.results.values():
i.event.set()
log.debug("Session stopped")
def restart(self):
@@ -401,7 +400,7 @@ class Session:
try:
return self._send(data)
except (OSError, TimeoutError):
log.warning("Retrying {}".format(type(data)))
(log.warning if i > 0 else log.info)("{}: {} Retrying {}".format(i, datetime.now(), type(data)))
continue
else:
return None