mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-29 13:27:47 +00:00
Merge branch 'develop' into other_start
This commit is contained in:
commit
31960d0272
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,6 +11,9 @@ pyrogram/api/all.py
|
|||||||
# PyCharm stuff
|
# PyCharm stuff
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
@ -78,6 +81,7 @@ instance/
|
|||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
|
docs/source/_build
|
||||||
|
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
target/
|
target/
|
||||||
|
@ -478,7 +478,6 @@ def start():
|
|||||||
|
|
||||||
f.write("\n 0xbc799737: \"pyrogram.api.core.BoolFalse\",")
|
f.write("\n 0xbc799737: \"pyrogram.api.core.BoolFalse\",")
|
||||||
f.write("\n 0x997275b5: \"pyrogram.api.core.BoolTrue\",")
|
f.write("\n 0x997275b5: \"pyrogram.api.core.BoolTrue\",")
|
||||||
f.write("\n 0x56730bcc: \"pyrogram.api.core.Null\",")
|
|
||||||
f.write("\n 0x1cb5c415: \"pyrogram.api.core.Vector\",")
|
f.write("\n 0x1cb5c415: \"pyrogram.api.core.Vector\",")
|
||||||
f.write("\n 0x73f1f8dc: \"pyrogram.api.core.MsgContainer\",")
|
f.write("\n 0x73f1f8dc: \"pyrogram.api.core.MsgContainer\",")
|
||||||
f.write("\n 0xae500895: \"pyrogram.api.core.FutureSalts\",")
|
f.write("\n 0xae500895: \"pyrogram.api.core.FutureSalts\",")
|
||||||
|
@ -1364,7 +1364,4 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
|
|||||||
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
|
||||||
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
folders.deleteFolder#1c295881 folder_id:int = Updates;
|
||||||
|
|
||||||
// LAYER 103
|
// LAYER 103
|
||||||
|
|
||||||
// Ports
|
|
||||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
|
@ -53,6 +53,15 @@ ipPortSecret#37982646 ipv4:int port:int secret:bytes = IpPort;
|
|||||||
accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector<IpPort> = AccessPointRule;
|
accessPointRule#4679b65f phone_prefix_rules:string dc_id:int ips:vector<IpPort> = AccessPointRule;
|
||||||
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
|
help.configSimple#5a592a6c date:int expires:int rules:vector<AccessPointRule> = help.ConfigSimple;
|
||||||
|
|
||||||
|
// tlsClientHello blocks:vector<TlsBlock> = TlsClientHello;
|
||||||
|
//
|
||||||
|
// tlsBlockString data:string = TlsBlock;
|
||||||
|
// tlsBlockRandom length:int = TlsBlock;
|
||||||
|
// tlsBlockZero length:int = TlsBlock;
|
||||||
|
// tlsBlockDomain = TlsBlock;
|
||||||
|
// tlsBlockGrease seed:int = TlsBlock;
|
||||||
|
// tlsBlockScope entries:Vector<TlsBlock> = TlsBlock;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
|
rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
|
||||||
|
@ -136,6 +136,7 @@ def pyrogram_api():
|
|||||||
remove_handler
|
remove_handler
|
||||||
stop_transmission
|
stop_transmission
|
||||||
export_session_string
|
export_session_string
|
||||||
|
set_parse_mode
|
||||||
""",
|
""",
|
||||||
messages="""
|
messages="""
|
||||||
Messages
|
Messages
|
||||||
@ -145,7 +146,6 @@ def pyrogram_api():
|
|||||||
send_audio
|
send_audio
|
||||||
send_document
|
send_document
|
||||||
send_sticker
|
send_sticker
|
||||||
send_animated_sticker
|
|
||||||
send_video
|
send_video
|
||||||
send_animation
|
send_animation
|
||||||
send_voice
|
send_voice
|
||||||
@ -189,6 +189,7 @@ def pyrogram_api():
|
|||||||
delete_chat_photo
|
delete_chat_photo
|
||||||
set_chat_title
|
set_chat_title
|
||||||
set_chat_description
|
set_chat_description
|
||||||
|
set_chat_permissions
|
||||||
pin_chat_message
|
pin_chat_message
|
||||||
unpin_chat_message
|
unpin_chat_message
|
||||||
get_chat
|
get_chat
|
||||||
@ -199,10 +200,15 @@ def pyrogram_api():
|
|||||||
get_dialogs
|
get_dialogs
|
||||||
iter_dialogs
|
iter_dialogs
|
||||||
get_dialogs_count
|
get_dialogs_count
|
||||||
restrict_chat
|
|
||||||
update_chat_username
|
update_chat_username
|
||||||
archive_chats
|
archive_chats
|
||||||
unarchive_chats
|
unarchive_chats
|
||||||
|
add_chat_members
|
||||||
|
create_channel
|
||||||
|
create_group
|
||||||
|
create_supergroup
|
||||||
|
delete_channel
|
||||||
|
delete_supergroup
|
||||||
""",
|
""",
|
||||||
users="""
|
users="""
|
||||||
Users
|
Users
|
||||||
@ -334,6 +340,8 @@ def pyrogram_api():
|
|||||||
InlineQuery
|
InlineQuery
|
||||||
InlineQueryResult
|
InlineQueryResult
|
||||||
InlineQueryResultArticle
|
InlineQueryResultArticle
|
||||||
|
InlineQueryResultPhoto
|
||||||
|
InlineQueryResultAnimation
|
||||||
""",
|
""",
|
||||||
input_message_content="""
|
input_message_content="""
|
||||||
InputMessageContent
|
InputMessageContent
|
||||||
@ -412,11 +420,15 @@ def pyrogram_api():
|
|||||||
Chat.unban_member
|
Chat.unban_member
|
||||||
Chat.restrict_member
|
Chat.restrict_member
|
||||||
Chat.promote_member
|
Chat.promote_member
|
||||||
|
Chat.join
|
||||||
|
Chat.leave
|
||||||
""",
|
""",
|
||||||
user="""
|
user="""
|
||||||
User
|
User
|
||||||
User.archive
|
User.archive
|
||||||
User.unarchive
|
User.unarchive
|
||||||
|
User.block
|
||||||
|
User.unblock
|
||||||
""",
|
""",
|
||||||
callback_query="""
|
callback_query="""
|
||||||
Callback Query
|
Callback Query
|
||||||
|
@ -113,4 +113,13 @@ FILE_PART_TOO_BIG The size limit (512 KB) for the content of the file part has b
|
|||||||
FILE_PART_EMPTY The file part sent is empty
|
FILE_PART_EMPTY The file part sent is empty
|
||||||
FILE_PART_SIZE_INVALID 512 KB cannot be evenly divided by part_size
|
FILE_PART_SIZE_INVALID 512 KB cannot be evenly divided by part_size
|
||||||
FILE_PART_SIZE_CHANGED The part size is different from the size of one of the previous parts in the same file
|
FILE_PART_SIZE_CHANGED The part size is different from the size of one of the previous parts in the same file
|
||||||
FILE_MIGRATE_X The file is in Data Center No. {x}
|
FILE_MIGRATE_X The file is in Data Center No. {x}
|
||||||
|
RESULT_TYPE_INVALID The result type is invalid
|
||||||
|
PHOTO_THUMB_URL_EMPTY The photo thumb URL is empty
|
||||||
|
PHOTO_THUMB_URL_INVALID The photo thumb URL is invalid
|
||||||
|
PHOTO_CONTENT_URL_EMPTY The photo content URL is empty
|
||||||
|
PHOTO_CONTENT_TYPE_INVALID The photo content type is invalid
|
||||||
|
WEBDOCUMENT_INVALID The web document is invalid
|
||||||
|
WEBDOCUMENT_URL_EMPTY The web document URL is empty
|
||||||
|
WEBDOCUMENT_URL_INVALID The web document URL is invalid
|
||||||
|
WEBDOCUMENT_MIME_INVALID The web document mime type is invalid
|
|
@ -144,7 +144,8 @@ I started a client and nothing happens!
|
|||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
|
||||||
partially or totally blocked in those countries.
|
partially or totally blocked in those countries. More information about this block can be found at
|
||||||
|
`Wikipedia <https://en.wikipedia.org/wiki/Blocking_Telegram_in_Russia>`_.
|
||||||
|
|
||||||
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
|
||||||
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
|
||||||
@ -161,9 +162,9 @@ fails or not.
|
|||||||
What are the IP addresses of Telegram Data Centers?
|
What are the IP addresses of Telegram Data Centers?
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
The Telegram cloud is currently composed by a decentralized, multi-DC infrastructure (each of which can work
|
The Telegram cloud is currently composed by a decentralized, multi-DC infrastructure (currently 5 DCs, each of which can
|
||||||
independently) spread in 5 different locations. However, some of the less busy DCs have been lately dismissed and their
|
work independently) spread in different locations worldwide. However, some of the less busy DCs have been lately
|
||||||
IP addresses are now kept as aliases.
|
dismissed and their IP addresses are now kept as aliases to the nearest one.
|
||||||
|
|
||||||
.. csv-table:: Production Environment
|
.. csv-table:: Production Environment
|
||||||
:header: ID, Location, IPv4, IPv6
|
:header: ID, Location, IPv4, IPv6
|
||||||
@ -191,7 +192,6 @@ IP addresses are now kept as aliases.
|
|||||||
|
|
||||||
Thanks to `@FrayxRulez <https://t.me/tgbetachat/104921>`_ for telling about alias DCs.
|
Thanks to `@FrayxRulez <https://t.me/tgbetachat/104921>`_ for telling about alias DCs.
|
||||||
|
|
||||||
|
|
||||||
I want to migrate my account from DCX to DCY.
|
I want to migrate my account from DCX to DCY.
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
@ -245,9 +245,13 @@ The error in question is ``[400 PEER_ID_INVALID]``, and could mean several thing
|
|||||||
|
|
||||||
- The chat id you tried to use is simply wrong, double check it.
|
- The chat id you tried to use is simply wrong, double check it.
|
||||||
- The chat id refers to a group or channel you are not a member of.
|
- The chat id refers to a group or channel you are not a member of.
|
||||||
- The chat id refers to a user you have't seen yet (from contacts, groups in common, forwarded messages or private
|
|
||||||
chats).
|
|
||||||
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
|
||||||
|
- The chat id refers to a user your current session haven't met yet.
|
||||||
|
|
||||||
|
About the last point: in order for you to meet a user and thus communicate with them, you should ask yourself how to
|
||||||
|
contact people using official apps. The answer is the same for Pyrogram too and involves normal usages such as searching
|
||||||
|
for usernames, meet them in a common group, have their phone contacts saved, getting a message mentioning them (either a
|
||||||
|
forward or a mention in the message text).
|
||||||
|
|
||||||
UnicodeEncodeError: '<encoding>' codec can't encode …
|
UnicodeEncodeError: '<encoding>' codec can't encode …
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
@ -257,6 +261,14 @@ shows up when you try to print something and has very little to do with Pyrogram
|
|||||||
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
|
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
|
||||||
better terminal altogether.
|
better terminal altogether.
|
||||||
|
|
||||||
|
Uploading with URLs gives error WEBPAGE_CURL_FAILED
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
When uploading media files using an URL, the server automatically tries to download the media and uploads it to the
|
||||||
|
Telegram cloud. This error usually happens in case the provided URL is not publicly accessible by Telegram itself or the
|
||||||
|
media exceeds 20 MB in size. In such cases, your only option is to download the media yourself and upload from your
|
||||||
|
local machine.
|
||||||
|
|
||||||
My verification code expires immediately!
|
My verification code expires immediately!
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
@ -45,8 +45,9 @@ Welcome to Pyrogram
|
|||||||
topics/tgcrypto
|
topics/tgcrypto
|
||||||
topics/storage-engines
|
topics/storage-engines
|
||||||
topics/text-formatting
|
topics/text-formatting
|
||||||
topics/serialize
|
topics/serializing
|
||||||
topics/proxy
|
topics/proxy
|
||||||
|
topics/scheduling
|
||||||
topics/bots-interaction
|
topics/bots-interaction
|
||||||
topics/mtproto-vs-botapi
|
topics/mtproto-vs-botapi
|
||||||
topics/debugging
|
topics/debugging
|
||||||
|
87
docs/source/topics/scheduling.rst
Normal file
87
docs/source/topics/scheduling.rst
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
Scheduling Tasks
|
||||||
|
================
|
||||||
|
|
||||||
|
Scheduling tasks means executing one or more functions periodically at pre-defined intervals or after a delay. This is
|
||||||
|
useful, for example, to send recurring messages to specific chats or users.
|
||||||
|
|
||||||
|
Since there's no built-in task scheduler in Pyrogram, this page will only show examples on how to integrate Pyrogram
|
||||||
|
with the main Python schedule libraries such as ``schedule`` and ``apscheduler``. For more detailed information, you can
|
||||||
|
visit and learn from each library documentation.
|
||||||
|
|
||||||
|
Using ``schedule``
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Install with ``pip3 install schedule``
|
||||||
|
- Documentation: https://schedule.readthedocs.io
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
import schedule
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
def job():
|
||||||
|
app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
schedule.every(3).seconds.do(job)
|
||||||
|
|
||||||
|
with app:
|
||||||
|
while True:
|
||||||
|
schedule.run_pending()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Using ``apscheduler``
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Install with ``pip3 install apscheduler``
|
||||||
|
- Documentation: https://apscheduler.readthedocs.io
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
def job():
|
||||||
|
app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
scheduler = BackgroundScheduler()
|
||||||
|
scheduler.add_job(job, "interval", seconds=3)
|
||||||
|
|
||||||
|
scheduler.start()
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
``apscheduler`` does also support async code, here's an example with
|
||||||
|
`Pyrogram Asyncio <https://docs.pyrogram.org/intro/install.html#asynchronous>`_:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
|
async def job():
|
||||||
|
await app.send_message("me", "Hi!")
|
||||||
|
|
||||||
|
|
||||||
|
scheduler = AsyncIOScheduler()
|
||||||
|
scheduler.add_job(job, "interval", seconds=3)
|
||||||
|
|
||||||
|
scheduler.start()
|
||||||
|
app.run()
|
||||||
|
|
@ -316,9 +316,9 @@ attribute. Here's an example:
|
|||||||
Unloading
|
Unloading
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
In order to unload a plugin, all you need to do is obtain a reference to it by importing the relevant module and call
|
||||||
relevant module and call :meth:`~pyrogram.Client.remove_handler` Client's method with your function
|
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* special attribute preceded by the
|
||||||
name preceded by the star ``*`` operator as argument. Example:
|
star ``*`` operator as argument. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
|
|
||||||
@ -328,14 +328,14 @@ name preceded by the star ``*`` operator as argument. Example:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
app.remove_handler(*echo)
|
app.remove_handler(*echo.handler)
|
||||||
|
|
||||||
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
||||||
exactly what is needed. The same could have been achieved with:
|
exactly what is needed. The same could have been achieved with:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
handler, group = echo
|
handler, group = echo.handler
|
||||||
app.remove_handler(handler, group)
|
app.remove_handler(handler, group)
|
||||||
|
|
||||||
Loading
|
Loading
|
||||||
@ -352,4 +352,4 @@ using :meth:`~pyrogram.Client.add_handler` instead. Example:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
app.add_handler(*echo)
|
app.add_handler(*echo.handler)
|
@ -19,8 +19,7 @@
|
|||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
from .all import objects
|
from .all import objects
|
||||||
from .core.tl_object import TLObject
|
|
||||||
|
|
||||||
for k, v in objects.items():
|
for k, v in objects.items():
|
||||||
path, name = v.rsplit(".", 1)
|
path, name = v.rsplit(".", 1)
|
||||||
TLObject.all[k] = getattr(import_module(path), name)
|
objects[k] = getattr(import_module(path), name)
|
||||||
|
@ -22,8 +22,5 @@ from .gzip_packed import GzipPacked
|
|||||||
from .list import List
|
from .list import List
|
||||||
from .message import Message
|
from .message import Message
|
||||||
from .msg_container import MsgContainer
|
from .msg_container import MsgContainer
|
||||||
from .primitives import (
|
from .primitives import *
|
||||||
Bool, BoolTrue, BoolFalse, Bytes, Double,
|
|
||||||
Int, Long, Int128, Int256, Null, String, Vector
|
|
||||||
)
|
|
||||||
from .tl_object import TLObject
|
from .tl_object import TLObject
|
||||||
|
@ -16,10 +16,11 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .bool import Bool, BoolTrue, BoolFalse
|
from .bool import Bool, BoolFalse, BoolTrue
|
||||||
from .bytes import Bytes
|
from .bytes import Bytes
|
||||||
from .double import Double
|
from .double import Double
|
||||||
from .int import Int, Long, Int128, Int256
|
from .int import Int, Long, Int128, Int256
|
||||||
from .null import Null
|
|
||||||
from .string import String
|
from .string import String
|
||||||
from .vector import Vector
|
from .vector import Vector
|
||||||
|
|
||||||
|
__all__ = ["Bool", "BoolFalse", "BoolTrue", "Bytes", "Double", "Int", "Long", "Int128", "Int256", "String", "Vector"]
|
||||||
|
@ -20,17 +20,17 @@ from collections import OrderedDict
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
|
from ..all import objects
|
||||||
|
|
||||||
|
|
||||||
class TLObject:
|
class TLObject:
|
||||||
all = {}
|
|
||||||
|
|
||||||
__slots__ = []
|
__slots__ = []
|
||||||
|
|
||||||
QUALNAME = "Base"
|
QUALNAME = "Base"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, *args): # TODO: Rename b -> data
|
def read(b: BytesIO, *args): # TODO: Rename b -> data
|
||||||
return TLObject.all[int.from_bytes(b.read(4), "little")].read(b, *args)
|
return objects[int.from_bytes(b.read(4), "little")].read(b, *args)
|
||||||
|
|
||||||
def write(self, *args) -> bytes:
|
def write(self, *args) -> bytes:
|
||||||
pass
|
pass
|
||||||
|
@ -174,6 +174,17 @@ class Client(Methods, BaseClient):
|
|||||||
download_media, ...) are less prone to throw FloodWait exceptions.
|
download_media, ...) are less prone to throw FloodWait exceptions.
|
||||||
Only available for users, bots will ignore this parameter.
|
Only available for users, bots will ignore this parameter.
|
||||||
Defaults to False (normal session).
|
Defaults to False (normal session).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
with app:
|
||||||
|
app.send_message("me", "Hi!")
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
terms_of_service_displayed = False
|
terms_of_service_displayed = False
|
||||||
@ -619,11 +630,28 @@ class Client(Methods, BaseClient):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start the Client.
|
"""Start the client.
|
||||||
|
|
||||||
|
This method connects the client to Telegram and, in case of new sessions, automatically manages the full login
|
||||||
|
process using an interactive prompt (by default).
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ConnectionError: In case you try to start an already started client.
|
||||||
ConnectionError: In case you try to start an already started Client.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 4
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
app.start()
|
||||||
|
|
||||||
|
... # Call API methods
|
||||||
|
|
||||||
|
app.stop()
|
||||||
"""
|
"""
|
||||||
if self.is_started:
|
if self.is_started:
|
||||||
raise ConnectionError("Client has already been started")
|
raise ConnectionError("Client has already been started")
|
||||||
@ -696,8 +724,25 @@ class Client(Methods, BaseClient):
|
|||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop the Client.
|
"""Stop the Client.
|
||||||
|
|
||||||
|
This method disconnects the client from Telegram and stops the underlying tasks.
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ConnectionError: In case you try to stop an already stopped Client.
|
ConnectionError: In case you try to stop an already stopped client.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
app.start()
|
||||||
|
|
||||||
|
... # Call API methods
|
||||||
|
|
||||||
|
app.stop()
|
||||||
"""
|
"""
|
||||||
if not self.is_started:
|
if not self.is_started:
|
||||||
raise ConnectionError("Client is already stopped")
|
raise ConnectionError("Client is already stopped")
|
||||||
@ -738,64 +783,125 @@ class Client(Methods, BaseClient):
|
|||||||
def restart(self):
|
def restart(self):
|
||||||
"""Restart the Client.
|
"""Restart the Client.
|
||||||
|
|
||||||
|
This method will first call :meth:`~Client.stop` and then :meth:`~Client.start` in a row in order to restart
|
||||||
|
a client using a single method.
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ConnectionError: In case you try to restart a stopped Client.
|
ConnectionError: In case you try to restart a stopped Client.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
app.start()
|
||||||
|
|
||||||
|
... # Call API methods
|
||||||
|
|
||||||
|
app.restart()
|
||||||
|
|
||||||
|
... # Call other API methods
|
||||||
|
|
||||||
|
app.stop()
|
||||||
"""
|
"""
|
||||||
self.stop()
|
self.stop()
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def idle(self, stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
|
@staticmethod
|
||||||
"""Block the main script execution until a signal (e.g.: from CTRL+C) is received.
|
def idle(stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
|
||||||
Once the signal is received, the client will automatically stop and the main script will continue its execution.
|
"""Block the main script execution until a signal is received.
|
||||||
|
|
||||||
This is used after starting one or more clients and is useful for event-driven applications only, that are,
|
This static method will run an infinite loop in order to block the main script execution and prevent it from
|
||||||
applications which react upon incoming Telegram updates through handlers, rather than executing a set of methods
|
exiting while having client(s) that are still running in the background.
|
||||||
sequentially.
|
|
||||||
|
|
||||||
The way Pyrogram works, will keep your handlers in a pool of workers, which are executed concurrently outside
|
It is useful for event-driven application only, that are, applications which react upon incoming Telegram
|
||||||
the main script; calling idle() will ensure the client(s) will be kept alive by not letting the main script to
|
updates through handlers, rather than executing a set of methods sequentially.
|
||||||
end, until you decide to quit.
|
|
||||||
|
The way Pyrogram works, it will keep your handlers in a pool of worker threads, which are executed concurrently
|
||||||
|
outside the main thread; calling idle() will ensure the client(s) will be kept alive by not letting the main
|
||||||
|
script to end, until you decide to quit.
|
||||||
|
|
||||||
|
Once a signal is received (e.g.: from CTRL+C) the inner infinite loop will break and your main script will
|
||||||
|
continue. Don't forget to call :meth:`~Client.stop` for each running client before the script ends.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
stop_signals (``tuple``, *optional*):
|
stop_signals (``tuple``, *optional*):
|
||||||
Iterable containing signals the signal handler will listen to.
|
Iterable containing signals the signal handler will listen to.
|
||||||
Defaults to (SIGINT, SIGTERM, SIGABRT).
|
Defaults to *(SIGINT, SIGTERM, SIGABRT)*.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 13
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app1 = Client("account1")
|
||||||
|
app2 = Client("account2")
|
||||||
|
app3 = Client("account3")
|
||||||
|
|
||||||
|
... # Set handlers up
|
||||||
|
|
||||||
|
app1.start()
|
||||||
|
app2.start()
|
||||||
|
app3.start()
|
||||||
|
|
||||||
|
Client.idle()
|
||||||
|
|
||||||
|
app1.stop()
|
||||||
|
app2.stop()
|
||||||
|
app3.stop()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO: Maybe make this method static and don't automatically stop
|
|
||||||
|
|
||||||
def signal_handler(*args):
|
def signal_handler(*args):
|
||||||
self.is_idle = False
|
Client.is_idling = False
|
||||||
|
|
||||||
for s in stop_signals:
|
for s in stop_signals:
|
||||||
signal(s, signal_handler)
|
signal(s, signal_handler)
|
||||||
|
|
||||||
self.is_idle = True
|
Client.is_idling = True
|
||||||
|
|
||||||
while self.is_idle:
|
while Client.is_idling:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Start the Client and automatically idle the main script.
|
"""Start the client, idle the main script and finally stop the client.
|
||||||
|
|
||||||
This is a convenience method that literally just calls :meth:`~Client.start` and :meth:`~Client.idle`. It makes
|
This is a convenience method that calls :meth:`~Client.start`, :meth:`~Client.idle` and :meth:`~Client.stop` in
|
||||||
running a client less verbose, but is not suitable in case you want to run more than one client in a single main
|
sequence. It makes running a client less verbose, but is not suitable in case you want to run more than one
|
||||||
script, since :meth:`~Client.idle` will block.
|
client in a single main script, since idle() will block after starting the own client.
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ConnectionError: In case you try to run an already started client.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 7
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
... # Set handlers up
|
||||||
|
|
||||||
|
app.run()
|
||||||
"""
|
"""
|
||||||
self.start()
|
self.start()
|
||||||
self.idle()
|
Client.idle()
|
||||||
|
self.stop()
|
||||||
|
|
||||||
def add_handler(self, handler: Handler, group: int = 0):
|
def add_handler(self, handler: Handler, group: int = 0):
|
||||||
"""Register an update handler.
|
"""Register an update handler.
|
||||||
|
|
||||||
You can register multiple handlers, but at most one handler within a group
|
You can register multiple handlers, but at most one handler within a group will be used for a single update.
|
||||||
will be used for a single update. To handle the same update more than once, register
|
To handle the same update more than once, register your handler using a different group id (lower group id
|
||||||
your handler using a different group id (lower group id == higher priority).
|
== higher priority). This mechanism is explained in greater details at
|
||||||
|
:doc:`More on Updates <../../topics/more-on-updates>`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
handler (``Handler``):
|
handler (``Handler``):
|
||||||
@ -805,7 +911,22 @@ class Client(Methods, BaseClient):
|
|||||||
The group identifier, defaults to 0.
|
The group identifier, defaults to 0.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``tuple``: A tuple consisting of (handler, group).
|
``tuple``: A tuple consisting of *(handler, group)*.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
|
from pyrogram import Client, MessageHandler
|
||||||
|
|
||||||
|
def dump(client, message):
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
app.add_handler(MessageHandler(dump))
|
||||||
|
|
||||||
|
app.run()
|
||||||
"""
|
"""
|
||||||
if isinstance(handler, DisconnectHandler):
|
if isinstance(handler, DisconnectHandler):
|
||||||
self.disconnect_handler = handler.callback
|
self.disconnect_handler = handler.callback
|
||||||
@ -817,9 +938,8 @@ class Client(Methods, BaseClient):
|
|||||||
def remove_handler(self, handler: Handler, group: int = 0):
|
def remove_handler(self, handler: Handler, group: int = 0):
|
||||||
"""Remove a previously-registered update handler.
|
"""Remove a previously-registered update handler.
|
||||||
|
|
||||||
Make sure to provide the right group that the handler was added in. You can use
|
Make sure to provide the right group where the handler was added in. You can use the return value of the
|
||||||
the return value of the :meth:`~Client.add_handler` method, a tuple of (handler, group), and
|
:meth:`~Client.add_handler` method, a tuple of *(handler, group)*, and pass it directly.
|
||||||
pass it directly.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
handler (``Handler``):
|
handler (``Handler``):
|
||||||
@ -827,6 +947,24 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
group (``int``, *optional*):
|
group (``int``, *optional*):
|
||||||
The group identifier, defaults to 0.
|
The group identifier, defaults to 0.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 11
|
||||||
|
|
||||||
|
from pyrogram import Client, MessageHandler
|
||||||
|
|
||||||
|
def dump(client, message):
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
handler = app.add_handler(MessageHandler(dump))
|
||||||
|
|
||||||
|
# Starred expression to unpack (handler, group)
|
||||||
|
app.remove_handler(*handler)
|
||||||
|
|
||||||
|
app.run()
|
||||||
"""
|
"""
|
||||||
if isinstance(handler, DisconnectHandler):
|
if isinstance(handler, DisconnectHandler):
|
||||||
self.disconnect_handler = None
|
self.disconnect_handler = None
|
||||||
@ -835,10 +973,109 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
def stop_transmission(self):
|
def stop_transmission(self):
|
||||||
"""Stop downloading or uploading a file.
|
"""Stop downloading or uploading a file.
|
||||||
Must be called inside a progress callback function.
|
|
||||||
|
This method must be called inside a progress callback function in order to stop the transmission at the
|
||||||
|
desired time. The progress callback is called every time a file chunk is uploaded/downloaded.
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 9
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
# Example to stop transmission once the upload progress reaches 50%
|
||||||
|
# Useless in practice, but shows how to stop on command
|
||||||
|
def progress(client, current, total):
|
||||||
|
if (current * 100 / total) > 50:
|
||||||
|
client.stop_transmission()
|
||||||
|
|
||||||
|
with app:
|
||||||
|
app.send_document("me", "files.zip", progress=progress)
|
||||||
"""
|
"""
|
||||||
raise Client.StopTransmission
|
raise Client.StopTransmission
|
||||||
|
|
||||||
|
def export_session_string(self):
|
||||||
|
"""Export the current authorized session as a serialized string.
|
||||||
|
|
||||||
|
Session strings are useful for storing in-memory authorized sessions in a portable, serialized string.
|
||||||
|
More detailed information about session strings can be found at the dedicated page of
|
||||||
|
:doc:`Storage Engines <../../topics/storage-engines>`.
|
||||||
|
|
||||||
|
Has no parameters.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``str``: The session serialized into a printable, url-safe string.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 6
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
with app:
|
||||||
|
print(app.export_session_string())
|
||||||
|
"""
|
||||||
|
return self.storage.export_session_string()
|
||||||
|
|
||||||
|
def set_parse_mode(self, parse_mode: Union[str, None] = "combined"):
|
||||||
|
"""Set the parse mode to be used globally by the client.
|
||||||
|
|
||||||
|
When setting the parse mode with this method, all other methods having a *parse_mode* parameter will follow the
|
||||||
|
global value by default. The default value *"combined"* enables both Markdown and HTML styles to be used and
|
||||||
|
combined together.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
parse_mode (``str``):
|
||||||
|
The new parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
|
||||||
|
to force Markdown-only styles. *"html"* to force HTML-only styles. *None* to disable the parser
|
||||||
|
completely.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: In case the provided *parse_mode* is not a valid parse mode.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 10,14,18,22
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
with app:
|
||||||
|
# Default combined mode: Markdown + HTML
|
||||||
|
app.send_message("haskell", "1. **markdown** and <i>html</i>")
|
||||||
|
|
||||||
|
# Force Markdown-only, HTML is disabled
|
||||||
|
app.set_parse_mode("markdown")
|
||||||
|
app.send_message("haskell", "2. **markdown** and <i>html</i>")
|
||||||
|
|
||||||
|
# Force HTML-only, Markdown is disabled
|
||||||
|
app.set_parse_mode("html")
|
||||||
|
app.send_message("haskell", "3. **markdown** and <i>html</i>")
|
||||||
|
|
||||||
|
# Disable the parser completely
|
||||||
|
app.set_parse_mode(None)
|
||||||
|
app.send_message("haskell", "4. **markdown** and <i>html</i>")
|
||||||
|
|
||||||
|
# Bring back the default combined mode
|
||||||
|
app.set_parse_mode()
|
||||||
|
app.send_message("haskell", "5. **markdown** and <i>html</i>")
|
||||||
|
"""
|
||||||
|
|
||||||
|
if parse_mode not in self.PARSE_MODES:
|
||||||
|
raise ValueError('parse_mode must be one of {} or None. Not "{}"'.format(
|
||||||
|
", ".join('"{}"'.format(m) for m in self.PARSE_MODES[:-1]),
|
||||||
|
parse_mode
|
||||||
|
))
|
||||||
|
|
||||||
|
self.parse_mode = parse_mode
|
||||||
|
|
||||||
def authorize_bot(self):
|
def authorize_bot(self):
|
||||||
try:
|
try:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
@ -1128,7 +1365,7 @@ class Client(Methods, BaseClient):
|
|||||||
access_hash = 0
|
access_hash = 0
|
||||||
peer_type = "group"
|
peer_type = "group"
|
||||||
elif isinstance(peer, (types.Channel, types.ChannelForbidden)):
|
elif isinstance(peer, (types.Channel, types.ChannelForbidden)):
|
||||||
peer_id = int("-100" + str(peer.id))
|
peer_id = utils.get_channel_id(peer.id)
|
||||||
access_hash = peer.access_hash
|
access_hash = peer.access_hash
|
||||||
|
|
||||||
username = getattr(peer, "username", None)
|
username = getattr(peer, "username", None)
|
||||||
@ -1244,7 +1481,7 @@ class Client(Methods, BaseClient):
|
|||||||
try:
|
try:
|
||||||
diff = self.send(
|
diff = self.send(
|
||||||
functions.updates.GetChannelDifference(
|
functions.updates.GetChannelDifference(
|
||||||
channel=self.resolve_peer(int("-100" + str(channel_id))),
|
channel=self.resolve_peer(utils.get_channel_id(channel_id)),
|
||||||
filter=types.ChannelMessagesFilter(
|
filter=types.ChannelMessagesFilter(
|
||||||
ranges=[types.MessageRange(
|
ranges=[types.MessageRange(
|
||||||
min_id=update.message.id,
|
min_id=update.message.id,
|
||||||
@ -1420,7 +1657,7 @@ class Client(Methods, BaseClient):
|
|||||||
])
|
])
|
||||||
|
|
||||||
if session_empty:
|
if session_empty:
|
||||||
self.storage.dc_id = 1
|
self.storage.dc_id = 4
|
||||||
self.storage.date = 0
|
self.storage.date = 0
|
||||||
|
|
||||||
self.storage.test_mode = self.test_mode
|
self.storage.test_mode = self.test_mode
|
||||||
@ -1456,7 +1693,7 @@ class Client(Methods, BaseClient):
|
|||||||
for name in vars(module).keys():
|
for name in vars(module).keys():
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
try:
|
try:
|
||||||
handler, group = getattr(module, name).pyrogram_plugin
|
handler, group = getattr(module, name).handler
|
||||||
|
|
||||||
if isinstance(handler, Handler) and isinstance(group, int):
|
if isinstance(handler, Handler) and isinstance(group, int):
|
||||||
self.add_handler(handler, group)
|
self.add_handler(handler, group)
|
||||||
@ -1491,7 +1728,7 @@ class Client(Methods, BaseClient):
|
|||||||
for name in handlers:
|
for name in handlers:
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
try:
|
try:
|
||||||
handler, group = getattr(module, name).pyrogram_plugin
|
handler, group = getattr(module, name).handler
|
||||||
|
|
||||||
if isinstance(handler, Handler) and isinstance(group, int):
|
if isinstance(handler, Handler) and isinstance(group, int):
|
||||||
self.add_handler(handler, group)
|
self.add_handler(handler, group)
|
||||||
@ -1529,7 +1766,7 @@ class Client(Methods, BaseClient):
|
|||||||
for name in handlers:
|
for name in handlers:
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
try:
|
try:
|
||||||
handler, group = getattr(module, name).pyrogram_plugin
|
handler, group = getattr(module, name).handler
|
||||||
|
|
||||||
if isinstance(handler, Handler) and isinstance(group, int):
|
if isinstance(handler, Handler) and isinstance(group, int):
|
||||||
self.remove_handler(handler, group)
|
self.remove_handler(handler, group)
|
||||||
@ -1632,33 +1869,38 @@ class Client(Methods, BaseClient):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise PeerIdInvalid
|
raise PeerIdInvalid
|
||||||
|
|
||||||
if peer_id > 0:
|
peer_type = utils.get_type(peer_id)
|
||||||
|
|
||||||
|
if peer_type == "user":
|
||||||
self.fetch_peers(
|
self.fetch_peers(
|
||||||
self.send(
|
self.send(
|
||||||
functions.users.GetUsers(
|
functions.users.GetUsers(
|
||||||
id=[types.InputUser(
|
id=[
|
||||||
user_id=peer_id,
|
types.InputUser(
|
||||||
access_hash=0
|
user_id=peer_id,
|
||||||
)]
|
access_hash=0
|
||||||
|
)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elif peer_type == "chat":
|
||||||
|
self.send(
|
||||||
|
functions.messages.GetChats(
|
||||||
|
id=[-peer_id]
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if str(peer_id).startswith("-100"):
|
self.send(
|
||||||
self.send(
|
functions.channels.GetChannels(
|
||||||
functions.channels.GetChannels(
|
id=[
|
||||||
id=[types.InputChannel(
|
types.InputChannel(
|
||||||
channel_id=int(str(peer_id)[4:]),
|
channel_id=utils.get_channel_id(peer_id),
|
||||||
access_hash=0
|
access_hash=0
|
||||||
)]
|
)
|
||||||
)
|
]
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.send(
|
|
||||||
functions.messages.GetChats(
|
|
||||||
id=[-peer_id]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self.storage.get_peer_by_id(peer_id)
|
return self.storage.get_peer_by_id(peer_id)
|
||||||
@ -1693,23 +1935,22 @@ class Client(Methods, BaseClient):
|
|||||||
In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
|
In case a file part expired, pass the file_id and the file_part to retry uploading that specific chunk.
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the upload progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes uploaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -2023,11 +2264,3 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
if extensions:
|
if extensions:
|
||||||
return extensions.split(" ")[0]
|
return extensions.split(" ")[0]
|
||||||
|
|
||||||
def export_session_string(self):
|
|
||||||
"""Export the current session as serialized string.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
``str``: The session serialized into a printable, url-safe string.
|
|
||||||
"""
|
|
||||||
return self.storage.export_session_string()
|
|
||||||
|
@ -59,6 +59,8 @@ class BaseClient:
|
|||||||
WORKDIR = PARENT_DIR
|
WORKDIR = PARENT_DIR
|
||||||
CONFIG_FILE = PARENT_DIR / "config.ini"
|
CONFIG_FILE = PARENT_DIR / "config.ini"
|
||||||
|
|
||||||
|
PARSE_MODES = ["combined", "markdown", "md", "html", None]
|
||||||
|
|
||||||
MEDIA_TYPE_ID = {
|
MEDIA_TYPE_ID = {
|
||||||
0: "photo_thumbnail",
|
0: "photo_thumbnail",
|
||||||
1: "chat_photo",
|
1: "chat_photo",
|
||||||
@ -87,19 +89,21 @@ class BaseClient:
|
|||||||
|
|
||||||
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
mime_types_to_extensions[mime_type] = " ".join(extensions)
|
||||||
|
|
||||||
|
is_idling = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.storage = None
|
self.storage = None
|
||||||
|
|
||||||
self.rnd_id = MsgId
|
self.rnd_id = MsgId
|
||||||
|
|
||||||
self.parser = Parser(self)
|
self.parser = Parser(self)
|
||||||
|
self.parse_mode = "combined"
|
||||||
|
|
||||||
self.session = None
|
self.session = None
|
||||||
self.media_sessions = {}
|
self.media_sessions = {}
|
||||||
self.media_sessions_lock = Lock()
|
self.media_sessions_lock = Lock()
|
||||||
|
|
||||||
self.is_started = None
|
self.is_started = None
|
||||||
self.is_idle = None
|
|
||||||
|
|
||||||
self.takeout_id = None
|
self.takeout_id = None
|
||||||
|
|
||||||
|
@ -166,8 +166,13 @@ class Dispatcher:
|
|||||||
args = None
|
args = None
|
||||||
|
|
||||||
if isinstance(handler, handler_type):
|
if isinstance(handler, handler_type):
|
||||||
if handler.check(parsed_update):
|
try:
|
||||||
args = (parsed_update,)
|
if handler.check(parsed_update):
|
||||||
|
args = (parsed_update,)
|
||||||
|
except Exception as e:
|
||||||
|
log.error(e, exc_info=True)
|
||||||
|
continue
|
||||||
|
|
||||||
elif isinstance(handler, RawUpdateHandler):
|
elif isinstance(handler, RawUpdateHandler):
|
||||||
args = (update, users, chats)
|
args = (update, users, chats)
|
||||||
|
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import struct
|
import struct
|
||||||
from typing import Union, List
|
from typing import List
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.api.types import PeerUser, PeerChat, PeerChannel
|
||||||
from . import BaseClient
|
from . import BaseClient
|
||||||
from ...api import types
|
from ...api import types
|
||||||
|
|
||||||
@ -30,10 +31,17 @@ def decode(s: str) -> bytes:
|
|||||||
s = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
|
s = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
|
||||||
r = b""
|
r = b""
|
||||||
|
|
||||||
assert s[-1] == 2
|
try:
|
||||||
|
assert s[-1] == 2
|
||||||
|
skip = 1
|
||||||
|
except AssertionError:
|
||||||
|
assert s[-2] == 22
|
||||||
|
assert s[-1] == 4
|
||||||
|
skip = 2
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(s) - 1:
|
|
||||||
|
while i < len(s) - skip:
|
||||||
if s[i] != 0:
|
if s[i] != 0:
|
||||||
r += bytes([s[i]])
|
r += bytes([s[i]])
|
||||||
else:
|
else:
|
||||||
@ -49,7 +57,7 @@ def encode(s: bytes) -> str:
|
|||||||
r = b""
|
r = b""
|
||||||
n = 0
|
n = 0
|
||||||
|
|
||||||
for i in s + bytes([2]):
|
for i in s + bytes([22]) + bytes([4]):
|
||||||
if i == 0:
|
if i == 0:
|
||||||
n += 1
|
n += 1
|
||||||
else:
|
else:
|
||||||
@ -62,23 +70,6 @@ def encode(s: bytes) -> str:
|
|||||||
return base64.urlsafe_b64encode(r).decode().rstrip("=")
|
return base64.urlsafe_b64encode(r).decode().rstrip("=")
|
||||||
|
|
||||||
|
|
||||||
def get_peer_id(input_peer) -> int:
|
|
||||||
return (
|
|
||||||
input_peer.user_id if isinstance(input_peer, types.InputPeerUser)
|
|
||||||
else -input_peer.chat_id if isinstance(input_peer, types.InputPeerChat)
|
|
||||||
else int("-100" + str(input_peer.channel_id))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_input_peer(peer_id: int, access_hash: int):
|
|
||||||
return (
|
|
||||||
types.InputPeerUser(user_id=peer_id, access_hash=access_hash) if peer_id > 0
|
|
||||||
else types.InputPeerChannel(channel_id=int(str(peer_id)[4:]), access_hash=access_hash)
|
|
||||||
if (str(peer_id).startswith("-100") and access_hash)
|
|
||||||
else types.InputPeerChat(chat_id=-peer_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_offset_date(dialogs):
|
def get_offset_date(dialogs):
|
||||||
for m in reversed(dialogs.messages):
|
for m in reversed(dialogs.messages):
|
||||||
if isinstance(m, types.MessageEmpty):
|
if isinstance(m, types.MessageEmpty):
|
||||||
@ -183,7 +174,7 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
|
|||||||
pyrogram.Message(
|
pyrogram.Message(
|
||||||
message_id=message,
|
message_id=message,
|
||||||
chat=pyrogram.Chat(
|
chat=pyrogram.Chat(
|
||||||
id=int("-100" + str(channel_id)),
|
id=get_channel_id(channel_id),
|
||||||
type="channel",
|
type="channel",
|
||||||
client=client
|
client=client
|
||||||
) if channel_id is not None else None,
|
) if channel_id is not None else None,
|
||||||
@ -203,3 +194,39 @@ def unpack_inline_message_id(inline_message_id: str) -> types.InputBotInlineMess
|
|||||||
id=r[1],
|
id=r[1],
|
||||||
access_hash=r[2]
|
access_hash=r[2]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MIN_CHANNEL_ID = -1002147483647
|
||||||
|
MAX_CHANNEL_ID = -1000000000000
|
||||||
|
MIN_CHAT_ID = -2147483647
|
||||||
|
MAX_USER_ID = 2147483647
|
||||||
|
|
||||||
|
|
||||||
|
def get_peer_id(peer: Union[PeerUser, PeerChat, PeerChannel]) -> int:
|
||||||
|
if isinstance(peer, PeerUser):
|
||||||
|
return peer.user_id
|
||||||
|
|
||||||
|
if isinstance(peer, PeerChat):
|
||||||
|
return -peer.chat_id
|
||||||
|
|
||||||
|
if isinstance(peer, PeerChannel):
|
||||||
|
return MAX_CHANNEL_ID - peer.channel_id
|
||||||
|
|
||||||
|
raise ValueError("Peer type invalid: {}".format(peer))
|
||||||
|
|
||||||
|
|
||||||
|
def get_type(peer_id: int) -> str:
|
||||||
|
if peer_id < 0:
|
||||||
|
if MIN_CHAT_ID <= peer_id:
|
||||||
|
return "chat"
|
||||||
|
|
||||||
|
if MIN_CHANNEL_ID <= peer_id < MAX_CHANNEL_ID:
|
||||||
|
return "channel"
|
||||||
|
elif 0 < peer_id <= MAX_USER_ID:
|
||||||
|
return "user"
|
||||||
|
|
||||||
|
raise ValueError("Peer id invalid: {}".format(peer_id))
|
||||||
|
|
||||||
|
|
||||||
|
def get_channel_id(peer_id: int) -> int:
|
||||||
|
return MAX_CHANNEL_ID - peer_id
|
||||||
|
@ -136,7 +136,7 @@ class Filters:
|
|||||||
poll = create(lambda _, m: m.poll, "PollFilter")
|
poll = create(lambda _, m: m.poll, "PollFilter")
|
||||||
"""Filter messages that contain :obj:`Poll` objects."""
|
"""Filter messages that contain :obj:`Poll` objects."""
|
||||||
|
|
||||||
private = create(lambda _, m: bool(m.chat and m.chat.type == "private"), "PrivateFilter")
|
private = create(lambda _, m: bool(m.chat and m.chat.type in {"private", "bot"}), "PrivateFilter")
|
||||||
"""Filter messages sent in private chats."""
|
"""Filter messages sent in private chats."""
|
||||||
|
|
||||||
group = create(lambda _, m: bool(m.chat and m.chat.type in {"group", "supergroup"}), "GroupFilter")
|
group = create(lambda _, m: bool(m.chat and m.chat.type in {"group", "supergroup"}), "GroupFilter")
|
||||||
@ -240,6 +240,7 @@ class Filters:
|
|||||||
|
|
||||||
def func(flt, message):
|
def func(flt, message):
|
||||||
text = message.text or message.caption
|
text = message.text or message.caption
|
||||||
|
message.command = None
|
||||||
|
|
||||||
if text:
|
if text:
|
||||||
for p in flt.p:
|
for p in flt.p:
|
||||||
@ -272,11 +273,15 @@ class Filters:
|
|||||||
RegEx flags.
|
RegEx flags.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def f(_, m):
|
def func(flt, message):
|
||||||
m.matches = [i for i in _.p.finditer(m.text or m.caption or "")]
|
text = message.text or message.caption
|
||||||
return bool(m.matches)
|
|
||||||
|
|
||||||
return create(f, "RegexFilter", p=re.compile(pattern, flags))
|
if text:
|
||||||
|
message.matches = list(flt.p.finditer(text)) or None
|
||||||
|
|
||||||
|
return bool(message.matches)
|
||||||
|
|
||||||
|
return create(func, "RegexFilter", p=re.compile(pattern, flags))
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class user(Filter, set):
|
class user(Filter, set):
|
||||||
|
@ -56,8 +56,14 @@ class AnswerCallbackQuery(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True, on success.
|
``bool``: True, on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Answer without alert
|
||||||
|
app.answer_callback_query(query_id, text=text)
|
||||||
|
|
||||||
|
# Answer with alert
|
||||||
|
app.answer_callback_query(query_id, text=text, show_alert=True)
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SetBotCallbackAnswer(
|
functions.messages.SetBotCallbackAnswer(
|
||||||
|
@ -29,28 +29,34 @@ class AnswerInlineQuery(BaseClient):
|
|||||||
inline_query_id: str,
|
inline_query_id: str,
|
||||||
results: List[InlineQueryResult],
|
results: List[InlineQueryResult],
|
||||||
cache_time: int = 300,
|
cache_time: int = 300,
|
||||||
is_personal: bool = None,
|
is_gallery: bool = False,
|
||||||
|
is_personal: bool = False,
|
||||||
next_offset: str = "",
|
next_offset: str = "",
|
||||||
switch_pm_text: str = "",
|
switch_pm_text: str = "",
|
||||||
switch_pm_parameter: str = ""
|
switch_pm_parameter: str = ""
|
||||||
):
|
):
|
||||||
"""Send answers to an inline query.
|
"""Send answers to an inline query.
|
||||||
No more than 50 results per query are allowed.
|
|
||||||
|
A maximum of 50 results per query is allowed.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inline_query_id (``str``):
|
inline_query_id (``str``):
|
||||||
Unique identifier for the answered query.
|
Unique identifier for the answered query.
|
||||||
|
|
||||||
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
results (List of :obj:`InlineQueryResult`):
|
||||||
A list of results for the inline query.
|
A list of results for the inline query.
|
||||||
|
|
||||||
cache_time (``int``, *optional*):
|
cache_time (``int``, *optional*):
|
||||||
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
||||||
Defaults to 300.
|
Defaults to 300.
|
||||||
|
|
||||||
|
is_gallery (``bool``, *optional*):
|
||||||
|
Pass True, if results should be displayed in gallery mode instead of list mode.
|
||||||
|
Defaults to False.
|
||||||
|
|
||||||
is_personal (``bool``, *optional*):
|
is_personal (``bool``, *optional*):
|
||||||
Pass True, if results may be cached on the server side only for the user that sent the query.
|
Pass True, if results may be cached on the server side only for the user that sent the query.
|
||||||
By default, results may be returned to any user who sends the same query.
|
By default (False), results may be returned to any user who sends the same query.
|
||||||
|
|
||||||
next_offset (``str``, *optional*):
|
next_offset (``str``, *optional*):
|
||||||
Pass the offset that a client should send in the next query with the same text to receive more results.
|
Pass the offset that a client should send in the next query with the same text to receive more results.
|
||||||
@ -75,15 +81,24 @@ class AnswerInlineQuery(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True, on success.
|
``bool``: True, on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InlineQueryResultArticle, InputTextMessageContent
|
||||||
|
|
||||||
|
app.answer_inline_query(
|
||||||
|
inline_query_id,
|
||||||
|
results=[
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
"Title",
|
||||||
|
InputTextMessageContent("Message content"))])
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SetInlineBotResults(
|
functions.messages.SetInlineBotResults(
|
||||||
query_id=int(inline_query_id),
|
query_id=int(inline_query_id),
|
||||||
results=[r.write() for r in results],
|
results=[r.write() for r in results],
|
||||||
cache_time=cache_time,
|
cache_time=cache_time,
|
||||||
gallery=None,
|
gallery=is_gallery or None,
|
||||||
private=is_personal or None,
|
private=is_personal or None,
|
||||||
next_offset=next_offset or None,
|
next_offset=next_offset or None,
|
||||||
switch_pm=types.InlineBotSwitchPM(
|
switch_pm=types.InlineBotSwitchPM(
|
||||||
|
@ -51,8 +51,11 @@ class GetGameHighScores(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`GameHighScore`: On success.
|
List of :obj:`GameHighScore`: On success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
scores = app.get_game_high_scores(user_id, chat_id, message_id)
|
||||||
|
print(scores)
|
||||||
"""
|
"""
|
||||||
# TODO: inline_message_id
|
# TODO: inline_message_id
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class GetInlineBotResults(BaseClient):
|
|||||||
def get_inline_bot_results(
|
def get_inline_bot_results(
|
||||||
self,
|
self,
|
||||||
bot: Union[int, str],
|
bot: Union[int, str],
|
||||||
query: str,
|
query: str = "",
|
||||||
offset: str = "",
|
offset: str = "",
|
||||||
latitude: float = None,
|
latitude: float = None,
|
||||||
longitude: float = None
|
longitude: float = None
|
||||||
@ -40,8 +40,9 @@ class GetInlineBotResults(BaseClient):
|
|||||||
Unique identifier of the inline bot you want to get results from. You can specify
|
Unique identifier of the inline bot you want to get results from. You can specify
|
||||||
a @username (str) or a bot ID (int).
|
a @username (str) or a bot ID (int).
|
||||||
|
|
||||||
query (``str``):
|
query (``str``, *optional*):
|
||||||
Text of the query (up to 512 characters).
|
Text of the query (up to 512 characters).
|
||||||
|
Defaults to "" (empty string).
|
||||||
|
|
||||||
offset (``str``, *optional*):
|
offset (``str``, *optional*):
|
||||||
Offset of the results to be returned.
|
Offset of the results to be returned.
|
||||||
@ -58,8 +59,13 @@ class GetInlineBotResults(BaseClient):
|
|||||||
:obj:`BotResults <pyrogram.api.types.messages.BotResults>`: On Success.
|
:obj:`BotResults <pyrogram.api.types.messages.BotResults>`: On Success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
TimeoutError: In case the bot fails to answer within 10 seconds.
|
TimeoutError: In case the bot fails to answer within 10 seconds.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
results = app.get_inline_bot_results("pyrogrambot")
|
||||||
|
print(results)
|
||||||
"""
|
"""
|
||||||
# TODO: Don't return the raw type
|
# TODO: Don't return the raw type
|
||||||
|
|
||||||
|
@ -53,8 +53,12 @@ class RequestCallbackAnswer(BaseClient):
|
|||||||
or as an alert.
|
or as an alert.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
TimeoutError: In case the bot fails to answer within 10 seconds.
|
TimeoutError: In case the bot fails to answer within 10 seconds.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.request_callback_answer(chat_id, message_id, "callback_data")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Telegram only wants bytes, but we are allowed to pass strings too.
|
# Telegram only wants bytes, but we are allowed to pass strings too.
|
||||||
|
@ -62,8 +62,10 @@ class SendGame(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent game message is returned.
|
:obj:`Message`: On success, the sent game message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_game(chat_id, "gamename")
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
|
@ -60,8 +60,10 @@ class SendInlineBotResult(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent inline result message is returned.
|
:obj:`Message`: On success, the sent inline result message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_inline_bot_result(chat_id, query_id, result_id)
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SendInlineBotResult(
|
functions.messages.SendInlineBotResult(
|
||||||
|
@ -66,8 +66,14 @@ class SetGameScore(BaseClient):
|
|||||||
:obj:`Message` | ``bool``: On success, if the message was sent by the bot, the edited message is returned,
|
:obj:`Message` | ``bool``: On success, if the message was sent by the bot, the edited message is returned,
|
||||||
True otherwise.
|
True otherwise.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Set new score
|
||||||
|
app.set_game_score(user_id, 1000)
|
||||||
|
|
||||||
|
# Force set new score
|
||||||
|
app.set_game_score(user_id, 25, force=True)
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SetGameScore(
|
functions.messages.SetGameScore(
|
||||||
|
@ -16,8 +16,14 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .add_chat_members import AddChatMembers
|
||||||
from .archive_chats import ArchiveChats
|
from .archive_chats import ArchiveChats
|
||||||
|
from .create_channel import CreateChannel
|
||||||
|
from .create_group import CreateGroup
|
||||||
|
from .create_supergroup import CreateSupergroup
|
||||||
|
from .delete_channel import DeleteChannel
|
||||||
from .delete_chat_photo import DeleteChatPhoto
|
from .delete_chat_photo import DeleteChatPhoto
|
||||||
|
from .delete_supergroup import DeleteSupergroup
|
||||||
from .export_chat_invite_link import ExportChatInviteLink
|
from .export_chat_invite_link import ExportChatInviteLink
|
||||||
from .get_chat import GetChat
|
from .get_chat import GetChat
|
||||||
from .get_chat_member import GetChatMember
|
from .get_chat_member import GetChatMember
|
||||||
@ -32,9 +38,9 @@ from .kick_chat_member import KickChatMember
|
|||||||
from .leave_chat import LeaveChat
|
from .leave_chat import LeaveChat
|
||||||
from .pin_chat_message import PinChatMessage
|
from .pin_chat_message import PinChatMessage
|
||||||
from .promote_chat_member import PromoteChatMember
|
from .promote_chat_member import PromoteChatMember
|
||||||
from .restrict_chat import RestrictChat
|
|
||||||
from .restrict_chat_member import RestrictChatMember
|
from .restrict_chat_member import RestrictChatMember
|
||||||
from .set_chat_description import SetChatDescription
|
from .set_chat_description import SetChatDescription
|
||||||
|
from .set_chat_permissions import SetChatPermissions
|
||||||
from .set_chat_photo import SetChatPhoto
|
from .set_chat_photo import SetChatPhoto
|
||||||
from .set_chat_title import SetChatTitle
|
from .set_chat_title import SetChatTitle
|
||||||
from .unarchive_chats import UnarchiveChats
|
from .unarchive_chats import UnarchiveChats
|
||||||
@ -65,9 +71,15 @@ class Chats(
|
|||||||
IterDialogs,
|
IterDialogs,
|
||||||
IterChatMembers,
|
IterChatMembers,
|
||||||
UpdateChatUsername,
|
UpdateChatUsername,
|
||||||
RestrictChat,
|
SetChatPermissions,
|
||||||
GetDialogsCount,
|
GetDialogsCount,
|
||||||
ArchiveChats,
|
ArchiveChats,
|
||||||
UnarchiveChats
|
UnarchiveChats,
|
||||||
|
CreateGroup,
|
||||||
|
CreateSupergroup,
|
||||||
|
CreateChannel,
|
||||||
|
AddChatMembers,
|
||||||
|
DeleteChannel,
|
||||||
|
DeleteSupergroup
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
88
pyrogram/client/methods/chats/add_chat_members.py
Normal file
88
pyrogram/client/methods/chats/add_chat_members.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from typing import Union, List
|
||||||
|
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class AddChatMembers(BaseClient):
|
||||||
|
def add_chat_members(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
user_ids: Union[Union[int, str], List[Union[int, str]]],
|
||||||
|
forward_limit: int = 100
|
||||||
|
) -> bool:
|
||||||
|
"""Add new chat members to a group, supergroup or channel
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
The group, supergroup or channel id
|
||||||
|
|
||||||
|
user_ids (``int`` | ``str`` | List of ``int`` or ``str``):
|
||||||
|
Users to add in the chat
|
||||||
|
You can pass an ID (int), username (str) or phone number (str).
|
||||||
|
Multiple users can be added by passing a list of IDs, usernames or phone numbers.
|
||||||
|
|
||||||
|
forward_limit (``int``, *optional*):
|
||||||
|
How many of the latest messages you want to forward to the new members. Pass 0 to forward none of them.
|
||||||
|
Only applicable to basic groups (the argument is ignored for supergroups or channels).
|
||||||
|
Defaults to 100 (max amount).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Add one member to a group or channel
|
||||||
|
app.add_chat_members(chat_id, user_id)
|
||||||
|
|
||||||
|
# Add multiple members to a group or channel
|
||||||
|
app.add_chat_members(chat_id, [user_id1, user_id2, user_id3])
|
||||||
|
|
||||||
|
# Change forward_limit (for basic groups only)
|
||||||
|
app.add_chat_members(chat_id, user_id, forward_limit=25)
|
||||||
|
"""
|
||||||
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
if not isinstance(user_ids, list):
|
||||||
|
user_ids = [user_ids]
|
||||||
|
|
||||||
|
if isinstance(peer, types.InputPeerChat):
|
||||||
|
for user_id in user_ids:
|
||||||
|
self.send(
|
||||||
|
functions.messages.AddChatUser(
|
||||||
|
chat_id=peer.chat_id,
|
||||||
|
user_id=self.resolve_peer(user_id),
|
||||||
|
fwd_limit=forward_limit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.send(
|
||||||
|
functions.channels.InviteToChannel(
|
||||||
|
channel=peer,
|
||||||
|
users=[
|
||||||
|
self.resolve_peer(user_id)
|
||||||
|
for user_id in user_ids
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -37,8 +37,14 @@ class ArchiveChats(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Archive chat
|
||||||
|
app.archive_chats(chat_id)
|
||||||
|
|
||||||
|
# Archive multiple chats at once
|
||||||
|
app.archive_chats([chat_id1, chat_id2, chat_id3])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(chat_ids, list):
|
if not isinstance(chat_ids, list):
|
||||||
|
55
pyrogram/client/methods/chats/create_channel.py
Normal file
55
pyrogram/client/methods/chats/create_channel.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# 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 pyrogram
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateChannel(BaseClient):
|
||||||
|
def create_channel(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
description: str = ""
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new broadcast channel.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The channel title.
|
||||||
|
|
||||||
|
description (``str``, *optional*):
|
||||||
|
The channel description.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_channel("Channel Title", "Channel Description")
|
||||||
|
"""
|
||||||
|
r = self.send(
|
||||||
|
functions.channels.CreateChannel(
|
||||||
|
title=title,
|
||||||
|
about=description,
|
||||||
|
broadcast=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
65
pyrogram/client/methods/chats/create_group.py
Normal file
65
pyrogram/client/methods/chats/create_group.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from typing import Union, List
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateGroup(BaseClient):
|
||||||
|
def create_group(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
users: Union[Union[int, str], List[Union[int, str]]]
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new basic group.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you want to create a new supergroup, use :meth:`~pyrogram.Client.create_supergroup` instead.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The group title.
|
||||||
|
|
||||||
|
users (``int`` | ``str`` | List of ``int`` or ``str``):
|
||||||
|
Users to create a chat with.
|
||||||
|
You must pass at least one user using their IDs (int), usernames (str) or phone numbers (str).
|
||||||
|
Multiple users can be invited by passing a list of IDs, usernames or phone numbers.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_group("Group Title", user_id)
|
||||||
|
"""
|
||||||
|
if not isinstance(users, list):
|
||||||
|
users = [users]
|
||||||
|
|
||||||
|
r = self.send(
|
||||||
|
functions.messages.CreateChat(
|
||||||
|
title=title,
|
||||||
|
users=[self.resolve_peer(u) for u in users]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
59
pyrogram/client/methods/chats/create_supergroup.py
Normal file
59
pyrogram/client/methods/chats/create_supergroup.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# 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 pyrogram
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class CreateSupergroup(BaseClient):
|
||||||
|
def create_supergroup(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
description: str = ""
|
||||||
|
) -> "pyrogram.Chat":
|
||||||
|
"""Create a new supergroup.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you want to create a new basic group, use :meth:`~pyrogram.Client.create_group` instead.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
title (``title``):
|
||||||
|
The supergroup title.
|
||||||
|
|
||||||
|
description (``str``, *optional*):
|
||||||
|
The supergroup description.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.create_supergroup("Supergroup Title", "Supergroup Description")
|
||||||
|
"""
|
||||||
|
r = self.send(
|
||||||
|
functions.channels.CreateChannel(
|
||||||
|
title=title,
|
||||||
|
about=description,
|
||||||
|
megagroup=True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_chat(self, r.chats[0])
|
@ -16,17 +16,33 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
from ..tl_object import TLObject
|
from typing import Union
|
||||||
|
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class Null(TLObject):
|
class DeleteChannel(BaseClient):
|
||||||
ID = 0x56730bcc
|
def delete_channel(self, chat_id: Union[int, str]) -> bool:
|
||||||
|
"""Delete a channel.
|
||||||
|
|
||||||
@staticmethod
|
Parameters:
|
||||||
def read(b: BytesIO, *args) -> None:
|
chat_id (``int`` | ``str``):
|
||||||
return None
|
The id of the channel to be deleted.
|
||||||
|
|
||||||
def __new__(cls) -> bytes:
|
Returns:
|
||||||
return cls.ID.to_bytes(4, "little")
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_channel(channel_id)
|
||||||
|
"""
|
||||||
|
self.send(
|
||||||
|
functions.channels.DeleteChannel(
|
||||||
|
channel=self.resolve_peer(chat_id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -28,12 +28,8 @@ class DeleteChatPhoto(BaseClient):
|
|||||||
chat_id: Union[int, str]
|
chat_id: Union[int, str]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Delete a chat photo.
|
"""Delete a chat photo.
|
||||||
Photos can't be changed for private chats.
|
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
|
||||||
|
|
||||||
Note:
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
|
|
||||||
setting is off.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -43,8 +39,12 @@ class DeleteChatPhoto(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: if a chat_id belongs to user.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_chat_photo(chat_id)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
48
pyrogram/client/methods/chats/delete_supergroup.py
Normal file
48
pyrogram/client/methods/chats/delete_supergroup.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteSupergroup(BaseClient):
|
||||||
|
def delete_supergroup(self, chat_id: Union[int, str]) -> bool:
|
||||||
|
"""Delete a supergroup.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
The id of the supergroup to be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_supergroup(supergroup_id)
|
||||||
|
"""
|
||||||
|
self.send(
|
||||||
|
functions.channels.DeleteChannel(
|
||||||
|
channel=self.resolve_peer(chat_id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
@ -47,22 +47,21 @@ class ExportChatInviteLink(BaseClient):
|
|||||||
``str``: On success, the exported invite link is returned.
|
``str``: On success, the exported invite link is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case the chat_id belongs to a user.
|
ValueError: In case the chat_id belongs to a user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
link = app.export_chat_invite_link(chat_id)
|
||||||
|
print(link)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if isinstance(peer, types.InputPeerChat):
|
if isinstance(peer, (types.InputPeerChat, types.InputPeerChannel)):
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.ExportChatInvite(
|
functions.messages.ExportChatInvite(
|
||||||
peer=peer
|
peer=peer
|
||||||
)
|
)
|
||||||
).link
|
).link
|
||||||
elif isinstance(peer, types.InputPeerChannel):
|
|
||||||
return self.send(
|
|
||||||
functions.channels.ExportInvite(
|
|
||||||
channel=peer
|
|
||||||
)
|
|
||||||
).link
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('The chat_id "{}" belongs to a user'.format(chat_id))
|
raise ValueError('The chat_id "{}" belongs to a user'.format(chat_id))
|
||||||
|
@ -20,7 +20,7 @@ from typing import Union
|
|||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
|
|
||||||
class GetChat(BaseClient):
|
class GetChat(BaseClient):
|
||||||
@ -44,8 +44,13 @@ class GetChat(BaseClient):
|
|||||||
otherwise, a chat preview object is returned.
|
otherwise, a chat preview object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case the chat invite link points to a chat you haven't joined yet.
|
ValueError: In case the chat invite link points to a chat you haven't joined yet.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
chat = app.get_chat("pyrogram")
|
||||||
|
print(chat)
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(str(chat_id))
|
match = self.INVITE_LINK_RE.match(str(chat_id))
|
||||||
|
|
||||||
@ -65,7 +70,7 @@ class GetChat(BaseClient):
|
|||||||
chat_id = -r.chat.id
|
chat_id = -r.chat.id
|
||||||
|
|
||||||
if isinstance(r.chat, types.Channel):
|
if isinstance(r.chat, types.Channel):
|
||||||
chat_id = int("-100" + str(r.chat.id))
|
chat_id = utils.get_channel_id(r.chat.id)
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -44,8 +44,11 @@ class GetChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`ChatMember`: On success, a chat member is returned.
|
:obj:`ChatMember`: On success, a chat member is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
dan = app.get_chat_member("pyrogramchat", "haskell")
|
||||||
|
print(dan)
|
||||||
"""
|
"""
|
||||||
chat = self.resolve_peer(chat_id)
|
chat = self.resolve_peer(chat_id)
|
||||||
user = self.resolve_peer(user_id)
|
user = self.resolve_peer(user_id)
|
||||||
|
@ -91,8 +91,19 @@ class GetChatMembers(BaseClient):
|
|||||||
List of :obj:`ChatMember`: On success, a list of chat members is returned.
|
List of :obj:`ChatMember`: On success, a list of chat members is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case you used an invalid filter or a chat id that belongs to a user.
|
ValueError: In case you used an invalid filter or a chat id that belongs to a user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get first 200 recent members
|
||||||
|
app.get_chat_members("pyrogramchat")
|
||||||
|
|
||||||
|
# Get all administrators
|
||||||
|
app.get_chat_members("pyrogramchat", filter="administrators")
|
||||||
|
|
||||||
|
# Get all bots
|
||||||
|
app.get_chat_members("pyrogramchat", filter="bots")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -37,8 +37,13 @@ class GetChatMembersCount(BaseClient):
|
|||||||
``int``: On success, the chat members count is returned.
|
``int``: On success, the chat members count is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to user.
|
ValueError: In case a chat id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_chat_members_count("pyrogramchat")
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ from typing import List
|
|||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.errors import FloodWait
|
from pyrogram.errors import FloodWait
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -56,8 +56,14 @@ class GetDialogs(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`Dialog`: On success, a list of dialogs is returned.
|
List of :obj:`Dialog`: On success, a list of dialogs is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get first 100 dialogs
|
||||||
|
app.get_dialogs()
|
||||||
|
|
||||||
|
# Get pinned dialogs
|
||||||
|
app.get_dialogs(pinned_only=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -94,10 +100,8 @@ class GetDialogs(BaseClient):
|
|||||||
chat_id = to_id.user_id
|
chat_id = to_id.user_id
|
||||||
else:
|
else:
|
||||||
chat_id = message.from_id
|
chat_id = message.from_id
|
||||||
elif isinstance(to_id, types.PeerChat):
|
|
||||||
chat_id = -to_id.chat_id
|
|
||||||
else:
|
else:
|
||||||
chat_id = int("-100" + str(to_id.channel_id))
|
chat_id = utils.get_peer_id(to_id)
|
||||||
|
|
||||||
messages[chat_id] = pyrogram.Message._parse(self, message, users, chats)
|
messages[chat_id] = pyrogram.Message._parse(self, message, users, chats)
|
||||||
|
|
||||||
|
@ -31,8 +31,11 @@ class GetDialogsCount(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``int``: On success, the dialogs count is returned.
|
``int``: On success, the dialogs count is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_dialogs_count()
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if pinned_only:
|
if pinned_only:
|
||||||
|
@ -77,8 +77,20 @@ class IterChatMembers(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``Generator``: A generator yielding :obj:`ChatMember` objects.
|
``Generator``: A generator yielding :obj:`ChatMember` objects.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Iterate though all chat members
|
||||||
|
for member in app.iter_chat_members("pyrogramchat"):
|
||||||
|
print(member.user.first_name)
|
||||||
|
|
||||||
|
# Iterate though all administrators
|
||||||
|
for member in app.iter_chat_members("pyrogramchat", filter="administrators"):
|
||||||
|
print(member.user.first_name)
|
||||||
|
|
||||||
|
# Iterate though all bots
|
||||||
|
for member in app.iter_chat_members("pyrogramchat", filter="bots"):
|
||||||
|
print(member.user.first_name)
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
yielded = set()
|
yielded = set()
|
||||||
|
@ -46,8 +46,12 @@ class IterDialogs(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``Generator``: A generator yielding :obj:`Dialog` objects.
|
``Generator``: A generator yielding :obj:`Dialog` objects.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Iterate through all dialogs
|
||||||
|
for dialog in app.iter_dialogs():
|
||||||
|
print(dialog.chat.first_name or dialog.chat.title)
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
total = limit or (1 << 31) - 1
|
total = limit or (1 << 31) - 1
|
||||||
|
@ -36,8 +36,14 @@ class JoinChat(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Join chat via username
|
||||||
|
app.join_chat("pyrogram")
|
||||||
|
|
||||||
|
# Join chat via invite link
|
||||||
|
app.join_chat("https://t.me/joinchat/AAAAAE0QmSW3IUmm3UFR7A")
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(chat_id)
|
match = self.INVITE_LINK_RE.match(chat_id)
|
||||||
|
|
||||||
|
@ -57,8 +57,16 @@ class KickChatMember(BaseClient):
|
|||||||
:obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
|
:obj:`Message` | ``bool``: On success, a service message will be returned (when applicable), otherwise, in
|
||||||
case a message object couldn't be returned, True is returned.
|
case a message object couldn't be returned, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
# Ban chat member forever
|
||||||
|
app.kick_chat_member(chat_id, user_id)
|
||||||
|
|
||||||
|
# Kick chat member and automatically unban after 24h
|
||||||
|
app.kick_chat_member(chat_id, user_id, int(time.time() + 86400))
|
||||||
"""
|
"""
|
||||||
chat_peer = self.resolve_peer(chat_id)
|
chat_peer = self.resolve_peer(chat_id)
|
||||||
user_peer = self.resolve_peer(user_id)
|
user_peer = self.resolve_peer(user_id)
|
||||||
|
@ -37,9 +37,16 @@ class LeaveChat(BaseClient):
|
|||||||
|
|
||||||
delete (``bool``, *optional*):
|
delete (``bool``, *optional*):
|
||||||
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
||||||
|
Defaults to False.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Leave chat or channel
|
||||||
|
app.leave_chat(chat_id)
|
||||||
|
|
||||||
|
# Leave basic chat and also delete the dialog
|
||||||
|
app.leave_chat(chat_id, delete=True)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -47,8 +47,14 @@ class PinChatMessage(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Pin with notification
|
||||||
|
app.pin_chat_message(chat_id, message_id)
|
||||||
|
|
||||||
|
# Pin without notification
|
||||||
|
app.pin_chat_message(chat_id, message_id, disable_notification=True)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
|
@ -78,8 +78,11 @@ class PromoteChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Promote chat member to supergroup admin
|
||||||
|
app.promote_chat_member(chat_id, user_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditAdmin(
|
functions.channels.EditAdmin(
|
||||||
|
@ -20,7 +20,7 @@ from typing import Union
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
from ...types.user_and_chats import Chat
|
from ...types.user_and_chats import Chat, ChatPermissions
|
||||||
|
|
||||||
|
|
||||||
class RestrictChatMember(BaseClient):
|
class RestrictChatMember(BaseClient):
|
||||||
@ -28,20 +28,13 @@ class RestrictChatMember(BaseClient):
|
|||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
until_date: int = 0,
|
permissions: ChatPermissions,
|
||||||
can_send_messages: bool = False,
|
until_date: int = 0
|
||||||
can_send_media_messages: bool = False,
|
|
||||||
can_send_other_messages: bool = False,
|
|
||||||
can_add_web_page_previews: bool = False,
|
|
||||||
can_send_polls: bool = False,
|
|
||||||
can_change_info: bool = False,
|
|
||||||
can_invite_users: bool = False,
|
|
||||||
can_pin_messages: bool = False
|
|
||||||
) -> Chat:
|
) -> Chat:
|
||||||
"""Restrict a user in a supergroup.
|
"""Restrict a user in a supergroup.
|
||||||
|
|
||||||
The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
|
You must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
|
||||||
Pass True for all boolean parameters to lift restrictions from a user.
|
Pass True for all permissions to lift restrictions from a user.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -51,42 +44,32 @@ class RestrictChatMember(BaseClient):
|
|||||||
Unique identifier (int) or username (str) of the target user.
|
Unique identifier (int) or username (str) of the target user.
|
||||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
For a contact that exists in your Telegram address book you can use his phone number (str).
|
||||||
|
|
||||||
|
permissions (:obj:`ChatPermissions`):
|
||||||
|
New user permissions.
|
||||||
|
|
||||||
until_date (``int``, *optional*):
|
until_date (``int``, *optional*):
|
||||||
Date when the user will be unbanned, unix time.
|
Date when the user will be unbanned, unix time.
|
||||||
If user is banned for more than 366 days or less than 30 seconds from the current time they are
|
If user is banned for more than 366 days or less than 30 seconds from the current time they are
|
||||||
considered to be banned forever. Defaults to 0 (ban forever).
|
considered to be banned forever. Defaults to 0 (ban forever).
|
||||||
|
|
||||||
can_send_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send text messages, contacts, locations and venues.
|
|
||||||
|
|
||||||
can_send_media_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send audios, documents, photos, videos, video notes and voice notes,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_other_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send animations, games, stickers and use inline bots,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_add_web_page_previews (``bool``, *optional*):
|
|
||||||
Pass True, if the user may add web page previews to their messages, implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_polls (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send polls, implies can_send_messages.
|
|
||||||
|
|
||||||
can_change_info (``bool``, *optional*):
|
|
||||||
Pass True, if the user can change the chat title, photo and other settings.
|
|
||||||
|
|
||||||
can_invite_users (``bool``, *optional*):
|
|
||||||
Pass True, if the user can invite new users to the chat.
|
|
||||||
|
|
||||||
can_pin_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can pin messages.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
from pyrogram import ChatPermissions
|
||||||
|
|
||||||
|
# Completely restrict chat member (mute) forever
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions())
|
||||||
|
|
||||||
|
# Chat member muted for 24h
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions(), int(time.time() + 86400))
|
||||||
|
|
||||||
|
# Chat member can only send text messages
|
||||||
|
app.restrict_chat_member(chat_id, user_id, ChatPermissions(can_send_messages=True))
|
||||||
"""
|
"""
|
||||||
send_messages = True
|
send_messages = True
|
||||||
send_media = True
|
send_media = True
|
||||||
@ -100,35 +83,35 @@ class RestrictChatMember(BaseClient):
|
|||||||
invite_users = True
|
invite_users = True
|
||||||
pin_messages = True
|
pin_messages = True
|
||||||
|
|
||||||
if can_send_messages:
|
if permissions.can_send_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
|
|
||||||
if can_send_media_messages:
|
if permissions.can_send_media_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
|
|
||||||
if can_send_other_messages:
|
if permissions.can_send_other_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_stickers = None
|
send_stickers = None
|
||||||
send_gifs = None
|
send_gifs = None
|
||||||
send_games = None
|
send_games = None
|
||||||
send_inline = None
|
send_inline = None
|
||||||
|
|
||||||
if can_add_web_page_previews:
|
if permissions.can_add_web_page_previews:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
embed_links = None
|
embed_links = None
|
||||||
|
|
||||||
if can_send_polls:
|
if permissions.can_send_polls:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_polls = None
|
send_polls = None
|
||||||
|
|
||||||
if can_change_info:
|
if permissions.can_change_info:
|
||||||
change_info = None
|
change_info = None
|
||||||
|
|
||||||
if can_invite_users:
|
if permissions.can_invite_users:
|
||||||
invite_users = None
|
invite_users = None
|
||||||
|
|
||||||
if can_pin_messages:
|
if permissions.can_pin_messages:
|
||||||
pin_messages = None
|
pin_messages = None
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -42,8 +42,12 @@ class SetChatDescription(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: if a chat_id doesn't belong to a supergroup or a channel.
|
||||||
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.set_chat_description(chat_id, "New Description")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -20,60 +20,47 @@ from typing import Union
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
from ...types.user_and_chats import Chat
|
from ...types.user_and_chats import Chat, ChatPermissions
|
||||||
|
|
||||||
|
|
||||||
class RestrictChat(BaseClient):
|
class SetChatPermissions(BaseClient):
|
||||||
def restrict_chat(
|
def set_chat_permissions(
|
||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
can_send_messages: bool = False,
|
permissions: ChatPermissions,
|
||||||
can_send_media_messages: bool = False,
|
|
||||||
can_send_other_messages: bool = False,
|
|
||||||
can_add_web_page_previews: bool = False,
|
|
||||||
can_send_polls: bool = False,
|
|
||||||
can_change_info: bool = False,
|
|
||||||
can_invite_users: bool = False,
|
|
||||||
can_pin_messages: bool = False
|
|
||||||
) -> Chat:
|
) -> Chat:
|
||||||
"""Restrict a chat.
|
"""Set default chat permissions for all members.
|
||||||
Pass True for all boolean parameters to lift restrictions from a chat.
|
|
||||||
|
You must be an administrator in the group or a supergroup for this to work and must have the
|
||||||
|
*can_restrict_members* admin rights.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
can_send_messages (``bool``, *optional*):
|
permissions (:obj:`ChatPermissions`):
|
||||||
Pass True, if the user can send text messages, contacts, locations and venues.
|
New default chat permissions.
|
||||||
|
|
||||||
can_send_media_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send audios, documents, photos, videos, video notes and voice notes,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_other_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send animations, games, stickers and use inline bots,
|
|
||||||
implies can_send_messages.
|
|
||||||
|
|
||||||
can_add_web_page_previews (``bool``, *optional*):
|
|
||||||
Pass True, if the user may add web page previews to their messages, implies can_send_messages.
|
|
||||||
|
|
||||||
can_send_polls (``bool``, *optional*):
|
|
||||||
Pass True, if the user can send polls, implies can_send_messages.
|
|
||||||
|
|
||||||
can_change_info (``bool``, *optional*):
|
|
||||||
Pass True, if the user can change the chat title, photo and other settings.
|
|
||||||
|
|
||||||
can_invite_users (``bool``, *optional*):
|
|
||||||
Pass True, if the user can invite new users to the chat.
|
|
||||||
|
|
||||||
can_pin_messages (``bool``, *optional*):
|
|
||||||
Pass True, if the user can pin messages.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`Chat`: On success, a chat object is returned.
|
:obj:`Chat`: On success, a chat object is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import ChatPermissions
|
||||||
|
|
||||||
|
# Completely restrict chat
|
||||||
|
app.set_chat_permissions(chat_id, ChatPermissions())
|
||||||
|
|
||||||
|
# Chat members can only send text messages, media, stickers and GIFs
|
||||||
|
app.set_chat_permissions(
|
||||||
|
chat_id,
|
||||||
|
ChatPermissions(
|
||||||
|
can_send_messages=True,
|
||||||
|
can_send_media_messages=True,
|
||||||
|
can_send_other_messages=True
|
||||||
|
)
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
send_messages = True
|
send_messages = True
|
||||||
send_media = True
|
send_media = True
|
||||||
@ -87,35 +74,35 @@ class RestrictChat(BaseClient):
|
|||||||
invite_users = True
|
invite_users = True
|
||||||
pin_messages = True
|
pin_messages = True
|
||||||
|
|
||||||
if can_send_messages:
|
if permissions.can_send_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
|
|
||||||
if can_send_media_messages:
|
if permissions.can_send_media_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
|
|
||||||
if can_send_other_messages:
|
if permissions.can_send_other_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_stickers = None
|
send_stickers = None
|
||||||
send_gifs = None
|
send_gifs = None
|
||||||
send_games = None
|
send_games = None
|
||||||
send_inline = None
|
send_inline = None
|
||||||
|
|
||||||
if can_add_web_page_previews:
|
if permissions.can_add_web_page_previews:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
embed_links = None
|
embed_links = None
|
||||||
|
|
||||||
if can_send_polls:
|
if permissions.can_send_polls:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
send_polls = None
|
send_polls = None
|
||||||
|
|
||||||
if can_change_info:
|
if permissions.can_change_info:
|
||||||
change_info = None
|
change_info = None
|
||||||
|
|
||||||
if can_invite_users:
|
if permissions.can_invite_users:
|
||||||
invite_users = None
|
invite_users = None
|
||||||
|
|
||||||
if can_pin_messages:
|
if permissions.can_pin_messages:
|
||||||
pin_messages = None
|
pin_messages = None
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
@ -17,12 +17,11 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from base64 import b64decode
|
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient, utils
|
||||||
|
|
||||||
|
|
||||||
class SetChatPhoto(BaseClient):
|
class SetChatPhoto(BaseClient):
|
||||||
@ -32,38 +31,43 @@ class SetChatPhoto(BaseClient):
|
|||||||
photo: str
|
photo: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Set a new profile photo for the chat.
|
"""Set a new profile photo for the chat.
|
||||||
Photos can't be changed for private chats.
|
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
|
||||||
|
|
||||||
Note:
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
In regular groups (non-supergroups), this method will only work if the "All Members Are Admins"
|
|
||||||
setting is off.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
photo (``str``):
|
photo (``str``):
|
||||||
New chat photo. You can pass a :obj:`Photo` id or a file path to upload a new photo.
|
New chat photo. You can pass a :obj:`Photo` file_id or a file path to upload a new photo from your local
|
||||||
|
machine.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: if a chat_id belongs to user.
|
ValueError: if a chat_id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Set chat photo using a local file
|
||||||
|
app.set_chat_photo(chat_id, "photo.jpg")
|
||||||
|
|
||||||
|
# Set chat photo using an exiting Photo file_id
|
||||||
|
app.set_chat_photo(chat_id, photo.file_id)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if os.path.exists(photo):
|
if os.path.exists(photo):
|
||||||
photo = types.InputChatUploadedPhoto(file=self.save_file(photo))
|
photo = types.InputChatUploadedPhoto(file=self.save_file(photo))
|
||||||
else:
|
else:
|
||||||
s = unpack("<qq", b64decode(photo + "=" * (-len(photo) % 4), "-_"))
|
unpacked = unpack("<iiqqc", utils.decode(photo))
|
||||||
|
|
||||||
photo = types.InputChatPhoto(
|
photo = types.InputChatPhoto(
|
||||||
id=types.InputPhoto(
|
id=types.InputPhoto(
|
||||||
id=s[0],
|
id=unpacked[2],
|
||||||
access_hash=s[1],
|
access_hash=unpacked[3],
|
||||||
file_reference=b""
|
file_reference=b""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -47,8 +47,12 @@ class SetChatTitle(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to user.
|
ValueError: In case a chat id belongs to user.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.set_chat_title(chat_id, "New Title")
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -37,8 +37,14 @@ class UnarchiveChats(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Unarchive chat
|
||||||
|
app.unarchive_chats(chat_id)
|
||||||
|
|
||||||
|
# Unarchive multiple chats at once
|
||||||
|
app.unarchive_chats([chat_id1, chat_id2, chat_id3])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(chat_ids, list):
|
if not isinstance(chat_ids, list):
|
||||||
|
@ -43,8 +43,11 @@ class UnbanChatMember(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Unban chat member right now
|
||||||
|
app.unban_chat_member(chat_id, user_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditBanned(
|
functions.channels.EditBanned(
|
||||||
|
@ -38,8 +38,10 @@ class UnpinChatMessage(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.unpin_chat_message(chat_id)
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
|
@ -42,8 +42,12 @@ class UpdateChatUsername(BaseClient):
|
|||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: In case a chat id belongs to a user or chat.
|
ValueError: In case a chat id belongs to a user or chat.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.update_chat_username(chat_id, "new_username")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -37,8 +37,15 @@ class AddContacts(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`types.contacts.ImportedContacts`
|
:obj:`types.contacts.ImportedContacts`
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InputPhoneContact
|
||||||
|
|
||||||
|
app.add_contacts([
|
||||||
|
InputPhoneContact("39123456789", "Foo"),
|
||||||
|
InputPhoneContact("38987654321", "Bar"),
|
||||||
|
InputPhoneContact("01234567891", "Baz")])
|
||||||
"""
|
"""
|
||||||
imported_contacts = self.send(
|
imported_contacts = self.send(
|
||||||
functions.contacts.ImportContacts(
|
functions.contacts.ImportContacts(
|
||||||
|
@ -38,8 +38,10 @@ class DeleteContacts(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success.
|
``bool``: True on success.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.delete_contacts([user_id1, user_id2, user_id3])
|
||||||
"""
|
"""
|
||||||
contacts = []
|
contacts = []
|
||||||
|
|
||||||
|
@ -30,14 +30,16 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class GetContacts(BaseClient):
|
class GetContacts(BaseClient):
|
||||||
def get_contacts(self) -> List["pyrogram.User"]:
|
def get_contacts(self) -> List["pyrogram.User"]:
|
||||||
# TODO: Create a Users object and return that
|
|
||||||
"""Get contacts from your Telegram address book.
|
"""Get contacts from your Telegram address book.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of :obj:`User`: On success, a list of users is returned.
|
List of :obj:`User`: On success, a list of users is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
contacts = app.get_contacts()
|
||||||
|
print(contacts)
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -27,8 +27,11 @@ class GetContactsCount(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``int``: On success, the contacts count is returned.
|
``int``: On success, the contacts count is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
count = app.get_contacts_count()
|
||||||
|
print(count)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return len(self.send(functions.contacts.GetContacts(hash=0)).contacts)
|
return len(self.send(functions.contacts.GetContacts(hash=0)).contacts)
|
||||||
|
@ -47,7 +47,7 @@ class OnCallbackQuery(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
|
self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.CallbackQueryHandler(func, self),
|
pyrogram.CallbackQueryHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -47,7 +47,7 @@ class OnDeletedMessages(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group)
|
self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.DeletedMessagesHandler(func, self),
|
pyrogram.DeletedMessagesHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -46,7 +46,7 @@ class OnInlineQuery(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.InlineQueryHandler(func, filters), group)
|
self.add_handler(pyrogram.InlineQueryHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.InlineQueryHandler(func, self),
|
pyrogram.InlineQueryHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -46,7 +46,7 @@ class OnMessage(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.MessageHandler(func, filters), group)
|
self.add_handler(pyrogram.MessageHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.MessageHandler(func, self),
|
pyrogram.MessageHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -46,7 +46,7 @@ class OnPoll(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.PollHandler(func, filters), group)
|
self.add_handler(pyrogram.PollHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.PollHandler(func, self),
|
pyrogram.PollHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ class OnRawUpdate(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.RawUpdateHandler(func), group)
|
self.add_handler(pyrogram.RawUpdateHandler(func), group)
|
||||||
else:
|
else:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.RawUpdateHandler(func),
|
pyrogram.RawUpdateHandler(func),
|
||||||
group if self is None else group
|
group if self is None else group
|
||||||
)
|
)
|
||||||
|
@ -44,7 +44,7 @@ class OnUserStatus(BaseClient):
|
|||||||
if isinstance(self, pyrogram.Client):
|
if isinstance(self, pyrogram.Client):
|
||||||
self.add_handler(pyrogram.UserStatusHandler(func, filters), group)
|
self.add_handler(pyrogram.UserStatusHandler(func, filters), group)
|
||||||
elif isinstance(self, Filter) or self is None:
|
elif isinstance(self, Filter) or self is None:
|
||||||
func.pyrogram_plugin = (
|
func.handler = (
|
||||||
pyrogram.UserStatusHandler(func, self),
|
pyrogram.UserStatusHandler(func, self),
|
||||||
group if filters is None else filters
|
group if filters is None else filters
|
||||||
)
|
)
|
||||||
|
@ -33,7 +33,6 @@ from .get_messages import GetMessages
|
|||||||
from .iter_history import IterHistory
|
from .iter_history import IterHistory
|
||||||
from .read_history import ReadHistory
|
from .read_history import ReadHistory
|
||||||
from .retract_vote import RetractVote
|
from .retract_vote import RetractVote
|
||||||
from .send_animated_sticker import SendAnimatedSticker
|
|
||||||
from .send_animation import SendAnimation
|
from .send_animation import SendAnimation
|
||||||
from .send_audio import SendAudio
|
from .send_audio import SendAudio
|
||||||
from .send_cached_media import SendCachedMedia
|
from .send_cached_media import SendCachedMedia
|
||||||
@ -85,7 +84,6 @@ class Messages(
|
|||||||
IterHistory,
|
IterHistory,
|
||||||
SendCachedMedia,
|
SendCachedMedia,
|
||||||
GetHistoryCount,
|
GetHistoryCount,
|
||||||
SendAnimatedSticker,
|
|
||||||
ReadHistory,
|
ReadHistory,
|
||||||
EditInlineText,
|
EditInlineText,
|
||||||
EditInlineCaption,
|
EditInlineCaption,
|
||||||
|
@ -50,8 +50,17 @@ class DeleteMessages(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: True on success, False otherwise.
|
``bool``: True on success, False otherwise.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Delete one message
|
||||||
|
app.delete_messages(chat_id, message_id)
|
||||||
|
|
||||||
|
# Delete multiple messages at once
|
||||||
|
app.delete_messages(chat_id, list_of_message_ids)
|
||||||
|
|
||||||
|
# Delete messages only on your side (without revoking)
|
||||||
|
app.delete_messages(chat_id, message_id, revoke=False)
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids]
|
message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids]
|
||||||
|
@ -57,24 +57,23 @@ class DownloadMedia(BaseClient):
|
|||||||
Blocks the code execution until the file has been downloaded.
|
Blocks the code execution until the file has been downloaded.
|
||||||
Defaults to True.
|
Defaults to True.
|
||||||
|
|
||||||
progress (``callable``):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the download progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes downloaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -85,8 +84,16 @@ class DownloadMedia(BaseClient):
|
|||||||
the download failed or was deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
the download failed or was deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
ValueError: if the message doesn't contain any downloadable media
|
ValueError: if the message doesn't contain any downloadable media
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Download from Message
|
||||||
|
app.download_media(message)
|
||||||
|
|
||||||
|
# Download from file id
|
||||||
|
app.download_media("CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
"""
|
"""
|
||||||
error_message = "This message doesn't contain any downloadable media"
|
error_message = "This message doesn't contain any downloadable media"
|
||||||
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note")
|
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note")
|
||||||
@ -207,7 +214,8 @@ class DownloadMedia(BaseClient):
|
|||||||
extension
|
extension
|
||||||
)
|
)
|
||||||
|
|
||||||
self.download_queue.put((data, directory, file_name, done, progress, progress_args, path))
|
# Cast to string because Path objects aren't supported by Python 3.5
|
||||||
|
self.download_queue.put((data, str(directory), str(file_name), done, progress, progress_args, path))
|
||||||
|
|
||||||
if block:
|
if block:
|
||||||
done.wait()
|
done.wait()
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.client.ext import BaseClient
|
from pyrogram.client.ext import BaseClient
|
||||||
|
|
||||||
@ -25,10 +27,10 @@ class EditInlineCaption(BaseClient):
|
|||||||
self,
|
self,
|
||||||
inline_message_id: str,
|
inline_message_id: str,
|
||||||
caption: str,
|
caption: str,
|
||||||
parse_mode: str = "",
|
parse_mode: Union[str, None] = object,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Edit the caption of **inline** media messages.
|
"""Edit the caption of inline media messages.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inline_message_id (``str``):
|
inline_message_id (``str``):
|
||||||
@ -50,8 +52,11 @@ class EditInlineCaption(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Bots only
|
||||||
|
app.edit_inline_caption(inline_message_id, "new media caption")
|
||||||
"""
|
"""
|
||||||
return self.edit_inline_text(
|
return self.edit_inline_text(
|
||||||
inline_message_id=inline_message_id,
|
inline_message_id=inline_message_id,
|
||||||
|
@ -33,7 +33,7 @@ class EditInlineMedia(BaseClient):
|
|||||||
media: InputMedia,
|
media: InputMedia,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Edit **inline** animation, audio, document, photo or video messages.
|
"""Edit inline animation, audio, document, photo or video messages.
|
||||||
|
|
||||||
When the inline message is edited, a new file can't be uploaded. Use a previously uploaded file via its file_id
|
When the inline message is edited, a new file can't be uploaded. Use a previously uploaded file via its file_id
|
||||||
or specify a URL.
|
or specify a URL.
|
||||||
@ -52,8 +52,21 @@ class EditInlineMedia(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InputMediaPhoto, InputMediaVideo, InputMediaAudio
|
||||||
|
|
||||||
|
# Bots only
|
||||||
|
|
||||||
|
# Replace the current media with a local photo
|
||||||
|
app.edit_inline_media(inline_message_id, InputMediaPhoto("new_photo.jpg"))
|
||||||
|
|
||||||
|
# Replace the current media with a local video
|
||||||
|
app.edit_inline_media(inline_message_id, InputMediaVideo("new_video.mp4"))
|
||||||
|
|
||||||
|
# Replace the current media with a local audio
|
||||||
|
app.edit_inline_media(inline_message_id, InputMediaAudio("new_audio.mp3"))
|
||||||
"""
|
"""
|
||||||
caption = media.caption
|
caption = media.caption
|
||||||
parse_mode = media.parse_mode
|
parse_mode = media.parse_mode
|
||||||
|
@ -27,7 +27,7 @@ class EditInlineReplyMarkup(BaseClient):
|
|||||||
inline_message_id: str,
|
inline_message_id: str,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Edit only the reply markup of **inline** messages sent via the bot (for inline bots).
|
"""Edit only the reply markup of inline messages sent via the bot (for inline bots).
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inline_message_id (``str``):
|
inline_message_id (``str``):
|
||||||
@ -39,8 +39,16 @@ class EditInlineReplyMarkup(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
# Bots only
|
||||||
|
app.edit_inline_reply_markup(
|
||||||
|
inline_message_id,
|
||||||
|
InlineKeyboardMarkup([[
|
||||||
|
InlineKeyboardButton("New button", callback_data="new_data")]]))
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.EditInlineBotMessage(
|
functions.messages.EditInlineBotMessage(
|
||||||
|
@ -28,11 +28,11 @@ class EditInlineText(BaseClient):
|
|||||||
self,
|
self,
|
||||||
inline_message_id: str,
|
inline_message_id: str,
|
||||||
text: str,
|
text: str,
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
disable_web_page_preview: bool = None,
|
disable_web_page_preview: bool = None,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Edit the text of **inline** messages.
|
"""Edit the text of inline messages.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inline_message_id (``str``):
|
inline_message_id (``str``):
|
||||||
@ -57,8 +57,18 @@ class EditInlineText(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Bots only
|
||||||
|
|
||||||
|
# Simple edit text
|
||||||
|
app.edit_inline_text(inline_message_id, "new text")
|
||||||
|
|
||||||
|
# Take the same text message, remove the web page preview only
|
||||||
|
app.edit_inline_text(
|
||||||
|
inline_message_id, message.text,
|
||||||
|
disable_web_page_preview=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.send(
|
return self.send(
|
||||||
|
@ -28,7 +28,7 @@ class EditMessageCaption(BaseClient):
|
|||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
message_id: int,
|
message_id: int,
|
||||||
caption: str,
|
caption: str,
|
||||||
parse_mode: str = "",
|
parse_mode: Union[str, None] = object,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> "pyrogram.Message":
|
) -> "pyrogram.Message":
|
||||||
"""Edit the caption of media messages.
|
"""Edit the caption of media messages.
|
||||||
@ -58,8 +58,10 @@ class EditMessageCaption(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the edited message is returned.
|
:obj:`Message`: On success, the edited message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.edit_message_caption(chat_id, message_id, "new media caption")
|
||||||
"""
|
"""
|
||||||
return self.edit_message_text(
|
return self.edit_message_text(
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
|
@ -60,8 +60,19 @@ class EditMessageMedia(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the edited message is returned.
|
:obj:`Message`: On success, the edited message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InputMediaPhoto, InputMediaVideo, InputMediaAudio
|
||||||
|
|
||||||
|
# Replace the current media with a local photo
|
||||||
|
app.edit_message_media(chat_id, message_id, InputMediaPhoto("new_photo.jpg"))
|
||||||
|
|
||||||
|
# Replace the current media with a local video
|
||||||
|
app.edit_message_media(chat_id, message_id, InputMediaVideo("new_video.mp4"))
|
||||||
|
|
||||||
|
# Replace the current media with a local audio
|
||||||
|
app.edit_message_media(chat_id, message_id, InputMediaAudio("new_audio.mp3"))
|
||||||
"""
|
"""
|
||||||
caption = media.caption
|
caption = media.caption
|
||||||
parse_mode = media.parse_mode
|
parse_mode = media.parse_mode
|
||||||
|
@ -47,8 +47,16 @@ class EditMessageReplyMarkup(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the edited message is returned.
|
:obj:`Message`: On success, the edited message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
# Bots only
|
||||||
|
app.edit_message_reply_markup(
|
||||||
|
chat_id, message_id,
|
||||||
|
InlineKeyboardMarkup([[
|
||||||
|
InlineKeyboardButton("New button", callback_data="new_data")]]))
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.EditMessage(
|
functions.messages.EditMessage(
|
||||||
|
@ -29,7 +29,7 @@ class EditMessageText(BaseClient):
|
|||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
message_id: int,
|
message_id: int,
|
||||||
text: str,
|
text: str,
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
disable_web_page_preview: bool = None,
|
disable_web_page_preview: bool = None,
|
||||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
|
||||||
) -> "pyrogram.Message":
|
) -> "pyrogram.Message":
|
||||||
@ -63,8 +63,16 @@ class EditMessageText(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the edited message is returned.
|
:obj:`Message`: On success, the edited message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Simple edit text
|
||||||
|
app.edit_message_text(chat_id, message_id, "new text")
|
||||||
|
|
||||||
|
# Take the same text message, remove the web page preview only
|
||||||
|
app.edit_message_text(
|
||||||
|
chat_id, message_id, message.text,
|
||||||
|
disable_web_page_preview=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -55,7 +55,8 @@ class ForwardMessages(BaseClient):
|
|||||||
Users will receive a notification with no sound.
|
Users will receive a notification with no sound.
|
||||||
|
|
||||||
as_copy (``bool``, *optional*):
|
as_copy (``bool``, *optional*):
|
||||||
Pass True to forward messages without the forward header (i.e.: send a copy of the message content).
|
Pass True to forward messages without the forward header (i.e.: send a copy of the message content so
|
||||||
|
that it appears as originally sent by you).
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
|
|
||||||
remove_caption (``bool``, *optional*):
|
remove_caption (``bool``, *optional*):
|
||||||
@ -68,8 +69,18 @@ class ForwardMessages(BaseClient):
|
|||||||
is returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of
|
is returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of
|
||||||
messages, even if such iterable contained just a single element.
|
messages, even if such iterable contained just a single element.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 2,5,8
|
||||||
|
|
||||||
|
# Forward a single message
|
||||||
|
app.forward_messages("me", "pyrogram", 20)
|
||||||
|
|
||||||
|
# Forward multiple messages at once
|
||||||
|
app.forward_messages("me", "pyrogram", [3, 20, 27])
|
||||||
|
|
||||||
|
# Forward messages as copy
|
||||||
|
app.forward_messages("me", "pyrogram", 20, as_copy=True)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
is_iterable = not isinstance(message_ids, int)
|
is_iterable = not isinstance(message_ids, int)
|
||||||
|
@ -70,8 +70,17 @@ class GetHistory(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`Message` - On success, a list of the retrieved messages is returned.
|
List of :obj:`Message` - On success, a list of the retrieved messages is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get the last 100 messages of a chat
|
||||||
|
app.get_history("pyrogramchat")
|
||||||
|
|
||||||
|
# Get the last 3 messages of a chat
|
||||||
|
app.get_history("pyrogramchat", limit=3)
|
||||||
|
|
||||||
|
# Get 3 messages after skipping the first 5
|
||||||
|
app.get_history("pyrogramchat", offset=5, limit=3)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
offset_id = offset_id or (1 if reverse else 0)
|
offset_id = offset_id or (1 if reverse else 0)
|
||||||
|
@ -45,8 +45,10 @@ class GetHistoryCount(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``int``: On success, the chat history count is returned.
|
``int``: On success, the chat history count is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.get_history_count("pyrogramchat")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -28,6 +28,9 @@ from ...ext import BaseClient, utils
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Rewrite using a flag for replied messages and have message_ids non-optional
|
||||||
|
|
||||||
|
|
||||||
class GetMessages(BaseClient):
|
class GetMessages(BaseClient):
|
||||||
def get_messages(
|
def get_messages(
|
||||||
self,
|
self,
|
||||||
@ -36,7 +39,8 @@ class GetMessages(BaseClient):
|
|||||||
reply_to_message_ids: Union[int, Iterable[int]] = None,
|
reply_to_message_ids: Union[int, Iterable[int]] = None,
|
||||||
replies: int = 1
|
replies: int = 1
|
||||||
) -> Union["pyrogram.Message", List["pyrogram.Message"]]:
|
) -> Union["pyrogram.Message", List["pyrogram.Message"]]:
|
||||||
"""Get one or more messages that belong to a specific chat.
|
"""Get one or more messages from a chat by using message identifiers.
|
||||||
|
|
||||||
You can retrieve up to 200 messages at once.
|
You can retrieve up to 200 messages at once.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -64,8 +68,26 @@ class GetMessages(BaseClient):
|
|||||||
returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of messages,
|
returned, otherwise, in case *message_ids* was an iterable, the returned value will be a list of messages,
|
||||||
even if such iterable contained just a single element.
|
even if such iterable contained just a single element.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Get one message
|
||||||
|
app.get_messages("pyrogramchat", 51110)
|
||||||
|
|
||||||
|
# Get more than one message (list of messages)
|
||||||
|
app.get_messages("pyrogramchat", [44625, 51110])
|
||||||
|
|
||||||
|
# Get message by ignoring any replied-to message
|
||||||
|
app.get_messages(chat_id, message_id, replies=0)
|
||||||
|
|
||||||
|
# Get message with all chained replied-to messages
|
||||||
|
app.get_messages(chat_id, message_id, replies=-1)
|
||||||
|
|
||||||
|
# Get the replied-to message of a message
|
||||||
|
app.get_messages(chat_id, reply_to_message_ids=message_id)
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: In case of invalid arguments.
|
||||||
"""
|
"""
|
||||||
ids, ids_type = (
|
ids, ids_type = (
|
||||||
(message_ids, types.InputMessageID) if message_ids
|
(message_ids, types.InputMessageID) if message_ids
|
||||||
@ -74,7 +96,7 @@ class GetMessages(BaseClient):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if ids is None:
|
if ids is None:
|
||||||
raise ValueError("No argument supplied")
|
raise ValueError("No argument supplied. Either pass message_ids or reply_to_message_ids")
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -64,8 +64,11 @@ class IterHistory(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``Generator``: A generator yielding :obj:`Message` objects.
|
``Generator``: A generator yielding :obj:`Message` objects.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
for message in app.iter_history("pyrogram"):
|
||||||
|
print(message.text)
|
||||||
"""
|
"""
|
||||||
offset_id = offset_id or (1 if reverse else 0)
|
offset_id = offset_id or (1 if reverse else 0)
|
||||||
current = 0
|
current = 0
|
||||||
|
@ -43,8 +43,14 @@ class ReadHistory(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
``bool`` - On success, True is returned.
|
``bool`` - On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Mark the whole chat as read
|
||||||
|
app.read_history("pyrogramlounge")
|
||||||
|
|
||||||
|
# Mark messages as read only up to the given message id
|
||||||
|
app.read_history("pyrogramlounge", 123456)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -43,8 +43,10 @@ class RetractVote(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Poll`: On success, the poll with the retracted vote is returned.
|
:obj:`Poll`: On success, the poll with the retracted vote is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.retract_vote(chat_id, message_id)
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendVote(
|
functions.messages.SendVote(
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
|
||||||
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
|
|
||||||
#
|
|
||||||
# This file is part of Pyrogram.
|
|
||||||
#
|
|
||||||
# Pyrogram is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Lesser General Public License as published
|
|
||||||
# by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Pyrogram is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# 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 os
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
import pyrogram
|
|
||||||
from pyrogram.api import functions, types
|
|
||||||
from pyrogram.client.ext import BaseClient, utils
|
|
||||||
from pyrogram.errors import FilePartMissing
|
|
||||||
|
|
||||||
|
|
||||||
class SendAnimatedSticker(BaseClient):
|
|
||||||
def send_animated_sticker(
|
|
||||||
self,
|
|
||||||
chat_id: Union[int, str],
|
|
||||||
animated_sticker: str,
|
|
||||||
disable_notification: bool = None,
|
|
||||||
reply_to_message_id: int = None,
|
|
||||||
reply_markup: Union[
|
|
||||||
"pyrogram.InlineKeyboardMarkup",
|
|
||||||
"pyrogram.ReplyKeyboardMarkup",
|
|
||||||
"pyrogram.ReplyKeyboardRemove",
|
|
||||||
"pyrogram.ForceReply"
|
|
||||||
] = None,
|
|
||||||
progress: callable = None,
|
|
||||||
progress_args: tuple = ()
|
|
||||||
) -> Union["pyrogram.Message", None]:
|
|
||||||
"""Send .tgs animated stickers.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
chat_id (``int`` | ``str``):
|
|
||||||
Unique identifier (int) or username (str) of the target chat.
|
|
||||||
For your personal cloud (Saved Messages) you can simply use "me" or "self".
|
|
||||||
For a contact that exists in your Telegram address book you can use his phone number (str).
|
|
||||||
|
|
||||||
animated_sticker (``str``):
|
|
||||||
Animated sticker to send.
|
|
||||||
Pass a file_id as string to send a animated sticker that exists on the Telegram servers,
|
|
||||||
pass an HTTP URL as a string for Telegram to get a .webp animated sticker file from the Internet, or
|
|
||||||
pass a file path as string to upload a new animated sticker that exists on your local machine.
|
|
||||||
|
|
||||||
disable_notification (``bool``, *optional*):
|
|
||||||
Sends the message silently.
|
|
||||||
Users will receive a notification with no sound.
|
|
||||||
|
|
||||||
reply_to_message_id (``int``, *optional*):
|
|
||||||
If the message is a reply, ID of the original message.
|
|
||||||
|
|
||||||
reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
|
|
||||||
Additional interface options. An object for an inline keyboard, custom reply keyboard,
|
|
||||||
instructions to remove reply keyboard or to force a reply from the user.
|
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
|
||||||
Pass a callback function to view the upload progress.
|
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
|
||||||
below for a detailed description).
|
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
|
||||||
|
|
||||||
Other Parameters:
|
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
|
||||||
The amount of bytes uploaded so far.
|
|
||||||
|
|
||||||
total (``int``):
|
|
||||||
The size of the file.
|
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
|
||||||
You can either keep *\*args* or add every single extra argument in your function signature.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
:obj:`Message` | ``None``: On success, the sent animated sticker message is returned, otherwise, in case the
|
|
||||||
upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
|
||||||
Raises:
|
|
||||||
RPCError: In case of a Telegram RPC error.
|
|
||||||
"""
|
|
||||||
file = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
if os.path.exists(animated_sticker):
|
|
||||||
file = self.save_file(animated_sticker, progress=progress, progress_args=progress_args)
|
|
||||||
media = types.InputMediaUploadedDocument(
|
|
||||||
mime_type=self.guess_mime_type(animated_sticker) or "application/x-tgsticker",
|
|
||||||
file=file,
|
|
||||||
attributes=[
|
|
||||||
types.DocumentAttributeFilename(file_name=os.path.basename(animated_sticker))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
elif animated_sticker.startswith("http"):
|
|
||||||
media = types.InputMediaDocumentExternal(
|
|
||||||
url=animated_sticker
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
media = utils.get_input_media_from_file_id(animated_sticker, 5)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
r = self.send(
|
|
||||||
functions.messages.SendMedia(
|
|
||||||
peer=self.resolve_peer(chat_id),
|
|
||||||
media=media,
|
|
||||||
silent=disable_notification or None,
|
|
||||||
reply_to_msg_id=reply_to_message_id,
|
|
||||||
random_id=self.rnd_id(),
|
|
||||||
reply_markup=reply_markup.write() if reply_markup else None,
|
|
||||||
message=""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
except FilePartMissing as e:
|
|
||||||
self.save_file(animated_sticker, file_id=file.id, file_part=e.x)
|
|
||||||
else:
|
|
||||||
for i in r.updates:
|
|
||||||
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
|
|
||||||
return pyrogram.Message._parse(
|
|
||||||
self, i.message,
|
|
||||||
{i.id: i for i in r.users},
|
|
||||||
{i.id: i for i in r.chats}
|
|
||||||
)
|
|
||||||
except BaseClient.StopTransmission:
|
|
||||||
return None
|
|
@ -32,7 +32,7 @@ class SendAnimation(BaseClient):
|
|||||||
animation: str,
|
animation: str,
|
||||||
caption: str = "",
|
caption: str = "",
|
||||||
unsave: bool = False,
|
unsave: bool = False,
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
duration: int = 0,
|
duration: int = 0,
|
||||||
width: int = 0,
|
width: int = 0,
|
||||||
height: int = 0,
|
height: int = 0,
|
||||||
@ -66,7 +66,7 @@ class SendAnimation(BaseClient):
|
|||||||
Animation caption, 0-1024 characters.
|
Animation caption, 0-1024 characters.
|
||||||
|
|
||||||
unsave (``bool``, *optional*):
|
unsave (``bool``, *optional*):
|
||||||
By default, the server will save into your own collection any new animation GIF you send.
|
By default, the server will save into your own collection any new animation you send.
|
||||||
Pass True to automatically unsave the sent animation. Defaults to False.
|
Pass True to automatically unsave the sent animation. Defaults to False.
|
||||||
|
|
||||||
parse_mode (``str``, *optional*):
|
parse_mode (``str``, *optional*):
|
||||||
@ -103,23 +103,22 @@ class SendAnimation(BaseClient):
|
|||||||
instructions to remove reply keyboard or to force a reply from the user.
|
instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the upload progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes uploaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -129,8 +128,23 @@ class SendAnimation(BaseClient):
|
|||||||
:obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Send animation by uploading from local file
|
||||||
|
app.send_animation("me", "animation.gif")
|
||||||
|
|
||||||
|
# Add caption to the animation
|
||||||
|
app.send_animation("me", "animation.gif", caption="cat")
|
||||||
|
|
||||||
|
# Unsave the animation once is sent
|
||||||
|
app.send_animation("me", "animation.gif", unsave=True)
|
||||||
|
|
||||||
|
# Keep track of the progress while uploading
|
||||||
|
def progress(current, total):
|
||||||
|
print("{:.1f}%".format(current * 100 / total))
|
||||||
|
|
||||||
|
app.send_animation("me", "animation.gif", progress=progress)
|
||||||
"""
|
"""
|
||||||
file = None
|
file = None
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class SendAudio(BaseClient):
|
|||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
audio: str,
|
audio: str,
|
||||||
caption: str = "",
|
caption: str = "",
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
duration: int = 0,
|
duration: int = 0,
|
||||||
performer: str = None,
|
performer: str = None,
|
||||||
title: str = None,
|
title: str = None,
|
||||||
@ -100,23 +100,22 @@ class SendAudio(BaseClient):
|
|||||||
instructions to remove reply keyboard or to force a reply from the user.
|
instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the upload progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes uploaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -126,8 +125,26 @@ class SendAudio(BaseClient):
|
|||||||
:obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent audio message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 2,5,8-10,13-16
|
||||||
|
|
||||||
|
# Send audio file by uploading from file
|
||||||
|
app.send_audio("me", "audio.mp3")
|
||||||
|
|
||||||
|
# Add caption to the audio
|
||||||
|
app.send_audio("me", "audio.mp3", caption="shoegaze")
|
||||||
|
|
||||||
|
# Set audio metadata
|
||||||
|
app.send_audio(
|
||||||
|
"me", "audio.mp3",
|
||||||
|
title="Printemps émeraude", performer="Alcest", duration=440)
|
||||||
|
|
||||||
|
# Keep track of the progress while uploading
|
||||||
|
def progress(current, total):
|
||||||
|
print("{:.1f}%".format(current * 100 / total))
|
||||||
|
|
||||||
|
app.send_audio("me", "audio.mp3", progress=progress)
|
||||||
"""
|
"""
|
||||||
file = None
|
file = None
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class SendCachedMedia(BaseClient):
|
|||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
file_id: str,
|
file_id: str,
|
||||||
caption: str = "",
|
caption: str = "",
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
reply_markup: Union[
|
reply_markup: Union[
|
||||||
@ -79,8 +79,10 @@ class SendCachedMedia(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent media message is returned.
|
:obj:`Message`: On success, the sent media message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_cached_media("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -64,8 +64,22 @@ class SendChatAction(BaseClient):
|
|||||||
``bool``: On success, True is returned.
|
``bool``: On success, True is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RPCError: In case of a Telegram RPC error.
|
ValueError: In case the provided string is not a valid chat action.
|
||||||
ValueError: In case the provided string is not a valid ChatAction.
|
|
||||||
|
Example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Send "typing" chat action
|
||||||
|
app.send_chat_action(chat_id, "typing")
|
||||||
|
|
||||||
|
# Send "upload_video" chat action
|
||||||
|
app.send_chat_action(chat_id, "upload_video")
|
||||||
|
|
||||||
|
# Send "playing" chat action
|
||||||
|
app.send_chat_action(chat_id, "playing")
|
||||||
|
|
||||||
|
# Cancel any current chat action
|
||||||
|
app.send_chat_action(chat_id, "cancel")
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -74,8 +74,10 @@ class SendContact(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent contact message is returned.
|
:obj:`Message`: On success, the sent contact message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_contact("me", "+39 123 456 7890", "Dan")
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
|
@ -32,7 +32,7 @@ class SendDocument(BaseClient):
|
|||||||
document: str,
|
document: str,
|
||||||
thumb: str = None,
|
thumb: str = None,
|
||||||
caption: str = "",
|
caption: str = "",
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
reply_markup: Union[
|
reply_markup: Union[
|
||||||
@ -86,23 +86,22 @@ class SendDocument(BaseClient):
|
|||||||
instructions to remove reply keyboard or to force a reply from the user.
|
instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the upload progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes uploaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -112,8 +111,20 @@ class SendDocument(BaseClient):
|
|||||||
:obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent document message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Send document by uploading from local file
|
||||||
|
app.send_document("me", "document.zip")
|
||||||
|
|
||||||
|
# Add caption to the document file
|
||||||
|
app.send_document("me", "document.zip", caption="archive")
|
||||||
|
|
||||||
|
# Keep track of the progress while uploading
|
||||||
|
def progress(current, total):
|
||||||
|
print("{:.1f}%".format(current * 100 / total))
|
||||||
|
|
||||||
|
app.send_document("me", "document.zip", progress=progress)
|
||||||
"""
|
"""
|
||||||
file = None
|
file = None
|
||||||
|
|
||||||
|
@ -66,8 +66,10 @@ class SendLocation(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent location message is returned.
|
:obj:`Message`: On success, the sent location message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
|
@ -31,7 +31,6 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class SendMediaGroup(BaseClient):
|
class SendMediaGroup(BaseClient):
|
||||||
# TODO: Add progress parameter
|
# TODO: Add progress parameter
|
||||||
# TODO: Figure out how to send albums using URLs
|
|
||||||
def send_media_group(
|
def send_media_group(
|
||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
@ -60,8 +59,19 @@ class SendMediaGroup(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
List of :obj:`Message`: On success, a list of the sent messages is returned.
|
List of :obj:`Message`: On success, a list of the sent messages is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import InputMediaPhoto, InputMediaVideo
|
||||||
|
|
||||||
|
app.send_media_group(
|
||||||
|
"me",
|
||||||
|
[
|
||||||
|
InputMediaPhoto("photo1.jpg"),
|
||||||
|
InputMediaPhoto("photo2.jpg", caption="photo caption"),
|
||||||
|
InputMediaVideo("video.mp4", caption="a video")
|
||||||
|
]
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
multi_media = []
|
multi_media = []
|
||||||
|
|
||||||
@ -88,7 +98,24 @@ class SendMediaGroup(BaseClient):
|
|||||||
id=types.InputPhoto(
|
id=types.InputPhoto(
|
||||||
id=media.photo.id,
|
id=media.photo.id,
|
||||||
access_hash=media.photo.access_hash,
|
access_hash=media.photo.access_hash,
|
||||||
file_reference=b""
|
file_reference=media.photo.file_reference
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif i.media.startswith("http"):
|
||||||
|
media = self.send(
|
||||||
|
functions.messages.UploadMedia(
|
||||||
|
peer=self.resolve_peer(chat_id),
|
||||||
|
media=types.InputMediaPhotoExternal(
|
||||||
|
url=i.media
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
media = types.InputMediaPhoto(
|
||||||
|
id=types.InputPhoto(
|
||||||
|
id=media.photo.id,
|
||||||
|
access_hash=media.photo.access_hash,
|
||||||
|
file_reference=media.photo.file_reference
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -126,7 +153,24 @@ class SendMediaGroup(BaseClient):
|
|||||||
id=types.InputDocument(
|
id=types.InputDocument(
|
||||||
id=media.document.id,
|
id=media.document.id,
|
||||||
access_hash=media.document.access_hash,
|
access_hash=media.document.access_hash,
|
||||||
file_reference=b""
|
file_reference=media.document.file_reference
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif i.media.startswith("http"):
|
||||||
|
media = self.send(
|
||||||
|
functions.messages.UploadMedia(
|
||||||
|
peer=self.resolve_peer(chat_id),
|
||||||
|
media=types.InputMediaDocumentExternal(
|
||||||
|
url=i.media
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
media = types.InputMediaDocument(
|
||||||
|
id=types.InputDocument(
|
||||||
|
id=media.document.id,
|
||||||
|
access_hash=media.document.access_hash,
|
||||||
|
file_reference=media.document.file_reference
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -28,7 +28,7 @@ class SendMessage(BaseClient):
|
|||||||
self,
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
text: str,
|
text: str,
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
disable_web_page_preview: bool = None,
|
disable_web_page_preview: bool = None,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
@ -74,9 +74,44 @@ class SendMessage(BaseClient):
|
|||||||
Returns:
|
Returns:
|
||||||
:obj:`Message`: On success, the sent text message is returned.
|
:obj:`Message`: On success, the sent text message is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 2,5,8,11,21-23,26-33
|
||||||
|
|
||||||
|
# Simple example
|
||||||
|
app.send_message("haskell", "Thanks for creating **Pyrogram**!")
|
||||||
|
|
||||||
|
# Disable web page previews
|
||||||
|
app.send_message("me", "https://docs.pyrogram.org", disable_web_page_preview=True)
|
||||||
|
|
||||||
|
# Reply to a message using its id
|
||||||
|
app.send_message("me", "this is a reply", reply_to_message_id=12345)
|
||||||
|
|
||||||
|
# Force HTML-only styles for this request only
|
||||||
|
app.send_message("me", "**not bold**, <i>italic<i>", parse_mode="html")
|
||||||
|
|
||||||
|
##
|
||||||
|
# For bots only, send messages with keyboards attached
|
||||||
|
##
|
||||||
|
|
||||||
|
from pyrogram import (
|
||||||
|
ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton)
|
||||||
|
|
||||||
|
# Send a normal keyboard
|
||||||
|
app.send_message(
|
||||||
|
chat_id, "Look at that button!",
|
||||||
|
reply_markup=ReplyKeyboardMarkup([["Nice!"]]))
|
||||||
|
|
||||||
|
# Send an inline keyboard
|
||||||
|
app.send_message(
|
||||||
|
chat_id, "These are inline buttons",
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[InlineKeyboardButton("Data", callback_data="hidden_callback_data")],
|
||||||
|
[InlineKeyboardButton("Docs", url="https://docs.pyrogram.org")]
|
||||||
|
]))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message, entities = self.parser.parse(text, parse_mode).values()
|
message, entities = self.parser.parse(text, parse_mode).values()
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -31,7 +31,7 @@ class SendPhoto(BaseClient):
|
|||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
photo: str,
|
photo: str,
|
||||||
caption: str = "",
|
caption: str = "",
|
||||||
parse_mode: Union[str, None] = "",
|
parse_mode: Union[str, None] = object,
|
||||||
ttl_seconds: int = None,
|
ttl_seconds: int = None,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
@ -85,23 +85,22 @@ class SendPhoto(BaseClient):
|
|||||||
instructions to remove reply keyboard or to force a reply from the user.
|
instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
|
||||||
progress (``callable``, *optional*):
|
progress (``callable``, *optional*):
|
||||||
Pass a callback function to view the upload progress.
|
Pass a callback function to view the file transmission progress.
|
||||||
The function must take *(client, current, total, \*args)* as positional arguments (look at the section
|
The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
|
||||||
below for a detailed description).
|
detailed description) and will be called back each time a new file chunk has been successfully
|
||||||
|
transmitted.
|
||||||
|
|
||||||
progress_args (``tuple``, *optional*):
|
progress_args (``tuple``, *optional*):
|
||||||
Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
|
Extra custom arguments for the progress callback function.
|
||||||
a chat_id and a message_id in order to edit a message with the updated progress.
|
You can pass anything you need to be available in the progress callback scope; for example, a Message
|
||||||
|
object or a Client instance in order to edit the message with the updated progress status.
|
||||||
|
|
||||||
Other Parameters:
|
Other Parameters:
|
||||||
client (:obj:`Client`):
|
|
||||||
The Client itself, useful when you want to call other API methods inside the callback function.
|
|
||||||
|
|
||||||
current (``int``):
|
current (``int``):
|
||||||
The amount of bytes uploaded so far.
|
The amount of bytes transmitted so far.
|
||||||
|
|
||||||
total (``int``):
|
total (``int``):
|
||||||
The size of the file.
|
The total size of the file.
|
||||||
|
|
||||||
*args (``tuple``, *optional*):
|
*args (``tuple``, *optional*):
|
||||||
Extra custom arguments as defined in the *progress_args* parameter.
|
Extra custom arguments as defined in the *progress_args* parameter.
|
||||||
@ -111,8 +110,20 @@ class SendPhoto(BaseClient):
|
|||||||
:obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload
|
:obj:`Message` | ``None``: On success, the sent photo message is returned, otherwise, in case the upload
|
||||||
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned.
|
||||||
|
|
||||||
Raises:
|
Example:
|
||||||
RPCError: In case of a Telegram RPC error.
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Send photo by uploading from local file
|
||||||
|
app.send_photo("me", "photo.jpg")
|
||||||
|
|
||||||
|
# Send photo by uploading from URL
|
||||||
|
app.send_photo("me", "https://i.imgur.com/BQBTP7d.png")
|
||||||
|
|
||||||
|
# Add caption to a photo
|
||||||
|
app.send_photo("me", "photo.jpg", caption="Holidays!")
|
||||||
|
|
||||||
|
# Send self-destructing photo
|
||||||
|
app.send_photo("me", "photo.jpg", ttl_seconds=10)
|
||||||
"""
|
"""
|
||||||
file = None
|
file = None
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user