From b7db8cade1f9e7e42031eb490d809cad4037dc59 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 27 Feb 2018 18:42:02 +0100
Subject: [PATCH 01/17] Update README.md
---
examples/README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/examples/README.md b/examples/README.md
index 3e4a7b85..eda57be6 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -8,6 +8,7 @@ you have to change are the target chats (username, id) and file paths for sendin
- [**hello_world.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/hello_world.py)
- [**get_history.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/get_history.py)
- [**get_participants.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/get_participants.py)
+- [**inline_bots.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/inline_bots.py)
- [**updates.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/updates.py)
- [**simple_echo.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/simple_echo.py)
- [**advanced_echo.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/advanced_echo.py)
From 2e9ee6b0731b52bba0e8d1cfafb73a4f7f6046c4 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 27 Feb 2018 18:48:30 +0100
Subject: [PATCH 02/17] Use proper client_id values
---
pyrogram/client/input_phone_contact.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pyrogram/client/input_phone_contact.py b/pyrogram/client/input_phone_contact.py
index 002a3121..9268ca0a 100644
--- a/pyrogram/client/input_phone_contact.py
+++ b/pyrogram/client/input_phone_contact.py
@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see .
from pyrogram.api.types import InputPhoneContact as RawInputPhoneContact
+from pyrogram.session.internals import MsgId
class InputPhoneContact:
@@ -36,7 +37,7 @@ class InputPhoneContact:
def __new__(cls, phone: str, first_name: str, last_name: str = ""):
return RawInputPhoneContact(
- client_id=0,
+ client_id=MsgId(),
phone="+" + phone.strip("+"),
first_name=first_name,
last_name=last_name
From 608feac985cda36b46f3a6d8ddecdcf69fede7b8 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Tue, 27 Feb 2018 20:05:11 +0100
Subject: [PATCH 03/17] Update to v0.6.2
---
pyrogram/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py
index db7a3a84..b2b85d0c 100644
--- a/pyrogram/__init__.py
+++ b/pyrogram/__init__.py
@@ -23,7 +23,7 @@ __copyright__ = "Copyright (C) 2017-2018 Dan Tès
Date: Thu, 1 Mar 2018 02:36:56 +0300
Subject: [PATCH 04/17] Added sending thumb with video.
---
pyrogram/client/client.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 0a5e6ef1..f62454d7 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1290,6 +1290,7 @@ class Client:
duration: int = 0,
width: int = 0,
height: int = 0,
+ thumb: str = None,
supports_streaming: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None):
@@ -1322,6 +1323,11 @@ class Client:
height (:obj:`int`, optional):
Video height.
+ thumb (:obj:`str`, optional):
+ Video thumbmail.
+ Pass a file path as string to send a image that exists on your local machine.
+ Thumbmail should have 90 or less pixels of width and 90 or less pixels of height.
+
supports_streaming (:obj:`bool`, optional):
Pass True, if the uploaded video is suitable for streaming.
@@ -1340,6 +1346,7 @@ class Client:
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
file = self.save_file(video)
+ fileThumb = None if thumb is None else self.save_file(thumb)
while True:
try:
@@ -1349,6 +1356,7 @@ class Client:
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"],
file=file,
+ thumb=fileThumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=supports_streaming,
From 950f680d683835afce1746129d279310759cdc10 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Wed, 7 Mar 2018 00:41:45 +0100
Subject: [PATCH 05/17] Add req_pq_multi function
---
compiler/api/source/auth_key.tl | 1 +
1 file changed, 1 insertion(+)
diff --git a/compiler/api/source/auth_key.tl b/compiler/api/source/auth_key.tl
index 77c4c602..e0af9dcd 100644
--- a/compiler/api/source/auth_key.tl
+++ b/compiler/api/source/auth_key.tl
@@ -29,6 +29,7 @@ destroy_auth_key_fail#ea109b13 = DestroyAuthKeyRes;
---functions---
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;
From efd435befd1f6be1a2fca875a7e332690c198519 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:09:03 +0100
Subject: [PATCH 06/17] Use snake_case style
---
pyrogram/client/client.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index f62454d7..0170169e 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1346,7 +1346,7 @@ class Client:
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
file = self.save_file(video)
- fileThumb = None if thumb is None else self.save_file(thumb)
+ file_thumb = None if thumb is None else self.save_file(thumb)
while True:
try:
@@ -1356,7 +1356,7 @@ class Client:
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"],
file=file,
- thumb=fileThumb,
+ thumb=file_thumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=supports_streaming,
From 20ec656d91040c826bb68f39fa4a784eff6478bb Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:11:47 +0100
Subject: [PATCH 07/17] Fix little typos
---
pyrogram/client/client.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 0170169e..9dd7377d 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1324,9 +1324,9 @@ class Client:
Video height.
thumb (:obj:`str`, optional):
- Video thumbmail.
- Pass a file path as string to send a image that exists on your local machine.
- Thumbmail should have 90 or less pixels of width and 90 or less pixels of height.
+ Video thumbnail.
+ Pass a file path as string to send an image that exists on your local machine.
+ Thumbnail should have 90 or less pixels of width and 90 or less pixels of height.
supports_streaming (:obj:`bool`, optional):
Pass True, if the uploaded video is suitable for streaming.
From 71f3e07dc1399e14319555461cece88f9128dab5 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:13:04 +0100
Subject: [PATCH 08/17] Add more public keys
---
pyrogram/crypto/rsa.py | 112 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 111 insertions(+), 1 deletion(-)
diff --git a/pyrogram/crypto/rsa.py b/pyrogram/crypto/rsa.py
index 1e733e8f..9f02e2cc 100644
--- a/pyrogram/crypto/rsa.py
+++ b/pyrogram/crypto/rsa.py
@@ -23,10 +23,16 @@ PublicKey = namedtuple("PublicKey", ["m", "e"])
class RSA:
# To get modulus and exponent:
+ #
+ # [RSA PUBLIC KEY]:
# grep -v -- - public.key | tr -d \\n | base64 -d | openssl asn1parse -inform DER -i
+ #
+ # [PUBLIC KEY]:
+ # openssl rsa -pubin -in key -text -noout
server_public_keys = {
- 0xc3b42b026ce86b21 - (1 << 64): PublicKey( # Telegram servers
+ # -4344800451088585951
+ 0xc3b42b026ce86b21 - (1 << 64): PublicKey( # Telegram servers #1
# -----BEGIN RSA PUBLIC KEY-----
# MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
# lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
@@ -48,6 +54,108 @@ class RSA:
), # Modulus
int("010001", 16) # Exponent
),
+
+ # 847625836280919973
+ 0x10bc35f3509f7b7a5 - (1 << 64): PublicKey( # Telegram servers #2
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruw2yP/BCcsJliRoW5eB
+ # VBVle9dtjJw+OYED160Wybum9SXtBBLXriwt4rROd9csv0t0OHCaTmRqBcQ0J8fx
+ # hN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvd
+ # l84Kd9ORYjDEAyFnEA7dD556OptgLQQ2e2iVNq8NZLYTzLp5YpOdO1doK+ttrltg
+ # gTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnSLj16yE5HvJQn0CNpRdENvRUXe6tBP78O
+ # 39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wFXGF710w9lwCGNbmNxNYhtIkdqfsEcwR5
+ # JwIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "AEEC36C8FFC109CB099624685B97815415657BD76D8C9C3E398103D7AD16C9BB"
+ "A6F525ED0412D7AE2C2DE2B44E77D72CBF4B7438709A4E646A05C43427C7F184"
+ "DEBF72947519680E651500890C6832796DD11F772C25FF8F576755AFE055B0A3"
+ "752C696EB7D8DA0D8BE1FAF38C9BDD97CE0A77D3916230C4032167100EDD0F9E"
+ "7A3A9B602D04367B689536AF0D64B613CCBA7962939D3B57682BEB6DAE5B6081"
+ "30B2E52ACA78BA023CF6CE806B1DC49C72CF928A7199D22E3D7AC84E47BC9427"
+ "D0236945D10DBD15177BAB413FBF0EDFDA09F014C7A7DA088DDE9759702CA760"
+ "AF2B8E4E97CC055C617BD74C3D97008635B98DC4D621B4891DA9FB0473047927",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
+
+ # 1562291298945373506
+ 0x115ae5fa8b5529542 - (1 << 64): PublicKey( # Telegram servers #3
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvfLHfYH2r9R70w8prHbl
+ # Wt/nDkh+XkgpflqQVcnAfSuTtO05lNPspQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOO
+ # KPi0OfJXoRVylFzAQG/j83u5K3kRLbae7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ
+ # 3TDS2pQOCtovG4eDl9wacrXOJTG2990VjgnIKNA0UMoP+KF03qzryqIt3oTvZq03
+ # DyWdGK+AZjgBLaDKSnC6qD2cFY81UryRWOab8zKkWAnhw2kFpcqhI0jdV5QaSCEx
+ # vnsjVaX0Y1N0870931/5Jb9ICe4nweZ9kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV
+ # /wIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "BDF2C77D81F6AFD47BD30F29AC76E55ADFE70E487E5E48297E5A9055C9C07D2B"
+ "93B4ED3994D3ECA5098BF18D978D54F8B7C713EB10247607E69AF9EF44F38E28"
+ "F8B439F257A11572945CC0406FE3F37BB92B79112DB69EEDF2DC71584A661638"
+ "EA5BECB9E23585074B80D57D9F5710DD30D2DA940E0ADA2F1B878397DC1A72B5"
+ "CE2531B6F7DD158E09C828D03450CA0FF8A174DEACEBCAA22DDE84EF66AD370F"
+ "259D18AF806638012DA0CA4A70BAA83D9C158F3552BC9158E69BF332A45809E1"
+ "C36905A5CAA12348DD57941A482131BE7B2355A5F4635374F3BD3DDF5FF925BF"
+ "4809EE27C1E67D9120C5FE08A9DE458B1B4A3C5D0A428437F2BECA81F4E2D5FF",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
+
+ # -5859577972006586033
+ 0xaeae98e13cd7f94f - (1 << 64): PublicKey( # Telegram servers #4
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/ditzm+mPND6xkhzwFI
+ # z6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGrzqTDHkO30R8VeRM/Kz2f4nR05GIFiITl
+ # 4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+th6knSU0yLtNKuQVP6voMrnt9MV1X92L
+ # GZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvSUwwc+yi1/gGaybwlzZwqXYoPOhwMebzK
+ # Uk0xW14htcJrRrq+PXXQbRzTMynseCoPIoke0dtCodbA3qQxQovE16q9zz4Otv2k
+ # 4j63cz53J+mhkVWAeWxVGI0lltJmWtEYK6er8VqqWot3nqmWMXogrgRLggv/Nbbo
+ # oQIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "B3F762B739BE98F343EB1921CF0148CFA27FF7AF02B6471213FED9DAA0098976"
+ "E667750324F1ABCEA4C31E43B7D11F1579133F2B3D9FE27474E462058884E5E1"
+ "B123BE9CBBC6A443B2925C08520E7325E6F1A6D50E117EB61EA49D2534C8BB4D"
+ "2AE4153FABE832B9EDF4C5755FDD8B19940B81D1D96CF433D19E6A22968A85DC"
+ "80F0312F596BD2530C1CFB28B5FE019AC9BC25CD9C2A5D8A0F3A1C0C79BCCA52"
+ "4D315B5E21B5C26B46BABE3D75D06D1CD33329EC782A0F22891ED1DB42A1D6C0"
+ "DEA431428BC4D7AABDCF3E0EB6FDA4E23EB7733E7727E9A1915580796C55188D"
+ "2596D2665AD1182BA7ABF15AAA5A8B779EA996317A20AE044B820BFF35B6E8A1",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
+
+ # 6491968696586960280
+ 0x15a181b2235057d98 - (1 << 64): PublicKey( # Telegram servers #5
+ # -----BEGIN PUBLIC KEY-----
+ # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q0
+ # 5shjg8/4p6047bn6/m8yPy1RBsvIyvuDuGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xb
+ # nfxL5BXHplJhMtADXKM9bWB11PU1Eioc3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA
+ # 9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvifRLJbY08/Gp66KpQvy7g8w7VB8wlgePe
+ # xW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqePji9NP3tJUFQjcECqcm0yV7/2d0t/pbC
+ # m+ZH1sadZspQCEPPrtbkQBlvHb4OLiIWPGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6M
+ # AQIDAQAB
+ # -----END PUBLIC KEY-----
+ int(
+ "BE6A71558EE577FF03023CFA17AAB4E6C86383CFF8A7AD38EDB9FAFE6F323F2D"
+ "5106CBC8CAFB83B869CFFD1CCF121CD743D509E589E68765C96601E813DC5B9D"
+ "FC4BE415C7A6526132D0035CA33D6D6075D4F535122A1CDFE017041F1088D141"
+ "9F65C8E5490EE613E16DBF662698C0F54870F0475FA893FC41EB55B08FF1AC21"
+ "1BC045DED31BE27D12C96D8D3CFC6A7AE8AA50BF2EE0F30ED507CC2581E3DEC5"
+ "6DE94F5DC0A7ABEE0BE990B893F2887BD2C6310A1E0A9E3E38BD34FDED254150"
+ "8DC102A9C9B4C95EFFD9DD2DFE96C29BE647D6C69D66CA500843CFAED6E44019"
+ "6F1DBE0E2E22163C61CA48C79116FA77216726749A976A1C4B0944B5121E8C01",
+ 16
+ ), # Modulus
+ int("010001", 16) # Exponent
+ ),
+
+ # 6427105915145367799
0x15931aac70e0d30f7 - (1 << 64): PublicKey( # CDN DC-121
# -----BEGIN RSA PUBLIC KEY-----
# MIIBCgKCAQEA+Lf3PvgE1yxbJUCMaEAkV0QySTVpnaDjiednB5RbtNWjCeqSVakY
@@ -70,6 +178,8 @@ class RSA:
), # Modulus
int("010001", 16) # Exponent
),
+
+ # 2685959930972952888
0x1254672538e935938 - (1 << 64): PublicKey( # CDN DC-140
# -----BEGIN RSA PUBLIC KEY-----
# MIIBCgKCAQEAzuHVC7sE50Kho/yDVZtWnlmA5Bf/aM8KZY3WzS16w6w1sBqipj8o
From cc49815cc590092715a5ac598023a991a35503f7 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:14:26 +0100
Subject: [PATCH 09/17] req_pq is deprecated, use req_pq_multi instead
---
pyrogram/session/auth.py | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/pyrogram/session/auth.py b/pyrogram/session/auth.py
index f48242e6..a1d8fd76 100644
--- a/pyrogram/session/auth.py
+++ b/pyrogram/session/auth.py
@@ -91,8 +91,19 @@ class Auth:
# Step 1; Step 2
nonce = int.from_bytes(urandom(16), "little", signed=True)
log.debug("Send req_pq: {}".format(nonce))
- res_pq = self.send(functions.ReqPq(nonce))
+ res_pq = self.send(functions.ReqPqMulti(nonce))
log.debug("Got ResPq: {}".format(res_pq.server_nonce))
+ log.debug("Server public key fingerprints: {}".format(res_pq.server_public_key_fingerprints))
+
+ for i in res_pq.server_public_key_fingerprints:
+ if i in RSA.server_public_keys:
+ log.debug("Using fingerprint: {}".format(i))
+ public_key_fingerprint = i
+ break
+ else:
+ log.debug("Fingerprint unknown: {}".format(i))
+ else:
+ raise Exception("Public key not found")
# Step 3
pq = int.from_bytes(res_pq.pq, "big")
@@ -118,7 +129,7 @@ class Auth:
sha = sha1(data).digest()
padding = urandom(- (len(data) + len(sha)) % 255)
data_with_hash = sha + data + padding
- encrypted_data = RSA.encrypt(data_with_hash, res_pq.server_public_key_fingerprints[0])
+ encrypted_data = RSA.encrypt(data_with_hash, public_key_fingerprint)
log.debug("Done encrypt data with RSA")
@@ -130,7 +141,7 @@ class Auth:
server_nonce,
int.to_bytes(p, 4, "big"),
int.to_bytes(q, 4, "big"),
- res_pq.server_public_key_fingerprints[0],
+ public_key_fingerprint,
encrypted_data
)
)
From 6b6122be9286a9d6ff26638aaa22803608164ce3 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:23:48 +0100
Subject: [PATCH 10/17] Add progress parameter
---
pyrogram/client/client.py | 45 ++++++++++++++++++++++++++-------------
1 file changed, 30 insertions(+), 15 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 9dd7377d..5360693e 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1014,7 +1014,8 @@ class Client:
parse_mode: str = "",
ttl_seconds: int = None,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send photos.
Args:
@@ -1054,7 +1055,7 @@ class Client:
:class:`pyrogram.Error`
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
- file = self.save_file(photo)
+ file = self.save_file(photo, progress=progress)
while True:
try:
@@ -1085,7 +1086,8 @@ class Client:
performer: str = None,
title: str = None,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send audio files.
For sending voice messages, use the :obj:`send_voice` method instead.
@@ -1131,7 +1133,7 @@ class Client:
:class:`pyrogram.Error`
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
- file = self.save_file(audio)
+ file = self.save_file(audio, progress=progress)
while True:
try:
@@ -1167,7 +1169,8 @@ class Client:
caption: str = "",
parse_mode: str = "",
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send general files.
Args:
@@ -1202,7 +1205,7 @@ class Client:
:class:`pyrogram.Error`
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
- file = self.save_file(document)
+ file = self.save_file(document, progress=progress)
while True:
try:
@@ -1231,7 +1234,8 @@ class Client:
chat_id: int or str,
sticker: str,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send .webp stickers.
Args:
@@ -1257,7 +1261,7 @@ class Client:
Raises:
:class:`pyrogram.Error`
"""
- file = self.save_file(sticker)
+ file = self.save_file(sticker, progress=progress)
while True:
try:
@@ -1293,7 +1297,8 @@ class Client:
thumb: str = None,
supports_streaming: bool = None,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send video files.
Args:
@@ -1345,7 +1350,7 @@ class Client:
:class:`pyrogram.Error`
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
- file = self.save_file(video)
+ file = self.save_file(video, progress=progress)
file_thumb = None if thumb is None else self.save_file(thumb)
while True:
@@ -1385,7 +1390,8 @@ class Client:
parse_mode: str = "",
duration: int = 0,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send audio files.
Args:
@@ -1423,7 +1429,7 @@ class Client:
:class:`pyrogram.Error`
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
- file = self.save_file(voice)
+ file = self.save_file(voice, progress=progress)
while True:
try:
@@ -1457,7 +1463,8 @@ class Client:
duration: int = 0,
length: int = 1,
disable_notification: bool = None,
- reply_to_message_id: int = None):
+ reply_to_message_id: int = None,
+ progress: callable = None):
"""Use this method to send video messages.
Args:
@@ -1489,7 +1496,7 @@ class Client:
Raises:
:class:`pyrogram.Error`
"""
- file = self.save_file(video_note)
+ file = self.save_file(video_note, progress=progress)
while True:
try:
@@ -1519,6 +1526,7 @@ class Client:
else:
return r
+ # TODO: Add progress parameter
def send_media_group(self,
chat_id: int or str,
media: list,
@@ -1973,7 +1981,11 @@ class Client:
)
# TODO: Remove redundant code
- def save_file(self, path: str, file_id: int = None, file_part: int = 0):
+ def save_file(self,
+ path: str,
+ file_id: int = None,
+ file_part: int = 0,
+ progress: callable = None):
part_size = 512 * 1024
file_size = os.path.getsize(path)
file_total_parts = math.ceil(file_size / part_size)
@@ -2013,6 +2025,9 @@ class Client:
md5_sum.update(chunk)
file_part += 1
+
+ if progress:
+ progress(file_part * part_size, file_size)
except Exception as e:
log.error(e)
else:
From b5c7cf781adc15da51198c58c03c2b3c7dac9327 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:25:10 +0100
Subject: [PATCH 11/17] Document the progress parameter
---
pyrogram/client/client.py | 77 +++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 5360693e..bbf1263d 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1048,6 +1048,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message.
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1126,6 +1137,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message.
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1198,6 +1220,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message.
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1255,6 +1288,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message.
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1343,6 +1387,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message.
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1422,6 +1477,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
@@ -1490,6 +1556,17 @@ class Client:
reply_to_message_id (:obj:`int`, optional):
If the message is a reply, ID of the original message
+ progress (:obj:`callable`):
+ Pass a callback function to view the upload progress.
+ The function must accept two arguments (progress, total).
+
+ Other Parameters:
+ progress (:obj:`int`):
+ The amount of bytes uploaded so far.
+
+ total (:obj:`int`):
+ The size of the file.
+
Returns:
On success, the sent Message is returned.
From 27a96a0df421861b36ae30e4e63284d8a9d3b389 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:31:34 +0100
Subject: [PATCH 12/17] Fix progress going over 100%
---
pyrogram/client/client.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index bbf1263d..d97ae0d9 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -2104,7 +2104,7 @@ class Client:
file_part += 1
if progress:
- progress(file_part * part_size, file_size)
+ progress(min(file_part * part_size, file_size), file_size)
except Exception as e:
log.error(e)
else:
@@ -2202,7 +2202,7 @@ class Client:
offset += limit
if progress:
- progress(offset, size)
+ progress(min(offset, size), size)
r = session.send(
functions.upload.GetFile(
From 859305b74463b1dd43e6b34edf4eeefae20fee1f Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 10:34:04 +0100
Subject: [PATCH 13/17] Update docstrings
---
pyrogram/client/client.py | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index d97ae0d9..b77644b4 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -1050,10 +1050,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1139,10 +1139,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1222,10 +1222,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1290,10 +1290,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1389,10 +1389,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1479,10 +1479,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -1558,10 +1558,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the upload progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes uploaded so far.
total (:obj:`int`):
@@ -2566,10 +2566,10 @@ class Client:
progress (:obj:`callable`):
Pass a callback function to view the download progress.
- The function must accept two arguments (progress, total).
+ The function must accept two arguments (current, total).
Other Parameters:
- progress (:obj:`int`):
+ current (:obj:`int`):
The amount of bytes downloaded so far.
total (:obj:`int`):
From f55062bc6d76c984bf0fa7cda993b264f2756e7e Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 8 Mar 2018 12:28:38 +0100
Subject: [PATCH 14/17] Add support for Bot API style basic group IDs (with
minus sign) Closes #32
---
pyrogram/client/client.py | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index b77644b4..5a834ee7 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -256,15 +256,16 @@ class Client:
if isinstance(entity, Chat):
chat_id = entity.id
+ peer_id = -chat_id
- if chat_id in self.peers_by_id:
+ if peer_id in self.peers_by_id:
continue
input_peer = InputPeerChat(
chat_id=chat_id
)
- self.peers_by_id[chat_id] = input_peer
+ self.peers_by_id[peer_id] = input_peer
if isinstance(entity, Channel):
channel_id = entity.id
@@ -886,17 +887,20 @@ class Client:
if isinstance(peer_id, types.PeerUser):
peer_id = peer_id.user_id
elif isinstance(peer_id, types.PeerChat):
- peer_id = peer_id.chat_id
+ peer_id = -peer_id.chat_id
elif isinstance(peer_id, types.PeerChannel):
peer_id = int("-100" + str(peer_id.channel_id))
- try:
+ try: # User
return self.peers_by_id[peer_id]
except KeyError:
- try:
- return self.peers_by_id[int("-100" + str(peer_id))]
+ try: # Chat
+ return self.peers_by_id[-peer_id]
except KeyError:
- raise PeerIdInvalid
+ try: # Channel
+ return self.peers_by_id[int("-100" + str(peer_id))]
+ except (KeyError, ValueError):
+ raise PeerIdInvalid
def get_me(self):
"""A simple method for testing the user authorization. Requires no parameters.
From 69f77cd1d751070af54062ba4e7af05642ace99e Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Fri, 9 Mar 2018 13:23:53 +0100
Subject: [PATCH 15/17] Add welcome_bot.py example
---
examples/README.md | 1 +
examples/welcome_bot.py | 52 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
create mode 100644 examples/welcome_bot.py
diff --git a/examples/README.md b/examples/README.md
index eda57be6..6f640ef4 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -13,3 +13,4 @@ you have to change are the target chats (username, id) and file paths for sendin
- [**simple_echo.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/simple_echo.py)
- [**advanced_echo.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/advanced_echo.py)
- [**advanced_echo2.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/advanced_echo2.py)
+- [**welcome_bot.py**](https://github.com/pyrogram/pyrogram/blob/master/examples/welcome_bot.py)
diff --git a/examples/welcome_bot.py b/examples/welcome_bot.py
new file mode 100644
index 00000000..d2e00a88
--- /dev/null
+++ b/examples/welcome_bot.py
@@ -0,0 +1,52 @@
+from pyrogram import Client, Emoji
+from pyrogram.api import types
+
+"""
+This is the Welcome Bot in @PyrogramChat
+The code is commented to help you understand each part
+
+It also uses the Emoji module to easily add emojis in your text messages
+"""
+
+# Your Supergroup ID
+SUPERGROUP_ID = 1387666944
+
+
+def update_handler(client, update, users, chats):
+ # Supergroup messages are contained in the "UpdateNewChannelMessage" update type
+ if isinstance(update, types.UpdateNewChannelMessage):
+ message = update.message
+ # When a user joins, a "MessageService" is received
+ if isinstance(message, types.MessageService):
+ # Check if the message is sent to your SUPERGROUP_ID
+ if message.to_id.channel_id == SUPERGROUP_ID:
+ # A "MessageService" contains the "action" field.
+ # The action for user joins is "MessageActionChatAddUser" if the user
+ # joined using the username, otherwise is "MessageActionChatJoinedByLink" if
+ # the user joined a private group by link
+ if isinstance(message.action, (types.MessageActionChatAddUser, types.MessageActionChatJoinedByLink)):
+ # Now send the welcome message. Extra info about a user (such as the first_name, username, ...)
+ # are contained in the users dictionary and can be accessed by the user ID
+ client.send_message(
+ SUPERGROUP_ID,
+ "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s "
+ "group chat, [{}](tg://user?id={})!".format(
+ Emoji.SPARKLES, # Add an emoji
+ users[message.from_id].first_name,
+ users[message.from_id].id
+ ),
+ reply_to_message_id=message.id,
+ disable_web_page_preview=True
+ )
+
+
+def main():
+ client = Client("example")
+ client.set_update_handler(update_handler)
+
+ client.start()
+ client.idle()
+
+
+if __name__ == "__main__":
+ main()
From ca54b62f636b8b1fa3b50517682079410eb6cff9 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sat, 10 Mar 2018 15:21:31 +0100
Subject: [PATCH 16/17] Strip "+" away from phone numbers when logging in
---
pyrogram/client/client.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 5a834ee7..b382a1fd 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -572,6 +572,8 @@ class Client:
elif confirm in ("n", "2"):
self.phone_number = input("Enter phone number: ")
+ self.phone_number = self.phone_number.strip("+")
+
try:
r = self.send(
functions.auth.SendCode(
From 62e67f5257e1b49efa69ac309662ff52689d1bc4 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 11 Mar 2018 17:16:38 +0100
Subject: [PATCH 17/17] Add get_messages method
---
pyrogram/client/client.py | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index b382a1fd..e554ae3a 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -2754,3 +2754,39 @@ class Client:
reply_to_msg_id=reply_to_message_id
)
)
+
+ def get_messages(self,
+ chat_id: int or str,
+ message_ids: list):
+ """Use this method to get messages that belong to a specific chat.
+ You can retrieve up to 200 messages at once.
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`):
+ Unique identifier for the target chat or username of the target channel/supergroup
+ (in the format @username). For your personal cloud storage (Saved Messages) you can
+ simply use "me" or "self". Phone numbers that exist in your Telegram address book are also supported.
+
+ message_ids (:obj:`list`):
+ A list of Message identifiers in the chat specified in *chat_id*.
+
+ Returns:
+ List of the requested messages
+
+ Raises:
+ :class:`pyrogram.Error`
+ """
+ peer = self.resolve_peer(chat_id)
+ message_ids = [types.InputMessageID(i) for i in message_ids]
+
+ if isinstance(peer, types.InputPeerChannel):
+ rpc = functions.channels.GetMessages(
+ channel=peer,
+ id=message_ids
+ )
+ else:
+ rpc = functions.messages.GetMessages(
+ id=message_ids
+ )
+
+ return self.send(rpc)