mirror of
https://github.com/TeamPGM/pyrogram.git
synced 2024-11-30 17:43:32 +00:00
Remove API key requirement for existing sessions
This commit is contained in:
parent
b8f39725c5
commit
124bcb4db7
@ -1,6 +1,6 @@
|
||||
id message
|
||||
FILE_MIGRATE_X The file to be accessed is currently stored in DC{x}
|
||||
NETWORK_MIGRATE_X The source IP address is associated with DC{x} (for registration)
|
||||
PHONE_MIGRATE_X The phone number a user is trying to use for authorization is associated with DC{x}
|
||||
STATS_MIGRATE_X The statistics of the group/channel are stored in DC{x}
|
||||
USER_MIGRATE_X The user whose identity is being used to execute queries is associated with DC{x} (for registration)
|
||||
FILE_MIGRATE_X The file to be accessed is currently stored in DC{value}
|
||||
NETWORK_MIGRATE_X The source IP address is associated with DC{value} (for registration)
|
||||
PHONE_MIGRATE_X The phone number a user is trying to use for authorization is associated with DC{value}
|
||||
STATS_MIGRATE_X The statistics of the group/channel are stored in DC{value}
|
||||
USER_MIGRATE_X The user whose identity is being used to execute queries is associated with DC{value} (for registration)
|
|
@ -89,7 +89,7 @@ DOCUMENT_INVALID The document is invalid
|
||||
EMAIL_HASH_EXPIRED The email hash expired and cannot be used to verify it
|
||||
EMAIL_INVALID The email provided is invalid
|
||||
EMAIL_UNCONFIRMED Email unconfirmed
|
||||
EMAIL_UNCONFIRMED_X The provided email isn't confirmed, {x} is the length of the verification code that was just sent to the email
|
||||
EMAIL_UNCONFIRMED_X The provided email isn't confirmed, {value} is the length of the verification code that was just sent to the email
|
||||
EMAIL_VERIFY_EXPIRED The verification email has expired
|
||||
EMOTICON_EMPTY The emoticon parameter is empty
|
||||
EMOTICON_INVALID The emoticon parameter is invalid
|
||||
@ -108,7 +108,7 @@ EXTERNAL_URL_INVALID The external media URL is invalid
|
||||
FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing
|
||||
FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid
|
||||
FILE_ID_INVALID The file id is invalid
|
||||
FILE_MIGRATE_X The file is in Data Center No. {x}
|
||||
FILE_MIGRATE_X The file is in Data Center No. {value}
|
||||
FILE_PARTS_INVALID Invalid number of parts. The value is not between 1 and 4000
|
||||
FILE_PART_EMPTY The file part sent is empty
|
||||
FILE_PART_INVALID The file part number is invalid. The value is not between 0 and 3999
|
||||
@ -116,7 +116,7 @@ FILE_PART_LENGTH_INVALID The length of a file part is invalid
|
||||
FILE_PART_SIZE_CHANGED The part size is different from the size of one of the previous parts in the same file
|
||||
FILE_PART_SIZE_INVALID 512 KB cannot be evenly divided by part_size
|
||||
FILE_PART_TOO_BIG The size limit (512 KB) for the content of the file part has been exceeded
|
||||
FILE_PART_X_MISSING Part {x} of the file is missing from storage
|
||||
FILE_PART_X_MISSING Part {value} of the file is missing from storage
|
||||
FILE_REFERENCE_EMPTY The file id contains an empty file reference, you must obtain a valid one by fetching the message from the origin context
|
||||
FILE_REFERENCE_EXPIRED The file id contains an expired file reference, you must obtain a valid one by fetching the message from the origin context
|
||||
FILE_REFERENCE_INVALID The file id contains an invalid file reference, you must obtain a valid one by fetching the message from the origin context
|
||||
@ -198,7 +198,7 @@ PASSWORD_HASH_INVALID The two-step verification password is invalid
|
||||
PASSWORD_MISSING The account is missing the two-step verification password
|
||||
PASSWORD_RECOVERY_NA The password recovery e-mail is not available
|
||||
PASSWORD_REQUIRED The two-step verification password is required for this method
|
||||
PASSWORD_TOO_FRESH_X The two-step verification password was added recently and you are required to wait {x} seconds
|
||||
PASSWORD_TOO_FRESH_X The two-step verification password was added recently and you are required to wait {value} seconds
|
||||
PAYMENT_PROVIDER_INVALID The payment provider was not recognised or its token was invalid
|
||||
PEER_FLOOD The method can't be used because your account is currently limited
|
||||
PEER_ID_INVALID The peer id being used is invalid or not known yet. Make sure you meet the peer before interacting with it
|
||||
|
|
@ -1,6 +1,6 @@
|
||||
id message
|
||||
2FA_CONFIRM_WAIT_X A wait of {x} seconds is required because this account is active and protected by a 2FA password
|
||||
FLOOD_TEST_PHONE_WAIT_X A wait of {x} seconds is required in the test servers
|
||||
FLOOD_WAIT_X A wait of {x} seconds is required
|
||||
SLOWMODE_WAIT_X A wait of {x} seconds is required to send messages in this chat.
|
||||
TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {x} seconds
|
||||
2FA_CONFIRM_WAIT_X A wait of {value} seconds is required because this account is active and protected by a 2FA password
|
||||
FLOOD_TEST_PHONE_WAIT_X A wait of {value} seconds is required in the test servers
|
||||
FLOOD_WAIT_X A wait of {value} seconds is required
|
||||
SLOWMODE_WAIT_X A wait of {value} seconds is required to send messages in this chat.
|
||||
TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {value} seconds
|
|
@ -13,8 +13,8 @@ GROUPCALL_ADD_PARTICIPANTS_FAILED Failure while adding voice chat member due to
|
||||
GROUPED_ID_OCCUPY_FAILED Telegram is having internal problems. Please try again later
|
||||
HISTORY_GET_FAILED The chat history couldn't be retrieved due to Telegram having internal problems. Please try again later
|
||||
IMAGE_ENGINE_DOWN Image engine down due to Telegram having internal problems. Please try again later
|
||||
INTERDC_X_CALL_ERROR An error occurred while Telegram was intercommunicating with DC{x}. Please try again later
|
||||
INTERDC_X_CALL_RICH_ERROR A rich error occurred while Telegram was intercommunicating with DC{x}. Please try again later
|
||||
INTERDC_X_CALL_ERROR An error occurred while Telegram was intercommunicating with DC{value}. Please try again later
|
||||
INTERDC_X_CALL_RICH_ERROR A rich error occurred while Telegram was intercommunicating with DC{value}. Please try again later
|
||||
MEMBER_FETCH_FAILED Telegram is having internal problems. Please try again later
|
||||
MEMBER_NO_LOCATION Couldn't find the member's location due to Telegram having internal problems. Please try again later
|
||||
MEMBER_OCCUPY_PRIMARY_LOC_FAILED Telegram is having internal problems. Please try again later
|
||||
|
|
@ -1,3 +1,3 @@
|
||||
id message
|
||||
Timeout Telegram is having internal problems. Please try again later.
|
||||
ApiCallError Telegram is having internal problems. Please try again later.
|
||||
Timeout Telegram is having internal problems. Please try again later.
|
|
8
docs/source/api/enums/NextCodeType.rst
Normal file
8
docs/source/api/enums/NextCodeType.rst
Normal file
@ -0,0 +1,8 @@
|
||||
NextCodeType
|
||||
============
|
||||
|
||||
.. autoclass:: pyrogram.enums.NextCodeType()
|
||||
:members:
|
||||
|
||||
.. raw:: html
|
||||
:file: ./cleanup.html
|
@ -25,6 +25,7 @@ to apply only a valid value among the expected ones.
|
||||
ParseMode
|
||||
PollType
|
||||
SentCodeType
|
||||
NextCodeType
|
||||
UserStatus
|
||||
|
||||
.. toctree::
|
||||
@ -42,4 +43,5 @@ to apply only a valid value among the expected ones.
|
||||
ParseMode
|
||||
PollType
|
||||
SentCodeType
|
||||
NextCodeType
|
||||
UserStatus
|
@ -111,12 +111,12 @@ Meta
|
||||
|
||||
intro/quickstart
|
||||
intro/install
|
||||
intro/setup
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:caption: Getting Started
|
||||
|
||||
start/setup
|
||||
start/auth
|
||||
start/invoking
|
||||
start/updates
|
||||
@ -144,7 +144,6 @@ Meta
|
||||
topics/use-filters
|
||||
topics/create-filters
|
||||
topics/more-on-updates
|
||||
topics/config-file
|
||||
topics/smart-plugins
|
||||
topics/client-settings
|
||||
topics/tgcrypto
|
||||
|
@ -26,10 +26,12 @@ Get Pyrogram Real Fast
|
||||
api_id = 12345
|
||||
api_hash = "0123456789abcdef0123456789abcdef"
|
||||
|
||||
|
||||
async def main():
|
||||
async with Client("my_account", api_id, api_hash) as app:
|
||||
await app.send_message("me", "Greetings from **Pyrogram**!")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
|
||||
4. Replace *api_id* and *api_hash* values with your own.
|
||||
|
@ -1,60 +0,0 @@
|
||||
Project Setup
|
||||
=============
|
||||
|
||||
We have just :doc:`installed Pyrogram <install>`. In this page we'll discuss what you need to do in order to set up a
|
||||
project with the framework.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
-----
|
||||
|
||||
API Keys
|
||||
--------
|
||||
|
||||
The very first step requires you to obtain a valid Telegram API key (API id/hash pair):
|
||||
|
||||
#. Visit https://my.telegram.org/apps and log in with your Telegram Account.
|
||||
#. Fill out the form with your details and register a new Telegram application.
|
||||
#. Done. The API key consists of two parts: **api_id** and **api_hash**. Keep it secret.
|
||||
|
||||
.. note::
|
||||
|
||||
The API key defines a token for a Telegram *application* you are going to build.
|
||||
This means that you are able to authorize multiple users or bots with a single API key.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project.
|
||||
There are two ways to do so, and you can choose what fits better for you:
|
||||
|
||||
- First option: create a new ``config.ini`` file next to your main script, copy-paste the following and
|
||||
replace the *api_id* and *api_hash* values with your own. This method allows you to keep your credentials out of
|
||||
your code without having to deal with how to load them.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pyrogram]
|
||||
api_id = 12345
|
||||
api_hash = 0123456789abcdef0123456789abcdef
|
||||
|
||||
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
|
||||
Client class. This way you can have full control on how to store and load your credentials:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client(
|
||||
"my_account",
|
||||
api_id=12345,
|
||||
api_hash="0123456789abcdef0123456789abcdef"
|
||||
)
|
||||
|
||||
.. note::
|
||||
|
||||
To keep code snippets clean and concise, from now on it is assumed you are making use of the ``config.ini`` file,
|
||||
thus, the *api_id* and *api_hash* parameters usage won't be shown anymore.
|
@ -1,7 +1,7 @@
|
||||
Authorization
|
||||
=============
|
||||
|
||||
Once a :doc:`project is set up <../intro/setup>`, you will still have to follow a few steps before you can actually use Pyrogram to make
|
||||
Once a :doc:`project is set up <setup>`, you will still have to follow a few steps before you can actually use Pyrogram to make
|
||||
API calls. This section provides all the information you need in order to authorize yourself as user or bot.
|
||||
|
||||
.. contents:: Contents
|
||||
@ -23,7 +23,11 @@ the :meth:`~pyrogram.Client.run` method:
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("my_account")
|
||||
api_id = 12345
|
||||
api_hash = "0123456789abcdef0123456789abcdef"
|
||||
|
||||
app = Client("my_account", api_id=api_id, api_hash=api_hash)
|
||||
|
||||
app.run()
|
||||
|
||||
This starts an interactive shell asking you to input your **phone number**, including your `Country Code`_ (the plus
|
||||
@ -38,8 +42,8 @@ authorized or via SMS:
|
||||
Logged in successfully
|
||||
|
||||
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram to
|
||||
execute API calls with your identity. This file is personal and will be loaded again when you restart your app, and as
|
||||
long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||
execute API calls with your identity. This file is personal and will be loaded again when you restart your app.
|
||||
You can now remove the api_id and api_hash values from the code as they are not needed anymore.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -51,7 +55,7 @@ Bot Authorization
|
||||
|
||||
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
||||
the `Bot Father`_. Bot tokens replace the users' phone numbers only — you still need to
|
||||
:doc:`configure a Telegram API key <../intro/setup>` with Pyrogram, even when using bots.
|
||||
:doc:`configure a Telegram API key <../start/setup>` with Pyrogram, even when using bots.
|
||||
|
||||
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
|
||||
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
||||
@ -61,12 +65,29 @@ after the session name, which will be ``my_bot.session`` for the example below.
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
api_id = 12345
|
||||
api_hash = "0123456789abcdef0123456789abcdef"
|
||||
bot_token = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
|
||||
app = Client(
|
||||
"my_bot",
|
||||
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
api_id=api_id, api_hash=api_hash,
|
||||
bot_token=bot_token
|
||||
)
|
||||
|
||||
app.run()
|
||||
|
||||
.. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
||||
.. _Bot Father: https://t.me/botfather
|
||||
|
||||
.. note::
|
||||
|
||||
The API key (api_id and api_hash) and the bot_token is not needed anymore after a successful authorization.
|
||||
This means you can now simply use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("my_account")
|
||||
app.run()
|
@ -22,10 +22,12 @@ Making API calls with Pyrogram is very simple. Here's a basic example we are goi
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
|
||||
async def main():
|
||||
async with app:
|
||||
await app.send_message("me", "Hi!")
|
||||
|
||||
|
||||
app.run(main())
|
||||
|
||||
Step-by-step
|
||||
@ -76,11 +78,13 @@ Below there's the same example as above, but without the use of the context mana
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
|
||||
async def main():
|
||||
await app.start()
|
||||
await app.send_message("me", "Hi!")
|
||||
await app.stop()
|
||||
|
||||
|
||||
app.run(main())
|
||||
|
||||
Using asyncio.run()
|
||||
@ -95,10 +99,12 @@ be instantiated inside the main function.
|
||||
import asyncio
|
||||
from pyrogram import Client
|
||||
|
||||
|
||||
async def main():
|
||||
app = Client("my_account")
|
||||
|
||||
async with app:
|
||||
await app.send_message("me", "Hi!")
|
||||
|
||||
|
||||
asyncio.run(main())
|
40
docs/source/start/setup.rst
Normal file
40
docs/source/start/setup.rst
Normal file
@ -0,0 +1,40 @@
|
||||
Project Setup
|
||||
=============
|
||||
|
||||
We have just :doc:`installed Pyrogram <../intro/install>`. In this page we'll discuss what you need to do in order to set up a
|
||||
project with the framework.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
-----
|
||||
|
||||
API Key
|
||||
-------
|
||||
|
||||
The first step requires you to obtain a valid Telegram API key (api_id and api_hash pair):
|
||||
|
||||
#. Visit https://my.telegram.org/apps and log in with your Telegram account.
|
||||
#. Fill out the form with your details and register a new Telegram application.
|
||||
#. Done. The API key consists of two parts: **api_id** and **api_hash**. Keep it secret.
|
||||
|
||||
.. note::
|
||||
|
||||
The API key defines a token for a Telegram *application* you are going to build.
|
||||
This means that you are able to authorize multiple users or bots with a single API key.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project: pass your API key to Pyrogram by using the *api_id* and *api_hash* parameters of the Client class:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
api_id = 12345
|
||||
api_hash = "0123456789abcdef0123456789abcdef"
|
||||
|
||||
app = Client("my_account", api_id=api_id, api_hash=api_hash)
|
@ -39,10 +39,12 @@ The most elegant way to register a message handler is by using the :meth:`~pyrog
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
|
||||
@app.on_message()
|
||||
async def my_handler(client, message):
|
||||
await message.forward("me")
|
||||
|
||||
|
||||
app.run()
|
||||
|
||||
The defined function ``my_handler``, which accepts the two arguments *(client, message)*, will be the function that gets
|
||||
@ -63,9 +65,11 @@ function and registers it in your Client. It is useful in case you want to progr
|
||||
from pyrogram import Client
|
||||
from pyrogram.handlers import MessageHandler
|
||||
|
||||
|
||||
async def my_function(client, message):
|
||||
await message.forward("me")
|
||||
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
my_handler = MessageHandler(my_function)
|
||||
|
@ -1,97 +0,0 @@
|
||||
Configuration File
|
||||
==================
|
||||
|
||||
As already mentioned in previous pages, Pyrogram can be configured by the use of an INI file.
|
||||
This page explains how this file is structured, how to use it and why.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
-----
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The idea behind using a configuration file is to help keeping your code free of private settings information such as
|
||||
the API Key and Proxy, without having you to deal with how to load such settings. The configuration file, usually
|
||||
referred as ``config.ini`` file, is automatically loaded from the root of your working directory; all you need to do is
|
||||
fill in the necessary parts.
|
||||
|
||||
.. note::
|
||||
|
||||
The configuration file is optional, but recommended. If, for any reason, you prefer not to use it, there's always an
|
||||
alternative way to configure Pyrogram via Client's parameters. Doing so, you can have full control on how to store
|
||||
and load your settings.
|
||||
|
||||
Settings specified via Client's parameter have higher priority and will override any setting stored in the
|
||||
configuration file.
|
||||
|
||||
|
||||
The config.ini File
|
||||
-------------------
|
||||
|
||||
By default, Pyrogram will look for a file named ``config.ini`` placed at the root of your working directory, that is,
|
||||
the same folder of your running script. You can change the name or location of your configuration file by specifying it
|
||||
in your Client's parameter *config_file*.
|
||||
|
||||
- Replace the default *config.ini* file with *my_configuration.ini*:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("my_account", config_file="my_configuration.ini")
|
||||
|
||||
|
||||
Configuration Sections
|
||||
----------------------
|
||||
|
||||
These are all the sections Pyrogram uses in its configuration file:
|
||||
|
||||
Pyrogram
|
||||
^^^^^^^^
|
||||
|
||||
The ``[pyrogram]`` section contains your Telegram API credentials: *api_id* and *api_hash*.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pyrogram]
|
||||
api_id = 12345
|
||||
api_hash = 0123456789abcdef0123456789abcdef
|
||||
|
||||
`More info about API Key. <../intro/setup#api-keys>`_
|
||||
|
||||
Proxy
|
||||
^^^^^
|
||||
|
||||
The ``[proxy]`` section contains settings about your SOCKS5 proxy.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[proxy]
|
||||
enabled = True
|
||||
hostname = 11.22.33.44
|
||||
port = 1080
|
||||
username = <your_username>
|
||||
password = <your_password>
|
||||
|
||||
`More info about SOCKS5 Proxy. <proxy>`_
|
||||
|
||||
Plugins
|
||||
^^^^^^^
|
||||
|
||||
The ``[plugins]`` section contains settings about Smart Plugins.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
include =
|
||||
module
|
||||
folder.module
|
||||
exclude =
|
||||
module fn2
|
||||
|
||||
`More info about Smart Plugins. <smart-plugins>`_
|
@ -1,8 +1,8 @@
|
||||
SOCKS5 Proxy
|
||||
============
|
||||
Proxy Settings
|
||||
==============
|
||||
|
||||
Pyrogram supports proxies with and without authentication. This feature allows Pyrogram to exchange data with Telegram
|
||||
through an intermediate SOCKS5 proxy server.
|
||||
through an intermediate SOCKS 4/5 or HTTP (CONNECT) proxy server.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
@ -14,44 +14,22 @@ through an intermediate SOCKS5 proxy server.
|
||||
Usage
|
||||
-----
|
||||
|
||||
- To use Pyrogram with a proxy, simply append the following to your ``config.ini`` file and replace the values
|
||||
with your own settings:
|
||||
To use Pyrogram with a proxy, use the *proxy* parameter in the Client class. If your proxy doesn't require authorization
|
||||
you can omit ``username`` and ``password``.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[proxy]
|
||||
enabled = True
|
||||
hostname = 11.22.33.44
|
||||
port = 1080
|
||||
username = <your_username>
|
||||
password = <your_password>
|
||||
|
||||
To enable or disable the proxy without deleting your settings from the config file,
|
||||
change the ``enabled`` value as follows:
|
||||
|
||||
- ``1``, ``yes``, ``True`` or ``on``: Enables the proxy
|
||||
- ``0``, ``no``, ``False`` or ``off``: Disables the proxy
|
||||
|
||||
- Alternatively, you can setup your proxy without the need of the ``config.ini`` file by using the *proxy* parameter
|
||||
in the Client class:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client(
|
||||
session_name="example",
|
||||
"my_account",
|
||||
proxy=dict(
|
||||
scheme="socks5", # "socks4", "socks5" and "http" are supported
|
||||
hostname="11.22.33.44",
|
||||
port=1080,
|
||||
port=1234,
|
||||
username="<your_username>",
|
||||
password="<your_password>"
|
||||
)
|
||||
)
|
||||
|
||||
app.start()
|
||||
|
||||
...
|
||||
|
||||
.. note:: If your proxy doesn't require authorization you can omit ``username`` and ``password`` by either leaving the
|
||||
values blank/empty or completely delete the lines.
|
||||
app.run()
|
||||
|
@ -57,11 +57,11 @@ operators ``~``, ``&`` and ``|``:
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- Message is a **text** message **and** is **not edited**.
|
||||
- Message is a **text** message **or** a **photo**.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(filters.text & ~filters.edited)
|
||||
@app.on_message(filters.text | filters.photo)
|
||||
def my_handler(client, message):
|
||||
print(message)
|
||||
|
||||
|
@ -27,7 +27,6 @@ import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from concurrent.futures.thread import ThreadPoolExecutor
|
||||
from configparser import ConfigParser
|
||||
from hashlib import sha256
|
||||
from importlib import import_module
|
||||
from io import StringIO
|
||||
@ -76,38 +75,37 @@ class Client(Methods):
|
||||
pass here as argument.
|
||||
|
||||
api_id (``int`` | ``str``, *optional*):
|
||||
The *api_id* part of your Telegram API Key, as integer. E.g.: "12345".
|
||||
This is an alternative way to pass it if you don't want to use the *config.ini* file.
|
||||
The *api_id* part of your Telegram API key, as integer.
|
||||
E.g.: 12345.
|
||||
|
||||
api_hash (``str``, *optional*):
|
||||
The *api_hash* part of your Telegram API Key, as string. E.g.: "0123456789abcdef0123456789abcdef".
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
The *api_hash* part of your Telegram API key, as string.
|
||||
E.g.: "0123456789abcdef0123456789abcdef".
|
||||
|
||||
app_version (``str``, *optional*):
|
||||
Application version. Defaults to "Pyrogram |version|".
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
Application version.
|
||||
Defaults to "Pyrogram x.y.z".
|
||||
|
||||
device_model (``str``, *optional*):
|
||||
Device model. Defaults to *platform.python_implementation() + " " + platform.python_version()*.
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
Device model.
|
||||
Defaults to *platform.python_implementation() + " " + platform.python_version()*.
|
||||
|
||||
system_version (``str``, *optional*):
|
||||
Operating System version. Defaults to *platform.system() + " " + platform.release()*.
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
Operating System version.
|
||||
Defaults to *platform.system() + " " + platform.release()*.
|
||||
|
||||
lang_code (``str``, *optional*):
|
||||
Code of the language used on the client, in ISO 639-1 standard. Defaults to "en".
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
Code of the language used on the client, in ISO 639-1 standard.
|
||||
Defaults to "en".
|
||||
|
||||
ipv6 (``bool``, *optional*):
|
||||
Pass True to connect to Telegram using IPv6.
|
||||
Defaults to False (IPv4).
|
||||
|
||||
proxy (``dict``, *optional*):
|
||||
Your SOCKS5 Proxy settings as dict,
|
||||
e.g.: *dict(hostname="11.22.33.44", port=1080, username="user", password="pass")*.
|
||||
The Proxy settings as dict.
|
||||
E.g.: *dict(scheme="socks5", hostname="11.22.33.44", port=1234, username="user", password="pass")*.
|
||||
The *username* and *password* can be omitted if your proxy doesn't require authorization.
|
||||
This is an alternative way to setup a proxy if you don't want to use the *config.ini* file.
|
||||
|
||||
test_mode (``bool``, *optional*):
|
||||
Enable or disable login to the test servers.
|
||||
@ -117,7 +115,6 @@ class Client(Methods):
|
||||
bot_token (``str``, *optional*):
|
||||
Pass your Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
Only applicable for new sessions.
|
||||
This is an alternative way to set it if you don't want to use the *config.ini* file.
|
||||
|
||||
phone_number (``str``, *optional*):
|
||||
Pass your phone number as string (with your Country Code prefix included) to avoid entering it manually.
|
||||
@ -131,11 +128,6 @@ class Client(Methods):
|
||||
Pass your Two-Step Verification password as string (if you have one) to avoid entering it manually.
|
||||
Only applicable for new sessions.
|
||||
|
||||
force_sms (``bool``, *optional*):
|
||||
Pass True to force Telegram sending the authorization code via SMS.
|
||||
Only applicable for new sessions.
|
||||
Defaults to False.
|
||||
|
||||
workers (``int``, *optional*):
|
||||
Number of maximum concurrent workers for handling incoming updates.
|
||||
Defaults to ``min(32, os.cpu_count() + 4)``.
|
||||
@ -145,13 +137,8 @@ class Client(Methods):
|
||||
will store your session files.
|
||||
Defaults to the parent directory of the main script.
|
||||
|
||||
config_file (``str``, *optional*):
|
||||
Path of the configuration file.
|
||||
Defaults to ./config.ini
|
||||
|
||||
plugins (``dict``, *optional*):
|
||||
Your Smart Plugins settings as dict, e.g.: *dict(root="plugins")*.
|
||||
This is an alternative way to setup plugins if you don't want to use the *config.ini* file.
|
||||
|
||||
parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
|
||||
The parse mode, can be any of: *"combined"*, for the default combined mode. *"markdown"* or *"md"*
|
||||
@ -194,7 +181,6 @@ class Client(Methods):
|
||||
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:joinchat/|\+))([\w-]+)$")
|
||||
WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None
|
||||
WORKDIR = PARENT_DIR
|
||||
CONFIG_FILE = PARENT_DIR / "config.ini"
|
||||
|
||||
mimetypes = MimeTypes()
|
||||
mimetypes.readfp(StringIO(mime_types))
|
||||
@ -204,10 +190,10 @@ class Client(Methods):
|
||||
session_name: Union[str, Storage],
|
||||
api_id: int = None,
|
||||
api_hash: str = None,
|
||||
app_version: str = None,
|
||||
device_model: str = None,
|
||||
system_version: str = None,
|
||||
lang_code: str = None,
|
||||
app_version: str = APP_VERSION,
|
||||
device_model: str = DEVICE_MODEL,
|
||||
system_version: str = SYSTEM_VERSION,
|
||||
lang_code: str = LANG_CODE,
|
||||
ipv6: bool = False,
|
||||
proxy: dict = None,
|
||||
test_mode: bool = False,
|
||||
@ -215,10 +201,8 @@ class Client(Methods):
|
||||
phone_number: str = None,
|
||||
phone_code: str = None,
|
||||
password: str = None,
|
||||
force_sms: bool = False,
|
||||
workers: int = WORKERS,
|
||||
workdir: str = WORKDIR,
|
||||
config_file: str = CONFIG_FILE,
|
||||
plugins: dict = None,
|
||||
parse_mode: "enums.ParseMode" = enums.ParseMode.DEFAULT,
|
||||
no_updates: bool = None,
|
||||
@ -236,17 +220,14 @@ class Client(Methods):
|
||||
self.system_version = system_version
|
||||
self.lang_code = lang_code
|
||||
self.ipv6 = ipv6
|
||||
# TODO: Make code consistent, use underscore for private/protected fields
|
||||
self._proxy = proxy
|
||||
self.proxy = proxy
|
||||
self.test_mode = test_mode
|
||||
self.bot_token = bot_token
|
||||
self.phone_number = phone_number
|
||||
self.phone_code = phone_code
|
||||
self.password = password
|
||||
self.force_sms = force_sms
|
||||
self.workers = workers
|
||||
self.workdir = Path(workdir)
|
||||
self.config_file = Path(config_file)
|
||||
self.plugins = plugins
|
||||
self.parse_mode = parse_mode
|
||||
self.no_updates = no_updates
|
||||
@ -295,29 +276,19 @@ class Client(Methods):
|
||||
return self.start()
|
||||
|
||||
def __exit__(self, *args):
|
||||
try:
|
||||
self.stop()
|
||||
except ConnectionError:
|
||||
pass
|
||||
|
||||
async def __aenter__(self):
|
||||
return await self.start()
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
try:
|
||||
await self.stop()
|
||||
|
||||
@property
|
||||
def proxy(self):
|
||||
return self._proxy
|
||||
|
||||
@proxy.setter
|
||||
def proxy(self, value):
|
||||
if value is None:
|
||||
self._proxy = None
|
||||
return
|
||||
|
||||
if self._proxy is None:
|
||||
self._proxy = {}
|
||||
|
||||
self._proxy["enabled"] = bool(value.get("enabled", True))
|
||||
self._proxy.update(value)
|
||||
except ConnectionError:
|
||||
pass
|
||||
|
||||
async def authorize(self) -> User:
|
||||
if self.bot_token:
|
||||
@ -355,17 +326,14 @@ class Client(Methods):
|
||||
else:
|
||||
break
|
||||
|
||||
if self.force_sms:
|
||||
sent_code = await self.resend_code(self.phone_number, sent_code.phone_code_hash)
|
||||
sent_code_descriptions = {
|
||||
enums.SentCodeType.APP: "Telegram app",
|
||||
enums.SentCodeType.SMS: "SMS",
|
||||
enums.SentCodeType.CALL: "phone call",
|
||||
enums.SentCodeType.FLASH_CALL: "phone flash call"
|
||||
}
|
||||
|
||||
print("The confirmation code has been sent via {}".format(
|
||||
{
|
||||
"app": "Telegram app",
|
||||
"sms": "SMS",
|
||||
"call": "phone call",
|
||||
"flash_call": "phone flash call"
|
||||
}[sent_code.type]
|
||||
))
|
||||
print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}")
|
||||
|
||||
while True:
|
||||
if not self.phone_code:
|
||||
@ -615,79 +583,6 @@ class Client(Methods):
|
||||
elif isinstance(updates, raw.types.UpdatesTooLong):
|
||||
log.info(updates)
|
||||
|
||||
def load_config(self):
|
||||
parser = ConfigParser()
|
||||
parser.read(str(self.config_file))
|
||||
|
||||
if self.bot_token:
|
||||
pass
|
||||
else:
|
||||
self.bot_token = parser.get("pyrogram", "bot_token", fallback=None)
|
||||
|
||||
if self.api_id and self.api_hash:
|
||||
pass
|
||||
else:
|
||||
if parser.has_section("pyrogram"):
|
||||
self.api_id = parser.getint("pyrogram", "api_id")
|
||||
self.api_hash = parser.get("pyrogram", "api_hash")
|
||||
else:
|
||||
raise AttributeError("No API Key found. More info: https://docs.pyrogram.org/intro/setup")
|
||||
|
||||
for option in ["app_version", "device_model", "system_version", "lang_code"]:
|
||||
if getattr(self, option):
|
||||
pass
|
||||
else:
|
||||
if parser.has_section("pyrogram"):
|
||||
setattr(self, option, parser.get(
|
||||
"pyrogram",
|
||||
option,
|
||||
fallback=getattr(Client, option.upper())
|
||||
))
|
||||
else:
|
||||
setattr(self, option, getattr(Client, option.upper()))
|
||||
|
||||
if self._proxy:
|
||||
self._proxy["enabled"] = bool(self._proxy.get("enabled", True))
|
||||
else:
|
||||
self._proxy = {}
|
||||
|
||||
if parser.has_section("proxy"):
|
||||
self._proxy["enabled"] = parser.getboolean("proxy", "enabled", fallback=True)
|
||||
self._proxy["hostname"] = parser.get("proxy", "hostname")
|
||||
self._proxy["port"] = parser.getint("proxy", "port")
|
||||
self._proxy["username"] = parser.get("proxy", "username", fallback=None) or None
|
||||
self._proxy["password"] = parser.get("proxy", "password", fallback=None) or None
|
||||
|
||||
if self.plugins:
|
||||
self.plugins = {
|
||||
"enabled": bool(self.plugins.get("enabled", True)),
|
||||
"root": self.plugins.get("root", None),
|
||||
"include": self.plugins.get("include", []),
|
||||
"exclude": self.plugins.get("exclude", [])
|
||||
}
|
||||
else:
|
||||
try:
|
||||
section = parser["plugins"]
|
||||
|
||||
self.plugins = {
|
||||
"enabled": section.getboolean("enabled", True),
|
||||
"root": section.get("root", None),
|
||||
"include": section.get("include", []),
|
||||
"exclude": section.get("exclude", [])
|
||||
}
|
||||
|
||||
include = self.plugins["include"]
|
||||
exclude = self.plugins["exclude"]
|
||||
|
||||
if include:
|
||||
self.plugins["include"] = include.strip().split("\n")
|
||||
|
||||
if exclude:
|
||||
self.plugins["exclude"] = exclude.strip().split("\n")
|
||||
|
||||
except KeyError:
|
||||
self.plugins = None
|
||||
|
||||
async def load_session(self):
|
||||
await self.storage.open()
|
||||
|
||||
@ -699,6 +594,12 @@ class Client(Methods):
|
||||
])
|
||||
|
||||
if session_empty:
|
||||
if not self.api_id or not self.api_hash:
|
||||
raise AttributeError("The API key is required for new authorizations. "
|
||||
"More info: https://docs.pyrogram.org/start/auth")
|
||||
|
||||
await self.storage.api_id(self.api_id)
|
||||
|
||||
await self.storage.dc_id(2)
|
||||
await self.storage.date(0)
|
||||
|
||||
@ -711,6 +612,24 @@ class Client(Methods):
|
||||
)
|
||||
await self.storage.user_id(None)
|
||||
await self.storage.is_bot(None)
|
||||
else:
|
||||
# Needed for migration from storage v2 to v3
|
||||
if not await self.storage.api_id():
|
||||
while True:
|
||||
try:
|
||||
value = int(await ainput("Enter the api_id part of the API key: "))
|
||||
|
||||
if value <= 0:
|
||||
print("Invalid value")
|
||||
continue
|
||||
|
||||
confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower()
|
||||
|
||||
if confirm == "y":
|
||||
await self.storage.api_id(value)
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def load_plugins(self):
|
||||
if self.plugins:
|
||||
|
@ -47,9 +47,8 @@ class TCP:
|
||||
self.lock = asyncio.Lock()
|
||||
self.loop = asyncio.get_event_loop()
|
||||
|
||||
if proxy.get("enabled", False):
|
||||
hostname = proxy.get("hostname", None)
|
||||
port = proxy.get("port", None)
|
||||
if proxy:
|
||||
hostname = proxy.get("hostname")
|
||||
|
||||
try:
|
||||
ip_address = ipaddress.ip_address(hostname)
|
||||
@ -62,14 +61,14 @@ class TCP:
|
||||
self.socket = socks.socksocket(socket.AF_INET)
|
||||
|
||||
self.socket.set_proxy(
|
||||
proxy_type=socks.SOCKS5,
|
||||
proxy_type=getattr(socks, proxy.get("scheme").upper()),
|
||||
addr=hostname,
|
||||
port=port,
|
||||
port=proxy.get("port", None),
|
||||
username=proxy.get("username", None),
|
||||
password=proxy.get("password", None)
|
||||
)
|
||||
|
||||
log.info(f"Using proxy {hostname}:{port}")
|
||||
log.info(f"Using proxy {hostname}")
|
||||
else:
|
||||
self.socket = socks.socksocket(
|
||||
socket.AF_INET6 if ipv6
|
||||
|
@ -25,6 +25,7 @@ from .message_entity_type import MessageEntityType
|
||||
from .message_media import MessageMedia
|
||||
from .message_service import MessageService
|
||||
from .messages_filter import MessagesFilter
|
||||
from .next_code_type import NextCodeType
|
||||
from .parse_mode import ParseMode
|
||||
from .poll_type import PollType
|
||||
from .sent_code_type import SentCodeType
|
||||
|
36
pyrogram/enums/next_code_type.py
Normal file
36
pyrogram/enums/next_code_type.py
Normal file
@ -0,0 +1,36 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-present Dan <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 pyrogram import raw
|
||||
from .auto_name import AutoName
|
||||
|
||||
|
||||
class NextCodeType(AutoName):
|
||||
"""Next code type enumeration used in :obj:`~pyrogram.types.SentCode`."""
|
||||
|
||||
CALL = raw.types.auth.CodeTypeCall
|
||||
"The code will be sent via a phone call. A synthesized voice will tell the user which verification code to input."
|
||||
|
||||
FLASH_CALL = raw.types.auth.CodeTypeFlashCall
|
||||
"The code will be sent via a flash phone call, that will be closed immediately."
|
||||
|
||||
MISSED_CALL = raw.types.auth.CodeTypeMissedCall
|
||||
"Missed call."
|
||||
|
||||
SMS = raw.types.auth.CodeTypeSms
|
||||
"The code was sent via SMS."
|
@ -33,7 +33,7 @@ class SentCodeType(AutoName):
|
||||
"The code will be sent via a flash phone call, that will be closed immediately."
|
||||
|
||||
MISSED_CALL = raw.types.auth.SentCodeTypeMissedCall
|
||||
"Missed call"
|
||||
"Missed call."
|
||||
|
||||
SMS = raw.types.auth.SentCodeTypeSms
|
||||
"The code was sent via SMS."
|
||||
|
@ -37,7 +37,6 @@ class Connect:
|
||||
if self.is_connected:
|
||||
raise ConnectionError("Client is already connected")
|
||||
|
||||
self.load_config()
|
||||
await self.load_session()
|
||||
|
||||
self.session = Session(
|
||||
|
@ -113,7 +113,7 @@ class Session:
|
||||
raw.functions.InvokeWithLayer(
|
||||
layer=layer,
|
||||
query=raw.functions.InitConnection(
|
||||
api_id=self.client.api_id,
|
||||
api_id=await self.client.storage.api_id(),
|
||||
app_version=self.client.app_version,
|
||||
device_model=self.client.device_model,
|
||||
system_version=self.client.system_version,
|
||||
|
@ -16,8 +16,6 @@
|
||||
# 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 base64
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sqlite3
|
||||
@ -36,37 +34,6 @@ class FileStorage(SQLiteStorage):
|
||||
|
||||
self.database = workdir / (self.name + self.FILE_EXTENSION)
|
||||
|
||||
def migrate_from_json(self, session_json: dict):
|
||||
self.open()
|
||||
|
||||
self.dc_id(session_json["dc_id"])
|
||||
self.test_mode(session_json["test_mode"])
|
||||
self.auth_key(base64.b64decode("".join(session_json["auth_key"])))
|
||||
self.user_id(session_json["user_id"])
|
||||
self.date(session_json.get("date", 0))
|
||||
self.is_bot(session_json.get("is_bot", False))
|
||||
|
||||
peers_by_id = session_json.get("peers_by_id", {})
|
||||
peers_by_phone = session_json.get("peers_by_phone", {})
|
||||
|
||||
peers = {}
|
||||
|
||||
for k, v in peers_by_id.items():
|
||||
if v is None:
|
||||
type_ = "group"
|
||||
elif k.startswith("-100"):
|
||||
type_ = "channel"
|
||||
else:
|
||||
type_ = "user"
|
||||
|
||||
peers[int(k)] = [int(k), int(v) if v is not None else None, type_, None, None]
|
||||
|
||||
for k, v in peers_by_phone.items():
|
||||
peers[v][4] = k
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
self.update_peers(peers.values())
|
||||
|
||||
def update(self):
|
||||
version = self.version()
|
||||
|
||||
@ -76,34 +43,18 @@ class FileStorage(SQLiteStorage):
|
||||
|
||||
version += 1
|
||||
|
||||
if version == 2:
|
||||
with self.lock, self.conn:
|
||||
self.conn.execute("ALTER TABLE sessions ADD api_id INTEGER")
|
||||
|
||||
version += 1
|
||||
|
||||
self.version(version)
|
||||
|
||||
async def open(self):
|
||||
path = self.database
|
||||
file_exists = path.is_file()
|
||||
|
||||
if file_exists:
|
||||
try:
|
||||
with open(str(path), encoding="utf-8") as f:
|
||||
session_json = json.load(f)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
log.warning("JSON session storage detected! Converting it into an SQLite session storage...")
|
||||
|
||||
path.rename(path.name + ".OLD")
|
||||
|
||||
log.warning(f'The old session file has been renamed to "{path.name}.OLD"')
|
||||
|
||||
self.migrate_from_json(session_json)
|
||||
|
||||
log.warning("Done! The session has been successfully converted from JSON to SQLite storage")
|
||||
|
||||
return
|
||||
|
||||
if Path(path.name + ".OLD").is_file():
|
||||
log.warning(f'Old session file detected: "{path.name}.OLD". You can remove this file now')
|
||||
|
||||
self.conn = sqlite3.connect(str(path), timeout=1, check_same_thread=False)
|
||||
|
||||
if not file_exists:
|
||||
|
@ -31,6 +31,7 @@ SCHEMA = """
|
||||
CREATE TABLE sessions
|
||||
(
|
||||
dc_id INTEGER PRIMARY KEY,
|
||||
api_id INTEGER,
|
||||
test_mode INTEGER,
|
||||
auth_key BLOB,
|
||||
date INTEGER NOT NULL,
|
||||
@ -90,7 +91,7 @@ def get_input_peer(peer_id: int, access_hash: int, peer_type: str):
|
||||
|
||||
|
||||
class SQLiteStorage(Storage):
|
||||
VERSION = 2
|
||||
VERSION = 3
|
||||
USERNAME_TTL = 8 * 60 * 60
|
||||
|
||||
def __init__(self, name: str):
|
||||
@ -109,8 +110,8 @@ class SQLiteStorage(Storage):
|
||||
)
|
||||
|
||||
self.conn.execute(
|
||||
"INSERT INTO sessions VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(2, None, None, 0, None, None)
|
||||
"INSERT INTO sessions VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(2, None, None, None, 0, None, None)
|
||||
)
|
||||
|
||||
async def open(self):
|
||||
@ -195,6 +196,9 @@ class SQLiteStorage(Storage):
|
||||
async def dc_id(self, value: int = object):
|
||||
return self._accessor(value)
|
||||
|
||||
async def api_id(self, value: int = object):
|
||||
return self._accessor(value)
|
||||
|
||||
async def test_mode(self, value: bool = object):
|
||||
return self._accessor(value)
|
||||
|
||||
|
@ -59,6 +59,9 @@ class Storage:
|
||||
async def dc_id(self, value: int = object):
|
||||
raise NotImplementedError
|
||||
|
||||
async def api_id(self, value: int = object):
|
||||
raise NotImplementedError
|
||||
|
||||
async def test_mode(self, value: bool = object):
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -31,7 +31,7 @@ class SentCode(Object):
|
||||
Confirmation code identifier useful for the next authorization steps (either
|
||||
:meth:`~pyrogram.Client.sign_in` or :meth:`~pyrogram.Client.sign_up`).
|
||||
|
||||
next_type (:obj:`~pyrogram.enums.SentCodeType`, *optional*):
|
||||
next_type (:obj:`~pyrogram.enums.NextCodeType`, *optional*):
|
||||
Type of the next code to be sent with :meth:`~pyrogram.Client.resend_code`.
|
||||
|
||||
timeout (``int``, *optional*):
|
||||
@ -42,7 +42,7 @@ class SentCode(Object):
|
||||
self, *,
|
||||
type: "enums.SentCodeType",
|
||||
phone_code_hash: str,
|
||||
next_type: "enums.SentCodeType" = None,
|
||||
next_type: "enums.NextCodeType" = None,
|
||||
timeout: int = None
|
||||
):
|
||||
super().__init__()
|
||||
@ -57,6 +57,6 @@ class SentCode(Object):
|
||||
return SentCode(
|
||||
type=enums.SentCodeType(type(sent_code.type)),
|
||||
phone_code_hash=sent_code.phone_code_hash,
|
||||
next_type=enums.SentCodeType(type(sent_code.next_type)) if sent_code.next_type else None,
|
||||
next_type=enums.NextCodeType(type(sent_code.next_type)) if sent_code.next_type else None,
|
||||
timeout=sent_code.timeout
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user