2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-31 14:25:55 +00:00

Merge develop -> asyncio

This commit is contained in:
Dan
2019-07-11 04:17:46 +02:00
51 changed files with 890 additions and 930 deletions

View File

@@ -400,8 +400,10 @@ class Client(Methods, BaseClient):
await self.start()
async def idle(self, stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
"""Block the main script execution until a signal (e.g.: from CTRL+C) is received.
Once the signal is received, the client will automatically stop and the main script will continue its execution.
"""Block the main script execution until a signal is received.
Once the signal is received (e.g.: from CTRL+C), the client will automatically stop and the main script will
continue its execution.
This is used after starting one or more clients and is useful for event-driven applications only, that are,
applications which react upon incoming Telegram updates through handlers, rather than executing a set of methods

View File

@@ -74,7 +74,7 @@ class Dispatcher:
return await pyrogram.CallbackQuery._parse(self.client, update, users), CallbackQueryHandler
async def user_status_parser(update, users, chats):
return pyrogram.UserStatus._parse(self.client, update.status, update.user_id), UserStatusHandler
return pyrogram.User._parse_user_status(self.client, update), UserStatusHandler
async def inline_query_parser(update, users, chats):
return pyrogram.InlineQuery._parse(self.client, update, users), InlineQueryHandler

View File

@@ -21,26 +21,24 @@ from .handler import Handler
class UserStatusHandler(Handler):
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
It is intended to be used with :meth:`~Client.add_handler`
It is intended to be used with :meth:`~Client.add_handler`.
For a nicer way to register this handler, have a look at the
:meth:`~Client.on_user_status` decorator.
For a nicer way to register this handler, have a look at the :meth:`~Client.on_user_status` decorator.
Parameters:
callback (``callable``):
Pass a function that will be called when a new UserStatus update arrives. It takes *(client, user_status)*
Pass a function that will be called when a new user status update arrives. It takes *(client, user)*
as positional arguments (look at the section below for a detailed description).
filters (:obj:`Filters`):
Pass one or more filters to allow only a subset of messages to be passed
in your callback function.
Pass one or more filters to allow only a subset of users to be passed in your callback function.
Other parameters:
client (:obj:`Client`):
The Client itself, useful when you want to call other API methods inside the user status handler.
user_status (:obj:`UserStatus`):
The received UserStatus update.
user (:obj:`User`):
The user containing the updated status.
"""
def __init__(self, callback: callable, filters=None):

View File

@@ -52,13 +52,13 @@ class RestrictChat(BaseClient):
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.
implies can_send_messages.
can_add_web_page_previews (``bool``, *optional*):
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
Pass True, if the user may add web page previews to their messages, implies can_send_messages.
can_send_polls (``bool``, *optional*):
Pass True, if the user can send polls, implies can_send_media_messages.
Pass True, if the user can send polls, implies can_send_messages.
can_change_info (``bool``, *optional*):
Pass True, if the user can change the chat title, photo and other settings.
@@ -96,7 +96,6 @@ class RestrictChat(BaseClient):
if can_send_other_messages:
send_messages = None
send_media = None
send_stickers = None
send_gifs = None
send_games = None
@@ -104,7 +103,6 @@ class RestrictChat(BaseClient):
if can_add_web_page_previews:
send_messages = None
send_media = None
embed_links = None
if can_send_polls:

View File

@@ -65,13 +65,13 @@ class RestrictChatMember(BaseClient):
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.
implies can_send_messages.
can_add_web_page_previews (``bool``, *optional*):
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
Pass True, if the user may add web page previews to their messages, implies can_send_messages.
can_send_polls (``bool``, *optional*):
Pass True, if the user can send polls, implies can_send_media_messages.
Pass True, if the user can send polls, implies can_send_messages.
can_change_info (``bool``, *optional*):
Pass True, if the user can change the chat title, photo and other settings.
@@ -109,7 +109,6 @@ class RestrictChatMember(BaseClient):
if can_send_other_messages:
send_messages = None
send_media = None
send_stickers = None
send_gifs = None
send_games = None
@@ -117,7 +116,6 @@ class RestrictChatMember(BaseClient):
if can_add_web_page_previews:
send_messages = None
send_media = None
embed_links = None
if can_send_polls:

View File

@@ -87,7 +87,7 @@ class DownloadMedia(BaseClient):
Raises:
RPCError: In case of a Telegram RPC error.
``ValueError`` if the message doesn't contain any downloadable media
ValueError: if the message doesn't contain any downloadable media
"""
error_message = "This message doesn't contain any downloadable media"
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note")

View File

@@ -40,7 +40,7 @@ class EditInlineCaption(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -44,7 +44,7 @@ class EditInlineText(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -48,7 +48,7 @@ class EditMessageCaption(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -50,7 +50,7 @@ class EditMessageText(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -72,7 +72,7 @@ class SendAnimation(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -68,7 +68,7 @@ class SendAudio(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -61,7 +61,7 @@ class SendCachedMedia(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -69,7 +69,7 @@ class SendDocument(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -53,7 +53,7 @@ class SendMessage(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -64,7 +64,7 @@ class SendPhoto(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -68,7 +68,7 @@ class SendVideo(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -89,6 +89,7 @@ class SendVideo(BaseClient):
supports_streaming (``bool``, *optional*):
Pass True, if the uploaded video is suitable for streaming.
Defaults to True.
disable_notification (``bool``, *optional*):
Sends the message silently.

View File

@@ -64,7 +64,7 @@ class SendVoice(BaseClient):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -21,7 +21,6 @@ from .delete_profile_photos import DeleteProfilePhotos
from .get_me import GetMe
from .get_profile_photos import GetProfilePhotos
from .get_profile_photos_count import GetProfilePhotosCount
from .get_user_dc import GetUserDC
from .get_users import GetUsers
from .iter_profile_photos import IterProfilePhotos
from .set_profile_photo import SetProfilePhoto
@@ -38,7 +37,6 @@ class Users(
GetMe,
UpdateUsername,
GetProfilePhotosCount,
GetUserDC,
IterProfilePhotos,
UnblockUser
):

View File

@@ -38,7 +38,7 @@ class BlockUser(BaseClient):
"""
return bool(
await self.send(
functions.contact.Block(
functions.contacts.Block(
id=await self.resolve_peer(user_id)
)
)

View File

@@ -1,58 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union
from pyrogram.api import functions, types
from ...ext import BaseClient
class GetUserDC(BaseClient):
async def get_user_dc(self, user_id: Union[int, str]) -> Union[int, None]:
"""Get the assigned DC (data center) of a user.
.. note::
This information is approximate: it is based on where Telegram stores a user profile pictures and does not
by any means tell you the user location (i.e. a user might travel far away, but will still connect to its
assigned DC). More info at `FAQs <../faq#what-are-the-ip-addresses-of-telegram-data-centers>`_.
Parameters:
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
``int`` | ``None``: The DC identifier as integer, or None in case it wasn't possible to get it (i.e. the
user has no profile picture or has the privacy setting enabled).
Raises:
RPCError: In case of a Telegram RPC error.
"""
r = await self.send(functions.users.GetUsers(id=[await self.resolve_peer(user_id)]))
if r:
r = r[0]
if r.photo:
if isinstance(r.photo, types.UserProfilePhoto):
return r.photo.dc_id
return None

View File

@@ -38,7 +38,7 @@ class UnblockUser(BaseClient):
"""
return bool(
await self.send(
functions.contact.Unblock(
functions.contacts.Unblock(
id=await self.resolve_peer(user_id)
)
)

View File

@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import html
import logging
import re
from collections import OrderedDict
from html.parser import HTMLParser
@@ -27,6 +28,8 @@ from pyrogram.api import types
from pyrogram.errors import PeerIdInvalid
from . import utils
log = logging.getLogger(__name__)
class Parser(HTMLParser):
MENTION_RE = re.compile(r"tg://user\?id=(\d+)")
@@ -94,7 +97,7 @@ class Parser(HTMLParser):
line, offset = self.getpos()
offset += 1
raise ValueError("Unmatched closing tag </{}> at line {}:{}".format(tag, line, offset))
log.warning("Unmatched closing tag </{}> at line {}:{}".format(tag, line, offset))
else:
if not self.tag_entities[tag]:
self.tag_entities.pop(tag)
@@ -120,7 +123,7 @@ class HTML:
for tag, entities in parser.tag_entities.items():
unclosed_tags.append("<{}> (x{})".format(tag, len(entities)))
raise ValueError("Unclosed tags: {}".format(", ".join(unclosed_tags)))
log.warning("Unclosed tags: {}".format(", ".join(unclosed_tags)))
entities = []

View File

@@ -44,7 +44,7 @@ class Parser:
if mode == "":
return self.markdown.parse(text)
if mode in "markdown":
if mode in ["markdown", "md"]:
return self.markdown.parse(text, True)
if mode == "html":

View File

@@ -191,7 +191,7 @@ class CallbackQuery(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -243,7 +243,7 @@ class CallbackQuery(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -42,7 +42,7 @@ class InputMediaAnimation(InputMedia):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -44,7 +44,7 @@ class InputMediaAudio(InputMedia):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -42,7 +42,7 @@ class InputMediaDocument(InputMedia):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
"""

View File

@@ -38,7 +38,7 @@ class InputMediaPhoto(InputMedia):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
"""

View File

@@ -44,7 +44,7 @@ class InputMediaVideo(InputMedia):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -33,7 +33,7 @@ class InputTextMessageContent(InputMessageContent):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -689,7 +689,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -786,7 +786,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -923,7 +923,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -1052,7 +1052,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -1270,7 +1270,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -1660,7 +1660,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -2058,7 +2058,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -2314,7 +2314,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -2412,7 +2412,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
@@ -2469,7 +2469,7 @@ class Message(Object, Update):
parse_mode (``str``, *optional*):
By default, texts are parsed using both Markdown and HTML styles.
You can combine both syntaxes together.
Pass "markdown" to enable Markdown-style parsing only.
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.

View File

@@ -23,8 +23,7 @@ from .chat_photo import ChatPhoto
from .chat_preview import ChatPreview
from .dialog import Dialog
from .user import User
from .user_status import UserStatus
__all__ = [
"Chat", "ChatMember", "ChatPermissions", "ChatPhoto", "ChatPreview", "Dialog", "User", "UserStatus"
"Chat", "ChatMember", "ChatPermissions", "ChatPhoto", "ChatPreview", "Dialog", "User"
]

View File

@@ -20,62 +20,81 @@ import html
import pyrogram
from pyrogram.api import types
from .chat_photo import ChatPhoto
from .user_status import UserStatus
from ..object import Object
from ..update import Update
class User(Object):
class User(Object, Update):
"""A Telegram user or bot.
Parameters:
id (``int``):
Unique identifier for this user or bot.
is_self(``bool``):
is_self(``bool``, *optional*):
True, if this user is you yourself.
is_contact(``bool``):
is_contact(``bool``, *optional*):
True, if this user is in your contacts.
is_mutual_contact(``bool``):
is_mutual_contact(``bool``, *optional*):
True, if you both have each other's contact.
is_deleted(``bool``):
is_deleted(``bool``, *optional*):
True, if this user is deleted.
is_bot (``bool``):
is_bot (``bool``, *optional*):
True, if this user is a bot.
is_verified (``bool``):
is_verified (``bool``, *optional*):
True, if this user has been verified by Telegram.
is_restricted (``bool``):
is_restricted (``bool``, *optional*):
True, if this user has been restricted. Bots only.
See *restriction_reason* for details.
is_scam (``bool``):
is_scam (``bool``, *optional*):
True, if this user has been flagged for scam.
is_support (``bool``):
is_support (``bool``, *optional*):
True, if this user is part of the Telegram support team.
first_name (``str``):
first_name (``str``, *optional*):
User's or bot's first name.
status (:obj:`UserStatus <pyrogram.UserStatus>`, *optional*):
User's Last Seen status. Empty for bots.
last_name (``str``, *optional*):
User's or bot's last name.
status (``str``, *optional*):
User's Last Seen & Online status.
Can be one of the following:
"*online*", user is online right now.
"*offline*", user is currently offline.
"*recently*", user with hidden last seen time who was online between 1 second and 2-3 days ago.
"*within_week*", user with hidden last seen time who was online between 2-3 and seven days ago.
"*within_month*", user with hidden last seen time who was online between 6-7 days and a month ago.
"*long_time_ago*", blocked user or user with hidden last seen time who was online more than a month ago.
*None*, for bots.
last_online_date (``int``, *optional*):
Last online date of a user. Only available in case status is "*offline*".
next_offline_date (``int``, *optional*):
Date when a user will automatically go offline. Only available in case status is "*online*".
username (``str``, *optional*):
User's or bot's username.
language_code (``str``, *optional*):
IETF language tag of the user's language.
dc_id (``int``, *optional*):
User's or bot's assigned DC (data center). Available only in case the user has set a public profile photo.
Note that this information is approximate; it is based on where Telegram stores a user profile pictures and
does not by any means tell you the user location (i.e. a user might travel far away, but will still connect
to its assigned DC). More info at `FAQs </faq#what-are-the-ip-addresses-of-telegram-data-centers>`_.
phone_number (``str``, *optional*):
User's phone number.
@@ -89,8 +108,8 @@ class User(Object):
__slots__ = [
"id", "is_self", "is_contact", "is_mutual_contact", "is_deleted", "is_bot", "is_verified", "is_restricted",
"is_scam", "is_support", "first_name", "last_name", "status", "username", "language_code", "phone_number",
"photo", "restriction_reason"
"is_scam", "is_support", "first_name", "last_name", "status", "last_online_date", "next_offline_date",
"username", "language_code", "dc_id", "phone_number", "photo", "restriction_reason"
]
def __init__(
@@ -98,20 +117,23 @@ class User(Object):
*,
client: "pyrogram.BaseClient" = None,
id: int,
is_self: bool,
is_contact: bool,
is_mutual_contact: bool,
is_deleted: bool,
is_bot: bool,
is_verified: bool,
is_restricted: bool,
is_scam: bool,
is_support: bool,
first_name: str,
is_self: bool = None,
is_contact: bool = None,
is_mutual_contact: bool = None,
is_deleted: bool = None,
is_bot: bool = None,
is_verified: bool = None,
is_restricted: bool = None,
is_scam: bool = None,
is_support: bool = None,
first_name: str = None,
last_name: str = None,
status: UserStatus = None,
status: str = None,
last_online_date: int = None,
next_offline_date: int = None,
username: str = None,
language_code: str = None,
dc_id: int = None,
phone_number: str = None,
photo: ChatPhoto = None,
restriction_reason: str = None
@@ -131,8 +153,11 @@ class User(Object):
self.first_name = first_name
self.last_name = last_name
self.status = status
self.last_online_date = last_online_date
self.next_offline_date = next_offline_date
self.username = username
self.language_code = language_code
self.dc_id = dc_id
self.phone_number = phone_number
self.photo = photo
self.restriction_reason = restriction_reason
@@ -161,15 +186,57 @@ class User(Object):
is_support=user.support,
first_name=user.first_name,
last_name=user.last_name,
status=UserStatus._parse(client, user.status, user.id, user.bot),
**User._parse_status(user.status, user.bot),
username=user.username,
language_code=user.lang_code,
dc_id=getattr(user.photo, "dc_id", None),
phone_number=user.phone,
photo=ChatPhoto._parse(client, user.photo, user.id),
restriction_reason=user.restriction_reason,
client=client
)
@staticmethod
def _parse_status(user_status: types.UpdateUserStatus, is_bot: bool = False):
if isinstance(user_status, types.UserStatusOnline):
status, date = "online", user_status.expires
elif isinstance(user_status, types.UserStatusOffline):
status, date = "offline", user_status.was_online
elif isinstance(user_status, types.UserStatusRecently):
status, date = "recently", None
elif isinstance(user_status, types.UserStatusLastWeek):
status, date = "within_week", None
elif isinstance(user_status, types.UserStatusLastMonth):
status, date = "within_month", None
else:
status, date = "long_time_ago", None
last_online_date = None
next_offline_date = None
if is_bot:
status = None
if status == "online":
next_offline_date = date
if status == "offline":
last_online_date = date
return {
"status": status,
"last_online_date": last_online_date,
"next_offline_date": next_offline_date
}
@staticmethod
def _parse_user_status(client, user_status: types.UpdateUserStatus):
return User(
id=user_status.user_id,
**User._parse_status(user_status.status),
client=client
)
async def archive(self):
"""Bound method *archive* of :obj:`User`.
@@ -215,3 +282,49 @@ class User(Object):
"""
return await self._client.unarchive_chats(self.id)
def block(self):
"""Bound method *block* of :obj:`User`.
Use as a shortcut for:
.. code-block:: python
client.block_user(123456789)
Example:
.. code-block:: python
user.block()
Returns:
True on success.
Raises:
RPCError: In case of a Telegram RPC error.
"""
return self._client.block_user(self.id)
def unblock(self):
"""Bound method *unblock* of :obj:`User`.
Use as a shortcut for:
.. code-block:: python
client.unblock_user(123456789)
Example:
.. code-block:: python
user.unblock()
Returns:
True on success.
Raises:
RPCError: In case of a Telegram RPC error.
"""
return self._client.unblock_user(self.id)

View File

@@ -1,116 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram.api import types
from ..object import Object
from ..update import Update
class UserStatus(Object, Update):
"""A User status (Last Seen privacy).
.. note::
You won't see exact last seen timestamps for people with whom you don't share your own. Instead, you get
"recently", "within_week", "within_month" or "long_time_ago" fields set.
Parameters:
user_id (``int``):
User's id.
online (``bool``, *optional*):
True if the user is online in this very moment, None otherwise.
If True, the "date" field will be also set containing the online expiration date (i.e.: the date when a
user will automatically go offline in case of no action by his client).
offline (``bool``, *optional*):
True if the user is offline in this moment and has the Last Seen privacy setting public, None otherwise.
If True, the "date" field will be also set containing the last seen date (i.e.: the date when a user
was online the last time).
date (``int``, *optional*):
Exact date in unix time. Available only in case "online" or "offline" equals to True.
recently (``bool``, *optional*):
True for users with hidden Last Seen privacy that have been online between 1 second and 2-3 days ago,
None otherwise.
within_week (``bool``, *optional*):
True for users with hidden Last Seen privacy that have been online between 2-3 and seven days ago,
None otherwise.
within_month (``bool``, *optional*):
True for users with hidden Last Seen privacy that have been online between 6-7 days and a month ago,
None otherwise.
long_time_ago (``bool``, *optional*):
True for users with hidden Last Seen privacy that have been online more than a month ago (this is also
always shown to blocked users), None otherwise.
"""
__slots__ = ["user_id", "online", "offline", "date", "recently", "within_week", "within_month", "long_time_ago"]
def __init__(
self,
*,
client: "pyrogram.BaseClient" = None,
user_id: int,
online: bool = None,
offline: bool = None,
date: int = None,
recently: bool = None,
within_week: bool = None,
within_month: bool = None,
long_time_ago: bool = None
):
super().__init__(client)
self.user_id = user_id
self.online = online
self.offline = offline
self.date = date
self.recently = recently
self.within_week = within_week
self.within_month = within_month
self.long_time_ago = long_time_ago
@staticmethod
def _parse(client, user_status, user_id: int, is_bot: bool = False):
if is_bot:
return None
status = UserStatus(user_id=user_id, client=client)
if isinstance(user_status, types.UserStatusOnline):
status.online = True
status.date = user_status.expires
elif isinstance(user_status, types.UserStatusOffline):
status.offline = True
status.date = user_status.was_online
elif isinstance(user_status, types.UserStatusRecently):
status.recently = True
elif isinstance(user_status, types.UserStatusLastWeek):
status.within_week = True
elif isinstance(user_status, types.UserStatusLastMonth):
status.within_month = True
else:
status.long_time_ago = True
return status

View File

@@ -32,12 +32,12 @@ class RPCError(Exception):
NAME = None
MESSAGE = "{x}"
def __init__(self, x: int or RawRPCError, rpc_name: str, is_unknown: bool):
super().__init__("[{} {}]: {} ({})".format(
def __init__(self, x: int or RawRPCError = None, rpc_name: str = None, is_unknown: bool = False):
super().__init__("[{} {}]: {} {}".format(
self.CODE,
self.ID or self.NAME,
self.MESSAGE.format(x=x),
'caused by "{}"'.format(rpc_name)
'(caused by "{}")'.format(rpc_name) if rpc_name else ""
))
try:

View File

@@ -26,11 +26,11 @@ class DataCenter:
}
PROD = {
1: "149.154.175.50",
1: "149.154.175.53",
2: "149.154.167.51",
3: "149.154.175.100",
4: "149.154.167.91",
5: "91.108.56.149",
5: "91.108.56.130",
121: "95.213.217.195"
}