2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-30 05:48:14 +00:00

Merge develop -> asyncio

This commit is contained in:
Dan 2019-06-05 11:25:31 +02:00
commit 7c3bbb3fc7
106 changed files with 711 additions and 376 deletions

View File

@ -53,10 +53,10 @@ def get_docstring_arg_type(t: str, is_list: bool = False, is_pyrogram_type: bool
return "``{}``".format(t.lower())
elif t == "true":
return "``bool``"
elif t == "Object" or t == "X":
return "Any object from :obj:`pyrogram.api.types`"
elif t == "TLObject" or t == "X":
return "Any object from :obj:`~pyrogram.api.types`"
elif t == "!X":
return "Any method from :obj:`pyrogram.api.functions`"
return "Any method from :obj:`~pyrogram.api.functions`"
elif t.startswith("Vector"):
return "List of " + get_docstring_arg_type(t.split("<", 1)[1][:-1], True, is_pyrogram_type)
else:
@ -394,7 +394,7 @@ def start():
)
read_types += "\n "
read_types += "{} = Object.read(b{}) if flags & (1 << {}) else []\n ".format(
read_types += "{} = TLObject.read(b{}) if flags & (1 << {}) else []\n ".format(
arg_name, ", {}".format(sub_type.title()) if sub_type in core_types else "", index
)
else:
@ -403,7 +403,7 @@ def start():
write_types += "b.write(self.{}.write())\n ".format(arg_name)
read_types += "\n "
read_types += "{} = Object.read(b) if flags & (1 << {}) else None\n ".format(
read_types += "{} = TLObject.read(b) if flags & (1 << {}) else None\n ".format(
arg_name, index
)
else:
@ -422,7 +422,7 @@ def start():
)
read_types += "\n "
read_types += "{} = Object.read(b{})\n ".format(
read_types += "{} = TLObject.read(b{})\n ".format(
arg_name, ", {}".format(sub_type.title()) if sub_type in core_types else ""
)
else:
@ -430,7 +430,7 @@ def start():
write_types += "b.write(self.{}.write())\n ".format(arg_name)
read_types += "\n "
read_types += "{} = Object.read(b)\n ".format(arg_name)
read_types += "{} = TLObject.read(b)\n ".format(arg_name)
if c.docs:
description = c.docs.split("|")[0].split("§")[1]

View File

@ -1356,4 +1356,7 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
folders.deleteFolder#1c295881 folder_id:int = Updates;
// LAYER 100
// LAYER 100
// Ports
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;

View File

@ -5,7 +5,7 @@ from io import BytesIO
from pyrogram.api.core import *
class {class_name}(Object):
class {class_name}(TLObject):
"""{docstring_args}
"""

80
docs/releases.py Normal file
View File

@ -0,0 +1,80 @@
# 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 shutil
from datetime import datetime
from pathlib import Path
import pypandoc
import requests
URL = "https://api.github.com/repos/pyrogram/pyrogram/releases"
DEST = Path("source/releases")
INTRO = """
Release Notes
=============
Release notes for Pyrogram releases will describe what's new in each version, and will also make you aware of any
backwards-incompatible changes made in that version.
When upgrading to a new version of Pyrogram, you will need to check all the breaking changes in order to find
incompatible code in your application, but also to take advantage of new features and improvements.
Releases
--------
""".lstrip("\n")
shutil.rmtree(DEST, ignore_errors=True)
DEST.mkdir(parents=True)
releases = requests.get(URL).json()
with open(DEST / "index.rst", "w") as index:
index.write(INTRO)
tags = []
for release in releases:
tag = release["tag_name"]
title = release["name"]
name = title.split(" - ")[1]
date = datetime.strptime(
release["published_at"],
"%Y-%m-%dT%H:%M:%SZ"
).strftime("%b %d, %Y - %H:%M:%S (UTC)")
body = pypandoc.convert_text(
release["body"].replace(r"\r\n", "\n"),
"rst",
format="markdown_github",
extra_args=["--wrap=none"]
)
index.write("- :doc:`{} <{}>`\n".format(title, tag))
tags.append(tag)
with open(DEST / "{}.rst".format(tag), "w") as page:
page.write("Pyrogram " + tag + "\n" + "=" * (len(tag) + 9) + "\n\n")
page.write("--- *Released on " + str(date) + "*\n\n")
page.write(name + "\n" + "-" * len(name) + "\n\n")
page.write(body + "\n\n")
index.write("\n.. toctree::\n :hidden:\n\n")
index.write("\n".join(" {}".format(tag) for tag in tags))

View File

@ -67,6 +67,7 @@ Messages
- :meth:`~Client.get_messages`
- :meth:`~Client.get_history`
- :meth:`~Client.get_history_count`
- :meth:`~Client.read_history`
- :meth:`~Client.iter_history`
- :meth:`~Client.send_poll`
- :meth:`~Client.vote_poll`
@ -200,6 +201,7 @@ Details
.. automethod:: Client.get_messages()
.. automethod:: Client.get_history()
.. automethod:: Client.get_history_count()
.. automethod:: Client.read_history()
.. automethod:: Client.iter_history()
.. automethod:: Client.send_poll()
.. automethod:: Client.vote_poll()

View File

@ -58,7 +58,7 @@ html_show_copyright = False
html_theme_options = {
"canonical_url": "https://docs.pyrogram.org/",
"collapse_navigation": True,
"sticky_navigation": False,
"sticky_navigation": True,
"logo_only": True,
"display_version": True,
"style_external_links": True

View File

@ -155,6 +155,14 @@ things:
chats).
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
UnicodeEncodeError: '<encoding>' codec can't encode …
-----------------------------------------------------
Where ``<encoding>`` might be *ascii*, *cp932*, *charmap* or anything else other than **utf-8**. This error usually
shows up when you try to print something and has very little to do with Pyrogram itself as it is strictly related to
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
better one.
My verification code expires immediately!
-----------------------------------------
@ -179,8 +187,20 @@ Having said that, here's a list of what Telegram definitely doesn't like:
- Spam, sending unsolicited messages or adding people to unwanted groups and channels.
- Virtual/VoIP and cheap real numbers, because they are relatively easy to get and likely used for spam/flood.
However, you might be right, and your account was deactivated/limited without any reason. This could happen because of
mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
And here's a good explanation of how, probably, the system works:
.. raw:: html
<script
async src="https://telegram.org/js/telegram-widget.js?5"
data-telegram-post="PyrogramChat/69424"
data-width="100%">
</script>
.. centered:: Join the discussion at `@PyrogramChat <https://t.me/pyrogramchat>`_
However, you might be right, and your account was deactivated/limited without any good reason. This could happen because
of mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_.
Are there any secret easter eggs?

View File

@ -9,7 +9,11 @@ general. Some words may as well link to dedicated articles in case the topic is
If you think something interesting could be added here, feel free to propose it by opening a `Feature Request`_.
Terms
-----
.. glossary::
:sorted:
API
Application Programming Interface: a set of methods, protocols and tools that make it easier to develop programs

View File

@ -83,10 +83,10 @@ Meta
- :doc:`Pyrogram FAQ <faq>`: Answers to common Pyrogram questions.
- :doc:`Pyrogram Glossary <glossary>`: List of words with brief explanations.
- :doc:`Release Notes <releases>`: Release notes for Pyrogram releases.
- :doc:`Powered by Pyrogram <powered-by>`: Collection of Pyrogram Projects.
- :doc:`Support Pyrogram <support-pyrogram>`: Ways to show your appreciation.
- :doc:`About the License <license>`: Information about the Project license.
- :doc:`Release Notes <releases/index>`: Release notes for Pyrogram releases.
.. toctree::
:hidden:
@ -122,7 +122,8 @@ Meta
:hidden:
:caption: Topic Guides
topics/filters
topics/use-filters
topics/create-filters
topics/more-on-updates
topics/config-file
topics/smart-plugins
@ -134,6 +135,7 @@ Meta
topics/proxy
topics/bots-interaction
topics/mtproto-vs-botapi
topics/debugging
topics/test-servers
topics/advanced-usage
topics/voice-calls
@ -144,10 +146,10 @@ Meta
faq
glossary
releases
powered-by
support-pyrogram
license
releases/index
.. toctree::
:hidden:

View File

@ -1,13 +0,0 @@
Release Notes
=============
Release notes for Pyrogram releases will describe what's new in each version, and will also make you aware of any
backwards-incompatible changes made in that version.
When upgrading to a new version of Pyrogram, you will need to check all the breaking changes in order to find
incompatible code in your application, but also to take advantage of new features and improvements.
.. note::
Currently, all Pyrogram release notes live inside the GitHub repository web page:
https://github.com/pyrogram/pyrogram/releases.

View File

@ -24,40 +24,40 @@ Making API method calls with Pyrogram is very simple. Here's an example we are g
app.stop()
Let's begin by importing the Client class from the Pyrogram package:
#. Let's begin by importing the Client class from the Pyrogram package:
.. code-block:: python
.. code-block:: python
from pyrogram import Client
from pyrogram import Client
Now instantiate a new Client object, "my_account" is a session name of your choice:
#. Now instantiate a new Client object, "my_account" is a session name of your choice:
.. code-block:: python
.. code-block:: python
app = Client("my_account")
app = Client("my_account")
To actually make use of any method, the client has to be started first:
#. To actually make use of any method, the client has to be started first:
.. code-block:: python
.. code-block:: python
app.start()
app.start()
Now, you can call any method you like:
#. Now, you can call any method you like:
.. code-block:: python
.. code-block:: python
print(app.get_me()) # Print information about yourself
print(app.get_me()) # Print information about yourself
# Send messages to yourself:
app.send_message("me", "Hi!") # Text message
app.send_location("me", 51.500729, -0.124583) # Location
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI") # Sticker
# Send messages to yourself:
app.send_message("me", "Hi!") # Text message
app.send_location("me", 51.500729, -0.124583) # Location
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI") # Sticker
Finally, when done, simply stop the client:
#. Finally, when done, simply stop the client:
.. code-block:: python
.. code-block:: python
app.stop()
app.stop()
Context Manager
---------------

View File

@ -45,36 +45,37 @@ arrives:
app.run()
Let's examine these four new pieces. First one: a callback function we defined which accepts two arguments -
*(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
call that function by passing the client instance and the new message instance as argument.
#. Let's examine these four new pieces. First one: a callback function we defined which accepts two arguments -
*(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
call that function by passing the client instance and the new message instance as argument.
.. code-block:: python
.. code-block:: python
def my_function(client, message):
print(message)
def my_function(client, message):
print(message)
Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must only
handle updates that are in form of a :class:`~pyrogram.Message`:
#. Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must
only handle updates that are in form of a :class:`~pyrogram.Message`:
.. code-block:: python
.. code-block:: python
my_handler = MessageHandler(my_function)
my_handler = MessageHandler(my_function)
Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase begins.
#. Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase
begins.
.. code-block:: python
.. code-block:: python
app.add_handler(my_handler)
app.add_handler(my_handler)
Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and a
special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the client
will be automatically stopped after that.
#. Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and
a special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the
client will be automatically stopped after that.
.. code-block:: python
.. code-block:: python
app.run()
app.run()
Using Decorators
----------------

View File

@ -122,7 +122,7 @@ For example, given the ID *123456789*, here's how Pyrogram can tell entities apa
- ``+ID`` User: *123456789*
- ``-ID`` Chat: *-123456789*
- ``-100ID`` Channel (and Supergroup): *-100123456789*
- ``-100ID`` Channel or Supergroup: *-100123456789*
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
high-level method.

View File

@ -0,0 +1,92 @@
Creating Filters
================
Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
for example) you can use :meth:`~pyrogram.Filters.create`.
.. note::
At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
Custom Filters
--------------
An example to demonstrate how custom filters work is to show how to create and use one for the
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots; create and
:doc:`authorize your bot <../start/auth>`, then send a message with an inline keyboard to yourself. This allows you to
test your filter by pressing the inline button:
.. code-block:: python
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
"Pyrogram's custom filter test",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton("Press me", b"pyrogram")]]
)
)
Basic Filters
-------------
For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
equals to ``b"Pyrogram"``.
.. code-block:: python
static_data = Filters.create(
name="StaticdData",
func=lambda flt, callback_query: callback_query.data == b"Pyrogram"
)
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
def func(flt, callback_query):
return callback_query.data == b"Pyrogram"
static_data = Filters.create(
name="StaticData",
func=func
)
The filter usage remains the same:
.. code-block:: python
@app.on_callback_query(static_data)
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")
Filters with Arguments
----------------------
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`.
This is how a dynamic custom filter looks like:
.. code-block:: python
def dynamic_data(data):
return Filters.create(
name="DynamicData",
func=lambda flt, callback_query: flt.data == callback_query.data,
data=data # "data" kwarg is accessed with "filter.data"
)
And its usage:
.. code-block:: python
@app.on_callback_query(dynamic_data(b"Pyrogram"))
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")

View File

@ -0,0 +1,135 @@
Debugging
=========
When working with the API, chances are you'll stumble upon bugs, get stuck and start wondering how to continue. Nothing
to actually worry about -- that's normal -- and luckily for you, Pyrogram provides some commodities to help you in this.
Caveman Debugging
-----------------
*The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.*
-- Brian Kernighan, "Unix for Beginners" (1979)
Adding ``print()`` statements in crucial parts of your code is by far the most ancient, yet efficient technique for
debugging programs, especially considering the concurrent nature of the framework itself. Pyrogram goodness in this
respect comes with the fact that any object can be nicely printed just by calling ``print(obj)``, thus giving to you
an insight of all its inner details.
Consider the following code:
.. code-block:: python
dan = app.get_users("haskell")
print(dan) # User
This will show a JSON representation of the object returned by :meth:`~pyrogram.Client.get_users`, which is a
:class:`~pyrogram.User` instance, in this case. The output on your terminal will be something similar to this:
.. code-block:: json
{
"_": "pyrogram.User",
"id": 23122162,
"is_self": false,
"is_contact": false,
"is_mutual_contact": false,
"is_deleted": false,
"is_bot": false,
"is_verified": false,
"is_restricted": false,
"is_support": false,
"is_scam": false,
"first_name": "Dan",
"status": {
"_": "pyrogram.UserStatus",
"user_id": 23122162,
"recently": true
},
"username": "haskell",
"language_code": "en",
"photo": {
"_": "pyrogram.ChatPhoto",
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
}
}
As you've probably guessed already, Pyrogram objects can be nested. That's how compound data are built, and nesting
keeps going until we are left with base data types only, such as ``str``, ``int``, ``bool``, etc.
Accessing Attributes
--------------------
Even though you see a JSON output, it doesn't mean we are dealing with dictionaries; in fact, all Pyrogram types are
full-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
.. code-block:: python
dan_photo = dan.photo
print(dan_photo) # ChatPhoto
.. code-block:: json
{
"_": "pyrogram.ChatPhoto",
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
}
However, the bracket notation ``[]`` is also supported, but its usage is discouraged:
.. warning::
Bracket notation in Python is not commonly used for getting/setting object attributes. While it works for Pyrogram
objects, it might not work for anything else and you should not rely on this.
.. code-block:: python
dan_photo_big = dan["photo"]["big_file_id"]
print(dan_photo_big) # str
.. code-block:: text
AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg
Checking an Object's Type
-------------------------
Another thing worth talking about is how to tell and check for an object's type.
As you noticed already, when printing an object you'll see the special attribute ``"_"``. This is just a visual thing
useful to show humans the object type, but doesn't really exist anywhere; any attempt in accessing it will lead to an
error. The correct way to get the object type is by using the built-in function ``type()``:
.. code-block:: python
dan_status = dan.status
print(type(dan_status))
.. code-block:: text
<class 'pyrogram.UserStatus'>
And to check if an object is an instance of a given class, you use the built-in function ``isinstance()``:
.. code-block:: python
:name: this-py
from pyrogram import UserStatus
dan_status = dan.status
print(isinstance(dan_status, UserStatus))
.. code-block:: text
True
.. raw:: html
<script>
var e = document.querySelector("blockquote p.attribution");
var s = e.innerHTML;
e.innerHTML = s[0] + " " + s.slice(1);
</script>

View File

@ -2,7 +2,7 @@ More on Updates
===============
Here we'll show some advanced usages when working with :doc:`update handlers <../start/updates>` and
:doc:`filters <filters>`.
:doc:`filters <use-filters>`.
Handler Groups
--------------

View File

@ -105,93 +105,3 @@ More handlers using different filters can also live together.
@app.on_message(Filters.chat("PyrogramChat"))
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")
Custom Filters
--------------
Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
for example) you can use :meth:`~pyrogram.Filters.create`.
.. note::
At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
An example to demonstrate how custom filters work is to show how to create and use one for the
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots; create and
:doc:`authorize your bot <../start/auth>`, then send a message with an inline keyboard to yourself. This allows you to
test your filter by pressing the inline button:
.. code-block:: python
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
"Pyrogram's custom filter test",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton("Press me", b"pyrogram")]]
)
)
Basic Filters
^^^^^^^^^^^^^
For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
equals to ``b"Pyrogram"``.
.. code-block:: python
static_data = Filters.create(
name="StaticdData",
func=lambda flt, callback_query: callback_query.data == b"Pyrogram"
)
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
def func(flt, callback_query):
return callback_query.data == b"Pyrogram"
static_data = Filters.create(
name="StaticData",
func=func
)
The filter usage remains the same:
.. code-block:: python
@app.on_callback_query(static_data)
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")
Filters with Arguments
^^^^^^^^^^^^^^^^^^^^^^
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`.
This is how a dynamic custom filter looks like:
.. code-block:: python
def dynamic_data(data):
return Filters.create(
name="DynamicData",
func=lambda flt, callback_query: flt.data == callback_query.data,
data=data # "data" kwarg is accessed with "filter.data"
)
And its usage:
.. code-block:: python
@app.on_callback_query(dynamic_data(b"Pyrogram"))
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")

View File

@ -19,8 +19,8 @@
from importlib import import_module
from .all import objects
from .core.object import Object
from .core.tl_object import TLObject
for k, v in objects.items():
path, name = v.rsplit(".", 1)
Object.all[k] = getattr(import_module(path), name)
TLObject.all[k] = getattr(import_module(path), name)

View File

@ -22,7 +22,7 @@ from .gzip_packed import GzipPacked
from .list import List
from .message import Message
from .msg_container import MsgContainer
from .object import Object
from .tl_object import TLObject
from .primitives import (
Bool, BoolTrue, BoolFalse, Bytes, Double,
Int, Long, Int128, Int256, Null, String, Vector

View File

@ -18,11 +18,11 @@
from io import BytesIO
from .object import Object
from .tl_object import TLObject
from .primitives import Int, Long
class FutureSalt(Object):
class FutureSalt(TLObject):
ID = 0x0949d9dc
__slots__ = ["valid_since", "valid_until", "salt"]

View File

@ -19,11 +19,11 @@
from io import BytesIO
from . import FutureSalt
from .object import Object
from .tl_object import TLObject
from .primitives import Int, Long
class FutureSalts(Object):
class FutureSalts(TLObject):
ID = 0xae500895
__slots__ = ["req_msg_id", "now", "salts"]

View File

@ -19,24 +19,24 @@
from gzip import compress, decompress
from io import BytesIO
from .object import Object
from .tl_object import TLObject
from .primitives import Int, Bytes
class GzipPacked(Object):
class GzipPacked(TLObject):
ID = 0x3072cfa1
__slots__ = ["packed_data"]
QUALNAME = "GzipPacked"
def __init__(self, packed_data: Object):
def __init__(self, packed_data: TLObject):
self.packed_data = packed_data
@staticmethod
def read(b: BytesIO, *args) -> "GzipPacked":
# Return the Object itself instead of a GzipPacked wrapping it
return Object.read(
return TLObject.read(
BytesIO(
decompress(
Bytes.read(b)

View File

@ -16,13 +16,13 @@
# 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 .object import Object
from .tl_object import TLObject
class List(list, Object):
class List(list, TLObject):
__slots__ = []
def __repr__(self):
return "pyrogram.api.core.List([{}])".format(
",".join(Object.__repr__(i) for i in self)
",".join(TLObject.__repr__(i) for i in self)
)

View File

@ -18,18 +18,18 @@
from io import BytesIO
from .object import Object
from .tl_object import TLObject
from .primitives import Int, Long
class Message(Object):
class Message(TLObject):
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):
def __init__(self, body: TLObject, msg_id: int, seq_no: int, length: int):
self.msg_id = msg_id
self.seq_no = seq_no
self.length = length
@ -42,7 +42,7 @@ class Message(Object):
length = Int.read(b)
body = b.read(length)
return Message(Object.read(BytesIO(body)), msg_id, seq_no, length)
return Message(TLObject.read(BytesIO(body)), msg_id, seq_no, length)
def write(self) -> bytes:
b = BytesIO()

View File

@ -19,11 +19,11 @@
from io import BytesIO
from .message import Message
from .object import Object
from .tl_object import TLObject
from .primitives import Int
class MsgContainer(Object):
class MsgContainer(TLObject):
ID = 0x73f1f8dc
__slots__ = ["messages"]

View File

@ -18,10 +18,10 @@
from io import BytesIO
from ..object import Object
from ..tl_object import TLObject
class BoolFalse(Object):
class BoolFalse(TLObject):
ID = 0xbc799737
value = False
@ -38,7 +38,7 @@ class BoolTrue(BoolFalse):
value = True
class Bool(Object):
class Bool(TLObject):
@classmethod
def read(cls, b: BytesIO) -> bool:
return int.from_bytes(b.read(4), "little") == BoolTrue.ID

View File

@ -18,10 +18,10 @@
from io import BytesIO
from ..object import Object
from ..tl_object import TLObject
class Bytes(Object):
class Bytes(TLObject):
@staticmethod
def read(b: BytesIO, *args) -> bytes:
length = int.from_bytes(b.read(1), "little")

View File

@ -19,10 +19,10 @@
from io import BytesIO
from struct import unpack, pack
from ..object import Object
from ..tl_object import TLObject
class Double(Object):
class Double(TLObject):
@staticmethod
def read(b: BytesIO, *args) -> float:
return unpack("d", b.read(8))[0]

View File

@ -18,10 +18,10 @@
from io import BytesIO
from ..object import Object
from ..tl_object import TLObject
class Int(Object):
class Int(TLObject):
SIZE = 4
@classmethod

View File

@ -18,10 +18,10 @@
from io import BytesIO
from ..object import Object
from ..tl_object import TLObject
class Null(Object):
class Null(TLObject):
ID = 0x56730bcc
@staticmethod

View File

@ -20,31 +20,31 @@ from io import BytesIO
from . import Int
from ..list import List
from ..object import Object
from ..tl_object import TLObject
class Vector(Object):
class Vector(TLObject):
ID = 0x1cb5c415
# Method added to handle the special case when a query returns a bare Vector (of Ints);
# i.e., RpcResult body starts with 0x1cb5c415 (Vector Id) - e.g., messages.GetMessagesViews.
@staticmethod
def _read(b: BytesIO) -> Object or int:
def _read(b: BytesIO) -> TLObject or int:
try:
return Object.read(b)
return TLObject.read(b)
except KeyError:
b.seek(-4, 1)
return Int.read(b)
@staticmethod
def read(b: BytesIO, t: Object = None) -> list:
def read(b: BytesIO, t: TLObject = None) -> list:
return List(
t.read(b) if t
else Vector._read(b)
for _ in range(Int.read(b))
)
def __new__(cls, value: list, t: Object = None) -> bytes:
def __new__(cls, value: list, t: TLObject = None) -> bytes:
return b"".join(
[Int(cls.ID, False), Int(len(value))]
+ [

View File

@ -21,7 +21,7 @@ from io import BytesIO
from json import dumps
class Object:
class TLObject:
all = {}
__slots__ = []
@ -30,13 +30,13 @@ class Object:
@staticmethod
def read(b: BytesIO, *args): # TODO: Rename b -> data
return Object.all[int.from_bytes(b.read(4), "little")].read(b, *args)
return TLObject.all[int.from_bytes(b.read(4), "little")].read(b, *args)
def write(self, *args) -> bytes:
pass
@staticmethod
def default(obj: "Object"):
def default(obj: "TLObject"):
if isinstance(obj, bytes):
return repr(obj)
@ -50,7 +50,7 @@ class Object:
)
def __str__(self) -> str:
return dumps(self, indent=4, default=Object.default, ensure_ascii=False)
return dumps(self, indent=4, default=TLObject.default, ensure_ascii=False)
def __repr__(self) -> str:
return "pyrogram.api.{}({})".format(
@ -62,7 +62,7 @@ class Object:
)
)
def __eq__(self, other: "Object") -> bool:
def __eq__(self, other: "TLObject") -> bool:
for attr in self.__slots__:
try:
if getattr(self, attr) != getattr(other, attr):
@ -77,3 +77,6 @@ class Object:
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, key, value):
setattr(self, key, value)

View File

@ -37,7 +37,7 @@ from signal import signal, SIGINT, SIGTERM, SIGABRT
from typing import Union, List
from pyrogram.api import functions, types
from pyrogram.api.core import Object
from pyrogram.api.core import TLObject
from pyrogram.client.handlers import DisconnectHandler
from pyrogram.client.handlers.handler import Handler
from pyrogram.client.methods.password.utils import compute_check
@ -1003,7 +1003,7 @@ class Client(Methods, BaseClient):
log.info("UpdatesWorkerTask stopped")
async def send(self,
data: Object,
data: TLObject,
retries: int = Session.MAX_RETRIES,
timeout: float = Session.WAIT_TIMEOUT):
"""Send raw Telegram queries.

View File

@ -54,7 +54,7 @@ class ExportChatInviteLink(BaseClient):
if isinstance(peer, types.InputPeerChat):
return await self.send(
functions.messages.ExportChatInvite(
peer=peer.chat_id
peer=peer
)
).link
elif isinstance(peer, types.InputPeerChannel):

View File

@ -27,6 +27,7 @@ from .get_history import GetHistory
from .get_history_count import GetHistoryCount
from .get_messages import GetMessages
from .iter_history import IterHistory
from .read_history import ReadHistory
from .retract_vote import RetractVote
from .send_animated_sticker import SendAnimatedSticker
from .send_animation import SendAnimation
@ -80,6 +81,7 @@ class Messages(
IterHistory,
SendCachedMedia,
GetHistoryCount,
SendAnimatedSticker
SendAnimatedSticker,
ReadHistory
):
pass

View File

@ -0,0 +1,65 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union
from pyrogram.api import functions, types
from ...ext import BaseClient
class ReadHistory(BaseClient):
def read_history(
self,
chat_id: Union[int, str],
max_id: int = 0
) -> bool:
"""Mark a chat's message history as read.
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
max_id (``int``, *optional*):
The id of the last message you want to mark as read; all the messages before this one will be marked as
read as well. Defaults to 0 (mark every unread message as read).
Returns:
``bool`` - On success, True is returned.
Raises:
RPCError: In case of a Telegram RPC error.
"""
peer = self.resolve_peer(chat_id)
if isinstance(peer, types.InputPeerChannel):
q = functions.channels.ReadHistory(
channel=peer,
max_id=max_id
)
else:
q = functions.messages.ReadHistory(
peer=peer,
max_id=max_id
)
self.send(q)
return True

View File

@ -31,6 +31,7 @@ class SendAnimation(BaseClient):
chat_id: Union[int, str],
animation: str,
caption: str = "",
unsave: bool = False,
parse_mode: str = "",
duration: int = 0,
width: int = 0,
@ -64,6 +65,10 @@ class SendAnimation(BaseClient):
caption (``str``, *optional*):
Animation caption, 0-1024 characters.
unsave (``bool``, *optional*):
By default, the server will save into your own collection any new animation GIF you send.
Pass True to automatically unsave the sent animation. Defaults to False.
parse_mode (``str``, *optional*):
Pass "markdown" or "html" if you want Telegram apps to show bold, italic, fixed-width text or inline
URLs in your caption. Defaults to "markdown".
@ -171,10 +176,24 @@ class SendAnimation(BaseClient):
else:
for i in r.updates:
if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)):
return await pyrogram.Message._parse(
message = await pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
)
if unsave:
document = message.animation or message.document
document_id = utils.get_input_media_from_file_id(document.file_id).id
await self.send(
functions.messages.SaveGif(
id=document_id,
unsave=True
)
)
return message
except BaseClient.StopTransmission:
return None

View File

@ -22,12 +22,12 @@ import pyrogram
from pyrogram.api import types
from .inline_query_result import InlineQueryResult
from ..messages_and_media import Location
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..update import Update
from ..user_and_chats import User
class InlineQuery(PyrogramType, Update):
class InlineQuery(Object, Update):
"""An incoming inline query.
When the user sends an empty query, your bot could return some default or trending results.

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..pyrogram_type import PyrogramType
from ..object import Object
"""- :obj:`InlineQueryResultCachedAudio`
- :obj:`InlineQueryResultCachedDocument`
@ -39,7 +39,7 @@ from ..pyrogram_type import PyrogramType
- :obj:`InlineQueryResultVoice`"""
class InlineQueryResult(PyrogramType):
class InlineQueryResult(Object):
"""One result of an inline query.
Pyrogram currently supports results of the following 20 types:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultAudio(PyrogramType):
class InlineQueryResultAudio(Object):
"""Represents a link to an mp3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio.
Attributes:

View File

@ -23,10 +23,10 @@ from pyrogram.api import types
from pyrogram.errors import FileIdInvalid
from pyrogram.client.ext import utils, BaseClient
from pyrogram.client.style import HTML, Markdown
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedAudio(PyrogramType):
class InlineQueryResultCachedAudio(Object):
"""Represents a link to an audio file stored on the Telegram servers.
By default, this audio file will be sent by the user. Alternatively, you can use *input_message_content* to send a
message with the specified content instead of the audio.

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedDocument(PyrogramType):
class InlineQueryResultCachedDocument(Object):
"""Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedGif(PyrogramType):
class InlineQueryResultCachedGif(Object):
"""Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with specified content instead of the animation.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedMpeg4Gif(PyrogramType):
class InlineQueryResultCachedMpeg4Gif(Object):
"""Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedPhoto(PyrogramType):
class InlineQueryResultCachedPhoto(Object):
"""Represents a link to a photo stored on the Telegram servers. By default, this photo will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the photo.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedSticker(PyrogramType):
class InlineQueryResultCachedSticker(Object):
"""Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the sticker.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedVideo(PyrogramType):
class InlineQueryResultCachedVideo(Object):
"""Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultCachedVoice(PyrogramType):
class InlineQueryResultCachedVoice(Object):
"""Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the voice message.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultContact(PyrogramType):
class InlineQueryResultContact(Object):
"""Represents a contact with a phone number. By default, this contact will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the contact.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultDocument(PyrogramType):
class InlineQueryResultDocument(Object):
"""Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. Currently, only .PDF and .ZIP files can be sent using this method.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultGame(PyrogramType):
class InlineQueryResultGame(Object):
"""Represents a Game.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultGif(PyrogramType):
class InlineQueryResultGif(Object):
"""Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultLocation(PyrogramType):
class InlineQueryResultLocation(Object):
"""Represents a location on a map. By default, the location will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the location.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultMpeg4Gif(PyrogramType):
class InlineQueryResultMpeg4Gif(Object):
"""Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation.
Attributes:

View File

@ -18,10 +18,10 @@
from pyrogram.api import types
from pyrogram.client.style import HTML, Markdown
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultPhoto(PyrogramType):
class InlineQueryResultPhoto(Object):
"""Represents a link to a photo. By default, this photo will be sent by the user with optional caption.
Alternatively, you can use input_message_content to send a message with the specified content instead of the photo.

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultVenue(PyrogramType):
class InlineQueryResultVenue(Object):
"""Represents a venue. By default, the venue will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the venue.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultVideo(PyrogramType):
class InlineQueryResultVideo(Object):
"""Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
class InlineQueryResultVoice(PyrogramType):
class InlineQueryResultVoice(Object):
"""Represents a link to a voice recording in an .ogg container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the the voice message.
Attributes:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..pyrogram_type import PyrogramType
from ..object import Object
class InputMedia(PyrogramType):
class InputMedia(Object):
"""Content of a media message to be sent.
It should be one of:

View File

@ -18,10 +18,10 @@
from pyrogram.api.types import InputPhoneContact as RawInputPhoneContact
from pyrogram.session.internals import MsgId
from ..pyrogram_type import PyrogramType
from ..object import Object
class InputPhoneContact(PyrogramType):
class InputPhoneContact(Object):
"""A Phone Contact to be added in your Telegram address book.
It is intended to be used with :meth:`~Client.add_contacts() <pyrogram.Client.add_contacts>`

View File

@ -16,14 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..pyrogram_type import PyrogramType
from ..object import Object
"""- :obj:`InputLocationMessageContent`
- :obj:`InputVenueMessageContent`
- :obj:`InputContactMessageContent`"""
class InputMessageContent(PyrogramType):
class InputMessageContent(Object):
"""Content of a message to be sent as a result of an inline query.
Pyrogram currently supports the following 4 types:

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..pyrogram_type import PyrogramType
from ..object import Object
class CallbackGame(PyrogramType):
class CallbackGame(Object):
"""Placeholder, currently holds no information.
Use BotFather to set up your game.

View File

@ -22,12 +22,12 @@ from typing import Union
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..update import Update
from ..user_and_chats import User
class CallbackQuery(PyrogramType, Update):
class CallbackQuery(Object, Update):
"""An incoming callback query from a callback button in an inline keyboard.
If the button that originated the query was attached to a message sent by the bot, the field *message*

View File

@ -17,10 +17,10 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.api.types import ReplyKeyboardForceReply
from ..pyrogram_type import PyrogramType
from ..object import Object
class ForceReply(PyrogramType):
class ForceReply(Object):
"""Object used to force clients to show a reply interface.
Upon receiving a message with this object, Telegram clients will display a reply interface to the user.

View File

@ -19,11 +19,11 @@
import pyrogram
from pyrogram.api import types
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
from pyrogram.client.types.user_and_chats import User
class GameHighScore(PyrogramType):
class GameHighScore(Object):
"""One row of the high scores table for a game.
Parameters:

View File

@ -20,11 +20,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from pyrogram.client.types.pyrogram_type import PyrogramType
from pyrogram.client.types.object import Object
from .game_high_score import GameHighScore
class GameHighScores(PyrogramType):
class GameHighScores(Object):
"""The high scores table for a game.
Parameters:

View File

@ -24,10 +24,10 @@ from pyrogram.api.types import (
KeyboardButtonSwitchInline, KeyboardButtonGame
)
from .callback_game import CallbackGame
from ..pyrogram_type import PyrogramType
from ..object import Object
class InlineKeyboardButton(PyrogramType):
class InlineKeyboardButton(Object):
"""One button of an inline keyboard.
You must use exactly one of the optional fields.

View File

@ -20,10 +20,10 @@ from typing import List
from pyrogram.api.types import ReplyInlineMarkup, KeyboardButtonRow
from . import InlineKeyboardButton
from ..pyrogram_type import PyrogramType
from ..object import Object
class InlineKeyboardMarkup(PyrogramType):
class InlineKeyboardMarkup(Object):
"""An inline keyboard that appears right next to the message it belongs to.
Parameters:

View File

@ -18,10 +18,10 @@
from pyrogram.api.types import KeyboardButton as RawKeyboardButton
from pyrogram.api.types import KeyboardButtonRequestPhone, KeyboardButtonRequestGeoLocation
from ..pyrogram_type import PyrogramType
from ..object import Object
class KeyboardButton(PyrogramType):
class KeyboardButton(Object):
"""One button of the reply keyboard.
For simple text buttons String can be used instead of this object to specify text of the button.
Optional fields are mutually exclusive.

View File

@ -21,10 +21,10 @@ from typing import List, Union
from pyrogram.api.types import KeyboardButtonRow
from pyrogram.api.types import ReplyKeyboardMarkup as RawReplyKeyboardMarkup
from . import KeyboardButton
from ..pyrogram_type import PyrogramType
from ..object import Object
class ReplyKeyboardMarkup(PyrogramType):
class ReplyKeyboardMarkup(Object):
"""A custom keyboard with reply options.
Parameters:

View File

@ -17,10 +17,10 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram.api.types import ReplyKeyboardHide
from ..pyrogram_type import PyrogramType
from ..object import Object
class ReplyKeyboardRemove(PyrogramType):
class ReplyKeyboardRemove(Object):
"""Object used to tell clients to remove a bot keyboard.
Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display

View File

@ -16,17 +16,17 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .pyrogram_type import PyrogramType
from .object import Object
class PyrogramList(list):
class List(list):
__slots__ = []
def __str__(self):
# noinspection PyCallByClass
return PyrogramType.__str__(self)
return Object.__str__(self)
def __repr__(self):
return "pyrogram.client.types.pyrogram_list.PyrogramList([{}])".format(
",".join(PyrogramType.__repr__(i) for i in self)
",".join(Object.__repr__(i) for i in self)
)

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Animation(PyrogramType):
class Animation(Object):
"""An animation file (GIF or H.264/MPEG-4 AVC video without sound).
Parameters:

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Audio(PyrogramType):
class Audio(Object):
"""An audio file to be treated as music by the Telegram clients.
Parameters:

View File

@ -19,10 +19,10 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
class Contact(PyrogramType):
class Contact(Object):
"""A phone contact.
Parameters:

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Document(PyrogramType):
class Document(Object):
"""A generic file (as opposed to photos, voice messages, audio files, ...).
Parameters:

View File

@ -20,10 +20,10 @@ import pyrogram
from pyrogram.api import types
from .animation import Animation
from .photo import Photo
from ..pyrogram_type import PyrogramType
from ..object import Object
class Game(PyrogramType):
class Game(Object):
"""A game.
Use BotFather to create and edit games, their short names will act as unique identifiers.

View File

@ -19,10 +19,10 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
class Location(PyrogramType):
class Location(Object):
"""A point on the map.
Parameters:

View File

@ -27,7 +27,7 @@ from .contact import Contact
from .location import Location
from .message_entity import MessageEntity
from ..messages_and_media.photo import Photo
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..update import Update
from ..user_and_chats.chat import Chat
from ..user_and_chats.user import User
@ -59,7 +59,7 @@ class Str(str):
return self._client.html.unparse(self, self._entities)
class Message(PyrogramType, Update):
class Message(Object, Update):
"""A message.
Parameters:

View File

@ -19,11 +19,11 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..user_and_chats.user import User
class MessageEntity(PyrogramType):
class MessageEntity(Object):
"""One special entity in a text message.
For example, hashtags, usernames, URLs, etc.

View File

@ -21,12 +21,12 @@ from typing import List, Union
import pyrogram
from pyrogram.api import types
from .message import Message
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..update import Update
from ..user_and_chats import Chat
class Messages(PyrogramType, Update):
class Messages(Object, Update):
"""Contains a chat's messages.
Parameters:

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Photo(PyrogramType):
class Photo(Object):
"""A Photo.
Parameters:

View File

@ -20,10 +20,10 @@ from typing import List
import pyrogram
from .photo import Photo
from ..pyrogram_type import PyrogramType
from ..object import Object
class Photos(PyrogramType):
class Photos(Object):
"""Contains a user's profile pictures.
Parameters:

View File

@ -21,11 +21,11 @@ from typing import List, Union
import pyrogram
from pyrogram.api import types
from .poll_option import PollOption
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..update import Update
class Poll(PyrogramType, Update):
class Poll(Object, Update):
"""A Poll.
Parameters:

View File

@ -17,10 +17,10 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from ..pyrogram_type import PyrogramType
from ..object import Object
class PollOption(PyrogramType):
class PollOption(Object):
"""Contains information about one answer option in a poll.
Parameters:

View File

@ -25,11 +25,11 @@ import pyrogram
from pyrogram.api import types, functions
from pyrogram.errors import StickersetInvalid
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Sticker(PyrogramType):
class Sticker(Object):
"""A sticker.
Parameters:

View File

@ -18,10 +18,10 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
class StrippedThumbnail(PyrogramType):
class StrippedThumbnail(Object):
"""A stripped thumbnail
Parameters:

View File

@ -23,10 +23,10 @@ import pyrogram
from pyrogram.api import types
from pyrogram.client.ext.utils import encode
from .stripped_thumbnail import StrippedThumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
class Thumbnail(PyrogramType):
class Thumbnail(Object):
"""One size of a photo or a file/sticker thumbnail.
Parameters:

View File

@ -19,10 +19,10 @@
import pyrogram
from pyrogram.api import types
from .location import Location
from ..pyrogram_type import PyrogramType
from ..object import Object
class Venue(PyrogramType):
class Venue(Object):
"""A venue.
Parameters:

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Video(PyrogramType):
class Video(Object):
"""A video file.
Parameters:

View File

@ -22,11 +22,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .thumbnail import Thumbnail
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class VideoNote(PyrogramType):
class VideoNote(Object):
"""A video note.
Parameters:

View File

@ -20,11 +20,11 @@ from struct import pack
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class Voice(PyrogramType):
class Voice(Object):
"""A voice note.
Parameters:

View File

@ -23,7 +23,12 @@ from json import dumps
import pyrogram
class PyrogramType:
class Meta(type, metaclass=type("", (type,), {"__str__": lambda _: "~hi"})):
def __str__(self):
return "<class 'pyrogram.{}'>".format(self.__name__)
class Object(metaclass=Meta):
__slots__ = ["_client"]
def __init__(self, client: "pyrogram.BaseClient" = None):
@ -32,35 +37,26 @@ class PyrogramType:
if self._client is None:
del self._client
def __eq__(self, other: "PyrogramType") -> bool:
for attr in self.__slots__:
try:
if getattr(self, attr) != getattr(other, attr):
return False
except AttributeError:
return False
@staticmethod
def default(obj: "Object"):
if isinstance(obj, bytes):
return repr(obj)
return True
return OrderedDict(
[("_", "pyrogram." + obj.__class__.__name__)]
+ [
(attr, "*" * len(getattr(obj, attr)))
if attr == "phone_number"
else (attr, str(datetime.fromtimestamp(getattr(obj, attr))))
if attr.endswith("date")
else (attr, getattr(obj, attr))
for attr in obj.__slots__
if getattr(obj, attr) is not None
]
)
def __str__(self) -> str:
def default(obj: PyrogramType):
try:
return OrderedDict(
[("_", "pyrogram." + obj.__class__.__name__)]
+ [
(attr, "*" * len(getattr(obj, attr)))
if attr == "phone_number"
else (attr, str(datetime.fromtimestamp(getattr(obj, attr))))
if attr.endswith("date")
else (attr, getattr(obj, attr))
for attr in obj.__slots__
if getattr(obj, attr) is not None
]
)
except AttributeError:
return repr(obj)
return dumps(self, indent=4, default=default, ensure_ascii=False)
return dumps(self, indent=4, default=Object.default, ensure_ascii=False)
def __repr__(self) -> str:
return "pyrogram.{}({})".format(
@ -72,5 +68,18 @@ class PyrogramType:
)
)
def __eq__(self, other: "Object") -> bool:
for attr in self.__slots__:
try:
if getattr(self, attr) != getattr(other, attr):
return False
except AttributeError:
return False
return True
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, key, value):
setattr(self, key, value)

View File

@ -22,10 +22,10 @@ import pyrogram
from pyrogram.api import types
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from ..pyrogram_type import PyrogramType
from ..object import Object
class Chat(PyrogramType):
class Chat(Object):
"""A chat.
Parameters:

View File

@ -19,10 +19,10 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
class ChatMember(PyrogramType):
class ChatMember(Object):
"""Contains information about one member of a chat.
Parameters:

View File

@ -21,10 +21,10 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .chat_member import ChatMember
from ..pyrogram_type import PyrogramType
from ..object import Object
class ChatMembers(PyrogramType):
class ChatMembers(Object):
"""Contains information about the members list of a chat.
Parameters:

View File

@ -19,10 +19,10 @@
from typing import Union
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
class ChatPermissions(PyrogramType):
class ChatPermissions(Object):
"""A chat default permissions and a single member permissions within a chat.
Some permissions make sense depending on the context: default chat permissions, restricted/kicked member or

View File

@ -20,11 +20,11 @@ from struct import pack
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
from ...ext.utils import encode
class ChatPhoto(PyrogramType):
class ChatPhoto(Object):
"""A chat photo.
Parameters:

View File

@ -21,11 +21,11 @@ from typing import List
import pyrogram
from pyrogram.api import types
from .chat_photo import ChatPhoto
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..user_and_chats.user import User
class ChatPreview(PyrogramType):
class ChatPreview(Object):
"""A chat preview.
Parameters:

View File

@ -19,11 +19,11 @@
import pyrogram
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
from ..object import Object
from ..user_and_chats import Chat
class Dialog(PyrogramType):
class Dialog(Object):
"""A user's dialog.
Parameters:

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