mirror of
https://github.com/pyrogram/pyrogram
synced 2025-09-01 14:55:12 +00:00
Merge branch 'develop' into session_storage
# Conflicts: # pyrogram/client/client.py # pyrogram/client/ext/base_client.py # pyrogram/client/ext/syncer.py # pyrogram/client/style/html.py # pyrogram/client/style/markdown.py
This commit is contained in:
@@ -24,25 +24,13 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
|
||||
# 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"
|
||||
)
|
||||
__version__ = "0.12.0"
|
||||
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
||||
__version__ = "0.11.1.develop"
|
||||
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
|
||||
"\xe8", "e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
|
||||
)
|
||||
|
||||
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, User, UserStatus,
|
||||
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
|
||||
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
|
||||
Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation, Game, CallbackGame, GameHighScore,
|
||||
GameHighScores
|
||||
)
|
||||
from .client import (
|
||||
Client, ChatAction, ParseMode, Emoji,
|
||||
MessageHandler, DeletedMessagesHandler, CallbackQueryHandler,
|
||||
RawUpdateHandler, DisconnectHandler, UserStatusHandler, Filters
|
||||
)
|
||||
from .errors import RPCError
|
||||
from .client import *
|
||||
from .client.handlers import *
|
||||
from .client.types import *
|
||||
|
@@ -26,6 +26,10 @@ from .primitives import Int, Long
|
||||
class FutureSalt(Object):
|
||||
ID = 0x0949d9dc
|
||||
|
||||
__slots__ = ["valid_since", "valid_until", "salt"]
|
||||
|
||||
QUALNAME = "FutureSalt"
|
||||
|
||||
def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int):
|
||||
self.valid_since = valid_since
|
||||
self.valid_until = valid_until
|
||||
|
@@ -27,6 +27,10 @@ from .primitives import Int, Long
|
||||
class FutureSalts(Object):
|
||||
ID = 0xae500895
|
||||
|
||||
__slots__ = ["req_msg_id", "now", "salts"]
|
||||
|
||||
QUALNAME = "FutureSalts"
|
||||
|
||||
def __init__(self, req_msg_id: int, now: int or datetime, salts: list):
|
||||
self.req_msg_id = req_msg_id
|
||||
self.now = now
|
||||
|
@@ -26,6 +26,10 @@ from .primitives import Int, Bytes
|
||||
class GzipPacked(Object):
|
||||
ID = 0x3072cfa1
|
||||
|
||||
__slots__ = ["packed_data"]
|
||||
|
||||
QUALNAME = "GzipPacked"
|
||||
|
||||
def __init__(self, packed_data: Object):
|
||||
self.packed_data = packed_data
|
||||
|
||||
|
@@ -25,6 +25,10 @@ from .primitives import Int, Long
|
||||
class Message(Object):
|
||||
ID = 0x5bb8e511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message"))
|
||||
|
||||
__slots__ = ["msg_id", "seq_no", "length", "body"]
|
||||
|
||||
QUALNAME = "Message"
|
||||
|
||||
def __init__(self, body: Object, msg_id: int, seq_no: int, length: int):
|
||||
self.msg_id = msg_id
|
||||
self.seq_no = seq_no
|
||||
|
@@ -26,6 +26,10 @@ from .primitives import Int
|
||||
class MsgContainer(Object):
|
||||
ID = 0x73f1f8dc
|
||||
|
||||
__slots__ = ["messages"]
|
||||
|
||||
QUALNAME = "MsgContainer"
|
||||
|
||||
def __init__(self, messages: list):
|
||||
self.messages = messages
|
||||
|
||||
|
@@ -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,20 +37,11 @@ class Object:
|
||||
pass
|
||||
|
||||
def __str__(self) -> str:
|
||||
return dumps(self, cls=Encoder, indent=4)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return True
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
return self.__dict__ == other.__dict__
|
||||
return dumps(self, indent=4, default=default, ensure_ascii=False)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.write())
|
||||
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
def __getitem__(self, item):
|
||||
return getattr(self, item)
|
||||
|
||||
@@ -62,29 +55,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)
|
||||
|
@@ -19,8 +19,7 @@
|
||||
from .client import Client
|
||||
from .ext import BaseClient, ChatAction, Emoji, ParseMode
|
||||
from .filters import Filters
|
||||
from .handlers import (
|
||||
MessageHandler, DeletedMessagesHandler,
|
||||
CallbackQueryHandler, RawUpdateHandler,
|
||||
DisconnectHandler, UserStatusHandler
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Client", "BaseClient", "ChatAction", "Emoji", "ParseMode", "Filters",
|
||||
]
|
||||
|
@@ -39,7 +39,11 @@ from typing import Union, List, Type
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.core import Object
|
||||
from pyrogram.api.errors import (
|
||||
from pyrogram.client.handlers import DisconnectHandler
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from pyrogram.client.methods.password.utils import compute_check
|
||||
from pyrogram.crypto import AES
|
||||
from pyrogram.errors import (
|
||||
PhoneMigrate, NetworkMigrate, PhoneNumberInvalid,
|
||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||
@@ -47,13 +51,8 @@ from pyrogram.api.errors import (
|
||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
||||
PasswordRecoveryNa, PasswordEmpty
|
||||
)
|
||||
from pyrogram.client.handlers import DisconnectHandler
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from pyrogram.client.methods.password.utils import compute_check
|
||||
from pyrogram.crypto import AES
|
||||
from pyrogram.session import Auth, Session
|
||||
from .dispatcher import Dispatcher
|
||||
from .ext import utils, Syncer, BaseClient
|
||||
from .ext import utils, Syncer, BaseClient, Dispatcher
|
||||
from .methods import Methods
|
||||
from .session_storage import (
|
||||
SessionDoesNotExist, SessionStorage, MemorySessionStorage, JsonSessionStorage,
|
||||
@@ -70,9 +69,10 @@ class Client(Methods, BaseClient):
|
||||
|
||||
Args:
|
||||
session_name (``str``):
|
||||
Name to uniquely identify a session of either a User or a Bot, e.g.: "my_main_account".
|
||||
You still can use bot token here, but it will be deprecated in next release.
|
||||
Note: as long as a valid User session file exists, Pyrogram won't ask you again to input your phone number.
|
||||
Name to uniquely identify a session of either a User or a Bot, e.g.: "my_account". This name will be used
|
||||
to save a file to disk that stores details needed for reconnecting without asking again for credentials.
|
||||
Note for bots: You can pass a bot token here, but this usage will be deprecated in next releases.
|
||||
Use *bot_token* instead.
|
||||
|
||||
api_id (``int``, *optional*):
|
||||
The *api_id* part of your Telegram API Key, as integer. E.g.: 12345
|
||||
@@ -182,31 +182,35 @@ class Client(Methods, BaseClient):
|
||||
Defaults to False (normal session).
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
session_name: Union[str, SessionStorage],
|
||||
api_id: Union[int, str] = None,
|
||||
api_hash: str = None,
|
||||
app_version: str = None,
|
||||
device_model: str = None,
|
||||
system_version: str = None,
|
||||
lang_code: str = None,
|
||||
ipv6: bool = False,
|
||||
proxy: dict = None,
|
||||
test_mode: bool = False,
|
||||
phone_number: str = None,
|
||||
phone_code: Union[str, callable] = None,
|
||||
password: str = None,
|
||||
recovery_code: callable = None,
|
||||
force_sms: bool = False,
|
||||
bot_token: str = None,
|
||||
first_name: str = None,
|
||||
last_name: str = None,
|
||||
workers: int = BaseClient.WORKERS,
|
||||
workdir: str = BaseClient.WORKDIR,
|
||||
config_file: str = BaseClient.CONFIG_FILE,
|
||||
plugins: dict = None,
|
||||
no_updates: bool = None,
|
||||
takeout: bool = None):
|
||||
terms_of_service_displayed = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session_name: str,
|
||||
api_id: Union[int, str] = None,
|
||||
api_hash: str = None,
|
||||
app_version: str = None,
|
||||
device_model: str = None,
|
||||
system_version: str = None,
|
||||
lang_code: str = None,
|
||||
ipv6: bool = False,
|
||||
proxy: dict = None,
|
||||
test_mode: bool = False,
|
||||
phone_number: str = None,
|
||||
phone_code: Union[str, callable] = None,
|
||||
password: str = None,
|
||||
recovery_code: callable = None,
|
||||
force_sms: bool = False,
|
||||
bot_token: str = None,
|
||||
first_name: str = None,
|
||||
last_name: str = None,
|
||||
workers: int = BaseClient.WORKERS,
|
||||
workdir: str = BaseClient.WORKDIR,
|
||||
config_file: str = BaseClient.CONFIG_FILE,
|
||||
plugins: dict = None,
|
||||
no_updates: bool = None,
|
||||
takeout: bool = None
|
||||
):
|
||||
|
||||
if isinstance(session_name, str):
|
||||
if session_name == ':memory:':
|
||||
@@ -222,6 +226,8 @@ class Client(Methods, BaseClient):
|
||||
|
||||
super().__init__(session_storage)
|
||||
|
||||
super().__init__(session_storage)
|
||||
|
||||
self.session_name = str(session_name) # TODO: build correct session name
|
||||
self.api_id = int(api_id) if api_id else None
|
||||
self.api_hash = api_hash
|
||||
@@ -277,7 +283,7 @@ class Client(Methods, BaseClient):
|
||||
Requires no parameters.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ConnectionError`` in case you try to start an already started Client.
|
||||
"""
|
||||
if self.is_started:
|
||||
@@ -288,10 +294,10 @@ class Client(Methods, BaseClient):
|
||||
self.session_storage.is_bot = True
|
||||
self.bot_token = self.session_storage._session_name
|
||||
self.session_storage._session_name = self.session_storage._session_name.split(":")[0]
|
||||
warnings.warn('\nYou are using a bot token as session name.\n'
|
||||
'It will be deprecated in next update, please use session file name to load '
|
||||
'existing sessions and bot_token argument to create new sessions.',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
warnings.warn('\nWARNING: You are using a bot token as session name!\n'
|
||||
'This usage will be deprecated soon. Please use a session file name to load '
|
||||
'an existing session and the bot_token argument to create new sessions.\n'
|
||||
'More info: https://docs.pyrogram.ml/start/Setup#bot-authorization\n')
|
||||
|
||||
self.load_config()
|
||||
self.load_session()
|
||||
@@ -309,6 +315,7 @@ class Client(Methods, BaseClient):
|
||||
try:
|
||||
if self.session_storage.user_id is None:
|
||||
if self.bot_token is None:
|
||||
self.is_bot = False
|
||||
self.authorize_user()
|
||||
else:
|
||||
self.session_storage.is_bot = True
|
||||
@@ -446,7 +453,7 @@ class Client(Methods, BaseClient):
|
||||
Requires no parameters.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.start()
|
||||
self.idle()
|
||||
@@ -558,9 +565,10 @@ class Client(Methods, BaseClient):
|
||||
try:
|
||||
r = self.send(
|
||||
functions.auth.SendCode(
|
||||
self.phone_number,
|
||||
self.api_id,
|
||||
self.api_hash
|
||||
phone_number=self.phone_number,
|
||||
api_id=self.api_id,
|
||||
api_hash=self.api_hash,
|
||||
settings=types.CodeSettings()
|
||||
)
|
||||
)
|
||||
except (PhoneMigrate, NetworkMigrate) as e:
|
||||
@@ -604,8 +612,9 @@ class Client(Methods, BaseClient):
|
||||
phone_code_hash = r.phone_code_hash
|
||||
terms_of_service = r.terms_of_service
|
||||
|
||||
if terms_of_service:
|
||||
if terms_of_service and not Client.terms_of_service_displayed:
|
||||
print("\n" + terms_of_service.text + "\n")
|
||||
Client.terms_of_service_displayed = True
|
||||
|
||||
if self.force_sms:
|
||||
self.send(
|
||||
@@ -640,9 +649,9 @@ class Client(Methods, BaseClient):
|
||||
try:
|
||||
r = self.send(
|
||||
functions.auth.SignIn(
|
||||
self.phone_number,
|
||||
phone_code_hash,
|
||||
self.phone_code
|
||||
phone_number=self.phone_number,
|
||||
phone_code_hash=phone_code_hash,
|
||||
phone_code=self.phone_code
|
||||
)
|
||||
)
|
||||
except PhoneNumberUnoccupied:
|
||||
@@ -653,11 +662,11 @@ class Client(Methods, BaseClient):
|
||||
try:
|
||||
r = self.send(
|
||||
functions.auth.SignUp(
|
||||
self.phone_number,
|
||||
phone_code_hash,
|
||||
self.phone_code,
|
||||
self.first_name,
|
||||
self.last_name
|
||||
phone_number=self.phone_number,
|
||||
phone_code_hash=phone_code_hash,
|
||||
phone_code=self.phone_code,
|
||||
first_name=self.first_name,
|
||||
last_name=self.last_name
|
||||
)
|
||||
)
|
||||
except PhoneNumberOccupied:
|
||||
@@ -751,7 +760,11 @@ class Client(Methods, BaseClient):
|
||||
break
|
||||
|
||||
if terms_of_service:
|
||||
assert self.send(functions.help.AcceptTermsOfService(terms_of_service.id))
|
||||
assert self.send(
|
||||
functions.help.AcceptTermsOfService(
|
||||
id=terms_of_service.id
|
||||
)
|
||||
)
|
||||
|
||||
self.password = None
|
||||
self.session_storage.user_id = r.user.id
|
||||
@@ -992,16 +1005,16 @@ class Client(Methods, BaseClient):
|
||||
Timeout in seconds.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
if not self.is_started:
|
||||
raise ConnectionError("Client has not been started")
|
||||
|
||||
if self.no_updates:
|
||||
data = functions.InvokeWithoutUpdates(data)
|
||||
data = functions.InvokeWithoutUpdates(query=data)
|
||||
|
||||
if self.takeout_id:
|
||||
data = functions.InvokeWithTakeout(self.takeout_id, data)
|
||||
data = functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
|
||||
|
||||
r = self.session.send(data, retries, timeout)
|
||||
|
||||
@@ -1118,7 +1131,7 @@ class Client(Methods, BaseClient):
|
||||
|
||||
try:
|
||||
module = import_module(module_path)
|
||||
except ModuleNotFoundError:
|
||||
except ImportError:
|
||||
log.warning('[LOAD] Ignoring non-existent module "{}"'.format(module_path))
|
||||
continue
|
||||
|
||||
@@ -1154,7 +1167,7 @@ class Client(Methods, BaseClient):
|
||||
|
||||
try:
|
||||
module = import_module(module_path)
|
||||
except ModuleNotFoundError:
|
||||
except ImportError:
|
||||
log.warning('[UNLOAD] Ignoring non-existent module "{}"'.format(module_path))
|
||||
continue
|
||||
|
||||
@@ -1241,7 +1254,7 @@ class Client(Methods, BaseClient):
|
||||
On success, the resolved peer id is returned in form of an InputPeer object.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``KeyError`` in case the peer doesn't exist in the internal database.
|
||||
"""
|
||||
try:
|
||||
@@ -1276,7 +1289,7 @@ class Client(Methods, BaseClient):
|
||||
self.fetch_peers(
|
||||
self.send(
|
||||
functions.users.GetUsers(
|
||||
id=[types.InputUser(peer_id, 0)]
|
||||
id=[types.InputUser(user_id=peer_id, access_hash=0)]
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -1284,7 +1297,7 @@ class Client(Methods, BaseClient):
|
||||
if str(peer_id).startswith("-100"):
|
||||
self.send(
|
||||
functions.channels.GetChannels(
|
||||
id=[types.InputChannel(int(str(peer_id)[4:]), 0)]
|
||||
id=[types.InputChannel(channel_id=int(str(peer_id)[4:]), access_hash=0)]
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -1348,7 +1361,7 @@ class Client(Methods, BaseClient):
|
||||
On success, the uploaded file is returned in form of an InputFile object.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
part_size = 512 * 1024
|
||||
file_size = os.path.getsize(path)
|
||||
@@ -1591,8 +1604,8 @@ class Client(Methods, BaseClient):
|
||||
|
||||
hashes = session.send(
|
||||
functions.upload.GetCdnFileHashes(
|
||||
r.file_token,
|
||||
offset
|
||||
file_token=r.file_token,
|
||||
offset=offset
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
from .base_client import BaseClient
|
||||
from .chat_action import ChatAction
|
||||
from .dispatcher import Dispatcher
|
||||
from .emoji import Emoji
|
||||
from .parse_mode import ParseMode
|
||||
from .syncer import Syncer
|
||||
|
@@ -74,8 +74,8 @@ class BaseClient:
|
||||
self.rnd_id = MsgId
|
||||
self.channels_pts = {}
|
||||
|
||||
self.markdown = Markdown(self.session_storage)
|
||||
self.html = HTML(self.session_storage)
|
||||
self.markdown = Markdown(self.session_storage, self)
|
||||
self.html = HTML(self.session_storage, self)
|
||||
|
||||
self.session = None
|
||||
self.media_sessions = {}
|
||||
@@ -122,3 +122,6 @@ class BaseClient:
|
||||
|
||||
def get_chat_members_count(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def answer_inline_query(self, *args, **kwargs):
|
||||
pass
|
||||
|
@@ -24,7 +24,10 @@ from threading import Thread
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import types
|
||||
from ..handlers import CallbackQueryHandler, MessageHandler, RawUpdateHandler, UserStatusHandler, DeletedMessagesHandler
|
||||
from ..handlers import (
|
||||
CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
|
||||
UserStatusHandler, RawUpdateHandler, InlineQueryHandler
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -73,7 +76,10 @@ class Dispatcher:
|
||||
(types.UpdateUserStatus,):
|
||||
lambda upd, usr, cht: (
|
||||
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
|
||||
)
|
||||
),
|
||||
|
||||
(types.UpdateBotInlineQuery,):
|
||||
lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler)
|
||||
}
|
||||
|
||||
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
|
@@ -67,10 +67,10 @@ def get_peer_id(input_peer) -> int:
|
||||
|
||||
def get_input_peer(peer_id: int, access_hash: int):
|
||||
return (
|
||||
types.InputPeerUser(peer_id, access_hash) if peer_id > 0
|
||||
else types.InputPeerChannel(int(str(peer_id)[4:]), access_hash)
|
||||
types.InputPeerUser(user_id=peer_id, access_hash=access_hash) if peer_id > 0
|
||||
else types.InputPeerChannel(channel_id=int(str(peer_id)[4:]), access_hash=access_hash)
|
||||
if (str(peer_id).startswith("-100") and access_hash)
|
||||
else types.InputPeerChat(-peer_id)
|
||||
else types.InputPeerChat(chat_id=-peer_id)
|
||||
)
|
||||
|
||||
|
||||
|
@@ -115,7 +115,7 @@ class Filters:
|
||||
voice = create("Voice", lambda _, m: bool(m.voice))
|
||||
"""Filter messages that contain :obj:`Voice <pyrogram.Voice>` note objects."""
|
||||
|
||||
video_note = create("Voice", lambda _, m: bool(m.video_note))
|
||||
video_note = create("VideoNote", lambda _, m: bool(m.video_note))
|
||||
"""Filter messages that contain :obj:`VideoNote <pyrogram.VideoNote>` objects."""
|
||||
|
||||
contact = create("Contact", lambda _, m: bool(m.contact))
|
||||
@@ -222,14 +222,16 @@ class Filters:
|
||||
- poll"""
|
||||
|
||||
@staticmethod
|
||||
def command(command: str or list,
|
||||
prefix: str or list = "/",
|
||||
separator: str = " ",
|
||||
case_sensitive: bool = False):
|
||||
def command(
|
||||
commands: str or list,
|
||||
prefix: str or list = "/",
|
||||
separator: str = " ",
|
||||
case_sensitive: bool = False
|
||||
):
|
||||
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
||||
|
||||
Args:
|
||||
command (``str`` | ``list``):
|
||||
commands (``str`` | ``list``):
|
||||
The command or list of commands as string the filter should look for.
|
||||
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
||||
a command arrives, the command itself and its arguments will be stored in the *command*
|
||||
@@ -249,31 +251,25 @@ class Filters:
|
||||
Examples: when True, command="Start" would trigger /Start but not /start.
|
||||
"""
|
||||
|
||||
def f(_, m):
|
||||
if m.text:
|
||||
for i in _.p:
|
||||
if m.text.startswith(i):
|
||||
t = m.text.split(_.s)
|
||||
c, a = t[0][len(i):], t[1:]
|
||||
c = c if _.cs else c.lower()
|
||||
m.command = ([c] + a) if c in _.c else None
|
||||
def func(flt, message):
|
||||
text = message.text or message.caption
|
||||
|
||||
if text:
|
||||
for p in flt.p:
|
||||
if text.startswith(p):
|
||||
s = text.split(flt.s)
|
||||
c, a = s[0][len(p):], s[1:]
|
||||
c = c if flt.cs else c.lower()
|
||||
message.command = ([c] + a) if c in flt.c else None
|
||||
break
|
||||
|
||||
return bool(m.command)
|
||||
return bool(message.command)
|
||||
|
||||
return create(
|
||||
"Command",
|
||||
f,
|
||||
c={command if case_sensitive
|
||||
else command.lower()}
|
||||
if not isinstance(command, list)
|
||||
else {c if case_sensitive
|
||||
else c.lower()
|
||||
for c in command},
|
||||
p=set(prefix) if prefix else {""},
|
||||
s=separator,
|
||||
cs=case_sensitive
|
||||
)
|
||||
commands = commands if type(commands) is list else [commands]
|
||||
commands = {c if case_sensitive else c.lower() for c in commands}
|
||||
prefixes = set(prefix) if prefix else {""}
|
||||
|
||||
return create("Command", func=func, c=commands, p=prefixes, s=separator, cs=case_sensitive)
|
||||
|
||||
@staticmethod
|
||||
def regex(pattern, flags: int = 0):
|
||||
@@ -311,21 +307,20 @@ class Filters:
|
||||
|
||||
def __init__(self, users: int or str or list = None):
|
||||
users = [] if users is None else users if type(users) is list else [users]
|
||||
|
||||
super().__init__(
|
||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in users}
|
||||
if type(users) is list else
|
||||
{"me" if users in ["me", "self"] else users.lower().strip("@") if type(users) is str else users}
|
||||
"me" if u in ["me", "self"]
|
||||
else u.lower().strip("@") if type(u) is str
|
||||
else u for u in users
|
||||
)
|
||||
|
||||
def __call__(self, message):
|
||||
return bool(
|
||||
message.from_user
|
||||
and (message.from_user.id in self
|
||||
or (message.from_user.username
|
||||
and message.from_user.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user.is_self))
|
||||
)
|
||||
return (message.from_user
|
||||
and (message.from_user.id in self
|
||||
or (message.from_user.username
|
||||
and message.from_user.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user.is_self)))
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class chat(Filter, set):
|
||||
@@ -343,21 +338,21 @@ class Filters:
|
||||
|
||||
def __init__(self, chats: int or str or list = None):
|
||||
chats = [] if chats is None else chats if type(chats) is list else [chats]
|
||||
|
||||
super().__init__(
|
||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in chats}
|
||||
if type(chats) is list else
|
||||
{"me" if chats in ["me", "self"] else chats.lower().strip("@") if type(chats) is str else chats}
|
||||
"me" if c in ["me", "self"]
|
||||
else c.lower().strip("@") if type(c) is str
|
||||
else c for c in chats
|
||||
)
|
||||
|
||||
def __call__(self, message):
|
||||
return bool(
|
||||
message.chat
|
||||
and (message.chat.id in self
|
||||
or (message.chat.username
|
||||
and message.chat.username.lower() in self)
|
||||
or ("me" in self and message.from_user
|
||||
and message.from_user.is_self
|
||||
and not message.outgoing))
|
||||
)
|
||||
return (message.chat
|
||||
and (message.chat.id in self
|
||||
or (message.chat.username
|
||||
and message.chat.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user
|
||||
and message.from_user.is_self
|
||||
and not message.outgoing)))
|
||||
|
||||
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
||||
|
@@ -19,6 +19,12 @@
|
||||
from .callback_query_handler import CallbackQueryHandler
|
||||
from .deleted_messages_handler import DeletedMessagesHandler
|
||||
from .disconnect_handler import DisconnectHandler
|
||||
from .inline_query_handler import InlineQueryHandler
|
||||
from .message_handler import MessageHandler
|
||||
from .raw_update_handler import RawUpdateHandler
|
||||
from .user_status_handler import UserStatusHandler
|
||||
|
||||
__all__ = [
|
||||
"MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler",
|
||||
"UserStatusHandler", "InlineQueryHandler"
|
||||
]
|
||||
|
54
pyrogram/client/handlers/inline_query_handler.py
Normal file
54
pyrogram/client/handlers/inline_query_handler.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 .handler import Handler
|
||||
|
||||
|
||||
class InlineQueryHandler(Handler):
|
||||
"""The InlineQuery handler class. Used to handle inline queries.
|
||||
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||
|
||||
For a nicer way to register this handler, have a look at the
|
||||
:meth:`on_inline_query() <pyrogram.Client.on_inline_query>` decorator.
|
||||
|
||||
Args:
|
||||
callback (``callable``):
|
||||
Pass a function that will be called when a new InlineQuery arrives. It takes *(client, inline_query)*
|
||||
as positional arguments (look at the section below for a detailed description).
|
||||
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of inline queries to be passed
|
||||
in your callback function.
|
||||
|
||||
Other parameters:
|
||||
client (:obj:`Client <pyrogram.Client>`):
|
||||
The Client itself, useful when you want to call other API methods inside the inline query handler.
|
||||
|
||||
inline_query (:obj:`InlineQuery <pyrogram.InlineQuery>`):
|
||||
The received inline query.
|
||||
"""
|
||||
|
||||
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
|
||||
)
|
@@ -17,6 +17,7 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
@@ -27,6 +28,7 @@ from .set_game_score import SetGameScore
|
||||
|
||||
class Bots(
|
||||
AnswerCallbackQuery,
|
||||
AnswerInlineQuery,
|
||||
GetInlineBotResults,
|
||||
RequestCallbackAnswer,
|
||||
SendInlineBotResult,
|
||||
|
@@ -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.
|
||||
|
||||
@@ -55,7 +57,7 @@ class AnswerCallbackQuery(BaseClient):
|
||||
True, on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
return self.send(
|
||||
functions.messages.SetBotCallbackAnswer(
|
||||
|
91
pyrogram/client/methods/bots/answer_inline_query.py
Normal file
91
pyrogram/client/methods/bots/answer_inline_query.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 List
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.client.ext import BaseClient
|
||||
from ...types.inline_mode import InlineQueryResult
|
||||
|
||||
|
||||
class AnswerInlineQuery(BaseClient):
|
||||
def answer_inline_query(
|
||||
self,
|
||||
inline_query_id: str,
|
||||
results: List[InlineQueryResult],
|
||||
cache_time: int = 300,
|
||||
is_personal: bool = None,
|
||||
next_offset: str = "",
|
||||
switch_pm_text: str = "",
|
||||
switch_pm_parameter: str = ""
|
||||
):
|
||||
"""Use this method to send answers to an inline query.
|
||||
No more than 50 results per query are allowed.
|
||||
|
||||
Args:
|
||||
inline_query_id (``str``):
|
||||
Unique identifier for the answered query.
|
||||
|
||||
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
||||
A list of results for the inline query.
|
||||
|
||||
cache_time (``int``, *optional*):
|
||||
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
||||
Defaults to 300.
|
||||
|
||||
is_personal (``bool``, *optional*):
|
||||
Pass True, if results may be cached on the server side only for the user that sent the query.
|
||||
By default, results may be returned to any user who sends the same query.
|
||||
|
||||
next_offset (``str``, *optional*):
|
||||
Pass the offset that a client should send in the next query with the same text to receive more results.
|
||||
Pass an empty string if there are no more results or if you don‘t support pagination.
|
||||
Offset length can’t exceed 64 bytes.
|
||||
|
||||
switch_pm_text (``str``, *optional*):
|
||||
If passed, clients will display a button with specified text that switches the user to a private chat
|
||||
with the bot and sends the bot a start message with the parameter switch_pm_parameter
|
||||
|
||||
switch_pm_parameter (``str``, *optional*):
|
||||
`Deep-linking <https://core.telegram.org/bots#deep-linking>`_ parameter for the /start message sent to
|
||||
the bot when user presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed.
|
||||
|
||||
Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube
|
||||
account to adapt search results accordingly. To do this, it displays a "Connect your YouTube account"
|
||||
button above the results, or even before showing any. The user presses the button, switches to a private
|
||||
chat with the bot and, in doing so, passes a start parameter that instructs the bot to return an oauth
|
||||
link. Once done, the bot can offer a switch_inline button so that the user can easily return to the chat
|
||||
where they wanted to use the bot's inline capabilities.
|
||||
|
||||
Returns:
|
||||
On success, True is returned.
|
||||
"""
|
||||
return self.send(
|
||||
functions.messages.SetInlineBotResults(
|
||||
query_id=int(inline_query_id),
|
||||
results=[r.write() for r in results],
|
||||
cache_time=cache_time,
|
||||
gallery=None,
|
||||
private=is_personal or None,
|
||||
next_offset=next_offset or None,
|
||||
switch_pm=types.InlineBotSwitchPM(
|
||||
text=switch_pm_text,
|
||||
start_param=switch_pm_parameter
|
||||
) if switch_pm_text else None
|
||||
)
|
||||
)
|
@@ -24,10 +24,12 @@ 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):
|
||||
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:
|
||||
@@ -50,7 +52,7 @@ class GetGameHighScores(BaseClient):
|
||||
On success, a :obj:`GameHighScores <pyrogram.GameHighScores>` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
# TODO: inline_message_id
|
||||
|
||||
|
@@ -19,17 +19,19 @@
|
||||
from typing import Union
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import UnknownError
|
||||
from pyrogram.errors import UnknownError
|
||||
from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class GetInlineBotResults(BaseClient):
|
||||
def get_inline_bot_results(self,
|
||||
bot: Union[int, 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>`
|
||||
|
||||
@@ -56,7 +58,7 @@ class GetInlineBotResults(BaseClient):
|
||||
On Success, :obj:`BotResults <pyrogram.api.types.messages.BotResults>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``TimeoutError`` if the bot fails to answer within 10 seconds
|
||||
"""
|
||||
# TODO: Don't return the raw type
|
||||
|
@@ -23,12 +23,14 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class RequestCallbackAnswer(BaseClient):
|
||||
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.
|
||||
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.
|
||||
|
||||
Args:
|
||||
chat_id (``int`` | ``str``):
|
||||
@@ -47,7 +49,7 @@ class RequestCallbackAnswer(BaseClient):
|
||||
or as an alert.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``TimeoutError`` if the bot fails to answer within 10 seconds.
|
||||
"""
|
||||
return self.send(
|
||||
|
@@ -24,15 +24,19 @@ 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":
|
||||
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:
|
||||
@@ -59,7 +63,7 @@ class SendGame(BaseClient):
|
||||
On success, the sent :obj:`Message` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
|
@@ -23,13 +23,15 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendInlineBotResult(BaseClient):
|
||||
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):
|
||||
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>`
|
||||
|
||||
@@ -59,7 +61,7 @@ class SendInlineBotResult(BaseClient):
|
||||
On success, the sent Message is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
return self.send(
|
||||
functions.messages.SendInlineBotResult(
|
||||
|
@@ -24,13 +24,15 @@ 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):
|
||||
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.
|
||||
|
||||
@@ -65,7 +67,7 @@ class SetGameScore(BaseClient):
|
||||
otherwise returns True.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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(
|
||||
|
@@ -31,12 +31,14 @@ 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(
|
||||
@@ -60,6 +62,8 @@ class Chats(
|
||||
GetChatMembersCount,
|
||||
GetChatPreview,
|
||||
IterDialogs,
|
||||
IterChatMembers
|
||||
IterChatMembers,
|
||||
UpdateChatUsername,
|
||||
RestrictChat
|
||||
):
|
||||
pass
|
||||
|
@@ -23,8 +23,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class DeleteChatPhoto(BaseClient):
|
||||
def delete_chat_photo(self,
|
||||
chat_id: Union[int, str]) -> bool:
|
||||
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.
|
||||
@@ -41,7 +43,7 @@ class DeleteChatPhoto(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id belongs to user.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
@@ -23,8 +23,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class ExportChatInviteLink(BaseClient):
|
||||
def export_chat_invite_link(self,
|
||||
chat_id: Union[int, str]) -> 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.
|
||||
@@ -38,14 +40,14 @@ class ExportChatInviteLink(BaseClient):
|
||||
On success, the exported invite link as string is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
||||
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):
|
||||
|
@@ -24,10 +24,13 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetChat(BaseClient):
|
||||
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.)
|
||||
def get_chat(
|
||||
self,
|
||||
chat_id: Union[int, str]
|
||||
) -> "pyrogram.Chat":
|
||||
"""Use this method to get up to date information about the chat.
|
||||
Information include current name of the user for one-on-one conversations, current username of a user, group or
|
||||
channel, etc.
|
||||
|
||||
Args:
|
||||
chat_id (``int`` | ``str``):
|
||||
@@ -39,7 +42,7 @@ class GetChat(BaseClient):
|
||||
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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))
|
||||
@@ -67,10 +70,10 @@ class GetChat(BaseClient):
|
||||
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 pyrogram.Chat._parse_full(self, r)
|
||||
|
@@ -19,14 +19,17 @@
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types, errors
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import UserNotParticipant
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetChatMember(BaseClient):
|
||||
def get_chat_member(self,
|
||||
chat_id: Union[int, str],
|
||||
user_id: Union[int, str]) -> "pyrogram.ChatMember":
|
||||
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:
|
||||
@@ -42,7 +45,7 @@ class GetChatMember(BaseClient):
|
||||
On success, a :obj:`ChatMember <pyrogram.ChatMember>` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
chat_id = self.resolve_peer(chat_id)
|
||||
user_id = self.resolve_peer(user_id)
|
||||
@@ -55,10 +58,10 @@ class GetChatMember(BaseClient):
|
||||
)
|
||||
|
||||
for member in pyrogram.ChatMembers._parse(self, full_chat).chat_members:
|
||||
if member.user.id == user_id.user_id:
|
||||
if member.user.is_self:
|
||||
return member
|
||||
else:
|
||||
raise errors.UserNotParticipant
|
||||
raise UserNotParticipant
|
||||
elif isinstance(chat_id, types.InputPeerChannel):
|
||||
r = self.send(
|
||||
functions.channels.GetParticipant(
|
||||
|
@@ -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/>.
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FloodWait
|
||||
from ...ext import BaseClient
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Filters:
|
||||
ALL = "all"
|
||||
@@ -33,12 +38,14 @@ class Filters:
|
||||
|
||||
|
||||
class GetChatMembers(BaseClient):
|
||||
def get_chat_members(self,
|
||||
chat_id: Union[int, str],
|
||||
offset: int = 0,
|
||||
limit: int = 200,
|
||||
query: str = "",
|
||||
filter: str = Filters.ALL) -> "pyrogram.ChatMembers":
|
||||
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.
|
||||
@@ -82,7 +89,7 @@ class GetChatMembers(BaseClient):
|
||||
On success, a :obj:`ChatMembers` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if you used an invalid filter or a chat_id that belongs to a user.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
@@ -92,7 +99,7 @@ class GetChatMembers(BaseClient):
|
||||
self,
|
||||
self.send(
|
||||
functions.messages.GetFullChat(
|
||||
peer.chat_id
|
||||
chat_id=peer.chat_id
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -114,17 +121,22 @@ class GetChatMembers(BaseClient):
|
||||
else:
|
||||
raise ValueError("Invalid filter \"{}\"".format(filter))
|
||||
|
||||
return pyrogram.ChatMembers._parse(
|
||||
self,
|
||||
self.send(
|
||||
functions.channels.GetParticipants(
|
||||
channel=peer,
|
||||
filter=filter,
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
hash=0
|
||||
while True:
|
||||
try:
|
||||
return pyrogram.ChatMembers._parse(
|
||||
self,
|
||||
self.send(
|
||||
functions.channels.GetParticipants(
|
||||
channel=peer,
|
||||
filter=filter,
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
hash=0
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
except FloodWait as e:
|
||||
log.warning("Sleeping for {}s".format(e.x))
|
||||
time.sleep(e.x)
|
||||
else:
|
||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||
|
@@ -23,8 +23,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetChatMembersCount(BaseClient):
|
||||
def get_chat_members_count(self,
|
||||
chat_id: Union[int, str]) -> int:
|
||||
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:
|
||||
@@ -35,7 +37,7 @@ class GetChatMembersCount(BaseClient):
|
||||
On success, an integer is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id belongs to user.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
@@ -22,8 +22,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetChatPreview(BaseClient):
|
||||
def get_chat_preview(self,
|
||||
invite_link: str):
|
||||
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`
|
||||
@@ -36,7 +38,7 @@ class GetChatPreview(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case of an invalid invite_link.
|
||||
"""
|
||||
match = self.INVITE_LINK_RE.match(invite_link)
|
||||
|
@@ -21,18 +21,20 @@ import time
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FloodWait
|
||||
from pyrogram.errors import FloodWait
|
||||
from ...ext import BaseClient
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetDialogs(BaseClient):
|
||||
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
|
||||
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`.
|
||||
@@ -54,7 +56,7 @@ class GetDialogs(BaseClient):
|
||||
On success, a :obj:`Dialogs` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
|
||||
while True:
|
||||
|
@@ -20,6 +20,7 @@ from string import ascii_lowercase
|
||||
from typing import Union, Generator
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import types
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
@@ -37,11 +38,13 @@ 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]:
|
||||
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
|
||||
@@ -75,13 +78,14 @@ class IterChatMembers(BaseClient):
|
||||
A generator yielding :obj:`ChatMember <pyrogram.ChatMember>` objects.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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
|
||||
@@ -107,6 +111,9 @@ class IterChatMembers(BaseClient):
|
||||
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:
|
||||
|
@@ -23,9 +23,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class IterDialogs(BaseClient):
|
||||
def iter_dialogs(self,
|
||||
offset_date: int = 0,
|
||||
limit: int = 0) -> Generator["pyrogram.Dialog", None, None]:
|
||||
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
|
||||
@@ -44,7 +46,7 @@ class IterDialogs(BaseClient):
|
||||
A generator yielding :obj:`Dialog <pyrogram.Dialog>` objects.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
current = 0
|
||||
total = limit or (1 << 31) - 1
|
||||
|
@@ -16,13 +16,16 @@
|
||||
# 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:
|
||||
@@ -30,17 +33,24 @@ class JoinChat(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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(
|
||||
@@ -53,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])
|
||||
|
@@ -24,10 +24,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class KickChatMember(BaseClient):
|
||||
def kick_chat_member(self,
|
||||
chat_id: Union[int, str],
|
||||
user_id: Union[int, str],
|
||||
until_date: int = 0) -> Union["pyrogram.Message", bool]:
|
||||
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
|
||||
@@ -55,7 +57,7 @@ class KickChatMember(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
chat_peer = self.resolve_peer(chat_id)
|
||||
user_peer = self.resolve_peer(user_id)
|
||||
@@ -65,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,
|
||||
|
@@ -23,9 +23,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class LeaveChat(BaseClient):
|
||||
def leave_chat(self,
|
||||
chat_id: Union[int, 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:
|
||||
@@ -37,7 +39,7 @@ class LeaveChat(BaseClient):
|
||||
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
||||
|
@@ -23,10 +23,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class PinChatMessage(BaseClient):
|
||||
def pin_chat_message(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: int,
|
||||
disable_notification: bool = None) -> bool:
|
||||
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.
|
||||
@@ -46,7 +48,7 @@ class PinChatMessage(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.send(
|
||||
functions.messages.UpdatePinnedMessage(
|
||||
@@ -55,3 +57,5 @@ class PinChatMessage(BaseClient):
|
||||
silent=disable_notification or None
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
|
@@ -23,18 +23,21 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class PromoteChatMember(BaseClient):
|
||||
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_invite_users: bool = True,
|
||||
can_restrict_members: bool = True,
|
||||
can_pin_messages: bool = False,
|
||||
can_promote_members: bool = False) -> bool:
|
||||
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.
|
||||
|
||||
@@ -58,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.
|
||||
|
||||
@@ -76,23 +79,21 @@ class PromoteChatMember(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.send(
|
||||
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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
143
pyrogram/client/methods/chats/restrict_chat.py
Normal file
143
pyrogram/client/methods/chats/restrict_chat.py
Normal 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:`RPCError <pyrogram.RPCError>` 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])
|
@@ -20,20 +20,28 @@ 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: 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) -> bool:
|
||||
"""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.
|
||||
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.
|
||||
|
||||
Args:
|
||||
chat_id (``int`` | ``str``):
|
||||
@@ -60,13 +68,25 @@ 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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
send_messages = True
|
||||
send_media = True
|
||||
@@ -75,6 +95,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
|
||||
@@ -84,6 +108,7 @@ class RestrictChatMember(BaseClient):
|
||||
send_media = None
|
||||
|
||||
if can_send_other_messages:
|
||||
send_messages = None
|
||||
send_media = None
|
||||
send_stickers = None
|
||||
send_gifs = None
|
||||
@@ -91,14 +116,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,
|
||||
@@ -106,9 +145,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])
|
||||
|
@@ -23,9 +23,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class SetChatDescription(BaseClient):
|
||||
def set_chat_description(self,
|
||||
chat_id: Union[int, str],
|
||||
description: str) -> bool:
|
||||
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.
|
||||
|
||||
@@ -40,20 +42,18 @@ class SetChatDescription(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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):
|
||||
if isinstance(peer, (types.InputPeerChannel, types.InputPeerChat)):
|
||||
self.send(
|
||||
functions.channels.EditAbout(
|
||||
channel=peer,
|
||||
functions.messages.EditChatAbout(
|
||||
peer=peer,
|
||||
about=description
|
||||
)
|
||||
)
|
||||
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))
|
||||
|
||||
|
@@ -26,9 +26,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class SetChatPhoto(BaseClient):
|
||||
def set_chat_photo(self,
|
||||
chat_id: Union[int, str],
|
||||
photo: str) -> bool:
|
||||
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.
|
||||
@@ -48,7 +50,7 @@ class SetChatPhoto(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id belongs to user.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
@@ -23,9 +23,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class SetChatTitle(BaseClient):
|
||||
def set_chat_title(self,
|
||||
chat_id: Union[int, str],
|
||||
title: str) -> bool:
|
||||
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.
|
||||
@@ -45,7 +47,7 @@ class SetChatTitle(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if a chat_id belongs to user.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
|
@@ -23,9 +23,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class UnbanChatMember(BaseClient):
|
||||
def unban_chat_member(self,
|
||||
chat_id: Union[int, str],
|
||||
user_id: Union[int, str]) -> bool:
|
||||
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.
|
||||
@@ -42,13 +44,13 @@ class UnbanChatMember(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
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=0
|
||||
)
|
||||
)
|
||||
|
@@ -23,8 +23,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class UnpinChatMessage(BaseClient):
|
||||
def unpin_chat_message(self,
|
||||
chat_id: Union[int, str]) -> bool:
|
||||
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.
|
||||
@@ -37,7 +39,7 @@ class UnpinChatMessage(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.send(
|
||||
functions.messages.UpdatePinnedMessage(
|
||||
|
61
pyrogram/client/methods/chats/update_chat_username.py
Normal file
61
pyrogram/client/methods/chats/update_chat_username.py
Normal 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:`RPCError <pyrogram.RPCError>` 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))
|
@@ -24,8 +24,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class AddContacts(BaseClient):
|
||||
def add_contacts(self,
|
||||
contacts: List["pyrogram.InputPhoneContact"]):
|
||||
def add_contacts(
|
||||
self,
|
||||
contacts: List["pyrogram.InputPhoneContact"]
|
||||
):
|
||||
"""Use this method to add contacts to your Telegram address book.
|
||||
|
||||
Args:
|
||||
@@ -36,7 +38,7 @@ class AddContacts(BaseClient):
|
||||
On success, the added contacts are returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
imported_contacts = self.send(
|
||||
functions.contacts.ImportContacts(
|
||||
|
@@ -19,14 +19,16 @@
|
||||
from typing import List
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import PeerIdInvalid
|
||||
from pyrogram.errors import PeerIdInvalid
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class DeleteContacts(BaseClient):
|
||||
def delete_contacts(self,
|
||||
ids: List[int]):
|
||||
"""Use this method to delete contacts from your Telegram address book
|
||||
def delete_contacts(
|
||||
self,
|
||||
ids: List[int]
|
||||
):
|
||||
"""Use this method to delete contacts from your Telegram address book.
|
||||
|
||||
Args:
|
||||
ids (List of ``int``):
|
||||
@@ -37,7 +39,7 @@ class DeleteContacts(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
contacts = []
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import time
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions
|
||||
from pyrogram.api.errors import FloodWait
|
||||
from pyrogram.errors import FloodWait
|
||||
from ...ext import BaseClient
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -35,11 +35,11 @@ class GetContacts(BaseClient):
|
||||
On success, a list of :obj:`User` objects is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
from .on_callback_query import OnCallbackQuery
|
||||
from .on_deleted_messages import OnDeletedMessages
|
||||
from .on_disconnect import OnDisconnect
|
||||
from .on_inline_query import OnInlineQuery
|
||||
from .on_message import OnMessage
|
||||
from .on_raw_update import OnRawUpdate
|
||||
from .on_user_status import OnUserStatus
|
||||
@@ -30,6 +31,7 @@ class Decorators(
|
||||
OnCallbackQuery,
|
||||
OnRawUpdate,
|
||||
OnDisconnect,
|
||||
OnUserStatus
|
||||
OnUserStatus,
|
||||
OnInlineQuery
|
||||
):
|
||||
pass
|
||||
|
@@ -25,19 +25,13 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnCallbackQuery(BaseClient):
|
||||
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.
|
||||
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`.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
|
@@ -25,19 +25,13 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnDeletedMessages(BaseClient):
|
||||
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.
|
||||
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`.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
|
@@ -23,9 +23,8 @@ from ...ext import BaseClient
|
||||
|
||||
class OnDisconnect(BaseClient):
|
||||
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`.
|
||||
"""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: callable) -> Handler:
|
||||
|
59
pyrogram/client/methods/decorators/on_inline_query.py
Normal file
59
pyrogram/client/methods/decorators/on_inline_query.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 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 Tuple
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.client.filters.filter import Filter
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnInlineQuery(BaseClient):
|
||||
def on_inline_query(
|
||||
self=None,
|
||||
filters=None,
|
||||
group: int = 0
|
||||
) -> callable:
|
||||
"""Use this decorator to automatically register a function for handling inline queries.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`InlineQueryHandler`.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of inline queries to be passed
|
||||
in your function.
|
||||
|
||||
group (``int``, *optional*):
|
||||
The group identifier, defaults to 0.
|
||||
"""
|
||||
|
||||
def decorator(func: callable) -> Tuple[Handler, int]:
|
||||
if isinstance(func, tuple):
|
||||
func = func[0].callback
|
||||
|
||||
handler = pyrogram.InlineQueryHandler(func, filters)
|
||||
|
||||
if isinstance(self, Filter):
|
||||
return pyrogram.InlineQueryHandler(func, self), group if filters is None else filters
|
||||
|
||||
if self is not None:
|
||||
self.add_handler(handler, group)
|
||||
|
||||
return handler, group
|
||||
|
||||
return decorator
|
@@ -25,19 +25,13 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnMessage(BaseClient):
|
||||
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.
|
||||
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`.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
|
@@ -24,18 +24,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnRawUpdate(BaseClient):
|
||||
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.
|
||||
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`.
|
||||
|
||||
Args:
|
||||
group (``int``, *optional*):
|
||||
|
@@ -25,19 +25,13 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class OnUserStatus(BaseClient):
|
||||
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.
|
||||
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`.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
|
@@ -30,6 +30,7 @@ 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
|
||||
@@ -74,6 +75,7 @@ class Messages(
|
||||
ClosePoll,
|
||||
RetractVote,
|
||||
DownloadMedia,
|
||||
IterHistory
|
||||
IterHistory,
|
||||
SendCachedMedia
|
||||
):
|
||||
pass
|
||||
|
@@ -23,9 +23,11 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class ClosePoll(BaseClient):
|
||||
def close_poll(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id) -> bool:
|
||||
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.
|
||||
@@ -43,7 +45,7 @@ class ClosePoll(BaseClient):
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
poll = self.get_messages(chat_id, message_id).poll
|
||||
|
||||
|
@@ -23,17 +23,13 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class DeleteMessages(BaseClient):
|
||||
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.
|
||||
- Users can delete outgoing messages in groups and supergroups.
|
||||
- Users granted *can_post_messages* permissions can delete outgoing messages in channels.
|
||||
- If the user is an administrator of a group, it can delete any message there.
|
||||
- If the user has *can_delete_messages* permission in a supergroup or a channel, it can delete any message there.
|
||||
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.
|
||||
|
||||
Args:
|
||||
chat_id (``int`` | ``str``):
|
||||
@@ -55,7 +51,7 @@ class DeleteMessages(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
peer = self.resolve_peer(chat_id)
|
||||
message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids]
|
||||
|
@@ -24,13 +24,15 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class DownloadMedia(BaseClient):
|
||||
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.
|
||||
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:
|
||||
message (:obj:`Message <pyrogram.Message>` | ``str``):
|
||||
@@ -75,7 +77,7 @@ class DownloadMedia(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if the message doesn't contain any downloadable media
|
||||
"""
|
||||
error_message = "This message doesn't contain any downloadable media"
|
||||
@@ -106,15 +108,15 @@ class DownloadMedia(BaseClient):
|
||||
else:
|
||||
raise ValueError(error_message)
|
||||
elif isinstance(message, (
|
||||
pyrogram.Photo,
|
||||
pyrogram.PhotoSize,
|
||||
pyrogram.Audio,
|
||||
pyrogram.Document,
|
||||
pyrogram.Video,
|
||||
pyrogram.Voice,
|
||||
pyrogram.VideoNote,
|
||||
pyrogram.Sticker,
|
||||
pyrogram.Animation
|
||||
pyrogram.Photo,
|
||||
pyrogram.PhotoSize,
|
||||
pyrogram.Audio,
|
||||
pyrogram.Document,
|
||||
pyrogram.Video,
|
||||
pyrogram.Voice,
|
||||
pyrogram.VideoNote,
|
||||
pyrogram.Sticker,
|
||||
pyrogram.Animation
|
||||
)):
|
||||
if isinstance(message, pyrogram.Photo):
|
||||
media = pyrogram.Document(
|
||||
|
@@ -24,12 +24,14 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class EditMessageCaption(BaseClient):
|
||||
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":
|
||||
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:
|
||||
@@ -56,7 +58,7 @@ class EditMessageCaption(BaseClient):
|
||||
On success, the edited :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
|
@@ -23,7 +23,7 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid
|
||||
from pyrogram.errors import FileIdInvalid
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
from pyrogram.client.types import (
|
||||
InputMediaPhoto, InputMediaVideo, InputMediaAudio,
|
||||
@@ -33,11 +33,13 @@ from pyrogram.client.types.input_media import InputMedia
|
||||
|
||||
|
||||
class EditMessageMedia(BaseClient):
|
||||
def edit_message_media(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: int,
|
||||
media: InputMedia,
|
||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
|
||||
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,
|
||||
@@ -54,7 +56,7 @@ class EditMessageMedia(BaseClient):
|
||||
message_id (``int``):
|
||||
Message identifier in the chat specified in chat_id.
|
||||
|
||||
media (:obj:`InputMediaAnimation` | :obj:`InputMediaAudio` | :obj:`InputMediaDocument` | :obj:`InputMediaPhoto` | :obj:`InputMediaVideo`)
|
||||
media (:obj:`InputMedia`)
|
||||
One of the InputMedia objects describing an animation, audio, document, photo or video.
|
||||
|
||||
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
|
||||
@@ -64,7 +66,7 @@ class EditMessageMedia(BaseClient):
|
||||
On success, the edited :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
style = self.html if media.parse_mode.lower() == "html" else self.markdown
|
||||
caption = media.caption
|
||||
@@ -131,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)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
@@ -187,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)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
@@ -244,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()
|
||||
]
|
||||
)
|
||||
@@ -296,7 +304,9 @@ class EditMessageMedia(BaseClient):
|
||||
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)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
@@ -24,10 +24,12 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class EditMessageReplyMarkup(BaseClient):
|
||||
def edit_message_reply_markup(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: int,
|
||||
reply_markup: "pyrogram.InlineKeyboardMarkup" = None) -> "pyrogram.Message":
|
||||
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:
|
||||
@@ -47,7 +49,7 @@ class EditMessageReplyMarkup(BaseClient):
|
||||
:obj:`Message <pyrogram.Message>` is returned, otherwise True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
|
||||
r = self.send(
|
||||
|
@@ -24,13 +24,15 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class EditMessageText(BaseClient):
|
||||
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":
|
||||
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:
|
||||
@@ -60,7 +62,7 @@ class EditMessageText(BaseClient):
|
||||
On success, the edited :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
|
@@ -24,11 +24,15 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class ForwardMessages(BaseClient):
|
||||
def forward_messages(self,
|
||||
chat_id: Union[int, str],
|
||||
from_chat_id: Union[int, str],
|
||||
message_ids: Iterable[int],
|
||||
disable_notification: bool = None) -> "pyrogram.Messages":
|
||||
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:
|
||||
@@ -50,6 +54,15 @@ 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 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
|
||||
@@ -57,37 +70,60 @@ class ForwardMessages(BaseClient):
|
||||
is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` 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(
|
||||
pyrogram.Message._parse(
|
||||
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 pyrogram.Messages(
|
||||
client=self,
|
||||
total_count=len(messages),
|
||||
messages=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]
|
||||
|
@@ -22,20 +22,22 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions
|
||||
from pyrogram.api.errors import FloodWait
|
||||
from pyrogram.errors import FloodWait
|
||||
from ...ext import BaseClient
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetHistory(BaseClient):
|
||||
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):
|
||||
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.
|
||||
@@ -68,7 +70,7 @@ class GetHistory(BaseClient):
|
||||
On success, a :obj:`Messages <pyrogram.Messages>` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
|
||||
while True:
|
||||
|
@@ -22,18 +22,20 @@ from typing import Union, Iterable
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FloodWait
|
||||
from pyrogram.errors import FloodWait
|
||||
from ...ext import BaseClient
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GetMessages(BaseClient):
|
||||
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"]:
|
||||
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.
|
||||
|
||||
@@ -61,7 +63,7 @@ class GetMessages(BaseClient):
|
||||
*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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
ids, ids_type = (
|
||||
(message_ids, types.InputMessageID) if message_ids
|
||||
@@ -76,7 +78,7 @@ 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)
|
||||
|
@@ -23,13 +23,15 @@ 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]:
|
||||
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
|
||||
@@ -62,7 +64,7 @@ class IterHistory(BaseClient):
|
||||
A generator yielding :obj:`Message <pyrogram.Message>` objects.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
offset_id = offset_id or (1 if reverse else 0)
|
||||
current = 0
|
||||
|
@@ -23,9 +23,11 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class RetractVote(BaseClient):
|
||||
def retract_vote(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id) -> bool:
|
||||
def retract_vote(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id
|
||||
) -> bool:
|
||||
"""Use this method to retract your vote in a poll.
|
||||
|
||||
Args:
|
||||
@@ -41,7 +43,7 @@ class RetractVote(BaseClient):
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
self.send(
|
||||
functions.messages.SendVote(
|
||||
|
@@ -23,28 +23,32 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendAnimation(BaseClient):
|
||||
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]:
|
||||
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:
|
||||
@@ -121,7 +125,7 @@ class SendAnimation(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
@@ -141,7 +145,7 @@ class SendAnimation(BaseClient):
|
||||
w=width,
|
||||
h=height
|
||||
),
|
||||
types.DocumentAttributeFilename(os.path.basename(animation)),
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(animation)),
|
||||
types.DocumentAttributeAnimated()
|
||||
]
|
||||
)
|
||||
|
@@ -23,28 +23,32 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendAudio(BaseClient):
|
||||
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]:
|
||||
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.
|
||||
@@ -123,7 +127,7 @@ class SendAudio(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
@@ -142,7 +146,7 @@ class SendAudio(BaseClient):
|
||||
performer=performer,
|
||||
title=title
|
||||
),
|
||||
types.DocumentAttributeFilename(os.path.basename(audio))
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(audio))
|
||||
]
|
||||
)
|
||||
elif audio.startswith("http"):
|
||||
|
135
pyrogram/client/methods/messages/send_cached_media.py
Normal file
135
pyrogram/client/methods/messages/send_cached_media.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# 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 binascii
|
||||
import struct
|
||||
from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.errors import FileIdInvalid
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendCachedMedia(BaseClient):
|
||||
def send_cached_media(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
file_id: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union[
|
||||
"pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"
|
||||
] = None
|
||||
) -> Union["pyrogram.Message", None]:
|
||||
"""Use this method to send any media stored on the Telegram servers using a file_id.
|
||||
|
||||
This convenience method works with any valid file_id only.
|
||||
It does the same as calling the relevant method for sending media using a file_id, thus saving you from the
|
||||
hassle of using the correct method for the media the file_id is pointing to.
|
||||
|
||||
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).
|
||||
|
||||
file_id (``str``):
|
||||
Media to send.
|
||||
Pass a file_id as string to send a media that exists on the Telegram servers.
|
||||
|
||||
caption (``bool``, *optional*):
|
||||
Media caption, 0-1024 characters.
|
||||
|
||||
parse_mode (``str``, *optional*):
|
||||
Use :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or :obj:`HTML <pyrogram.ParseMode.HTML>`
|
||||
if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to Markdown.
|
||||
|
||||
disable_notification (``bool``, *optional*):
|
||||
Sends the message silently.
|
||||
Users will receive a notification with no sound.
|
||||
|
||||
reply_to_message_id (``int``, *optional*):
|
||||
If the message is a reply, ID of the original message.
|
||||
|
||||
reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*):
|
||||
Additional interface options. An object for an inline keyboard, custom reply keyboard,
|
||||
instructions to remove reply keyboard or to force a reply from the user.
|
||||
|
||||
Returns:
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
try:
|
||||
decoded = utils.decode(file_id)
|
||||
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
|
||||
unpacked = struct.unpack(fmt, decoded)
|
||||
except (AssertionError, binascii.Error, struct.error):
|
||||
raise FileIdInvalid from None
|
||||
else:
|
||||
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
|
||||
|
||||
if not media_type:
|
||||
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
|
||||
|
||||
if media_type == "photo":
|
||||
media = types.InputMediaPhoto(
|
||||
id=types.InputPhoto(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
else:
|
||||
media = types.InputMediaDocument(
|
||||
id=types.InputDocument(
|
||||
id=unpacked[2],
|
||||
access_hash=unpacked[3],
|
||||
file_reference=b""
|
||||
)
|
||||
)
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
@@ -23,10 +23,12 @@ from pyrogram.client.ext import BaseClient, ChatAction
|
||||
|
||||
|
||||
class SendChatAction(BaseClient):
|
||||
def send_chat_action(self,
|
||||
chat_id: Union[int, str],
|
||||
action: Union[ChatAction, str],
|
||||
progress: int = 0):
|
||||
def send_chat_action(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
action: Union[ChatAction, str],
|
||||
progress: int = 0
|
||||
):
|
||||
"""Use this method when you need to tell the other party that something is happening on your side.
|
||||
|
||||
Args:
|
||||
@@ -49,7 +51,7 @@ class SendChatAction(BaseClient):
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` if the provided string is not a valid ChatAction.
|
||||
"""
|
||||
|
||||
@@ -60,7 +62,7 @@ class SendChatAction(BaseClient):
|
||||
action = action.value
|
||||
|
||||
if "Upload" in action.__name__:
|
||||
action = action(progress)
|
||||
action = action(progress=progress)
|
||||
else:
|
||||
action = action()
|
||||
|
||||
|
@@ -24,18 +24,22 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendContact(BaseClient):
|
||||
def send_contact(self,
|
||||
chat_id: Union[int, str],
|
||||
phone_number: str,
|
||||
first_name: str,
|
||||
last_name: str = "",
|
||||
vcard: 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":
|
||||
def send_contact(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
phone_number: str,
|
||||
first_name: str,
|
||||
last_name: str = None,
|
||||
vcard: str = None,
|
||||
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 phone contacts.
|
||||
|
||||
Args:
|
||||
@@ -71,7 +75,7 @@ class SendContact(BaseClient):
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
@@ -79,8 +83,8 @@ class SendContact(BaseClient):
|
||||
media=types.InputMediaContact(
|
||||
phone_number=phone_number,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
vcard=vcard
|
||||
last_name=last_name or "",
|
||||
vcard=vcard or ""
|
||||
),
|
||||
message="",
|
||||
silent=disable_notification or None,
|
||||
|
@@ -23,25 +23,29 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendDocument(BaseClient):
|
||||
def send_document(self,
|
||||
chat_id: Union[int, str],
|
||||
document: str,
|
||||
thumb: str = None,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"] = None,
|
||||
progress: callable = None,
|
||||
progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
|
||||
def send_document(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
document: str,
|
||||
thumb: str = None,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union[
|
||||
"pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"
|
||||
] = None,
|
||||
progress: callable = None,
|
||||
progress_args: tuple = ()
|
||||
) -> Union["pyrogram.Message", None]:
|
||||
"""Use this method to send general files.
|
||||
|
||||
Args:
|
||||
@@ -56,7 +60,7 @@ class SendDocument(BaseClient):
|
||||
pass an HTTP URL as a string for Telegram to get a file from the Internet, or
|
||||
pass a file path as string to upload a new file that exists on your local machine.
|
||||
|
||||
thumb (``str``):
|
||||
thumb (``str``, *optional*):
|
||||
Thumbnail of the file sent.
|
||||
The thumbnail should be in JPEG format and less than 200 KB in size.
|
||||
A thumbnail's width and height should not exceed 90 pixels.
|
||||
@@ -109,7 +113,7 @@ class SendDocument(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
@@ -123,7 +127,7 @@ class SendDocument(BaseClient):
|
||||
file=file,
|
||||
thumb=thumb,
|
||||
attributes=[
|
||||
types.DocumentAttributeFilename(os.path.basename(document))
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(document))
|
||||
]
|
||||
)
|
||||
elif document.startswith("http"):
|
||||
|
@@ -24,16 +24,20 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendLocation(BaseClient):
|
||||
def send_location(self,
|
||||
chat_id: Union[int, str],
|
||||
latitude: float,
|
||||
longitude: float,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"] = None) -> "pyrogram.Message":
|
||||
def send_location(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
latitude: float,
|
||||
longitude: float,
|
||||
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 points on the map.
|
||||
|
||||
Args:
|
||||
@@ -63,15 +67,15 @@ class SendLocation(BaseClient):
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
media=types.InputMediaGeoPoint(
|
||||
types.InputGeoPoint(
|
||||
latitude,
|
||||
longitude
|
||||
geo_point=types.InputGeoPoint(
|
||||
lat=latitude,
|
||||
long=longitude
|
||||
)
|
||||
),
|
||||
message="",
|
||||
|
@@ -25,7 +25,7 @@ from typing import Union, List
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FloodWait
|
||||
from pyrogram.errors import FileIdInvalid, FloodWait
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -34,11 +34,13 @@ log = logging.getLogger(__name__)
|
||||
class SendMediaGroup(BaseClient):
|
||||
# TODO: Add progress parameter
|
||||
# TODO: Figure out how to send albums using URLs
|
||||
def send_media_group(self,
|
||||
chat_id: Union[int, str],
|
||||
media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]],
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
def send_media_group(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]],
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None
|
||||
):
|
||||
"""Use this method to send a group of photos or videos as an album.
|
||||
|
||||
Args:
|
||||
@@ -47,10 +49,8 @@ class SendMediaGroup(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).
|
||||
|
||||
media (``list``):
|
||||
A list containing either :obj:`InputMediaPhoto <pyrogram.InputMediaPhoto>` or
|
||||
:obj:`InputMediaVideo <pyrogram.InputMediaVideo>` objects
|
||||
describing photos and videos to be sent, must include 2–10 items.
|
||||
media (List of :obj:`InputMediaPhoto` and :obj:`InputMediaVideo`):
|
||||
A list describing photos and videos to be sent, must include 2–10 items.
|
||||
|
||||
disable_notification (``bool``, *optional*):
|
||||
Sends the message silently.
|
||||
@@ -64,7 +64,7 @@ class SendMediaGroup(BaseClient):
|
||||
single messages sent.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
multi_media = []
|
||||
|
||||
@@ -137,7 +137,7 @@ class SendMediaGroup(BaseClient):
|
||||
w=i.width,
|
||||
h=i.height
|
||||
),
|
||||
types.DocumentAttributeFilename(os.path.basename(i.media))
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
|
||||
]
|
||||
)
|
||||
)
|
||||
|
@@ -24,17 +24,21 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class SendMessage(BaseClient):
|
||||
def send_message(self,
|
||||
chat_id: Union[int, str],
|
||||
text: str,
|
||||
parse_mode: str = "",
|
||||
disable_web_page_preview: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"] = None) -> "pyrogram.Message":
|
||||
def send_message(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
text: str,
|
||||
parse_mode: str = "",
|
||||
disable_web_page_preview: bool = None,
|
||||
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 text messages.
|
||||
|
||||
Args:
|
||||
@@ -69,7 +73,7 @@ class SendMessage(BaseClient):
|
||||
On success, the sent :obj:`Message` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
message, entities = style.parse(text).values()
|
||||
|
@@ -23,25 +23,29 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendPhoto(BaseClient):
|
||||
def send_photo(self,
|
||||
chat_id: Union[int, str],
|
||||
photo: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
ttl_seconds: int = 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]:
|
||||
def send_photo(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
photo: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
ttl_seconds: int = 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 photos.
|
||||
|
||||
Args:
|
||||
@@ -108,7 +112,7 @@ class SendPhoto(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
@@ -24,16 +24,20 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendPoll(BaseClient):
|
||||
def send_poll(self,
|
||||
chat_id: Union[int, str],
|
||||
question: str,
|
||||
options: List[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":
|
||||
def send_poll(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
question: str,
|
||||
options: List[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 new poll.
|
||||
|
||||
Args:
|
||||
@@ -63,7 +67,7 @@ class SendPoll(BaseClient):
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
|
@@ -23,22 +23,26 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendSticker(BaseClient):
|
||||
def send_sticker(self,
|
||||
chat_id: Union[int, str],
|
||||
sticker: str,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"] = None,
|
||||
progress: callable = None,
|
||||
progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
|
||||
def send_sticker(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
sticker: str,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
reply_markup: Union[
|
||||
"pyrogram.InlineKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardMarkup",
|
||||
"pyrogram.ReplyKeyboardRemove",
|
||||
"pyrogram.ForceReply"
|
||||
] = None,
|
||||
progress: callable = None,
|
||||
progress_args: tuple = ()
|
||||
) -> Union["pyrogram.Message", None]:
|
||||
"""Use this method to send .webp stickers.
|
||||
|
||||
Args:
|
||||
@@ -92,7 +96,7 @@ class SendSticker(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
|
||||
@@ -103,7 +107,7 @@ class SendSticker(BaseClient):
|
||||
mime_type="image/webp",
|
||||
file=file,
|
||||
attributes=[
|
||||
types.DocumentAttributeFilename(os.path.basename(sticker))
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(sticker))
|
||||
]
|
||||
)
|
||||
elif sticker.startswith("http"):
|
||||
|
@@ -24,20 +24,24 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class SendVenue(BaseClient):
|
||||
def send_venue(self,
|
||||
chat_id: Union[int, str],
|
||||
latitude: float,
|
||||
longitude: float,
|
||||
title: str,
|
||||
address: str,
|
||||
foursquare_id: str = "",
|
||||
foursquare_type: 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":
|
||||
def send_venue(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
latitude: float,
|
||||
longitude: float,
|
||||
title: str,
|
||||
address: str,
|
||||
foursquare_id: str = "",
|
||||
foursquare_type: 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 information about a venue.
|
||||
|
||||
Args:
|
||||
@@ -80,7 +84,7 @@ class SendVenue(BaseClient):
|
||||
On success, the sent :obj:`Message <pyrogram.Message>` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
r = self.send(
|
||||
functions.messages.SendMedia(
|
||||
|
@@ -23,29 +23,33 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendVideo(BaseClient):
|
||||
def send_video(self,
|
||||
chat_id: Union[int, str],
|
||||
video: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
thumb: str = None,
|
||||
supports_streaming: bool = True,
|
||||
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]:
|
||||
def send_video(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
video: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
thumb: str = None,
|
||||
supports_streaming: bool = True,
|
||||
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 video files.
|
||||
|
||||
Args:
|
||||
@@ -125,7 +129,7 @@ class SendVideo(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
@@ -145,7 +149,7 @@ class SendVideo(BaseClient):
|
||||
w=width,
|
||||
h=height
|
||||
),
|
||||
types.DocumentAttributeFilename(os.path.basename(video))
|
||||
types.DocumentAttributeFilename(file_name=os.path.basename(video))
|
||||
]
|
||||
)
|
||||
elif video.startswith("http"):
|
||||
|
@@ -23,25 +23,29 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendVideoNote(BaseClient):
|
||||
def send_video_note(self,
|
||||
chat_id: Union[int, str],
|
||||
video_note: str,
|
||||
duration: int = 0,
|
||||
length: int = 1,
|
||||
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]:
|
||||
def send_video_note(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
video_note: str,
|
||||
duration: int = 0,
|
||||
length: int = 1,
|
||||
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 video messages.
|
||||
|
||||
Args:
|
||||
@@ -107,7 +111,7 @@ class SendVideoNote(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
|
||||
|
@@ -23,25 +23,29 @@ from typing import Union
|
||||
|
||||
import pyrogram
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.errors import FileIdInvalid, FilePartMissing
|
||||
from pyrogram.client.ext import BaseClient, utils
|
||||
|
||||
|
||||
class SendVoice(BaseClient):
|
||||
def send_voice(self,
|
||||
chat_id: Union[int, str],
|
||||
voice: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
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]:
|
||||
def send_voice(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
voice: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
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.
|
||||
|
||||
Args:
|
||||
@@ -106,7 +110,7 @@ class SendVoice(BaseClient):
|
||||
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.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
file = None
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
@@ -23,10 +23,12 @@ from pyrogram.client.ext import BaseClient
|
||||
|
||||
|
||||
class VotePoll(BaseClient):
|
||||
def vote_poll(self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id,
|
||||
option: int) -> bool:
|
||||
def vote_poll(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
message_id: id,
|
||||
option: int
|
||||
) -> bool:
|
||||
"""Use this method to vote a poll.
|
||||
|
||||
Args:
|
||||
@@ -45,7 +47,7 @@ class VotePoll(BaseClient):
|
||||
On success, True is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
poll = self.get_messages(chat_id, message_id).poll
|
||||
|
||||
|
@@ -24,10 +24,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class ChangeCloudPassword(BaseClient):
|
||||
def change_cloud_password(self,
|
||||
current_password: str,
|
||||
new_password: str,
|
||||
new_hint: str = "") -> bool:
|
||||
def change_cloud_password(
|
||||
self,
|
||||
current_password: str,
|
||||
new_password: str,
|
||||
new_hint: str = ""
|
||||
) -> bool:
|
||||
"""Use this method to change your Two-Step Verification password (Cloud Password) with a new one.
|
||||
|
||||
Args:
|
||||
@@ -44,7 +46,7 @@ class ChangeCloudPassword(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is no cloud password to change.
|
||||
"""
|
||||
r = self.send(functions.account.GetPassword())
|
||||
|
@@ -24,10 +24,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class EnableCloudPassword(BaseClient):
|
||||
def enable_cloud_password(self,
|
||||
password: str,
|
||||
hint: str = "",
|
||||
email: str = None) -> bool:
|
||||
def enable_cloud_password(
|
||||
self,
|
||||
password: str,
|
||||
hint: str = "",
|
||||
email: str = None
|
||||
) -> bool:
|
||||
"""Use this method to enable the Two-Step Verification security feature (Cloud Password) on your account.
|
||||
|
||||
This password will be asked when you log-in on a new device in addition to the SMS code.
|
||||
@@ -46,7 +48,7 @@ class EnableCloudPassword(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is already a cloud password enabled.
|
||||
"""
|
||||
r = self.send(functions.account.GetPassword())
|
||||
|
@@ -22,8 +22,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class RemoveCloudPassword(BaseClient):
|
||||
def remove_cloud_password(self,
|
||||
password: str) -> bool:
|
||||
def remove_cloud_password(
|
||||
self,
|
||||
password: str
|
||||
) -> bool:
|
||||
"""Use this method to turn off the Two-Step Verification security feature (Cloud Password) on your account.
|
||||
|
||||
Args:
|
||||
@@ -34,7 +36,7 @@ class RemoveCloudPassword(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
``ValueError`` in case there is no cloud password to remove.
|
||||
"""
|
||||
r = self.send(functions.account.GetPassword())
|
||||
|
@@ -101,4 +101,4 @@ def compute_check(r: types.account.Password, password: str) -> types.InputCheckP
|
||||
+ K_bytes
|
||||
)
|
||||
|
||||
return types.InputCheckPasswordSRP(srp_id, A_bytes, M1_bytes)
|
||||
return types.InputCheckPasswordSRP(srp_id=srp_id, A=A_bytes, M1=M1_bytes)
|
||||
|
@@ -21,6 +21,7 @@ from .get_me import GetMe
|
||||
from .get_user_profile_photos import GetUserProfilePhotos
|
||||
from .get_users import GetUsers
|
||||
from .set_user_profile_photo import SetUserProfilePhoto
|
||||
from .update_username import UpdateUsername
|
||||
|
||||
|
||||
class Users(
|
||||
@@ -28,6 +29,7 @@ class Users(
|
||||
SetUserProfilePhoto,
|
||||
DeleteUserProfilePhotos,
|
||||
GetUsers,
|
||||
GetMe
|
||||
GetMe,
|
||||
UpdateUsername
|
||||
):
|
||||
pass
|
||||
|
@@ -25,9 +25,11 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class DeleteUserProfilePhotos(BaseClient):
|
||||
def delete_user_profile_photos(self,
|
||||
id: Union[str, List[str]]) -> bool:
|
||||
"""Use this method to delete your own profile photos
|
||||
def delete_user_profile_photos(
|
||||
self,
|
||||
id: Union[str, List[str]]
|
||||
) -> bool:
|
||||
"""Use this method to delete your own profile photos.
|
||||
|
||||
Args:
|
||||
id (``str`` | ``list``):
|
||||
@@ -38,7 +40,7 @@ class DeleteUserProfilePhotos(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
id = id if isinstance(id, list) else [id]
|
||||
input_photos = []
|
||||
|
@@ -29,13 +29,13 @@ class GetMe(BaseClient):
|
||||
Basic information about the user or bot in form of a :obj:`User` object
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
return pyrogram.User._parse(
|
||||
self,
|
||||
self.send(
|
||||
functions.users.GetFullUser(
|
||||
types.InputPeerSelf()
|
||||
id=types.InputPeerSelf()
|
||||
)
|
||||
).user
|
||||
)
|
||||
|
@@ -24,10 +24,12 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetUserProfilePhotos(BaseClient):
|
||||
def get_user_profile_photos(self,
|
||||
user_id: Union[int, str],
|
||||
offset: int = 0,
|
||||
limit: int = 100) -> "pyrogram.UserProfilePhotos":
|
||||
def get_user_profile_photos(
|
||||
self,
|
||||
user_id: Union[int, str],
|
||||
offset: int = 0,
|
||||
limit: int = 100
|
||||
) -> "pyrogram.UserProfilePhotos":
|
||||
"""Use this method to get a list of profile pictures for a user.
|
||||
|
||||
Args:
|
||||
@@ -48,7 +50,7 @@ class GetUserProfilePhotos(BaseClient):
|
||||
On success, a :obj:`UserProfilePhotos` object is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
return pyrogram.UserProfilePhotos._parse(
|
||||
self,
|
||||
|
@@ -24,8 +24,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class GetUsers(BaseClient):
|
||||
def get_users(self,
|
||||
user_ids: Iterable[Union[int, str]]) -> Union["pyrogram.User", List["pyrogram.User"]]:
|
||||
def get_users(
|
||||
self,
|
||||
user_ids: Iterable[Union[int, str]]
|
||||
) -> Union["pyrogram.User", List["pyrogram.User"]]:
|
||||
"""Use this method to get information about a user.
|
||||
You can retrieve up to 200 users at once.
|
||||
|
||||
@@ -41,7 +43,7 @@ class GetUsers(BaseClient):
|
||||
*user_ids* was an integer or string, the single requested :obj:`User` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
is_iterable = not isinstance(user_ids, (int, str))
|
||||
user_ids = list(user_ids) if is_iterable else [user_ids]
|
||||
|
@@ -21,8 +21,10 @@ from ...ext import BaseClient
|
||||
|
||||
|
||||
class SetUserProfilePhoto(BaseClient):
|
||||
def set_user_profile_photo(self,
|
||||
photo: str) -> bool:
|
||||
def set_user_profile_photo(
|
||||
self,
|
||||
photo: str
|
||||
) -> bool:
|
||||
"""Use this method to set a new profile photo.
|
||||
|
||||
This method only works for Users.
|
||||
@@ -37,13 +39,13 @@ class SetUserProfilePhoto(BaseClient):
|
||||
True on success.
|
||||
|
||||
Raises:
|
||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
||||
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||
"""
|
||||
|
||||
return bool(
|
||||
self.send(
|
||||
functions.photos.UploadProfilePhoto(
|
||||
self.save_file(photo)
|
||||
file=self.save_file(photo)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user