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

Merge branch 'develop' into inline-mode

# Conflicts:
#	compiler/api/compiler.py
#	compiler/error/source/400_BAD_REQUEST.tsv
#	pyrogram/__init__.py
#	pyrogram/client/dispatcher/dispatcher.py
#	pyrogram/client/ext/utils.py
#	pyrogram/client/methods/bots/__init__.py
#	pyrogram/client/types/__init__.py
This commit is contained in:
Dan
2019-03-21 17:40:49 +01:00
267 changed files with 12512 additions and 3959 deletions

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -18,22 +18,30 @@
import sys
__copyright__ = "Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>".replace(
if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
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
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
"\xe8",
"e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
)
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__version__ = "0.9.2.dev1"
__version__ = "0.12.0.develop"
from .api.errors import Error
from .client.types import (
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User, UserStatus,
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus,
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
InlineQuery, InlineQueryResult, InlineQueryResultArticle, InlineQueryResultPhoto, InputTextMessageContent,
InlineQueryResultCachedAudio, InputMessageContent
InlineQueryResultCachedAudio, InputMessageContent, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton,
ReplyKeyboardMarkup, ReplyKeyboardRemove, Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation,
Game, CallbackGame, GameHighScore, GameHighScores, ChatPermissions
)
from .client import (
Client, ChatAction, ParseMode, Emoji,

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -19,14 +19,16 @@
from collections import OrderedDict
from datetime import datetime
from io import BytesIO
from json import JSONEncoder, dumps
from ..all import objects
from json import dumps
class Object:
all = {}
__slots__ = []
QUALNAME = "Base"
@staticmethod
def read(b: BytesIO, *args):
return Object.all[int.from_bytes(b.read(4), "little")].read(b, *args)
@@ -35,7 +37,7 @@ class Object:
pass
def __str__(self) -> str:
return dumps(self, cls=Encoder, indent=4)
return dumps(self, indent=4, default=default, ensure_ascii=False)
def __bool__(self) -> bool:
return True
@@ -62,29 +64,18 @@ def remove_none(obj):
return obj
class Encoder(JSONEncoder):
def default(self, o: Object):
try:
content = o.__dict__
except AttributeError:
if isinstance(o, datetime):
return o.strftime("%d-%b-%Y %H:%M:%S")
else:
return repr(o)
def default(o: "Object"):
try:
content = {i: getattr(o, i) for i in o.__slots__}
name = o.__class__.__name__
o = objects.get(getattr(o, "ID", None), None)
if o is not None:
if o.startswith("pyrogram.client"):
r = remove_none(OrderedDict([("_", "pyrogram:" + name)] + [i for i in content.items()]))
r.pop("_client", None)
return r
else:
return OrderedDict(
[("_", o.replace("pyrogram.api.types.", "telegram:"))]
+ [i for i in content.items()]
)
return remove_none(
OrderedDict(
[("_", o.QUALNAME)]
+ [i for i in content.items()]
)
)
except AttributeError:
if isinstance(o, datetime):
return o.strftime("%d-%b-%Y %H:%M:%S")
else:
return None
return repr(o)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -22,6 +22,7 @@ from collections import OrderedDict
from queue import Queue
from threading import Thread
import pyrogram
from pyrogram.api import types
from ..ext import utils
from ..handlers import (
@@ -43,7 +44,7 @@ class Dispatcher:
types.UpdateEditChannelMessage
)
DELETE_MESSAGE_UPDATES = (
DELETE_MESSAGES_UPDATES = (
types.UpdateDeleteMessages,
types.UpdateDeleteChannelMessages
)
@@ -55,34 +56,34 @@ class Dispatcher:
MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES
UPDATES = None
def __init__(self, client, workers: int):
self.client = client
self.workers = workers
self.workers_list = []
self.updates = Queue()
self.updates_queue = Queue()
self.groups = OrderedDict()
Dispatcher.UPDATES = {
self.update_parsers = {
Dispatcher.MESSAGE_UPDATES:
lambda upd, usr, cht: (utils.parse_messages(self.client, upd.message, usr, cht), MessageHandler),
lambda upd, usr, cht: (pyrogram.Message._parse(self.client, upd.message, usr, cht), MessageHandler),
Dispatcher.DELETE_MESSAGE_UPDATES:
lambda upd, usr, cht: (utils.parse_deleted_messages(upd), DeletedMessagesHandler),
Dispatcher.DELETE_MESSAGES_UPDATES:
lambda upd, usr, cht: (pyrogram.Messages._parse_deleted(self.client, upd), DeletedMessagesHandler),
Dispatcher.CALLBACK_QUERY_UPDATES:
lambda upd, usr, cht: (utils.parse_callback_query(self.client, upd, usr), CallbackQueryHandler),
lambda upd, usr, cht: (pyrogram.CallbackQuery._parse(self.client, upd, usr), CallbackQueryHandler),
(types.UpdateUserStatus,):
lambda upd, usr, cht: (utils.parse_user_status(upd.status, upd.user_id), UserStatusHandler),
lambda upd, usr, cht: (
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
),
(types.UpdateBotInlineQuery,):
lambda upd, usr, cht: (utils.parse_inline_query(self.client, upd, usr), InlineQueryHandler)
}
Dispatcher.UPDATES = {key: value for key_tuple, value in Dispatcher.UPDATES.items() for key in key_tuple}
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
def start(self):
for i in range(self.workers):
@@ -97,7 +98,7 @@ class Dispatcher:
def stop(self):
for _ in range(self.workers):
self.updates.put(None)
self.updates_queue.put(None)
for worker in self.workers_list:
worker.join()
@@ -122,7 +123,7 @@ class Dispatcher:
log.debug("{} started".format(name))
while True:
update = self.updates.get()
update = self.updates_queue.get()
if update is None:
break
@@ -132,32 +133,39 @@ class Dispatcher:
chats = {i.id: i for i in update[2]}
update = update[0]
parser = Dispatcher.UPDATES.get(type(update), None)
parser = self.update_parsers.get(type(update), None)
if parser is None:
continue
update, handler_type = parser(update, users, chats)
parsed_update, handler_type = (
parser(update, users, chats)
if parser is not None
else (None, type(None))
)
for group in self.groups.values():
for handler in group:
args = None
if isinstance(handler, RawUpdateHandler):
if isinstance(handler, handler_type):
if handler.check(parsed_update):
args = (parsed_update,)
elif isinstance(handler, RawUpdateHandler):
args = (update, users, chats)
elif isinstance(handler, handler_type):
if handler.check(update):
args = (update,)
if args is None:
continue
try:
handler.callback(self.client, *args)
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
continue
except Exception as e:
log.error(e, exc_info=True)
finally:
break
break
except pyrogram.StopPropagation:
pass
except Exception as e:
log.error(e, exc_info=True)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -23,12 +23,13 @@ from threading import Lock
from pyrogram import __version__
from ..style import Markdown, HTML
from ...api.core import Object
from ...session import Session
from ...session.internals import MsgId
class BaseClient:
class StopTransmission(StopIteration):
pass
APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__)
DEVICE_MODEL = "{} {}".format(
@@ -67,7 +68,7 @@ class BaseClient:
}
def __init__(self):
self.bot_token = None
self.is_bot = None
self.dc_id = None
self.auth_key = None
self.user_id = None
@@ -90,6 +91,8 @@ class BaseClient:
self.is_started = None
self.is_idle = None
self.takeout_id = None
self.updates_queue = Queue()
self.updates_workers_list = []
self.download_queue = Queue()
@@ -97,30 +100,32 @@ class BaseClient:
self.disconnect_handler = None
def send(self, data: Object, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
def send(self, *args, **kwargs):
pass
def resolve_peer(self, peer_id: int or str):
def resolve_peer(self, *args, **kwargs):
pass
def add_handler(self, handler, group: int = 0) -> tuple:
def fetch_peers(self, *args, **kwargs):
pass
def save_file(
self,
path: str,
file_id: int = None,
file_part: int = 0,
progress: callable = None,
progress_args: tuple = ()
):
def add_handler(self, *args, **kwargs):
pass
def get_messages(
self,
chat_id: int or str,
message_ids: int or list = None,
reply_to_message_ids: int or list = None,
replies: int = 1
):
def save_file(self, *args, **kwargs):
pass
def get_messages(self, *args, **kwargs):
pass
def get_history(self, *args, **kwargs):
pass
def get_dialogs(self, *args, **kwargs):
pass
def get_chat_members(self, *args, **kwargs):
pass
def get_chat_members_count(self, *args, **kwargs):
pass

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -94,6 +94,7 @@ class Syncer:
auth_key=auth_key,
user_id=client.user_id,
date=int(time.time()),
is_bot=client.is_bot,
peers_by_id={
k: getattr(v, "access_hash", None)
for k, v in client.peers_by_id.copy().items()

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -61,14 +61,17 @@ class Filters:
create = create
me = create("Me", lambda _, m: bool(m.from_user and m.from_user.is_self))
"""Filter messages generated by you yourself."""
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)
"""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)
"""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))
"""Filter text messages."""
@@ -86,37 +89,49 @@ class Filters:
"""Filter edited messages."""
audio = create("Audio", lambda _, m: bool(m.audio))
"""Filter messages that contain :obj:`Audio <pyrogram.api.types.pyrogram.Audio>` objects."""
"""Filter messages that contain :obj:`Audio <pyrogram.Audio>` objects."""
document = create("Document", lambda _, m: bool(m.document))
"""Filter messages that contain :obj:`Document <pyrogram.api.types.pyrogram.Document>` objects."""
"""Filter messages that contain :obj:`Document <pyrogram.Document>` objects."""
photo = create("Photo", lambda _, m: bool(m.photo))
"""Filter messages that contain :obj:`Photo <pyrogram.api.types.pyrogram.PhotoSize>` objects."""
"""Filter messages that contain :obj:`Photo <pyrogram.PhotoSize>` objects."""
sticker = create("Sticker", lambda _, m: bool(m.sticker))
"""Filter messages that contain :obj:`Sticker <pyrogram.api.types.pyrogram.Sticker>` objects."""
"""Filter messages that contain :obj:`Sticker <pyrogram.Sticker>` objects."""
animation = create("GIF", lambda _, m: bool(m.animation))
"""Filter messages that contain :obj:`Animation <pyrogram.api.types.pyrogram.Animation>` objects."""
animation = create("Animation", lambda _, m: bool(m.animation))
"""Filter messages that contain :obj:`Animation <pyrogram.Animation>` objects."""
game = create("Game", lambda _, m: bool(m.game))
"""Filter messages that contain :obj:`Game <pyrogram.Game>` objects."""
video = create("Video", lambda _, m: bool(m.video))
"""Filter messages that contain :obj:`Video <pyrogram.api.types.pyrogram.Video>` objects."""
"""Filter messages that contain :obj:`Video <pyrogram.Video>` objects."""
media_group = create("MediaGroup", lambda _, m: bool(m.media_group_id))
"""Filter messages containing photos or videos being part of an album."""
voice = create("Voice", lambda _, m: bool(m.voice))
"""Filter messages that contain :obj:`Voice <pyrogram.api.types.pyrogram.Voice>` note objects."""
"""Filter messages that contain :obj:`Voice <pyrogram.Voice>` note objects."""
video_note = create("Voice", lambda _, m: bool(m.video_note))
"""Filter messages that contain :obj:`VideoNote <pyrogram.api.types.pyrogram.VideoNote>` objects."""
"""Filter messages that contain :obj:`VideoNote <pyrogram.VideoNote>` objects."""
contact = create("Contact", lambda _, m: bool(m.contact))
"""Filter messages that contain :obj:`Contact <pyrogram.api.types.pyrogram.Contact>` objects."""
"""Filter messages that contain :obj:`Contact <pyrogram.Contact>` objects."""
location = create("Location", lambda _, m: bool(m.location))
"""Filter messages that contain :obj:`Location <pyrogram.api.types.pyrogram.Location>` objects."""
"""Filter messages that contain :obj:`Location <pyrogram.Location>` objects."""
venue = create("Venue", lambda _, m: bool(m.venue))
"""Filter messages that contain :obj:`Venue <pyrogram.api.types.pyrogram.Venue>` objects."""
"""Filter messages that contain :obj:`Venue <pyrogram.Venue>` objects."""
web_page = create("WebPage", lambda _, m: m.web_page)
"""Filter messages sent with a webpage preview."""
poll = create("Poll", lambda _, m: m.poll)
"""Filter messages that contain :obj:`Poll <pyrogram.Poll>` objects."""
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
"""Filter messages sent in private chats."""
@@ -160,6 +175,9 @@ class Filters:
pinned_message = create("PinnedMessage", lambda _, m: bool(m.pinned_message))
"""Filter service messages for pinned messages."""
game_high_score = create("GameHighScore", lambda _, m: bool(m.game_high_score))
"""Filter service messages for game high scores."""
reply_keyboard = create("ReplyKeyboard", lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup))
"""Filter messages containing reply keyboard markups"""
@@ -169,6 +187,9 @@ class Filters:
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
"""Filter messages containing mentions"""
via_bot = create("ViaBot", lambda _, m: bool(m.via_bot))
"""Filter messages sent via inline bots"""
service = create("Service", lambda _, m: bool(m.service))
"""Filter service messages. A service message contains any of the following fields set
@@ -181,7 +202,8 @@ class Filters:
- channel_chat_created
- migrate_to_chat_id
- migrate_from_chat_id
- pinned_message"""
- pinned_message
- game_score"""
media = create("Media", lambda _, m: bool(m.media))
"""Filter media messages. A media message contains any of the following fields set
@@ -196,7 +218,8 @@ class Filters:
- video_note
- contact
- location
- venue"""
- venue
- poll"""
@staticmethod
def command(command: str or list,
@@ -267,7 +290,7 @@ class Filters:
"""
def f(_, m):
m.matches = [i for i in _.p.finditer(m.text or "")]
m.matches = [i for i in _.p.finditer(m.text or m.caption or "")]
return bool(m.matches)
return create("Regex", f, p=re.compile(pattern, flags))

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -45,10 +45,3 @@ class CallbackQueryHandler(Handler):
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)
def check(self, callback_query):
return (
self.filters(callback_query)
if callable(self.filters)
else True
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -48,8 +48,4 @@ class DeletedMessagesHandler(Handler):
super().__init__(callback, filters)
def check(self, messages):
return (
self.filters(messages.messages[0])
if callable(self.filters)
else True
)
return super().check(messages.messages[0])

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -21,3 +21,10 @@ class Handler:
def __init__(self, callback: callable, filters=None):
self.callback = callback
self.filters = filters
def check(self, update):
return (
self.filters(update)
if callable(self.filters)
else True
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -46,10 +46,3 @@ class MessageHandler(Handler):
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)
def check(self, message):
return (
self.filters(message)
if callable(self.filters)
else True
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -45,10 +45,3 @@ class UserStatusHandler(Handler):
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)
def check(self, user_status):
return (
self.filters(user_status)
if callable(self.filters)
else True
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -23,7 +23,6 @@ from .decorators import Decorators
from .messages import Messages
from .password import Password
from .users import Users
from .utilities import Utilities
class Methods(
@@ -32,7 +31,6 @@ class Methods(
Password,
Chats,
Users,
Utilities,
Messages,
Decorators
):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -18,9 +18,12 @@
from .answer_callback_query import AnswerCallbackQuery
from .answer_inline_query import AnswerInlineQuery
from .get_game_high_scores import GetGameHighScores
from .get_inline_bot_results import GetInlineBotResults
from .request_callback_answer import RequestCallbackAnswer
from .send_game import SendGame
from .send_inline_bot_result import SendInlineBotResult
from .set_game_score import SetGameScore
class Bots(
@@ -28,6 +31,9 @@ class Bots(
AnswerInlineQuery,
GetInlineBotResults,
RequestCallbackAnswer,
SendInlineBotResult
SendInlineBotResult,
SendGame,
SetGameScore,
GetGameHighScores
):
pass

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -21,12 +21,14 @@ from pyrogram.client.ext import BaseClient
class AnswerCallbackQuery(BaseClient):
def answer_callback_query(self,
callback_query_id: str,
text: str = None,
show_alert: bool = None,
url: str = None,
cache_time: int = 0):
def answer_callback_query(
self,
callback_query_id: str,
text: str = None,
show_alert: bool = None,
url: str = None,
cache_time: int = 0
):
"""Use this method to send answers to callback queries sent from inline keyboards.
The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.

View File

@@ -0,0 +1,68 @@
# 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
import pyrogram
from pyrogram.api import functions
from pyrogram.client.ext import BaseClient
class GetGameHighScores(BaseClient):
def get_game_high_scores(
self,
user_id: Union[int, str],
chat_id: Union[int, str],
message_id: int = None
):
"""Use this method to get data for high score tables.
Args:
user_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).
chat_id (``int`` | ``str``, *optional*):
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).
Required if inline_message_id is not specified.
message_id (``int``, *optional*):
Identifier of the sent message.
Required if inline_message_id is not specified.
Returns:
On success, a :obj:`GameHighScores <pyrogram.GameHighScores>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
# TODO: inline_message_id
return pyrogram.GameHighScores._parse(
self,
self.send(
functions.messages.GetGameHighScores(
peer=self.resolve_peer(chat_id),
id=message_id,
user_id=self.resolve_peer(user_id)
)
)
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,18 +16,22 @@
# 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, types
from pyrogram.api.errors import UnknownError
from pyrogram.client.ext import BaseClient
class GetInlineBotResults(BaseClient):
def get_inline_bot_results(self,
bot: int or str,
query: str,
offset: str = "",
latitude: float = None,
longitude: float = None):
def get_inline_bot_results(
self,
bot: Union[int, str],
query: str,
offset: str = "",
latitude: float = None,
longitude: float = None
):
"""Use this method to get bot results via inline queries.
You can then send a result using :obj:`send_inline_bot_result <pyrogram.Client.send_inline_bot_result>`

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,15 +16,19 @@
# 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 pyrogram.client.ext import BaseClient
class RequestCallbackAnswer(BaseClient):
def request_callback_answer(self,
chat_id: int or str,
message_id: int,
callback_data: str):
def request_callback_answer(
self,
chat_id: Union[int, str],
message_id: int,
callback_data: bytes
):
"""Use this method to request a callback answer from bots. This is the equivalent of clicking an
inline button containing callback data.
@@ -37,7 +41,7 @@ class RequestCallbackAnswer(BaseClient):
message_id (``int``):
The message id the inline keyboard is attached on.
callback_data (``str``):
callback_data (``bytes``):
Callback data associated with the inline button you want to get the answer from.
Returns:
@@ -52,7 +56,7 @@ class RequestCallbackAnswer(BaseClient):
functions.messages.GetBotCallbackAnswer(
peer=self.resolve_peer(chat_id),
msg_id=message_id,
data=callback_data.encode()
data=callback_data
),
retries=0,
timeout=10

View File

@@ -0,0 +1,91 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class SendGame(BaseClient):
def send_game(
self,
chat_id: Union[int, str],
game_short_name: str,
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
"pyrogram.InlineKeyboardMarkup",
"pyrogram.ReplyKeyboardMarkup",
"pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"
] = None
) -> "pyrogram.Message":
"""Use this method to send a game.
Args:
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).
game_short_name (``str``):
Short name of the game, serves as the unique identifier for the game. Set up your games via Botfather.
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`, *optional*):
An object for an inline keyboard. If empty, one Play game_title button will be shown automatically.
If not empty, the first button must launch the game.
Returns:
On success, the sent :obj:`Message` is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
r = self.send(
functions.messages.SendMedia(
peer=self.resolve_peer(chat_id),
media=types.InputMediaGame(
id=types.InputGameShortName(
bot_id=types.InputUserSelf(),
short_name=game_short_name
),
),
message="",
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
)
)
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}
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,22 @@
# 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 pyrogram.client.ext import BaseClient
class SendInlineBotResult(BaseClient):
def send_inline_bot_result(self,
chat_id: int or str,
query_id: int,
result_id: str,
disable_notification: bool = None,
reply_to_message_id: int = None):
def send_inline_bot_result(
self,
chat_id: Union[int, str],
query_id: int,
result_id: str,
disable_notification: bool = None,
reply_to_message_id: int = None,
hide_via: bool = None
):
"""Use this method to send an inline bot result.
Bot results can be retrieved using :obj:`get_inline_bot_results <pyrogram.Client.get_inline_bot_results>`
@@ -49,6 +54,9 @@ class SendInlineBotResult(BaseClient):
reply_to_message_id (``bool``, *optional*):
If the message is a reply, ID of the original message.
hide_via (``bool``):
Sends the message with *via @bot* hidden.
Returns:
On success, the sent Message is returned.
@@ -62,6 +70,7 @@ class SendInlineBotResult(BaseClient):
id=result_id,
random_id=self.rnd_id(),
silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id
reply_to_msg_id=reply_to_message_id,
hide_via=hide_via or None
)
)

View File

@@ -0,0 +1,92 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class SetGameScore(BaseClient):
def set_game_score(
self,
user_id: Union[int, str],
score: int,
force: bool = None,
disable_edit_message: bool = None,
chat_id: Union[int, str] = None,
message_id: int = None
):
# inline_message_id: str = None): TODO Add inline_message_id
"""Use this method to set the score of the specified user in a game.
Args:
user_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).
score (``int``):
New score, must be non-negative.
force (``bool``, *optional*):
Pass True, if the high score is allowed to decrease.
This can be useful when fixing mistakes or banning cheaters.
disable_edit_message (``bool``, *optional*):
Pass True, if the game message should not be automatically edited to include the current scoreboard.
chat_id (``int`` | ``str``, *optional*):
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).
Required if inline_message_id is not specified.
message_id (``int``, *optional*):
Identifier of the sent message.
Required if inline_message_id is not specified.
Returns:
On success, if the message was sent by the bot, returns the edited :obj:`Message <pyrogram.Message>`,
otherwise returns True.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
:class:`BotScoreNotModified` if the new score is not greater than the user's current score in the chat and force is False.
"""
r = self.send(
functions.messages.SetGameScore(
peer=self.resolve_peer(chat_id),
score=score,
id=message_id,
user_id=self.resolve_peer(user_id),
force=force or None,
edit_message=not disable_edit_message or None
)
)
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
)
return True

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -22,18 +22,23 @@ from .get_chat import GetChat
from .get_chat_member import GetChatMember
from .get_chat_members import GetChatMembers
from .get_chat_members_count import GetChatMembersCount
from .get_chat_preview import GetChatPreview
from .get_dialogs import GetDialogs
from .iter_chat_members import IterChatMembers
from .iter_dialogs import IterDialogs
from .join_chat import JoinChat
from .kick_chat_member import KickChatMember
from .leave_chat import LeaveChat
from .pin_chat_message import PinChatMessage
from .promote_chat_member import PromoteChatMember
from .restrict_chat import RestrictChat
from .restrict_chat_member import RestrictChatMember
from .set_chat_description import SetChatDescription
from .set_chat_photo import SetChatPhoto
from .set_chat_title import SetChatTitle
from .unban_chat_member import UnbanChatMember
from .unpin_chat_message import UnpinChatMessage
from .update_chat_username import UpdateChatUsername
class Chats(
@@ -54,6 +59,11 @@ class Chats(
PinChatMessage,
UnpinChatMessage,
GetDialogs,
GetChatMembersCount
GetChatMembersCount,
GetChatPreview,
IterDialogs,
IterChatMembers,
UpdateChatUsername,
RestrictChat
):
pass

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,17 @@
# 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, types
from ...ext import BaseClient
class DeleteChatPhoto(BaseClient):
def delete_chat_photo(self, chat_id: int or str):
def delete_chat_photo(
self,
chat_id: Union[int, str]
) -> bool:
"""Use this method to 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.

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,17 @@
# 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, types
from ...ext import BaseClient
class ExportChatInviteLink(BaseClient):
def export_chat_invite_link(self, chat_id: int or str):
def export_chat_invite_link(
self,
chat_id: Union[int, str]
) -> str:
"""Use this method to generate a new invite link for a chat; any previously generated link is revoked.
You must be an administrator in the chat for this to work and have the appropriate admin rights.
@@ -42,7 +47,7 @@ class ExportChatInviteLink(BaseClient):
if isinstance(peer, types.InputPeerChat):
return self.send(
functions.messages.ExportChatInvite(
chat_id=peer.chat_id
peer=peer.chat_id
)
).link
elif isinstance(peer, types.InputPeerChannel):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,32 +16,63 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient, utils
from ...ext import BaseClient
class GetChat(BaseClient):
def get_chat(self, chat_id: int or str):
def get_chat(
self,
chat_id: Union[int, str]
) -> "pyrogram.Chat":
"""Use this method to get up to date information about the chat (current name of the user for
one-on-one conversations, current username of a user, group or channel, etc.)
Args:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
Unique identifier for the target chat in form of a *t.me/joinchat/* link, identifier (int) or username
of the target channel/supergroup (in the format @username).
Returns:
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
``ValueError`` in case the chat invite link refers to a chat you haven't joined yet.
"""
match = self.INVITE_LINK_RE.match(str(chat_id))
if match:
h = match.group(1)
r = self.send(
functions.messages.CheckChatInvite(
hash=h
)
)
if isinstance(r, types.ChatInvite):
raise ValueError("You haven't joined \"t.me/joinchat/{}\" yet".format(h))
self.fetch_peers([r.chat])
if isinstance(r.chat, types.Chat):
chat_id = -r.chat.id
if isinstance(r.chat, types.Channel):
chat_id = int("-100" + str(r.chat.id))
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChannel):
r = self.send(functions.channels.GetFullChannel(peer))
r = self.send(functions.channels.GetFullChannel(channel=peer))
elif isinstance(peer, (types.InputPeerUser, types.InputPeerSelf)):
r = self.send(functions.users.GetFullUser(peer))
r = self.send(functions.users.GetFullUser(id=peer))
else:
r = self.send(functions.messages.GetFullChat(peer.chat_id))
r = self.send(functions.messages.GetFullChat(chat_id=peer.chat_id))
return utils.parse_chat_full(self, r)
return pyrogram.Chat._parse_full(self, r)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,14 +16,19 @@
# 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
import pyrogram
from pyrogram.api import functions, types, errors
from ...ext import BaseClient, utils
from ...ext import BaseClient
class GetChatMember(BaseClient):
def get_chat_member(self,
chat_id: int or str,
user_id: int or str):
def get_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str]
) -> "pyrogram.ChatMember":
"""Use this method to get information about one member of a chat.
Args:
@@ -51,8 +56,8 @@ class GetChatMember(BaseClient):
)
)
for member in utils.parse_chat_members(full_chat).chat_members:
if member.user.id == user_id.user_id:
for member in pyrogram.ChatMembers._parse(self, full_chat).chat_members:
if member.user.is_self:
return member
else:
raise errors.UserNotParticipant
@@ -64,12 +69,8 @@ class GetChatMember(BaseClient):
)
)
return utils.parse_chat_members(
types.channels.ChannelParticipants(
count=1,
participants=[r.participant],
users=r.users
)
).chat_members[0]
users = {i.id: i for i in r.users}
return pyrogram.ChatMember._parse(self, r.participant, users)
else:
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,8 +16,11 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient, utils
from ...ext import BaseClient
class Filters:
@@ -30,16 +33,20 @@ class Filters:
class GetChatMembers(BaseClient):
def get_chat_members(self,
chat_id: int or str,
offset: int = 0,
limit: int = 200,
query: str = "",
filter: str = Filters.ALL):
"""Use this method to get the members list of a chat.
def get_chat_members(
self,
chat_id: Union[int, str],
offset: int = 0,
limit: int = 200,
query: str = "",
filter: str = Filters.ALL
) -> "pyrogram.ChatMembers":
"""Use this method to get a chunk of the members list of a chat.
You can get up to 200 chat members at once.
A chat can be either a basic group, a supergroup or a channel.
You must be admin to retrieve the members list of a channel (also known as "subscribers").
For a more convenient way of getting chat members see :meth:`iter_chat_members`.
Args:
chat_id (``int`` | ``str``):
@@ -83,10 +90,11 @@ class GetChatMembers(BaseClient):
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChat):
return utils.parse_chat_members(
return pyrogram.ChatMembers._parse(
self,
self.send(
functions.messages.GetFullChat(
peer.chat_id
chat_id=peer.chat_id
)
)
)
@@ -108,7 +116,8 @@ class GetChatMembers(BaseClient):
else:
raise ValueError("Invalid filter \"{}\"".format(filter))
return utils.parse_chat_members(
return pyrogram.ChatMembers._parse(
self,
self.send(
functions.channels.GetParticipants(
channel=peer,

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,17 @@
# 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, types
from ...ext import BaseClient
class GetChatMembersCount(BaseClient):
def get_chat_members_count(self, chat_id: int or str):
def get_chat_members_count(
self,
chat_id: Union[int, str]
) -> int:
"""Use this method to get the number of members in a chat.
Args:

View 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/>.
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient
class GetChatPreview(BaseClient):
def get_chat_preview(
self,
invite_link: str
):
"""Use this method to get the preview of a chat using the invite link.
This method only returns a chat preview, if you want to join a chat use :meth:`join_chat`
Args:
invite_link (``str``):
Unique identifier for the target chat in form of *t.me/joinchat/* links.
Returns:
Either :obj:`Chat` or :obj:`ChatPreview`, depending on whether you already joined the chat or not.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
``ValueError`` in case of an invalid invite_link.
"""
match = self.INVITE_LINK_RE.match(invite_link)
if match:
r = self.send(
functions.messages.CheckChatInvite(
hash=match.group(1)
)
)
if isinstance(r, types.ChatInvite):
return pyrogram.ChatPreview._parse(self, r)
if isinstance(r, types.ChatInviteAlready):
chat = r.chat
if isinstance(chat, types.Chat):
return pyrogram.Chat._parse_chat_chat(self, chat)
if isinstance(chat, types.Channel):
return pyrogram.Chat._parse_channel_chat(self, chat)
else:
raise ValueError("The invite_link is invalid")

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,33 +16,42 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
import time
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient, utils
from pyrogram.api.errors import FloodWait
from ...ext import BaseClient
log = logging.getLogger(__name__)
class GetDialogs(BaseClient):
def get_dialogs(self,
offset_dialogs=None,
limit: int = 100,
pinned_only: bool = False):
"""Use this method to get the user's dialogs
def get_dialogs(
self,
offset_date: int = 0,
limit: int = 100,
pinned_only: bool = False
) -> "pyrogram.Dialogs":
"""Use this method to get a chunk of the user's dialogs
You can get up to 100 dialogs at once.
For a more convenient way of getting a user's dialogs see :meth:`iter_dialogs`.
Args:
offset_date (``int``):
The offset date in Unix time taken from the top message of a :obj:`Dialog`.
Defaults to 0. Valid for non-pinned dialogs only.
limit (``str``, *optional*):
Limits the number of dialogs to be retrieved.
Defaults to 100
Defaults to 100. Valid for non-pinned dialogs only.
pinned_only (``bool``, *optional*):
Pass True if you want to get only pinned dialogs.
Defaults to False.
offset_dialogs (:obj:`Dialogs`):
Pass the previous dialogs object to retrieve the next dialogs chunk starting from the last dialog.
Defaults to None (start from the beginning).
Returns:
On success, a :obj:`Dialogs` object is returned.
@@ -50,76 +59,25 @@ class GetDialogs(BaseClient):
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
if pinned_only:
r = self.send(functions.messages.GetPinnedDialogs())
else:
offset_date = 0
if offset_dialogs:
for dialog in reversed(offset_dialogs.dialogs):
top_message = dialog.top_message
if top_message:
message_date = top_message.date
if message_date:
offset_date = message_date
break
r = self.send(
functions.messages.GetDialogs(
offset_date=offset_date,
offset_id=0,
offset_peer=types.InputPeerEmpty(),
limit=limit,
hash=0,
exclude_pinned=True
)
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
messages = {}
for message in r.messages:
to_id = message.to_id
if isinstance(to_id, types.PeerUser):
if message.out:
chat_id = to_id.user_id
while True:
try:
if pinned_only:
r = self.send(functions.messages.GetPinnedDialogs())
else:
chat_id = message.from_id
elif isinstance(to_id, types.PeerChat):
chat_id = -to_id.chat_id
r = self.send(
functions.messages.GetDialogs(
offset_date=offset_date,
offset_id=0,
offset_peer=types.InputPeerEmpty(),
limit=limit,
hash=0,
exclude_pinned=True
)
)
except FloodWait as e:
log.warning("Sleeping {}s".format(e.x))
time.sleep(e.x)
else:
chat_id = int("-100" + str(to_id.channel_id))
break
messages[chat_id] = utils.parse_messages(self, message, users, chats)
dialogs = []
for dialog in r.dialogs:
chat_id = dialog.peer
if isinstance(chat_id, types.PeerUser):
chat_id = chat_id.user_id
elif isinstance(chat_id, types.PeerChat):
chat_id = -chat_id.chat_id
else:
chat_id = int("-100" + str(chat_id.channel_id))
dialogs.append(
pyrogram.Dialog(
chat=utils.parse_dialog_chat(dialog.peer, users, chats),
top_message=messages.get(chat_id),
unread_messages_count=dialog.unread_count,
unread_mentions_count=dialog.unread_mentions_count,
unread_mark=dialog.unread_mark,
is_pinned=dialog.pinned
)
)
return pyrogram.Dialogs(
total_count=getattr(r, "count", len(r.dialogs)),
dialogs=dialogs
)
return pyrogram.Dialogs._parse(self, r)

View File

@@ -0,0 +1,132 @@
# 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 string import ascii_lowercase
from typing import Union, Generator
import pyrogram
from pyrogram.api import types
from ...ext import BaseClient
class Filters:
ALL = "all"
KICKED = "kicked"
RESTRICTED = "restricted"
BOTS = "bots"
RECENT = "recent"
ADMINISTRATORS = "administrators"
QUERIES = [""] + [str(i) for i in range(10)] + list(ascii_lowercase)
QUERYABLE_FILTERS = (Filters.ALL, Filters.KICKED, Filters.RESTRICTED)
class IterChatMembers(BaseClient):
def iter_chat_members(
self,
chat_id: Union[int, str],
limit: int = 0,
query: str = "",
filter: str = Filters.ALL
) -> Generator["pyrogram.ChatMember", None, None]:
"""Use this method to iterate through the members of a chat sequentially.
This convenience method does the same as repeatedly calling :meth:`get_chat_members` in a loop, thus saving you
from the hassle of setting up boilerplate code. It is useful for getting the whole members list of a chat with
a single call.
Args:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
limit (``int``, *optional*):
Limits the number of members to be retrieved.
By default, no limit is applied and all members are returned.
query (``str``, *optional*):
Query string to filter members based on their display names and usernames.
Defaults to "" (empty string).
filter (``str``, *optional*):
Filter used to select the kind of members you want to retrieve. Only applicable for supergroups
and channels. It can be any of the followings:
*"all"* - all kind of members,
*"kicked"* - kicked (banned) members only,
*"restricted"* - restricted members only,
*"bots"* - bots only,
*"recent"* - recent members only,
*"administrators"* - chat administrators only.
Defaults to *"all"*.
Returns:
A generator yielding :obj:`ChatMember <pyrogram.ChatMember>` objects.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
current = 0
yielded = set()
queries = [query] if query else QUERIES
total = limit or (1 << 31) - 1
limit = min(200, total)
resolved_chat_id = self.resolve_peer(chat_id)
filter = (
Filters.RECENT
if self.get_chat_members_count(chat_id) <= 10000 and filter == Filters.ALL
else filter
)
if filter not in QUERYABLE_FILTERS:
queries = [""]
for q in queries:
offset = 0
while True:
chat_members = self.get_chat_members(
chat_id=chat_id,
offset=offset,
limit=limit,
query=q,
filter=filter
).chat_members
if not chat_members:
break
if isinstance(resolved_chat_id, types.InputPeerChat):
total = len(chat_members)
offset += len(chat_members)
for chat_member in chat_members:
user_id = chat_member.user.id
if user_id in yielded:
continue
yield chat_member
yielded.add(chat_member.user.id)
current += 1
if current >= total:
return

View File

@@ -0,0 +1,84 @@
# 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 Generator
import pyrogram
from ...ext import BaseClient
class IterDialogs(BaseClient):
def iter_dialogs(
self,
offset_date: int = 0,
limit: int = 0
) -> Generator["pyrogram.Dialog", None, None]:
"""Use this method to iterate through a user's dialogs sequentially.
This convenience method does the same as repeatedly calling :meth:`get_dialogs` in a loop, thus saving you from
the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list with a single call.
Args:
offset_date (``int``):
The offset date in Unix time taken from the top message of a :obj:`Dialog`.
Defaults to 0 (most recent dialog).
limit (``str``, *optional*):
Limits the number of dialogs to be retrieved.
By default, no limit is applied and all dialogs are returned.
Returns:
A generator yielding :obj:`Dialog <pyrogram.Dialog>` objects.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
current = 0
total = limit or (1 << 31) - 1
limit = min(100, total)
pinned_dialogs = self.get_dialogs(
pinned_only=True
).dialogs
for dialog in pinned_dialogs:
yield dialog
current += 1
if current >= total:
return
while True:
dialogs = self.get_dialogs(
offset_date=offset_date,
limit=limit
).dialogs
if not dialogs:
return
offset_date = dialogs[-1].top_message.date
for dialog in dialogs:
yield dialog
current += 1
if current >= total:
return

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,30 +16,41 @@
# 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, types
from ...ext import BaseClient
class JoinChat(BaseClient):
def join_chat(self, chat_id: str):
def join_chat(
self,
chat_id: str
):
"""Use this method to join a group chat or channel.
Args:
chat_id (``str``):
Unique identifier for the target chat in form of *t.me/joinchat/* links or username of the target
Unique identifier for the target chat in form of a *t.me/joinchat/* link or username of the target
channel/supergroup (in the format @username).
Returns:
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
match = self.INVITE_LINK_RE.match(chat_id)
if match:
return self.send(
chat = self.send(
functions.messages.ImportChatInvite(
hash=match.group(1)
)
)
if isinstance(chat.chats[0], types.Chat):
return pyrogram.Chat._parse_chat_chat(self, chat.chats[0])
elif isinstance(chat.chats[0], types.Channel):
return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])
else:
resolved_peer = self.send(
functions.contacts.ResolveUsername(
@@ -52,8 +63,10 @@ class JoinChat(BaseClient):
access_hash=resolved_peer.chats[0].access_hash
)
return self.send(
chat = self.send(
functions.channels.JoinChannel(
channel=channel
)
)
return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,16 +16,20 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import utils
from ...ext import BaseClient
class KickChatMember(BaseClient):
def kick_chat_member(self,
chat_id: int or str,
user_id: int or str,
until_date: int = 0):
def kick_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
until_date: int = 0
) -> Union["pyrogram.Message", bool]:
"""Use this method to kick a user from a group, a supergroup or a channel.
In the case of supergroups and channels, the user will not be able to return to the group on their own using
invite links, etc., unless unbanned first. You must be an administrator in the chat for this to work and must
@@ -50,7 +54,7 @@ class KickChatMember(BaseClient):
considered to be banned forever. Defaults to 0 (ban forever).
Returns:
True on success.
On success, either True or a service :obj:`Message <pyrogram.Message>` will be returned (when applicable).
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -63,7 +67,7 @@ class KickChatMember(BaseClient):
functions.channels.EditBanned(
channel=chat_peer,
user_id=user_peer,
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=until_date,
view_messages=True,
send_messages=True,
@@ -86,8 +90,10 @@ class KickChatMember(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
return utils.parse_messages(
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
)
else:
return True

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,18 @@
# 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, types
from ...ext import BaseClient
class LeaveChat(BaseClient):
def leave_chat(self, chat_id: int or str, delete: bool = False):
def leave_chat(
self,
chat_id: Union[int, str],
delete: bool = False
):
"""Use this method to leave a group chat or channel.
Args:

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,13 +16,20 @@
# 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 pyrogram.api import functions, types
from typing import Union
from pyrogram.api import functions
from ...ext import BaseClient
class PinChatMessage(BaseClient):
def pin_chat_message(self, chat_id: int or str, message_id: int, disable_notification: bool = None):
"""Use this method to pin a message in a supergroup or a channel.
def pin_chat_message(
self,
chat_id: Union[int, str],
message_id: int,
disable_notification: bool = None
) -> bool:
"""Use this method to pin a message in a group, channel or your own chat.
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin right in
the supergroup or "can_edit_messages" admin right in the channel.
@@ -42,21 +49,13 @@ class PinChatMessage(BaseClient):
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
"""
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChannel):
self.send(
functions.channels.UpdatePinnedMessage(
channel=peer,
id=message_id,
silent=disable_notification or None
)
self.send(
functions.messages.UpdatePinnedMessage(
peer=self.resolve_peer(chat_id),
id=message_id,
silent=disable_notification or None
)
elif isinstance(peer, types.InputPeerChat):
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
else:
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
)
return True

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,23 +16,28 @@
# 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, types
from ...ext import BaseClient
class PromoteChatMember(BaseClient):
def promote_chat_member(self,
chat_id: int or str,
user_id: int or str,
can_change_info: bool = True,
can_post_messages: bool = False,
can_edit_messages: bool = False,
can_delete_messages: bool = True,
can_invite_users: bool = True,
can_restrict_members: bool = True,
can_pin_messages: bool = False,
can_promote_members: bool = False):
def promote_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
can_change_info: bool = True,
can_post_messages: bool = False,
can_edit_messages: bool = False,
can_delete_messages: bool = True,
can_restrict_members: bool = True,
can_invite_users: bool = True,
can_pin_messages: bool = False,
can_promote_members: bool = False
) -> bool:
"""Use this method to promote or demote a user in a supergroup or a channel.
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
Pass False for all boolean parameters to demote a user.
@@ -56,12 +61,12 @@ class PromoteChatMember(BaseClient):
can_delete_messages (``bool``, *optional*):
Pass True, if the administrator can delete messages of other users.
can_invite_users (``bool``, *optional*):
Pass True, if the administrator can invite new users to the chat.
can_restrict_members (``bool``, *optional*):
Pass True, if the administrator can restrict, ban or unban chat members.
can_invite_users (``bool``, *optional*):
Pass True, if the administrator can invite new users to the chat.
can_pin_messages (``bool``, *optional*):
Pass True, if the administrator can pin messages, supergroups only.
@@ -80,17 +85,15 @@ class PromoteChatMember(BaseClient):
functions.channels.EditAdmin(
channel=self.resolve_peer(chat_id),
user_id=self.resolve_peer(user_id),
admin_rights=types.ChannelAdminRights(
admin_rights=types.ChatAdminRights(
change_info=can_change_info or None,
post_messages=can_post_messages or None,
edit_messages=can_edit_messages or None,
delete_messages=can_delete_messages or None,
ban_users=can_restrict_members or None,
invite_users=can_invite_users or None,
invite_link=can_invite_users or None,
pin_messages=can_pin_messages or None,
add_admins=can_promote_members or None,
manage_call=None
)
)
)

View File

@@ -0,0 +1,143 @@
# 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, types
from ...ext import BaseClient
from ...types.user_and_chats import Chat
class RestrictChat(BaseClient):
def restrict_chat(
self,
chat_id: Union[int, str],
can_send_messages: bool = False,
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:
"""Use this method to restrict a chat.
Pass True for all boolean parameters to lift restrictions from a chat.
Args:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
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_media_messages.
can_add_web_page_previews (``bool``, *optional*):
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
can_send_polls (``bool``, *optional*):
Pass True, if the user can send polls, implies can_send_media_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:
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
send_messages = True
send_media = True
send_stickers = True
send_gifs = True
send_games = True
send_inline = True
embed_links = True
send_polls = True
change_info = True
invite_users = True
pin_messages = True
if can_send_messages:
send_messages = None
if can_send_media_messages:
send_messages = None
send_media = None
if can_send_other_messages:
send_messages = None
send_media = None
send_stickers = None
send_gifs = None
send_games = None
send_inline = None
if can_add_web_page_previews:
send_messages = None
send_media = None
embed_links = None
if can_send_polls:
send_messages = None
send_polls = None
if can_change_info:
change_info = None
if can_invite_users:
invite_users = None
if can_pin_messages:
pin_messages = None
r = self.send(
functions.messages.EditChatDefaultBannedRights(
peer=self.resolve_peer(chat_id),
banned_rights=types.ChatBannedRights(
until_date=0,
send_messages=send_messages,
send_media=send_media,
send_stickers=send_stickers,
send_gifs=send_gifs,
send_games=send_games,
send_inline=send_inline,
embed_links=embed_links,
send_polls=send_polls,
change_info=change_info,
invite_users=invite_users,
pin_messages=pin_messages
)
)
)
return Chat._parse_chat(self, r.chats[0])

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,19 +16,28 @@
# 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, types
from ...ext import BaseClient
from ...types.user_and_chats import Chat
class RestrictChatMember(BaseClient):
def restrict_chat_member(self,
chat_id: int or str,
user_id: int or str,
until_date: int = 0,
can_send_messages: bool = False,
can_send_media_messages: bool = False,
can_send_other_messages: bool = False,
can_add_web_page_previews: bool = False):
def restrict_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str],
until_date: int = 0,
can_send_messages: bool = False,
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:
"""Use this method to 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. Pass True for all boolean parameters to lift
restrictions from a user.
@@ -58,10 +67,22 @@ class RestrictChatMember(BaseClient):
implies can_send_media_messages.
can_add_web_page_previews (``bool``, *optional*):
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
can_send_polls (``bool``, *optional*):
Pass True, if the user can send polls, implies can_send_media_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:
True on success.
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -73,6 +94,10 @@ class RestrictChatMember(BaseClient):
send_games = True
send_inline = True
embed_links = True
send_polls = True
change_info = True
invite_users = True
pin_messages = True
if can_send_messages:
send_messages = None
@@ -82,6 +107,7 @@ class RestrictChatMember(BaseClient):
send_media = None
if can_send_other_messages:
send_messages = None
send_media = None
send_stickers = None
send_gifs = None
@@ -89,14 +115,28 @@ class RestrictChatMember(BaseClient):
send_inline = None
if can_add_web_page_previews:
send_messages = None
send_media = None
embed_links = None
self.send(
if can_send_polls:
send_messages = None
send_polls = None
if can_change_info:
change_info = None
if can_invite_users:
invite_users = None
if can_pin_messages:
pin_messages = None
r = self.send(
functions.channels.EditBanned(
channel=self.resolve_peer(chat_id),
user_id=self.resolve_peer(user_id),
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=until_date,
send_messages=send_messages,
send_media=send_media,
@@ -104,9 +144,13 @@ class RestrictChatMember(BaseClient):
send_gifs=send_gifs,
send_games=send_games,
send_inline=send_inline,
embed_links=embed_links
embed_links=embed_links,
send_polls=send_polls,
change_info=change_info,
invite_users=invite_users,
pin_messages=pin_messages
)
)
)
return True
return Chat._parse_chat(self, r.chats[0])

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,18 @@
# 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, types
from ...ext import BaseClient
class SetChatDescription(BaseClient):
def set_chat_description(self, chat_id: int or str, description: str):
def set_chat_description(
self,
chat_id: Union[int, str],
description: str
) -> bool:
"""Use this method to change the description of a supergroup or a channel.
You must be an administrator in the chat for this to work and must have the appropriate admin rights.

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -19,13 +19,18 @@
import os
from base64 import b64decode
from struct import unpack
from typing import Union
from pyrogram.api import functions, types
from ...ext import BaseClient
class SetChatPhoto(BaseClient):
def set_chat_photo(self, chat_id: int or str, photo: str):
def set_chat_photo(
self,
chat_id: Union[int, str],
photo: str
) -> bool:
"""Use this method to 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.
@@ -58,7 +63,8 @@ class SetChatPhoto(BaseClient):
photo = types.InputChatPhoto(
id=types.InputPhoto(
id=s[0],
access_hash=s[1]
access_hash=s[1],
file_reference=b""
)
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,12 +16,18 @@
# 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, types
from ...ext import BaseClient
class SetChatTitle(BaseClient):
def set_chat_title(self, chat_id: int or str, title: str):
def set_chat_title(
self,
chat_id: Union[int, str],
title: str
) -> bool:
"""Use this method to change the title of a chat.
Titles 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.

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,14 +16,18 @@
# 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, types
from ...ext import BaseClient
class UnbanChatMember(BaseClient):
def unban_chat_member(self,
chat_id: int or str,
user_id: int or str):
def unban_chat_member(
self,
chat_id: Union[int, str],
user_id: Union[int, str]
) -> bool:
"""Use this method to unban a previously kicked user in a supergroup or channel.
The user will **not** return to the group or channel automatically, but will be able to join via link, etc.
You must be an administrator for this to work.
@@ -46,7 +50,7 @@ class UnbanChatMember(BaseClient):
functions.channels.EditBanned(
channel=self.resolve_peer(chat_id),
user_id=self.resolve_peer(user_id),
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=0
)
)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,13 +16,18 @@
# 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 pyrogram.api import functions, types
from typing import Union
from pyrogram.api import functions
from ...ext import BaseClient
class UnpinChatMessage(BaseClient):
def unpin_chat_message(self, chat_id: int or str):
"""Use this method to unpin a message in a supergroup or a channel.
def unpin_chat_message(
self,
chat_id: Union[int, str]
) -> bool:
"""Use this method to unpin a message in a group, channel or your own chat.
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin
right in the supergroup or "can_edit_messages" admin right in the channel.
@@ -35,20 +40,12 @@ class UnpinChatMessage(BaseClient):
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
"""
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChannel):
self.send(
functions.channels.UpdatePinnedMessage(
channel=peer,
id=0
)
self.send(
functions.messages.UpdatePinnedMessage(
peer=self.resolve_peer(chat_id),
id=0
)
elif isinstance(peer, types.InputPeerChat):
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
else:
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
)
return True

View File

@@ -0,0 +1,61 @@
# 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, types
from ...ext import BaseClient
class UpdateChatUsername(BaseClient):
def update_chat_username(
self,
chat_id: Union[int, str],
username: Union[str, None]
) -> bool:
"""Use this method to update a channel or a supergroup username.
To update your own username (for users only, not bots) you can use :meth:`update_username`.
Args:
chat_id (``int`` | ``str``)
Unique identifier (int) or username (str) of the target chat.
username (``str`` | ``None``):
Username to set. Pass "" (empty string) or None to remove the username.
Returns:
True on success.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
``ValueError`` if a chat_id belongs to a user or chat.
"""
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChannel):
return bool(
self.send(
functions.channels.UpdateUsername(
channel=peer,
username=username or ""
)
)
)
else:
raise ValueError("The chat_id \"{}\" belongs to a user or chat".format(chat_id))

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,23 @@
# 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 List
import pyrogram
from pyrogram.api import functions
from ...ext import BaseClient
class AddContacts(BaseClient):
def add_contacts(self, contacts: list):
def add_contacts(
self,
contacts: List["pyrogram.InputPhoneContact"]
):
"""Use this method to add contacts to your Telegram address book.
Args:
contacts (``list``):
A list of :obj:`InputPhoneContact <pyrogram.InputPhoneContact>`
contacts (List of :obj:`InputPhoneContact <pyrogram.InputPhoneContact>`):
The contact list to be added
Returns:
On success, the added contacts are returned.

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,22 @@
# 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 List
from pyrogram.api import functions, types
from pyrogram.api.errors import PeerIdInvalid
from ...ext import BaseClient
class DeleteContacts(BaseClient):
def delete_contacts(self, ids: list):
def delete_contacts(
self,
ids: List[int]
):
"""Use this method to delete contacts from your Telegram address book
Args:
ids (``list``):
ids (List of ``int``):
A list of unique identifiers for the target users.
Can be an ID (int), a username (string) or phone number (string).

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -19,7 +19,8 @@
import logging
import time
from pyrogram.api import functions, types
import pyrogram
from pyrogram.api import functions
from pyrogram.api.errors import FloodWait
from ...ext import BaseClient
@@ -28,25 +29,20 @@ log = logging.getLogger(__name__)
class GetContacts(BaseClient):
def get_contacts(self):
"""Use this method to get contacts from your Telegram address book
Requires no parameters.
"""Use this method to get contacts from your Telegram address book.
Returns:
On success, the user's contacts are returned
On success, a list of :obj:`User` objects is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
while True:
try:
contacts = self.send(functions.contacts.GetContacts(0))
contacts = self.send(functions.contacts.GetContacts(hash=0))
except FloodWait as e:
log.warning("get_contacts flood: waiting {} seconds".format(e.x))
time.sleep(e.x)
continue
else:
if isinstance(contacts, types.contacts.Contacts):
log.info("Total contacts: {}".format(len(self.peers_by_phone)))
return contacts
log.info("Total contacts: {}".format(len(self.peers_by_phone)))
return [pyrogram.User._parse(self, user) for user in contacts.users]

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,31 @@
# 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 Tuple
import pyrogram
from pyrogram.client.filters.filter import Filter
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnCallbackQuery(BaseClient):
def on_callback_query(self, filters=None, group: int = 0):
def on_callback_query(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling
callback queries. This does the same thing as :meth:`add_handler` using the
:class:`CallbackQueryHandler`.
.. note::
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
To reference your own function after it has been decorated, you need to access
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
first element in the tuple.
Args:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of callback queries to be passed
@@ -36,7 +50,10 @@ class OnCallbackQuery(BaseClient):
The group identifier, defaults to 0.
"""
def decorator(func):
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.CallbackQueryHandler(func, filters)
if isinstance(self, Filter):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,31 @@
# 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 Tuple
import pyrogram
from pyrogram.client.filters.filter import Filter
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnDeletedMessages(BaseClient):
def on_deleted_messages(self, filters=None, group: int = 0):
def on_deleted_messages(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling
deleted messages. This does the same thing as :meth:`add_handler` using the
:class:`DeletedMessagesHandler`.
.. note::
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
To reference your own function after it has been decorated, you need to access
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
first element in the tuple.
Args:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of messages to be passed
@@ -36,7 +50,10 @@ class OnDeletedMessages(BaseClient):
The group identifier, defaults to 0.
"""
def decorator(func):
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.DeletedMessagesHandler(func, filters)
if isinstance(self, Filter):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -17,17 +17,18 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnDisconnect(BaseClient):
def on_disconnect(self):
def on_disconnect(self=None) -> callable:
"""Use this decorator to automatically register a function for handling
disconnections. This does the same thing as :meth:`add_handler` using the
:class:`DisconnectHandler`.
"""
def decorator(func):
def decorator(func: callable) -> Handler:
handler = pyrogram.DisconnectHandler(func)
if self is not None:

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,31 @@
# 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 Tuple
import pyrogram
from pyrogram.client.filters.filter import Filter
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnMessage(BaseClient):
def on_message(self=None, filters=None, group: int = 0):
def on_message(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling
messages. This does the same thing as :meth:`add_handler` using the
:class:`MessageHandler`.
.. note::
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
To reference your own function after it has been decorated, you need to access
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
first element in the tuple.
Args:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of messages to be passed
@@ -36,7 +50,10 @@ class OnMessage(BaseClient):
The group identifier, defaults to 0.
"""
def decorator(func):
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.MessageHandler(func, filters)
if isinstance(self, Filter):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,22 +16,38 @@
# 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 Tuple
import pyrogram
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnRawUpdate(BaseClient):
def on_raw_update(self=None, group: int = 0):
def on_raw_update(
self=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling
raw updates. This does the same thing as :meth:`add_handler` using the
:class:`RawUpdateHandler`.
.. note::
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
To reference your own function after it has been decorated, you need to access
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
first element in the tuple.
Args:
group (``int``, *optional*):
The group identifier, defaults to 0.
"""
def decorator(func):
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.RawUpdateHandler(func)
if isinstance(self, int):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,31 @@
# 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 Tuple
import pyrogram
from pyrogram.client.filters.filter import Filter
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnUserStatus(BaseClient):
def on_user_status(self=None, filters=None, group: int = 0):
def on_user_status(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling
user status updates. This does the same thing as :meth:`add_handler` using the
:class:`UserStatusHandler`.
.. note::
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
To reference your own function after it has been decorated, you need to access
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
first element in the tuple.
Args:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
@@ -35,7 +49,10 @@ class OnUserStatus(BaseClient):
The group identifier, defaults to 0.
"""
def decorator(func):
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.UserStatusHandler(func, filters)
if isinstance(self, Filter):

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,7 +16,9 @@
# 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 .close_poll import ClosePoll
from .delete_messages import DeleteMessages
from .download_media import DownloadMedia
from .edit_message_caption import EditMessageCaption
from .edit_message_media import EditMessageMedia
from .edit_message_reply_markup import EditMessageReplyMarkup
@@ -24,8 +26,11 @@ from .edit_message_text import EditMessageText
from .forward_messages import ForwardMessages
from .get_history import GetHistory
from .get_messages import GetMessages
from .iter_history import IterHistory
from .retract_vote import RetractVote
from .send_animation import SendAnimation
from .send_audio import SendAudio
from .send_cached_media import SendCachedMedia
from .send_chat_action import SendChatAction
from .send_contact import SendContact
from .send_document import SendDocument
@@ -33,11 +38,13 @@ from .send_location import SendLocation
from .send_media_group import SendMediaGroup
from .send_message import SendMessage
from .send_photo import SendPhoto
from .send_poll import SendPoll
from .send_sticker import SendSticker
from .send_venue import SendVenue
from .send_video import SendVideo
from .send_video_note import SendVideoNote
from .send_voice import SendVoice
from .vote_poll import VotePoll
class Messages(
@@ -62,6 +69,13 @@ class Messages(
SendVenue,
SendVideo,
SendVideoNote,
SendVoice
SendVoice,
SendPoll,
VotePoll,
ClosePoll,
RetractVote,
DownloadMedia,
IterHistory,
SendCachedMedia
):
pass

View File

@@ -0,0 +1,67 @@
# 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, types
from pyrogram.client.ext import BaseClient
class ClosePoll(BaseClient):
def close_poll(
self,
chat_id: Union[int, str],
message_id: id
) -> bool:
"""Use this method to close (stop) a poll.
Closed polls can't be reopened and nobody will be able to vote in it anymore.
Args:
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).
message_id (``int``):
Unique poll message identifier inside this chat.
Returns:
On success, True is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
poll = self.get_messages(chat_id, message_id).poll
self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),
id=message_id,
media=types.InputMediaPoll(
poll=types.Poll(
id=poll.id,
closed=True,
question="",
answers=[]
)
)
)
)
return True

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,15 +16,19 @@
# 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, Iterable
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class DeleteMessages(BaseClient):
def delete_messages(self,
chat_id: int or str,
message_ids,
revoke: bool = True):
def delete_messages(
self,
chat_id: Union[int, str],
message_ids: Iterable[int],
revoke: bool = True
) -> bool:
"""Use this method to delete messages, including service messages, with the following limitations:
- A message can only be deleted if it was sent less than 48 hours ago.

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -17,18 +17,21 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from threading import Event
from typing import Union
from pyrogram.client import types as pyrogram_types
from ...ext import BaseClient
import pyrogram
from pyrogram.client.ext import BaseClient
class DownloadMedia(BaseClient):
def download_media(self,
message: pyrogram_types.Message or str,
file_name: str = "",
block: bool = True,
progress: callable = None,
progress_args: tuple = None):
def download_media(
self,
message: Union["pyrogram.Message", str],
file_name: str = "",
block: bool = True,
progress: callable = None,
progress_args: tuple = ()
) -> Union[str, None]:
"""Use this method to download the media from a Message.
Args:
@@ -71,6 +74,7 @@ class DownloadMedia(BaseClient):
Returns:
On success, the absolute path of the downloaded file as string is returned, None otherwise.
In case the download is deliberately stopped with :meth:`stop_transmission`, None is returned as well.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -78,13 +82,14 @@ class DownloadMedia(BaseClient):
"""
error_message = "This message doesn't contain any downloadable media"
if isinstance(message, pyrogram_types.Message):
if isinstance(message, pyrogram.Message):
if message.photo:
media = pyrogram_types.Document(
media = pyrogram.Document(
file_id=message.photo.sizes[-1].file_id,
file_size=message.photo.sizes[-1].file_size,
mime_type="",
date=message.photo.date
date=message.photo.date,
client=self
)
elif message.audio:
media = message.audio
@@ -103,30 +108,32 @@ class DownloadMedia(BaseClient):
else:
raise ValueError(error_message)
elif isinstance(message, (
pyrogram_types.Photo,
pyrogram_types.PhotoSize,
pyrogram_types.Audio,
pyrogram_types.Document,
pyrogram_types.Video,
pyrogram_types.Voice,
pyrogram_types.VideoNote,
pyrogram_types.Sticker,
pyrogram_types.Animation
pyrogram.Photo,
pyrogram.PhotoSize,
pyrogram.Audio,
pyrogram.Document,
pyrogram.Video,
pyrogram.Voice,
pyrogram.VideoNote,
pyrogram.Sticker,
pyrogram.Animation
)):
if isinstance(message, pyrogram_types.Photo):
media = pyrogram_types.Document(
if isinstance(message, pyrogram.Photo):
media = pyrogram.Document(
file_id=message.sizes[-1].file_id,
file_size=message.sizes[-1].file_size,
mime_type="",
date=message.date
date=message.date,
client=self
)
else:
media = message
elif isinstance(message, str):
media = pyrogram_types.Document(
media = pyrogram.Document(
file_id=message,
file_size=0,
mime_type=""
mime_type="",
client=self
)
else:
raise ValueError(error_message)

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,17 +16,22 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient, utils
from pyrogram.client.ext import BaseClient
class EditMessageCaption(BaseClient):
def edit_message_caption(self,
chat_id: int or str,
message_id: int,
caption: str,
parse_mode: str = "",
reply_markup=None):
def edit_message_caption(
self,
chat_id: Union[int, str],
message_id: int,
caption: str,
parse_mode: str = "",
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Use this method to edit captions of messages.
Args:
@@ -68,7 +73,7 @@ class EditMessageCaption(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return utils.parse_messages(
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -17,10 +17,11 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import binascii
import mimetypes
import os
import struct
from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid
from pyrogram.client.ext import BaseClient, utils
@@ -28,14 +29,17 @@ from pyrogram.client.types import (
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
InputMediaAnimation, InputMediaDocument
)
from pyrogram.client.types.input_media import InputMedia
class EditMessageMedia(BaseClient):
def edit_message_media(self,
chat_id: int or str,
message_id: int,
media,
reply_markup=None):
def edit_message_media(
self,
chat_id: Union[int, str],
message_id: int,
media: InputMedia,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Use this method to edit audio, document, photo, or video messages.
If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise,
@@ -81,7 +85,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaPhoto(
id=types.InputPhoto(
id=media.photo.id,
access_hash=media.photo.access_hash
access_hash=media.photo.access_hash,
file_reference=b""
)
)
elif media.media.startswith("http"):
@@ -107,7 +112,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaPhoto(
id=types.InputPhoto(
id=unpacked[2],
access_hash=unpacked[3]
access_hash=unpacked[3],
file_reference=b""
)
)
@@ -117,7 +123,8 @@ class EditMessageMedia(BaseClient):
functions.messages.UploadMedia(
peer=self.resolve_peer(chat_id),
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"],
mime_type="video/mp4",
thumb=None if media.thumb is None else self.save_file(media.thumb),
file=self.save_file(media.media),
attributes=[
types.DocumentAttributeVideo(
@@ -126,7 +133,9 @@ class EditMessageMedia(BaseClient):
w=media.width,
h=media.height
),
types.DocumentAttributeFilename(os.path.basename(media.media))
types.DocumentAttributeFilename(
file_name=os.path.basename(media.media)
)
]
)
)
@@ -135,7 +144,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash
access_hash=media.document.access_hash,
file_reference=b""
)
)
elif media.media.startswith("http"):
@@ -161,7 +171,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
access_hash=unpacked[3],
file_reference=b""
)
)
@@ -171,7 +182,8 @@ class EditMessageMedia(BaseClient):
functions.messages.UploadMedia(
peer=self.resolve_peer(chat_id),
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map.get("." + media.media.split(".")[-1], "audio/mpeg"),
mime_type="audio/mpeg",
thumb=None if media.thumb is None else self.save_file(media.thumb),
file=self.save_file(media.media),
attributes=[
types.DocumentAttributeAudio(
@@ -179,7 +191,9 @@ class EditMessageMedia(BaseClient):
performer=media.performer,
title=media.title
),
types.DocumentAttributeFilename(os.path.basename(media.media))
types.DocumentAttributeFilename(
file_name=os.path.basename(media.media)
)
]
)
)
@@ -188,7 +202,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash
access_hash=media.document.access_hash,
file_reference=b""
)
)
elif media.media.startswith("http"):
@@ -214,7 +229,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
access_hash=unpacked[3],
file_reference=b""
)
)
@@ -224,7 +240,8 @@ class EditMessageMedia(BaseClient):
functions.messages.UploadMedia(
peer=self.resolve_peer(chat_id),
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"],
mime_type="video/mp4",
thumb=None if media.thumb is None else self.save_file(media.thumb),
file=self.save_file(media.media),
attributes=[
types.DocumentAttributeVideo(
@@ -233,7 +250,9 @@ class EditMessageMedia(BaseClient):
w=media.width,
h=media.height
),
types.DocumentAttributeFilename(os.path.basename(media.media)),
types.DocumentAttributeFilename(
file_name=os.path.basename(media.media)
),
types.DocumentAttributeAnimated()
]
)
@@ -243,7 +262,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash
access_hash=media.document.access_hash,
file_reference=b""
)
)
elif media.media.startswith("http"):
@@ -269,7 +289,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
access_hash=unpacked[3],
file_reference=b""
)
)
@@ -279,10 +300,13 @@ class EditMessageMedia(BaseClient):
functions.messages.UploadMedia(
peer=self.resolve_peer(chat_id),
media=types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map.get("." + media.media.split(".")[-1], "text/plain"),
mime_type="application/zip",
thumb=None if media.thumb is None else self.save_file(media.thumb),
file=self.save_file(media.media),
attributes=[
types.DocumentAttributeFilename(os.path.basename(media.media))
types.DocumentAttributeFilename(
file_name=os.path.basename(media.media)
)
]
)
)
@@ -291,7 +315,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=media.document.id,
access_hash=media.document.access_hash
access_hash=media.document.access_hash,
file_reference=b""
)
)
elif media.media.startswith("http"):
@@ -317,7 +342,8 @@ class EditMessageMedia(BaseClient):
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
access_hash=unpacked[3],
file_reference=b""
)
)
@@ -333,7 +359,7 @@ class EditMessageMedia(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return utils.parse_messages(
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,15 +16,20 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient, utils
from pyrogram.client.ext import BaseClient
class EditMessageReplyMarkup(BaseClient):
def edit_message_reply_markup(self,
chat_id: int or str,
message_id: int,
reply_markup=None):
def edit_message_reply_markup(
self,
chat_id: Union[int, str],
message_id: int,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Use this method to edit only the reply markup of messages sent by the bot or via the bot (for inline bots).
Args:
@@ -57,7 +62,7 @@ class EditMessageReplyMarkup(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return utils.parse_messages(
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,18 +16,23 @@
# 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
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient, utils
from pyrogram.client.ext import BaseClient
class EditMessageText(BaseClient):
def edit_message_text(self,
chat_id: int or str,
message_id: int,
text: str,
parse_mode: str = "",
disable_web_page_preview: bool = None,
reply_markup=None):
def edit_message_text(
self,
chat_id: Union[int, str],
message_id: int,
text: str,
parse_mode: str = "",
disable_web_page_preview: bool = None,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Use this method to edit text messages.
Args:
@@ -73,7 +78,7 @@ class EditMessageText(BaseClient):
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return utils.parse_messages(
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,16 +16,23 @@
# 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, Iterable
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient, utils
from ...ext import BaseClient
class ForwardMessages(BaseClient):
def forward_messages(self,
chat_id: int or str,
from_chat_id: int or str,
message_ids,
disable_notification: bool = None):
def forward_messages(
self,
chat_id: Union[int, str],
from_chat_id: Union[int, str],
message_ids: Iterable[int],
disable_notification: bool = None,
as_copy: bool = False,
remove_caption: bool = False
) -> "pyrogram.Messages":
"""Use this method to forward messages of any kind.
Args:
@@ -47,8 +54,17 @@ class ForwardMessages(BaseClient):
Sends the message silently.
Users will receive a notification with no sound.
as_copy (``bool``, *optional*):
Pass True to forward messages without the forward header (i.e.: send a copy of the message content).
Defaults to False.
remove_caption (``bool``, *optional*):
If set to True and *as_copy* is enabled as well, media captions are not preserved when copying the
message. Has no effect if *as_copy* is not enabled.
Defaults to False.
Returns:
On success and in case *message_ids* was a list, the returned value will be a list of the forwarded
On success and in case *message_ids* was an iterable, the returned value will be a list of the forwarded
:obj:`Messages <pyrogram.Message>` even if a list contains just one element, otherwise if
*message_ids* was an integer, the single forwarded :obj:`Message <pyrogram.Message>`
is returned.
@@ -56,31 +72,58 @@ class ForwardMessages(BaseClient):
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
is_iterable = not isinstance(message_ids, int)
message_ids = list(message_ids) if is_iterable else [message_ids]
r = self.send(
functions.messages.ForwardMessages(
to_peer=self.resolve_peer(chat_id),
from_peer=self.resolve_peer(from_chat_id),
id=message_ids,
silent=disable_notification or None,
random_id=[self.rnd_id() for _ in message_ids]
)
)
if as_copy:
forwarded_messages = []
messages = []
for chunk in [message_ids[i:i + 200] for i in range(0, len(message_ids), 200)]:
messages = self.get_messages(chat_id=from_chat_id, message_ids=chunk) # type: pyrogram.Messages
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
messages.append(
utils.parse_messages(
self, i.message,
users, chats
for message in messages.messages:
forwarded_messages.append(
message.forward(
chat_id,
disable_notification=disable_notification,
as_copy=True,
remove_caption=remove_caption
)
)
)
return messages if is_iterable else messages[0]
return pyrogram.Messages(
client=self,
total_count=len(forwarded_messages),
messages=forwarded_messages
) if is_iterable else forwarded_messages[0]
else:
r = self.send(
functions.messages.ForwardMessages(
to_peer=self.resolve_peer(chat_id),
from_peer=self.resolve_peer(from_chat_id),
id=message_ids,
silent=disable_notification or None,
random_id=[self.rnd_id() for _ in message_ids]
)
)
forwarded_messages = []
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
forwarded_messages.append(
pyrogram.Message._parse(
self, i.message,
users, chats
)
)
return pyrogram.Messages(
client=self,
total_count=len(forwarded_messages),
messages=forwarded_messages
) if is_iterable else forwarded_messages[0]

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,21 +16,32 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
import time
from typing import Union
import pyrogram
from pyrogram.api import functions
from ...ext import BaseClient, utils
from pyrogram.api.errors import FloodWait
from ...ext import BaseClient
log = logging.getLogger(__name__)
class GetHistory(BaseClient):
def get_history(self,
chat_id: int or str,
offset: int = 0,
limit: int = 100,
offset_id: int = 0,
offset_date: int = 0):
"""Use this method to retrieve the history of a chat.
def get_history(
self,
chat_id: Union[int, str],
limit: int = 100,
offset: int = 0,
offset_id: int = 0,
offset_date: int = 0,
reverse: bool = False
):
"""Use this method to retrieve a chunk of the history of a chat.
You can get up to 100 messages at once.
For a more convenient way of getting a chat history see :meth:`iter_history`.
Args:
chat_id (``int`` | ``str``):
@@ -38,20 +49,23 @@ class GetHistory(BaseClient):
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).
offset (``int``, *optional*)
Sequential number of the first message to be returned.
Defaults to 0 (most recent message).
limit (``int``, *optional*):
Limits the number of messages to be retrieved.
By default, the first 100 messages are returned.
offset (``int``, *optional*):
Sequential number of the first message to be returned. Defaults to 0 (most recent message).
Negative values are also accepted and become useful in case you set offset_id or offset_date.
offset_id (``int``, *optional*):
Pass a message identifier as offset to retrieve only older messages starting from that message.
offset_date (``int``, *optional*):
Pass a date in Unix time as offset to retrieve only older messages starting from that date.
reverse (``bool``, *optional*):
Pass True to retrieve the messages in reversed order (from older to most recent).
Returns:
On success, a :obj:`Messages <pyrogram.Messages>` object is returned.
@@ -59,52 +73,30 @@ class GetHistory(BaseClient):
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
r = self.send(
functions.messages.GetHistory(
peer=self.resolve_peer(chat_id),
offset_id=offset_id,
offset_date=offset_date,
add_offset=offset,
limit=limit,
max_id=0,
min_id=0,
hash=0
)
)
while True:
try:
messages = pyrogram.Messages._parse(
self,
self.send(
functions.messages.GetHistory(
peer=self.resolve_peer(chat_id),
offset_id=offset_id,
offset_date=offset_date,
add_offset=offset * (-1 if reverse else 1) - (limit if reverse else 0),
limit=limit,
max_id=0,
min_id=0,
hash=0
)
)
)
except FloodWait as e:
log.warning("Sleeping for {}s".format(e.x))
time.sleep(e.x)
else:
break
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
if reverse:
messages.messages.reverse()
reply_to_messages = {
i.reply_to_msg_id: None
for i in r.messages
if i.reply_to_msg_id
}
if reply_to_messages:
temp = self.get_messages(
chat_id, reply_to_messages,
replies=0
)
assert len(temp) == len(reply_to_messages)
for i in range(len(temp)):
reply_to_messages[temp[i].message_id] = temp[i]
messages = utils.parse_messages(
self, r.messages,
users, chats,
replies=0
)
assert len(messages) == len(r.messages)
for i in range(len(messages)):
if r.messages[i].reply_to_msg_id:
messages[i].reply_to_message = reply_to_messages[r.messages[i].reply_to_msg_id]
return pyrogram.Messages(
total_count=getattr(r, "count", len(r.messages)),
messages=messages
)
return messages

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -16,16 +16,26 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
import time
from typing import Union, Iterable
import pyrogram
from pyrogram.api import functions, types
from ...ext import BaseClient, utils
from pyrogram.api.errors import FloodWait
from ...ext import BaseClient
log = logging.getLogger(__name__)
class GetMessages(BaseClient):
def get_messages(self,
chat_id: int or str,
message_ids: int or list = None,
reply_to_message_ids: int or list = None,
replies: int = 1):
def get_messages(
self,
chat_id: Union[int, str],
message_ids: Union[int, Iterable[int]] = None,
reply_to_message_ids: Union[int, Iterable[int]] = None,
replies: int = 1
) -> Union["pyrogram.Message", "pyrogram.Messages"]:
"""Use this method to get one or more messages that belong to a specific chat.
You can retrieve up to 200 messages at once.
@@ -48,10 +58,9 @@ class GetMessages(BaseClient):
The number of subsequent replies to get for each message. Defaults to 1.
Returns:
On success and in case *message_ids* or *reply_to_message_ids* was a list, the returned value will be a
list of the requested :obj:`Messages <pyrogram.Messages>` even if a list contains just one element,
otherwise if *message_ids* or *reply_to_message_ids* was an integer, the single requested
:obj:`Message <pyrogram.Message>` is returned.
On success and in case *message_ids* or *reply_to_message_ids* was an iterable, the returned value will be a
:obj:`Messages <pyrogram.Messages>` even if a list contains just one element. Otherwise, if *message_ids* or
*reply_to_message_ids* was an integer, the single requested :obj:`Message <pyrogram.Message>` is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -69,20 +78,22 @@ class GetMessages(BaseClient):
is_iterable = not isinstance(ids, int)
ids = list(ids) if is_iterable else [ids]
ids = [ids_type(i) for i in ids]
ids = [ids_type(id=i) for i in ids]
if isinstance(peer, types.InputPeerChannel):
rpc = functions.channels.GetMessages(channel=peer, id=ids)
else:
rpc = functions.messages.GetMessages(id=ids)
r = self.send(rpc)
while True:
try:
r = self.send(rpc)
except FloodWait as e:
log.warning("Sleeping for {}s".format(e.x))
time.sleep(e.x)
else:
break
messages = utils.parse_messages(
self, r.messages,
{i.id: i for i in r.users},
{i.id: i for i in r.chats},
replies=replies
)
messages = pyrogram.Messages._parse(self, r, replies=replies)
return messages if is_iterable else messages[0]
return messages if is_iterable else messages.messages[0]

View File

@@ -0,0 +1,95 @@
# 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, Generator
import pyrogram
from ...ext import BaseClient
class IterHistory(BaseClient):
def iter_history(
self,
chat_id: Union[int, str],
limit: int = 0,
offset: int = 0,
offset_id: int = 0,
offset_date: int = 0,
reverse: bool = False
) -> Generator["pyrogram.Message", None, None]:
"""Use this method to iterate through a chat history sequentially.
This convenience method does the same as repeatedly calling :meth:`get_history` in a loop, thus saving you from
the hassle of setting up boilerplate code. It is useful for getting the whole chat history with a single call.
Args:
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).
limit (``int``, *optional*):
Limits the number of messages to be retrieved.
By default, no limit is applied and all messages are returned.
offset (``int``, *optional*):
Sequential number of the first message to be returned..
Negative values are also accepted and become useful in case you set offset_id or offset_date.
offset_id (``int``, *optional*):
Identifier of the first message to be returned.
offset_date (``int``, *optional*):
Pass a date in Unix time as offset to retrieve only older messages starting from that date.
reverse (``bool``, *optional*):
Pass True to retrieve the messages in reversed order (from older to most recent).
Returns:
A generator yielding :obj:`Message <pyrogram.Message>` objects.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
offset_id = offset_id or (1 if reverse else 0)
current = 0
total = limit or (1 << 31) - 1
limit = min(100, total)
while True:
messages = self.get_history(
chat_id=chat_id,
limit=limit,
offset=offset,
offset_id=offset_id,
offset_date=offset_date,
reverse=reverse
).messages
if not messages:
return
offset_id = messages[-1].message_id + (1 if reverse else 0)
for message in messages:
yield message
current += 1
if current >= total:
return

View File

@@ -0,0 +1,56 @@
# 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 pyrogram.client.ext import BaseClient
class RetractVote(BaseClient):
def retract_vote(
self,
chat_id: Union[int, str],
message_id: id
) -> bool:
"""Use this method to retract your vote in a poll.
Args:
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).
message_id (``int``):
Unique poll message identifier inside this chat.
Returns:
On success, True is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
self.send(
functions.messages.SendVote(
peer=self.resolve_peer(chat_id),
msg_id=message_id,
options=[]
)
)
return True

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -17,30 +17,38 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import binascii
import mimetypes
import os
import struct
from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
class SendAnimation(BaseClient):
def send_animation(self,
chat_id: int or str,
animation: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
width: int = 0,
height: int = 0,
thumb: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup=None,
progress: callable = None,
progress_args: tuple = ()):
def send_animation(
self,
chat_id: Union[int, str],
animation: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
width: int = 0,
height: int = 0,
thumb: str = None,
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]:
"""Use this method to send animation files (animation or H.264/MPEG-4 AVC video without sound).
Args:
@@ -114,6 +122,7 @@ class SendAnimation(BaseClient):
Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -121,71 +130,75 @@ class SendAnimation(BaseClient):
file = None
style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(animation):
thumb = None if thumb is None else self.save_file(thumb)
file = self.save_file(animation, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map[".mp4"],
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=True,
duration=duration,
w=width,
h=height
),
types.DocumentAttributeFilename(os.path.basename(animation)),
types.DocumentAttributeAnimated()
]
)
elif animation.startswith("http"):
media = types.InputMediaDocumentExternal(
url=animation
)
else:
try:
decoded = utils.decode(animation)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 10:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
)
try:
if os.path.exists(animation):
thumb = None if thumb is None else self.save_file(thumb)
file = self.save_file(animation, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type="video/mp4",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=True,
duration=duration,
w=width,
h=height
),
types.DocumentAttributeFilename(file_name=os.path.basename(animation)),
types.DocumentAttributeAnimated()
]
)
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,
**style.parse(caption)
)
elif animation.startswith("http"):
media = types.InputMediaDocumentExternal(
url=animation
)
except FilePartMissing as e:
self.save_file(animation, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
return utils.parse_messages(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
try:
decoded = utils.decode(animation)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 10:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
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,
**style.parse(caption)
)
)
except FilePartMissing as e:
self.save_file(animation, 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

View File

@@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@@ -17,30 +17,38 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import binascii
import mimetypes
import os
import struct
from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
from pyrogram.client.ext import BaseClient, utils
class SendAudio(BaseClient):
def send_audio(self,
chat_id: int or str,
audio: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
performer: str = None,
title: str = None,
thumb: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup=None,
progress: callable = None,
progress_args: tuple = ()):
def send_audio(
self,
chat_id: Union[int, str],
audio: str,
caption: str = "",
parse_mode: str = "",
duration: int = 0,
performer: str = None,
title: str = None,
thumb: str = None,
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]:
"""Use this method to send audio files.
For sending voice messages, use the :obj:`send_voice()` method instead.
@@ -116,6 +124,7 @@ class SendAudio(BaseClient):
Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@@ -123,69 +132,73 @@ class SendAudio(BaseClient):
file = None
style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(audio):
thumb = None if thumb is None else self.save_file(thumb)
file = self.save_file(audio, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=mimetypes.types_map.get("." + audio.split(".")[-1], "audio/mpeg"),
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeAudio(
duration=duration,
performer=performer,
title=title
),
types.DocumentAttributeFilename(os.path.basename(audio))
]
)
elif audio.startswith("http"):
media = types.InputMediaDocumentExternal(
url=audio
)
else:
try:
decoded = utils.decode(audio)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 9:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3]
)
try:
if os.path.exists(audio):
thumb = None if thumb is None else self.save_file(thumb)
file = self.save_file(audio, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type="audio/mpeg",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeAudio(
duration=duration,
performer=performer,
title=title
),
types.DocumentAttributeFilename(file_name=os.path.basename(audio))
]
)
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,
**style.parse(caption)
)
elif audio.startswith("http"):
media = types.InputMediaDocumentExternal(
url=audio
)
except FilePartMissing as e:
self.save_file(audio, file_id=file.id, file_part=e.x)
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
return utils.parse_messages(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
try:
decoded = utils.decode(audio)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 9:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
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,
**style.parse(caption)
)
)
except FilePartMissing as e:
self.save_file(audio, 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

Some files were not shown because too many files have changed in this diff Show More