2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-30 13:57:54 +00:00

Merge branch 'develop' into asyncio

# Conflicts:
#	pyrogram/__init__.py
#	pyrogram/client/client.py
#	pyrogram/client/methods/contacts/get_contacts.py
#	pyrogram/client/methods/messages/send_media_group.py
#	requirements.txt
This commit is contained in:
Dan
2019-02-07 16:20:03 +01:00
11 changed files with 2545 additions and 58 deletions

View File

@@ -87,4 +87,6 @@ MESSAGE_POLL_CLOSED You can't interact with a closed poll
MEDIA_INVALID The media is invalid MEDIA_INVALID The media is invalid
BOT_SCORE_NOT_MODIFIED The bot score was not modified BOT_SCORE_NOT_MODIFIED The bot score was not modified
USER_BOT_REQUIRED The method can be used by bots only USER_BOT_REQUIRED The method can be used by bots only
IMAGE_PROCESS_FAILED The server failed to process your image IMAGE_PROCESS_FAILED The server failed to process your image
CALL_ALREADY_ACCEPTED The call is already accepted
CALL_ALREADY_DECLINED The call is already declined
1 id message
87 MEDIA_INVALID The media is invalid
88 BOT_SCORE_NOT_MODIFIED The bot score was not modified
89 USER_BOT_REQUIRED The method can be used by bots only
90 IMAGE_PROCESS_FAILED The server failed to process your image
91 CALL_ALREADY_ACCEPTED The call is already accepted
92 CALL_ALREADY_DECLINED The call is already declined

View File

@@ -82,7 +82,7 @@ If no error shows up you are good to go.
>>> import pyrogram >>> import pyrogram
>>> pyrogram.__version__ >>> pyrogram.__version__
'0.10.3' '0.11.0'
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto .. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
.. _develop: http://github.com/pyrogram/pyrogram .. _develop: http://github.com/pyrogram/pyrogram

View File

@@ -19,6 +19,11 @@
import asyncio import asyncio
import sys import sys
from .vendor import typing
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
sys.modules["typing"] = typing
try: try:
import uvloop import uvloop
except ImportError: except ImportError:
@@ -31,7 +36,7 @@ __copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance
"e" if sys.getfilesystemencoding() != "utf-8" else "\xe8" "e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
) )
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)" __license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__version__ = "0.11.0.asyncio" __version__ = "0.11.1.asyncio"
from .api.errors import Error from .api.errors import Error
from .client.types import ( from .client.types import (

View File

@@ -62,16 +62,16 @@ class Filters:
create = create create = create
me = create("Me", lambda _, m: bool(m.from_user and m.from_user.is_self)) me = create("Me", lambda _, m: bool(m.from_user and m.from_user.is_self))
"""Filter messages coming from you yourself""" """Filter messages generated by you yourself."""
bot = create("Bot", lambda _, m: bool(m.from_user and m.from_user.is_bot)) bot = create("Bot", lambda _, m: bool(m.from_user and m.from_user.is_bot))
"""Filter messages coming from bots""" """Filter messages coming from bots."""
incoming = create("Incoming", lambda _, m: not m.outgoing) incoming = create("Incoming", lambda _, m: not m.outgoing)
"""Filter incoming messages.""" """Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
outgoing = create("Outgoing", lambda _, m: m.outgoing) outgoing = create("Outgoing", lambda _, m: m.outgoing)
"""Filter outgoing messages.""" """Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
text = create("Text", lambda _, m: bool(m.text)) text = create("Text", lambda _, m: bool(m.text))
"""Filter text messages.""" """Filter text messages."""

View File

@@ -19,7 +19,8 @@
import asyncio import asyncio
import logging import logging
from pyrogram.api import functions, types import pyrogram
from pyrogram.api import functions
from pyrogram.api.errors import FloodWait from pyrogram.api.errors import FloodWait
from ...ext import BaseClient from ...ext import BaseClient
@@ -28,12 +29,10 @@ log = logging.getLogger(__name__)
class GetContacts(BaseClient): class GetContacts(BaseClient):
async def get_contacts(self): async def get_contacts(self):
"""Use this method to get contacts from your Telegram address book """Use this method to get contacts from your Telegram address book.
Requires no parameters.
Returns: Returns:
On success, the user's contacts are returned On success, a list of :obj:`User` objects is returned.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -44,9 +43,6 @@ class GetContacts(BaseClient):
except FloodWait as e: except FloodWait as e:
log.warning("get_contacts flood: waiting {} seconds".format(e.x)) log.warning("get_contacts flood: waiting {} seconds".format(e.x))
await asyncio.sleep(e.x) await asyncio.sleep(e.x)
continue
else: else:
if isinstance(contacts, types.contacts.Contacts): log.info("Total contacts: {}".format(len(self.peers_by_phone)))
log.info("Total contacts: {}".format(len(self.peers_by_phone))) return [pyrogram.User._parse(self, user) for user in contacts.users]
return contacts

View File

@@ -17,20 +17,23 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import binascii import binascii
import logging
import mimetypes import mimetypes
import os import os
import struct import struct
from typing import Union, List from typing import Union, List
import asyncio
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid from pyrogram.api.errors import FileIdInvalid, FloodWait
from pyrogram.client.ext import BaseClient, utils from pyrogram.client.ext import BaseClient, utils
log = logging.getLogger(__name__)
class SendMediaGroup(BaseClient): class SendMediaGroup(BaseClient):
# TODO: Add progress parameter # TODO: Add progress parameter
# TODO: Return new Message object
# TODO: Figure out how to send albums using URLs # TODO: Figure out how to send albums using URLs
async def send_media_group(self, async def send_media_group(self,
chat_id: Union[int, str], chat_id: Union[int, str],
@@ -38,7 +41,6 @@ class SendMediaGroup(BaseClient):
disable_notification: bool = None, disable_notification: bool = None,
reply_to_message_id: int = None): reply_to_message_id: int = None):
"""Use this method to send a group of photos or videos as an album. """Use this method to send a group of photos or videos as an album.
On success, an Update containing the sent Messages is returned.
Args: Args:
chat_id (``int`` | ``str``): chat_id (``int`` | ``str``):
@@ -57,6 +59,13 @@ class SendMediaGroup(BaseClient):
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
Returns:
On success, a :obj:`Messages <pyrogram.Messages>` object is returned containing all the
single messages sent.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
""" """
multi_media = [] multi_media = []
@@ -65,14 +74,21 @@ class SendMediaGroup(BaseClient):
if isinstance(i, pyrogram.InputMediaPhoto): if isinstance(i, pyrogram.InputMediaPhoto):
if os.path.exists(i.media): if os.path.exists(i.media):
media = await self.send( while True:
functions.messages.UploadMedia( try:
peer=await self.resolve_peer(chat_id), media = await self.send(
media=types.InputMediaUploadedPhoto( functions.messages.UploadMedia(
file=await self.save_file(i.media) peer=await self.resolve_peer(chat_id),
media=types.InputMediaUploadedPhoto(
file=await self.save_file(i.media)
)
)
) )
) except FloodWait as e:
) log.warning("Sleeping for {}s".format(e.x))
await asyncio.sleep(e.x)
else:
break
media = types.InputMediaPhoto( media = types.InputMediaPhoto(
id=types.InputPhoto( id=types.InputPhoto(
@@ -106,25 +122,32 @@ class SendMediaGroup(BaseClient):
) )
elif isinstance(i, pyrogram.InputMediaVideo): elif isinstance(i, pyrogram.InputMediaVideo):
if os.path.exists(i.media): if os.path.exists(i.media):
media = await self.send( while True:
functions.messages.UploadMedia( try:
peer=await self.resolve_peer(chat_id), media = await self.send(
media=types.InputMediaUploadedDocument( functions.messages.UploadMedia(
file=await self.save_file(i.media), peer=await self.resolve_peer(chat_id),
thumb=None if i.thumb is None else self.save_file(i.thumb), media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"], file=await self.save_file(i.media),
attributes=[ thumb=None if i.thumb is None else self.save_file(i.thumb),
types.DocumentAttributeVideo( mime_type=mimetypes.types_map[".mp4"],
supports_streaming=i.supports_streaming or None, attributes=[
duration=i.duration, types.DocumentAttributeVideo(
w=i.width, supports_streaming=i.supports_streaming or None,
h=i.height duration=i.duration,
), w=i.width,
types.DocumentAttributeFilename(os.path.basename(i.media)) h=i.height
] ),
types.DocumentAttributeFilename(os.path.basename(i.media))
]
)
)
) )
) except FloodWait as e:
) log.warning("Sleeping for {}s".format(e.x))
await asyncio.sleep(e.x)
else:
break
media = types.InputMediaDocument( media = types.InputMediaDocument(
id=types.InputDocument( id=types.InputDocument(
@@ -165,11 +188,30 @@ class SendMediaGroup(BaseClient):
) )
) )
return await self.send( while True:
functions.messages.SendMultiMedia( try:
peer=await self.resolve_peer(chat_id), r = await self.send(
multi_media=multi_media, functions.messages.SendMultiMedia(
silent=disable_notification or None, peer=await self.resolve_peer(chat_id),
reply_to_msg_id=reply_to_message_id multi_media=multi_media,
silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id
)
)
except FloodWait as e:
log.warning("Sleeping for {}s".format(e.x))
await asyncio.sleep(e.x)
else:
break
return await pyrogram.Messages._parse(
self,
types.messages.Messages(
messages=[m.message for m in filter(
lambda u: isinstance(u, (types.UpdateNewMessage, types.UpdateNewChannelMessage)),
r.updates
)],
users=r.users,
chats=r.chats
) )
) )

19
pyrogram/vendor/__init__.py vendored Normal file
View File

@@ -0,0 +1,19 @@
# 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 typing

17
pyrogram/vendor/typing/__init__.py vendored Normal file
View File

@@ -0,0 +1,17 @@
# 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/>.

2413
pyrogram/vendor/typing/typing.py vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
build:
image: latest
python:
version: 3.6
setup_py_install: true

View File

@@ -1,5 +1,4 @@
pyaes==1.6.1 pyaes==1.6.1
pysocks==1.6.8 pysocks==1.6.8
typing==3.6.6; python_version<"3.5"
async_lru==1.0.1 async_lru==1.0.1
async_generator==1.10 async_generator==1.10