mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-10-31 16:07:44 +03:00 
			
		
		
		
	Add documentation
This commit is contained in:
		
							parent
							
								
									e36c35c805
								
							
						
					
					
						commit
						b62327308b
					
				|  | @ -8,13 +8,15 @@ python tools/codegen.py | |||
| Formatting, type-checking and testing: | ||||
| 
 | ||||
| ```sh | ||||
| pip install isort black mypy pytest pytest-asyncio | ||||
| pip install -e client/[dev] | ||||
| python tools/check.py | ||||
| ``` | ||||
| 
 | ||||
| Documentation: | ||||
| Documentation (requires [sphinx](https://www.sphinx-doc.org) and [graphviz](https://www.graphviz.org)'s `dot`): | ||||
| 
 | ||||
| ```sh | ||||
| pip install sphinx_rtd_theme | ||||
| pip install -e client/[doc] | ||||
| python tools/docgen.py | ||||
| ``` | ||||
| 
 | ||||
| Note that multiple optional dependency sets can be specified by separating them with a comma (`[dev,doc]`). | ||||
|  |  | |||
							
								
								
									
										59
									
								
								client/doc/basic/installation.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								client/doc/basic/installation.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| Installation | ||||
| ============ | ||||
| 
 | ||||
| Telethon is a Python 3 library, which means you need to download and install Python to use it. | ||||
| Installing Python, using virtual environments, and the basics of the language, are outside of the scope of this guide. | ||||
| 
 | ||||
| You can find the official resources to `download Python <https://www.python.org/downloads/>`_, | ||||
| learn about the `Python Setup and Usage <https://docs.python.org/3/using/index.html>`_ for different platforms, | ||||
| or follow the `The Python Tutorial <https://docs.python.org/3/tutorial/index.html>`_ to learn the basics. | ||||
| These are not necessarily the best resources to learn, but they are official. | ||||
| Be sure to search online if you prefer learning in video form or otherwise. | ||||
| 
 | ||||
| You can confirm that you have Python installed with: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     python --version | ||||
| 
 | ||||
| Which should print something similar to ``Python 3.11.5`` (or newer). | ||||
| 
 | ||||
| 
 | ||||
| Installing the latest stable version | ||||
| ------------------------------------ | ||||
| 
 | ||||
| Once you have a working Python 3 installation, you can install or upgrade the ``telethon`` package with ``pip``: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     python -m pip install --upgrade telethon | ||||
| 
 | ||||
| Be sure to use lock-files if your project depends on a specific, older version of the library! | ||||
| 
 | ||||
| 
 | ||||
| Installing development versions | ||||
| ------------------------------- | ||||
| 
 | ||||
| If you want the *latest* unreleased changes, you can run the following command instead: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     python -m pip install --upgrade https://github.com/LonamiWebs/Telethon/archive/v2.zip | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     The development version may have bugs and is not recommended for production use. | ||||
|     However, when you are `reporting a library bug <https://github.com/LonamiWebs/Telethon/issues/>`, | ||||
|     you must reproduce the issue in this version before reporting the problem. | ||||
| 
 | ||||
| 
 | ||||
| Verifying the installation | ||||
| -------------------------- | ||||
| 
 | ||||
| To verify that the library is installed correctly, run the following command: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     python -c "import telethon; print(telethon.__version__)" | ||||
| 
 | ||||
| The version number of the library should show in the output. | ||||
							
								
								
									
										32
									
								
								client/doc/basic/next-steps.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								client/doc/basic/next-steps.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| Next steps | ||||
| ========== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| By now, you should have successfully gone through both the :doc:`installation` and :doc:`signing-in` processes. | ||||
| 
 | ||||
| With a :class:`Client` instance connected and authorized, you can send any request to Telegram. | ||||
| Some requests are bot-specific, and some are user-specific, but most can be used by any account. | ||||
| You will need to have the correct permissions and pass valid parameters, but after that, your imagination is the limit. | ||||
| 
 | ||||
| Telethon features extensive documentation for every public item offered by the library. | ||||
| All methods within the :class:`Client` also contain one or more examples on how to use them. | ||||
| 
 | ||||
| Whatever you build, remember to comply with both `Telegram's Terms of Service <https://telegram.org/tos>`_ | ||||
| and `Telegram's API ToS <https://core.telegram.org/api/terms>`_. | ||||
| There are `several requests that applications must make <https://core.telegram.org/api/config#terms-of-service>`_: | ||||
| 
 | ||||
| .. epigraph:: | ||||
| 
 | ||||
|     […] when logging in as an existing user, apps are supposed to call :tl:`help.getTermsOfServiceUpdate` | ||||
|     to check for any updates to the Terms of Service; | ||||
|     this call should be repeated after ``expires`` seconds have elapsed. | ||||
|     If an update to the Terms Of Service is available, clients are supposed to show a consent popup; | ||||
|     if accepted, clients should call :tl:`help.acceptTermsOfService`, | ||||
|     providing the ``termsOfService id`` JSON object; | ||||
|     in case of denial, clients are to delete the account using :tl:`account.deleteAccount`, | ||||
|     providing Decline ToS update as deletion reason. | ||||
| 
 | ||||
| The library will not make these calls for you, as it cannot know how users interact with the application being developed. | ||||
| If you use an official client alongside the application you are developing, | ||||
| it should be safe to rely on that client making the requests instead. | ||||
							
								
								
									
										211
									
								
								client/doc/basic/signing-in.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								client/doc/basic/signing-in.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,211 @@ | |||
| Signing in | ||||
| ========== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| Most of Telegram's API methods are gated behind an account login. | ||||
| But before you can interact with the API at all, you will need to obtain an API ID and hash pair for your application. | ||||
| 
 | ||||
| 
 | ||||
| Registering your Telegram application | ||||
| ------------------------------------- | ||||
| 
 | ||||
| Before working with Telegram's API, you (as the application developer) need to get an API ID and hash: | ||||
| 
 | ||||
| 1.  `Login to your Telegram account <https://my.telegram.org/>`_ with the phone number of the developer account to use. | ||||
| 
 | ||||
| 2.  Click under *API Development tools*. | ||||
| 
 | ||||
| 3.  A *Create new application* window will appear. Fill in your application details. | ||||
|     There is no need to enter any *URL*, and only the first two fields (*App title* and *Short name*) can currently be changed later. | ||||
| 
 | ||||
| 4.  Click on *Create application* at the end. | ||||
|     Remember that your **API hash is secret** and Telegram won't let you revoke it. | ||||
|     Don't post it anywhere! | ||||
| 
 | ||||
| This API ID and hash can now be used to develop an application using Telegram's API. | ||||
| Telethon consumes this API ID and hash in order to make the requests to Telegram. | ||||
| 
 | ||||
| It is important to note that this API ID and hash is attached to a developer account, | ||||
| and can be used to develop applications or otherwise using libraries such as Telethon. | ||||
| 
 | ||||
| The *users* of the application you develop do *not* need to provide their own API ID and hash. | ||||
| The API ID and hash values are meant to be hardcoded in the application. | ||||
| Any user is then able to login with just their phone number or bot token, even if they have not registered an application themselves. | ||||
| 
 | ||||
| .. important:: | ||||
| 
 | ||||
|     The API ID and hash are meant to be *secret*, but Python is often distributed in source-code form. | ||||
|     These two things conflict with eachother! | ||||
|     You can opt to obfuscate the values somehow, or perhaps distribute an executable binary file instead. | ||||
|     Depending on what you are developing, it might be reasonable to expect users to provide their own API ID and hash instead. | ||||
| 
 | ||||
|     Official applications *also* must embed the API ID and hash, but these are often distributed as binary files. | ||||
|     Whatever you do, **do not use other people's API ID and hash!** | ||||
|     Telegram may detect this as suspicious and ban the accounts. | ||||
| 
 | ||||
| If you receive an error, Telegram is likely blocking the registration of a new applications. | ||||
| The best you can do is wait and try again later. | ||||
| If the issue persists, you may try contacting them, using a proxy or using a VPN. | ||||
| Be aware that some phone numbers are not eligible to register applications with. | ||||
| 
 | ||||
| 
 | ||||
| Interactive login | ||||
| ----------------- | ||||
| 
 | ||||
| The library offers a method for "quick and dirty" scripts known as :meth:`~Client.interactive_login`. | ||||
| This method will first check whether the account was previously logged-in, and if not, ask for a phone number to be input. | ||||
| 
 | ||||
| You can write the code in a file (such as ``hello.py``) and then run it, or use the built-in ``asyncio``-enabled REPL. | ||||
| For this tutorial, we'll be using the ``asyncio`` REPL: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     python -m asyncio | ||||
| 
 | ||||
| .. important:: | ||||
| 
 | ||||
|     If you opt to write your code in a file, do **not** call your script ``telethon.py``! | ||||
|     Python will try to import from there and it will fail with an error such as "ImportError: cannot import name ...". | ||||
| 
 | ||||
| The first thing we need to do is import the :class:`Client` class and create an instance of it: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     from telethon import Client | ||||
| 
 | ||||
|     client = Client('name', 12345, '0123456789abcdef0123456789abcdef') | ||||
| 
 | ||||
| The second and third parameters must be the API ID and hash, respectively. | ||||
| We have a client instance now, but we can't send requests to Telegram until we connect! | ||||
| So the next step is to :meth:`~Client.connect`: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     await client.connect() | ||||
| 
 | ||||
| If all went well, you will have connected to one of Telegram's servers. | ||||
| If you run into issues, you might need to try a different hosting provider or use some sort of proxy. | ||||
| 
 | ||||
| Once you're connected, we can begin the :meth:`~Client.interactive_login`: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     await client.interactive_login() | ||||
| 
 | ||||
| Do as the prompts say on the terminal, and you will have successfully logged-in! | ||||
| 
 | ||||
| Once you're done, make sure to :meth:`~Client.disconnect` for a graceful shutdown. | ||||
| 
 | ||||
| 
 | ||||
| Manual login | ||||
| ------------ | ||||
| 
 | ||||
| We've talked about the second and third parameters of the :class:`Client` constructor, but not the first: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     client = Client('name', 12345, '0123456789abcdef0123456789abcdef') | ||||
| 
 | ||||
| The first parameter is the "session". | ||||
| When using a string or a :class:`~pathlib.Path`, the library will create a SQLite database in that path. | ||||
| The session path can contain directory separators and live anywhere in the file system. | ||||
| Telethon will automatically append the ``.session`` extension if you don't provide any. | ||||
| 
 | ||||
| Briefly, the session contains some of the information needed to connect to Telegram. | ||||
| This includes the datacenter belonging to the account logged-in, and the authorization key used for encryption, among other things. | ||||
| 
 | ||||
| .. important:: | ||||
| 
 | ||||
|     **Do not leak the session file!** | ||||
|     Anyone with that file can login to the account stored in it. | ||||
|     If you believe someone else has obtained this file, immediately revoke all active sessions from an official client. | ||||
| 
 | ||||
| Let's take a look at what :meth:`~Client.interactive_login` does under the hood. | ||||
| 
 | ||||
| 1. First, it's using an equivalent of :meth:`~Client.is_authorized` to check whether the session was logged-in previously. | ||||
| 2. Then, it will either :meth:`~Client.bot_sign_in` with a bot token or :meth:`~Client.request_login_code` with a phone number. | ||||
| 
 | ||||
|     * If it logged-in as a bot account, a :class:`~types.User` is returned and we're done. | ||||
|     * Otherwise, a login code was sent. Go to step 3. | ||||
| 
 | ||||
| 3. Attempt to complete the user sign-in with :meth:`~Client.sign_in`, by entering the login code. | ||||
| 
 | ||||
|     * If a :class:`~types.User` is returned, we're done. | ||||
|     * Otherwise, a 2FA password is required. Go to step 4. | ||||
| 
 | ||||
| 4. Use :meth:`Client.check_password` to check that the password is correct. | ||||
| 
 | ||||
|     * If the password is correct, :class:`~types.User` is returned and we're done. | ||||
| 
 | ||||
| Put into code, a user can thus login as follows: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     from telethon import Client | ||||
|     from telethon.types import User | ||||
| 
 | ||||
|     # SESSION, API_ID, API_HASH should be previously defined in your code | ||||
|     async with Client(SESSION, API_ID, API_HASH) as client: | ||||
|         if not await client.is_authorized(): | ||||
|             phone = input('phone: ') | ||||
|             login_token = await client.request_login_code(phone_or_token) | ||||
| 
 | ||||
|         code = input('code: ') | ||||
|         user_or_token = await client.sign_in(login_token, code) | ||||
| 
 | ||||
|         if isinstance(user_or_token, User): | ||||
|             return user_or_token | ||||
| 
 | ||||
|         # user_or_token is PasswordToken | ||||
|         password_token = user_or_token | ||||
| 
 | ||||
|         import getpass | ||||
|         password = getpass.getpass("password: ") | ||||
|         user = await client.check_password(password_token, password) | ||||
|         return user | ||||
| 
 | ||||
| A bot account does not need to request login code and cannot have passwords, so the login flow is much simpler: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     from telethon import Client | ||||
| 
 | ||||
|     # SESSION, API_ID, API_HASH should be previously defined in your code | ||||
|     async with Client(SESSION, API_ID, API_HASH) as client: | ||||
|         bot_token = input('token: ') | ||||
|         bot_user = await client.bot_sign_in(bot_token) | ||||
|         return bot_user | ||||
| 
 | ||||
| To get a bot account, you need to talk with `@BotFather <https://t.me/BotFather>`_. | ||||
| 
 | ||||
| You may have noticed the ``async with`` keywords. | ||||
| The :class:`Client` can be used in a context-manager. | ||||
| This will automatically call :meth:`Client.connect` and :meth:`Client.disconnect` for you. | ||||
| 
 | ||||
| A good way to structure your code is as follows: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     import asyncio | ||||
|     from telethon import Client | ||||
| 
 | ||||
|     SESSION = ... | ||||
|     API_ID = ... | ||||
|     API_HASH = ... | ||||
| 
 | ||||
|     async def main(): | ||||
|         async with Client(SESSION, API_ID, API_HASH) as client: | ||||
|             ...  # use client to your heart's content | ||||
| 
 | ||||
|     if __name__ == '__main__': | ||||
|         asyncio.run(main()) | ||||
| 
 | ||||
| This way, both the :mod:`asyncio` event loop and the :class:`Client` will exit cleanly. | ||||
| Otherwise, you might run into errors such as tasks being destroyed while pending. | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     Once a :class:`Client` instance has been connected, you cannot change the :mod:`asyncio` event loop. | ||||
|     Methods like :func:`asyncio.run` setup and tear-down a new event loop every time. | ||||
|     If the loop changes, the client is likely to be "stuck" because its loop cannot advance. | ||||
							
								
								
									
										117
									
								
								client/doc/concepts/botapi-vs-mtproto.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								client/doc/concepts/botapi-vs-mtproto.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| HTTP Bot API vs MTProto | ||||
| ======================= | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| Telethon is more than capable to develop bots for Telegram. | ||||
| If you haven't decided which wrapper library for bots to use yet, | ||||
| using Telethon from the beginning may save you some headaches later. | ||||
| 
 | ||||
| 
 | ||||
| What is Bot API? | ||||
| ---------------- | ||||
| 
 | ||||
| `Telegram's HTTP Bot API <https://core.telegram.org/bots/api>`_, | ||||
| from now on referred to as simply "Bot API", is Telegram's official way for developers to control their own Telegram bots. | ||||
| Quoting their main page: | ||||
| 
 | ||||
| .. epigraph:: | ||||
| 
 | ||||
|     The Bot API is an HTTP-based interface created for developers keen on building bots for Telegram. | ||||
| 
 | ||||
|     To learn how to create and set up a bot, please consult our | ||||
|     `Introduction to Bots <https://core.telegram.org/bots>`_ | ||||
|     and `Bot FAQ <https://core.telegram.org/bots/faq>`_. | ||||
| 
 | ||||
| Bot API is simply an HTTP endpoint offering a custom HTTP API. | ||||
| Underneath, it uses `tdlib <https://core.telegram.org/tdlib>`_ to talk to Telegram's servers. | ||||
| 
 | ||||
| You can configure your bot details via `@BotFather <https://t.me/BotFather>`_. | ||||
| This includes name, commands, and auto-completion. | ||||
| 
 | ||||
| 
 | ||||
| What is MTProto? | ||||
| ---------------- | ||||
| 
 | ||||
| `MTProto <https://core.telegram.org/mtproto>`_ stands for "Mobile Transport Protocol". | ||||
| It is the language that the Telegram servers "speak". | ||||
| You can think of it as an alternative to HTTP. | ||||
| 
 | ||||
| Telegram offers multiple APIs. | ||||
| All user accounts must use the API offered via MTProto. | ||||
| We will call this API the "MTProto API". | ||||
| This is the canonical Telegram API. | ||||
| 
 | ||||
| The MTProto API is different from Bot API, but bot accounts can use either in the same way. | ||||
| In fact, the Bot API is implemented to use the MTProto API to map the requests and responses. | ||||
| 
 | ||||
| Telethon implements the MTProto and offers classes and methods that can be called to send requests. | ||||
| In Telethon, all the methods and types generated from Telegram's API definitions are also known as :term:`Raw API`. | ||||
| This name was chosen because it gives you "raw" access to the MTProto API. | ||||
| Telethon's :class:`Client` and other custom types are implemented using the :term:`Raw API`. | ||||
| 
 | ||||
| 
 | ||||
| Advantages of MTProto over Bot API | ||||
| ---------------------------------- | ||||
| 
 | ||||
| MTProto clients (like Telethon) connect directly to Telegram's servers via TCP or UDP. | ||||
| There is no HTTP connection, no "polling", and no "web hooks". | ||||
| We can compare the two visually: | ||||
| 
 | ||||
| .. graphviz:: | ||||
|     :caption: Communication between a Client and the Bot API | ||||
| 
 | ||||
|     digraph botapi { | ||||
|         rankdir=LR; | ||||
|         "Client" -> "HTTP API"; | ||||
|         "HTTP API" -> "MTProto API"; | ||||
|         "MTProto API" -> "Telegram Servers"; | ||||
| 
 | ||||
|         "Telegram Servers" -> "MTProto API" [label="IPC"]; | ||||
|         "MTProto API" -> "HTTP API" [label="MTProto"]; | ||||
|         "HTTP API" -> "Client" [label="JSON"]; | ||||
|     } | ||||
| 
 | ||||
| .. graphviz:: | ||||
|     :caption: Communication between a Client and the MTProto API | ||||
| 
 | ||||
|     digraph botapi { | ||||
|         rankdir=LR; | ||||
|         "Client" -> "MTProto API"; | ||||
|         "MTProto API" -> "Telegram Servers"; | ||||
| 
 | ||||
|         "Telegram Servers" -> "MTProto API" [label="IPC"]; | ||||
|         "MTProto API" -> "Client" [label="MTProto"]; | ||||
|     } | ||||
| 
 | ||||
| When interacting with the MTProto API directly, we can cut down one intermediary (the HTTP API). | ||||
| This is less theoretical overhead and latency. | ||||
| It also means that, even if the Bot API endpoint is down, talking to the MTProto API could still work. | ||||
| 
 | ||||
| The methods offered by the Bot API map to some of the methods in the MTProto API, but not all. | ||||
| The Bot API is its own abstraction, and chooses to expose less details. | ||||
| By talking to the MTProto API directly, you unlock the `full potential <https://github.com/LonamiWebs/Telethon/wiki/MTProto-vs-HTTP-Bot-API>`_. | ||||
| 
 | ||||
| The serialization format used by MTProto is more compact than JSON and can still be compressed. | ||||
| 
 | ||||
| Another benefit of avoiding the Bot API is the ease to switch to user accounts instead of bots. | ||||
| The MTProto API is the same for users and bots, so by using Telethon, you don't need to learn to use a second library. | ||||
| 
 | ||||
| 
 | ||||
| Migrating from Bot API to Telethon | ||||
| ---------------------------------- | ||||
| 
 | ||||
| If the above points convinced you to switch to Telethon, the following short guides should help you make the switch! | ||||
| 
 | ||||
| It doesn't matter if you wrote your bot with `requests <https://pypi.org/project/requests/>`_ | ||||
| and you were making API requests manually, or if you used a wrapper library like | ||||
| `python-telegram-bot <https://python-telegram-bot.readthedocs.io>`_ | ||||
| or `pyTelegramBotAPI <https://pytba.readthedocs.io/en/latest/index.html>`. | ||||
| You will surely be pleased with Telethon! | ||||
| 
 | ||||
| If you were using an asynchronous library like `aiohttp <https://docs.aiohttp.org/en/stable>`_ | ||||
| or a wrapper like `aiogram <https://docs.aiohttp.org/en/stable>`_, the switch will be even easier. | ||||
| 
 | ||||
| 
 | ||||
| Migrating from TODO | ||||
| ^^^^^^^^^^^^^^^^^^^ | ||||
							
								
								
									
										108
									
								
								client/doc/concepts/chats.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								client/doc/concepts/chats.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,108 @@ | |||
| Chats | ||||
| ===== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| The term :term:`chat` is extremely overloaded, so it's no surprise many are confused by what it means. | ||||
| This section should hopefully clear that up. | ||||
| 
 | ||||
| 
 | ||||
| Telethon Chat | ||||
| ------------- | ||||
| 
 | ||||
| The word :term:`chat` in Telethon is used to refer a place where messages are sent to. | ||||
| Therefore, a Telethon :term:`chat` can be another user, a bot, a group, or a broadcast channel. | ||||
| All of those are places where messages can be sent. | ||||
| 
 | ||||
| Of course, chats do more things than contain messages. | ||||
| They often have a name, username, photo, description, and other information. | ||||
| 
 | ||||
| When a :term:`chat` appears in a parameter or as a property, | ||||
| it means that it will be either a :class:`~types.User`, :class:`~types.Group` or :class:`~types.Channel`. | ||||
| 
 | ||||
| When a parameter must be "chat-like", it means Telethon will accept anything that can be "converted" to a :term:`chat`. | ||||
| The following types are chat-like: | ||||
| 
 | ||||
| * The ``'me'`` literal string. This represents the account that is logged in ("yourself"). | ||||
| * An ``'@username'``. The at-sign ``@`` is optional. Note that links are not supported. | ||||
| * An ``'+1 23'`` phone number string. It must be an ``str`` and start with the plus-sign ``+`` character. | ||||
| * An ``123`` integer identifier. It must be an ``int`` and cannot be negative. | ||||
| * An existing :class:`~types.User`, :class:`~types.Group` or :class:`~types.Channel`. | ||||
| * A :class:`~types.PackedChat`. | ||||
| 
 | ||||
| Previous versions of Telethon referred to this term as "entity" or "entities" instead. | ||||
| 
 | ||||
| 
 | ||||
| Telegram Chat | ||||
| ------------- | ||||
| 
 | ||||
| The Telegram API is very confusing when it comes to the word "chat". | ||||
| You only need to know about this if you plan to use the :term:`Raw API`. | ||||
| 
 | ||||
| In the schema definitions, there are two boxed types, :tl:`User` and :tl:`Chat`. | ||||
| A boxed :tl:`User` can only be the bare :tl:`user`, but the boxed :tl:`Chat` can be either a bare :tl:`chat` or a bare :tl:`channel`. | ||||
| 
 | ||||
| A bare :tl:`chat` always refers to small groups. | ||||
| A bare :tl:`channel` can have either the ``broadcast`` or the ``megagroup`` flag set to ``True``. | ||||
| 
 | ||||
| A bare :tl:`channel` with the ``broadcast`` flag set to ``True`` is known as a broadcast channel. | ||||
| A bare :tl:`channel` with the ``megagroup`` flag set to ``True`` is known as a supergroup. | ||||
| 
 | ||||
| A bare :tl:`chat` with has less features than a bare :tl:`channel` ``megagroup``. | ||||
| Official clients are very good at hiding this difference. | ||||
| They will implicitly convert bare :tl:`chat` to bare :tl:`channel` ``megagroup`` when doing certain operations. | ||||
| Doing things like setting a username is actually a two-step process (migration followed by updating the username). | ||||
| Official clients transparently merge the history of migrated :tl:`channel` with their old :tl:`chat`. | ||||
| 
 | ||||
| In Telethon: | ||||
| 
 | ||||
| * A :class:`~types.User` always corresponds to :tl:`user`. | ||||
| * A :class:`~types.Group` represents either a :tl:`chat` or a :tl:`channel` ``megagroup``. | ||||
| * A :class:`~types.Channel` represents a :tl:`channel` ``broadcast``. | ||||
| 
 | ||||
| Telethon classes aim to map to similar concepts in official applications. | ||||
| 
 | ||||
| 
 | ||||
| Bot API chat | ||||
| ------------ | ||||
| 
 | ||||
| The Bot API follows a certain convention when it comes to identifiers: | ||||
| 
 | ||||
| * User IDs are positive. | ||||
| * Chat IDs are negative. | ||||
| * Channel IDs are prefixed with ``-100``. | ||||
| 
 | ||||
| Telethon encourages the use of :class:`~types.PackedChat` instead of naked identifiers. | ||||
| As a reminder, negative identifiers are not supported in Telethon's chat-like parameters. | ||||
| 
 | ||||
| 
 | ||||
| Encountering chats | ||||
| ------------------ | ||||
| 
 | ||||
| The way you encounter chats in Telethon is no different from official clients. | ||||
| If you: | ||||
| 
 | ||||
| * …have joined a group or channel, or have sent private messages to some user, you can :meth:`~Client.get_dialogs`. | ||||
| * …know the user is in your contact list, you can :meth:`~Client.get_contacts`. | ||||
| * …know the user has a common chat with you, you can :meth:`~Client.get_participants` of the chat in common. | ||||
| * …know the username of the user, group, or channel, you can :meth:`~Client.resolve_username`. | ||||
| * …are a bot responding to users, you will be able to access the :attr:`types.Message.sender`. | ||||
| 
 | ||||
| Chats access hash | ||||
| ----------------- | ||||
| 
 | ||||
| Users, supergroups and channels all need an :term:`access hash`. | ||||
| 
 | ||||
| In Telethon, the :class:`~types.PackedChat` is the recommended way to deal with the identifier-hash pairs. | ||||
| This compact type can be used anywhere a chat is expected. | ||||
| It's designed to be easy to store and cache in any way your application chooses. | ||||
| 
 | ||||
| Bot accounts can get away with an invalid :term:`access hash` for certain operations under certain conditions. | ||||
| The same is true for user accounts, although to a lesser extent. | ||||
| 
 | ||||
| When using just the identifier to refer to a chat, Telethon will attempt to retrieve its hash from its in-memory cache. | ||||
| If this fails, an invalid hash will be used. This may or may not make the API call succeed. | ||||
| For this reason, it is recommended that you always use :class:`~types.PackedChat` instead. | ||||
| 
 | ||||
| Remember that an :term:`access hash` is account-bound. | ||||
| You cannot obtain an :term:`access hash` in Account-A and use it in Account-B. | ||||
							
								
								
									
										40
									
								
								client/doc/concepts/errors.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								client/doc/concepts/errors.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| RPC Errors | ||||
| ========== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| :term:`RPC` stands for Remote Procedure Call. | ||||
| By extension, RPC Errors occur when a RPC fails to execute in the server. | ||||
| In Telethon, a :term:`RPC error` corresponds to the :class:`RpcError` class. | ||||
| 
 | ||||
| Telethon will only ever raise :class:`RpcError` when the result to a :term:`RPC` is an error. | ||||
| If the error is raised, you know it comes from Telegram. | ||||
| Consequently, when using :term:`Raw API`, if a :class:`RpcError` occurs, it is never a bug in the library. | ||||
| 
 | ||||
| :term:`RPC error` consist of an integer :attr:`~RpcError.code` and a string :attr:`~RpcError.name`. | ||||
| The :attr:`RpcError.code` is roughly the same as `HTTP status codes <https://developer.mozilla.org/en-US/docs/Web/HTTP/Status>`_. | ||||
| The :attr:`RpcError.name` is often a string in ``SCREAMING_CASE`` and refers to what went wrong. | ||||
| 
 | ||||
| Certain error names also contain an integer value. | ||||
| This value is removed from the :attr:`~RpcError.name` and put into :attr:`RpcError.value`. | ||||
| If Telegram responds with ``FLOOD_WAIT_60``, the name would be ``'FLOOD_WAIT'`` and the value ``60``. | ||||
| 
 | ||||
| A very common error is ``FLOOD_WAIT``. | ||||
| It occurs when you have attempted to use a request too many times during a certain window of time: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     import asyncio | ||||
|     from telethon import RpcError | ||||
| 
 | ||||
|     try: | ||||
|         await client.send_message('me', 'Spam') | ||||
|     except RpcError as e: | ||||
|         # If we get a flood error, sleep. Else, propagate the error. | ||||
|         if e.name == 'FLOOD_WAIT': | ||||
|             await asyncio.sleep(e.value) | ||||
|         else: | ||||
|             raise | ||||
| 
 | ||||
| Note that the library can automatically handle and retry on ``FLOOD_WAIT`` for you. | ||||
| Refer to the ``flood_sleep_threshold`` of the :class:`Client` to learn how. | ||||
							
								
								
									
										66
									
								
								client/doc/concepts/full-api.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								client/doc/concepts/full-api.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| The Full API | ||||
| ============ | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| The API surface offered by Telethon is not exhaustive. | ||||
| Telegram is constantly adding new features, and both implementing and documenting custom methods would an exhausting, never-ending job. | ||||
| 
 | ||||
| Telethon concedes to this fact and implements only commonly-used features to keep a lean API. | ||||
| Access to the entirity of Telegram's API via Telethon's :term:`Raw API` is a necessary evil. | ||||
| 
 | ||||
| The ``telethon._tl`` module has a leading underscore to signal that it is private. | ||||
| It is not covered by the semver guarantees of the library, but you may need to use it regardless. | ||||
| If the :class:`Client` doesn't offer a method for what you need, using the :term:`Raw API` is inevitable. | ||||
| 
 | ||||
| 
 | ||||
| Invoking Raw API methods | ||||
| ------------------------ | ||||
| 
 | ||||
| The :term:`Raw API` can be *invoked* in a very similar way to other client methods: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     from telethon import _tl as tl | ||||
| 
 | ||||
|     was_reset = await client(tl.functions.account.reset_wall_papers()) | ||||
| 
 | ||||
| Inside ``telethon._tl.functions`` you will find a function for every single :term:`RPC` supported by Telegram. | ||||
| The parameters are keyword-only and do not have defaults. | ||||
| Whatever arguments you pass is exactly what Telegram will receive. | ||||
| Whatever is returned is exactly what Telegram responded with. | ||||
| 
 | ||||
| All functions inside ``telethon._tl.functions`` will return the serialized request. | ||||
| When calling a :class:`Client` instance with this request as input, it will be sent to Telegram and wait for a response. | ||||
| 
 | ||||
| Multiple requests may be in-flight at the same time, specially when using :mod:`asyncio`. | ||||
| Telethon will attempt to combine these into a single "container" when possible as an optimization. | ||||
| 
 | ||||
| 
 | ||||
| Exploring the Raw API | ||||
| --------------------- | ||||
| 
 | ||||
| Everything under ``telethon._tl.types`` implements :func:`repr`. | ||||
| This means you can print any response and get the Python representation of that object. | ||||
| 
 | ||||
| All types are proper classes with attributes. | ||||
| You do not need to use a regular expression on the string representation to access the field you want. | ||||
| 
 | ||||
| Most :term:`RPC` return an abstract class from ``telethon._tl.abcs``. | ||||
| To check for a concrete type, you can use :func:`isinstance`: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     invite = await client(tl.functions.messages.check_chat_invite(hash='aBcDeF')) | ||||
|     if isinstance(invite, tl.types.ChatInviteAlready): | ||||
|         print(invite.chat) | ||||
| 
 | ||||
| The ``telethon._tl`` module is not documented here because it would result in tens of megabytes. | ||||
| Instead, there are multiple alternatives: | ||||
| 
 | ||||
| * Use Telethon's separate site to search in the `Telethon Raw API <https://tl.telethon.dev/>`_. | ||||
|   This is the recommended way. It also features auto-generated examples. | ||||
| * Use Python's built-in :func:`help` and :func:`dir` to help you navigate the module. | ||||
| * Use an editor with autocompletion support. | ||||
| * Choose the right layer from `Telegram's official API Layers <https://core.telegram.org/api/layers>`_. | ||||
|   Note that the `TL Schema <https://core.telegram.org/schema>`_ might not be up-to-date. | ||||
							
								
								
									
										42
									
								
								client/doc/concepts/glossary.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								client/doc/concepts/glossary.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| Glossary | ||||
| ======== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| .. glossary:: | ||||
|     :sorted: | ||||
| 
 | ||||
|     chat | ||||
|         A :class:`~types.User`, :class:`~types.Group` or :class:`~types.Channel`. | ||||
| 
 | ||||
|         .. seealso:: The :doc:`../concepts/chats` concept. | ||||
| 
 | ||||
|     Raw API | ||||
|         Functions and types under ``telethon._tl`` that enable access to all of Telegram's API. | ||||
| 
 | ||||
|         .. seealso:: The :doc:`../concepts/full-api` concept. | ||||
| 
 | ||||
|     access hash | ||||
|         Account-bound integer tied to a specific resource. | ||||
|         Users, channels, photos and documents are all resources with an access hash. | ||||
|         The access hash doesn't change, but every account will see a different value for the same resource. | ||||
| 
 | ||||
|     RPC | ||||
|         Remote Procedure Call. | ||||
|         Invoked when calling a :class:`Client` with a function from ``telethon._tl.functions``. | ||||
| 
 | ||||
|     RPC Error | ||||
|         Error type returned by Telegram. | ||||
|         :class:`RpcError` contains an integer code similar to HTTP status codes and a name. | ||||
| 
 | ||||
|         .. seealso:: The :doc:`../concepts/errors` concept. | ||||
| 
 | ||||
|     session | ||||
|         Data used to securely connect to Telegram and other state related to the logged-in account. | ||||
| 
 | ||||
|         .. seealso:: The :doc:`../concepts/sessions` concept. | ||||
| 
 | ||||
|     MTProto | ||||
|         Mobile Transport Protocol used to interact with Telegram's API. | ||||
| 
 | ||||
|         .. seealso:: The :doc:`../concepts/botapi-vs-mtproto` concept. | ||||
							
								
								
									
										55
									
								
								client/doc/concepts/sessions.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								client/doc/concepts/sessions.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| Sessions | ||||
| ======== | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| In Telethon, the word :term:`session` is used to refer to the set of data needed to connect to Telegram. | ||||
| This includes the server address of your home datacenter, as well as the authorization key bound to an account. | ||||
| When you first connect to Telegram, an authorization key is generated to encrypt all communication. | ||||
| After login, Telegram remembers this authorization key as logged-in, so you don't need to login again. | ||||
| 
 | ||||
| .. important:: | ||||
| 
 | ||||
|     **Do not leak the session file!** | ||||
|     Anyone with that file can login to the account stored in it. | ||||
|     If you believe someone else has obtained this file, immediately revoke all active sessions from an official client. | ||||
| 
 | ||||
| Some auxiliary information such as the user ID of the logged-in user is also kept. | ||||
| 
 | ||||
| The update state, which can change every time an update is received from Telegram, is also stored in the session. | ||||
| Telethon needs this information to catch up on all missed updates while your code was not running. | ||||
| This is why it's important to call :meth:`Client.disconnect`. | ||||
| Doing so flushes all the update state to the session and saves it. | ||||
| 
 | ||||
| 
 | ||||
| Session files | ||||
| ------------- | ||||
| 
 | ||||
| Telethon defaults to using SQLite to store the session state. | ||||
| The session state is written to ``.session`` files, so make sure your VCS ignores them! | ||||
| To make sure the ``.session`` file is saved, you should call :meth:`Client.disconnect` before exiting the program. | ||||
| 
 | ||||
| The first parameter in the :class:`Client` constructor is the session to use. | ||||
| You can use a `str`, a :class:`pathlib.Path` or a :class:`session.Storage`. | ||||
| The string or path are relative to the Current Working Directory. | ||||
| You can use absolute paths or relative paths to folders elsewhere. | ||||
| The ``.session`` extension is automatically added if the path has no extension. | ||||
| 
 | ||||
| 
 | ||||
| Session storages | ||||
| ---------------- | ||||
| 
 | ||||
| The :class:`session.Storage` abstract base class defines the required methods to create custom storages. | ||||
| Telethon comes with two built-in storages: | ||||
| 
 | ||||
| * :class:`~session.SqliteSession`. This is used by default when a string or path is used. | ||||
| * :class:`~session.MemorySession`. This is used by default when the path is ``None``. | ||||
|   You can also use it directly when you have a :class:`~session.Session` instance. | ||||
|   It's useful when you don't have file-system access. | ||||
| 
 | ||||
| If you would like to store the session state in a different way, you can subclass :class:`session.Storage`. | ||||
| 
 | ||||
| Some Python installations do not have the ``sqlite3`` module. | ||||
| In this case, attempting to use the default :class:`~session.SqliteSession` will fail. | ||||
| If this happens, you can try reinstalling Python. | ||||
| If you still don't have the ``sqlite3`` module, you should use a different storage. | ||||
							
								
								
									
										75
									
								
								client/doc/concepts/updates.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								client/doc/concepts/updates.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| Updates | ||||
| ======= | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| Updates are an important topic in a messaging platform like Telegram. | ||||
| After all, you want to be notified as soon as certain events happen, such as new message arrives. | ||||
| 
 | ||||
| Telethon abstracts away Telegram updates with :mod:`~telethon.events`. | ||||
| 
 | ||||
| .. important:: | ||||
| 
 | ||||
|     It is strongly advised to configure logging when working with events: | ||||
| 
 | ||||
|     .. code-block:: python | ||||
| 
 | ||||
|         import logging | ||||
|         logging.basicConfig( | ||||
|             format='[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s', | ||||
|             level=logging.WARNING | ||||
|         ) | ||||
| 
 | ||||
|     With the above, you will see all warnings and errors and when they happened. | ||||
| 
 | ||||
| 
 | ||||
| Filtering events | ||||
| ---------------- | ||||
| 
 | ||||
| There is no way to tell Telegram to only send certain updates. | ||||
| Telethon must be received and process all updates to ensure correct ordering. | ||||
| 
 | ||||
| Filters are not magic. | ||||
| They work all the same as ``if`` conditions inside your event handlers. | ||||
| However, they offer a more convenient and consistent way to check for certain conditions. | ||||
| 
 | ||||
| All built-in filters can be found in :mod:`telethon.events.filters`. | ||||
| 
 | ||||
| When registering an event handler, you can optionally define the filter to use. | ||||
| You can retrieve a handler's filter with :meth:`~Client.get_handler_filter`. | ||||
| You can set (and overwrite) a handler's filter with :meth:`~Client.set_handler_filter`. | ||||
| 
 | ||||
| Filters are meant to be fast and never raise exceptions. | ||||
| For this reason, filters cannot be asynchronous. | ||||
| This reduces the chance a filter will do slow IO and potentially fail. | ||||
| 
 | ||||
| A filter is simply a callable function that takes an event as input and returns a boolean. | ||||
| If the filter returns ``True``, the handler will be called. | ||||
| Using this knowledge, you can create custom filters too. | ||||
| If you need state, you can use a class with a ``__call__`` method defined: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     def only_odd_messages(event): | ||||
|         "A filter that only handles messages when their ID is divisible by 2" | ||||
|         return event.id % 2 == 0 | ||||
| 
 | ||||
|     client.add_event_handler(handler, events.NewMessage, only_odd_messages) | ||||
| 
 | ||||
|     # ... | ||||
| 
 | ||||
|     class OnlyDivisibleMessages: | ||||
|         "A filter that only handles messages when their ID is divisible by some amount" | ||||
|         def __init__(self, divisible_by): | ||||
|             self.divisible_by = divisible_by | ||||
| 
 | ||||
|         def __call__(self, event): | ||||
|             return event.id % self.divisible_by == 0 | ||||
| 
 | ||||
|     client.add_event_handler(handler, events.NewMessage, OnlyDivisibleMessages(7)) | ||||
| 
 | ||||
| Custom filters should accept any :class:`~events.Event`. | ||||
| You can use :func:`isinstance` if your filter can only deal with certain types of events. | ||||
| 
 | ||||
| If you need to perform asynchronous operations, you can't use a filter. | ||||
| Instead, manually check for those conditions inside your handler. | ||||
|  | @ -3,6 +3,11 @@ | |||
| # For the full list of built-in configuration values, see the documentation: | ||||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| 
 | ||||
| sys.path.insert(0, os.path.abspath(os.curdir))  # for custom extensions | ||||
| 
 | ||||
| # -- Project information ----------------------------------------------------- | ||||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information | ||||
| 
 | ||||
|  | @ -14,11 +19,21 @@ release = "2.0.0a0" | |||
| # -- General configuration --------------------------------------------------- | ||||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration | ||||
| 
 | ||||
| # extensions = [] | ||||
| 
 | ||||
| templates_path = ["_templates"] | ||||
| # exclude_patterns = [] | ||||
| extensions = [ | ||||
|     "sphinx.ext.autodoc", | ||||
|     "sphinx.ext.intersphinx", | ||||
|     "sphinx.ext.graphviz", | ||||
|     "roles.tl", | ||||
| ] | ||||
| 
 | ||||
| intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)} | ||||
| tl_ref_url = "https://tl.telethon.dev" | ||||
| autodoc_default_options = { | ||||
|     "members": True, | ||||
|     "undoc-members": True, | ||||
| } | ||||
| modindex_common_prefix = ["telethon."] | ||||
| graphviz_output_format = "svg" | ||||
| 
 | ||||
| # -- Options for HTML output ------------------------------------------------- | ||||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output | ||||
|  |  | |||
							
								
								
									
										8
									
								
								client/doc/developing/changelog.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								client/doc/developing/changelog.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| Changelog (Version History) | ||||
| =========================== | ||||
| 
 | ||||
| 
 | ||||
| v2 alpha | ||||
| -------- | ||||
| 
 | ||||
| WIP! | ||||
							
								
								
									
										17
									
								
								client/doc/developing/coding-style.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								client/doc/developing/coding-style.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| Coding style | ||||
| ============ | ||||
| 
 | ||||
| Knowledge of Python is a obviously a must to develop a Python library. | ||||
| A good online resource is `Dive Into Python 3 <http://www.diveintopython3.net/>`_. | ||||
| 
 | ||||
| Telethon uses multiple tools to automatically format the code and check for linting rules. | ||||
| This means you can simply ignore formatting and let the tools handle it for you. | ||||
| You can find these tools under the ``tools/`` folder. | ||||
| 
 | ||||
| The documentation is written with mostly a newline after every period. | ||||
| This is not a hard rule. | ||||
| Lines can be cut earlier if they become too long to be comfortable. | ||||
| 
 | ||||
| Commit messages should be short and descriptive. | ||||
| They should start with an action in the present ("Fix" and not "Fixed"). | ||||
| This saves a few characters and represents what the commit will "do" after applied. | ||||
							
								
								
									
										4
									
								
								client/doc/developing/migration-guide.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								client/doc/developing/migration-guide.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| Migrating from v1 to v2 | ||||
| ======================= | ||||
| 
 | ||||
| WIP! | ||||
							
								
								
									
										10
									
								
								client/doc/developing/philosophy.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								client/doc/developing/philosophy.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| Philosophy | ||||
| ========== | ||||
| 
 | ||||
| * Dependencies should only be added when absolutely necessary. | ||||
| * Dependencies written in anything other than Python cannot be mandatory. | ||||
| * The library must work correctly with no system dependencies other than Python 3. | ||||
| * Strict type-checking is required to pass everywhere in the library to make upgrades easier. | ||||
| * The code structure must make use of hard and clear boundaries to keep the different parts decoupled. | ||||
| * The API should cover only the most commonly used features to avoid bloat and reduce maintenance costs. | ||||
| * Documentation must be a pleasure to use and contain plenty of code examples. | ||||
							
								
								
									
										95
									
								
								client/doc/developing/project-structure.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								client/doc/developing/project-structure.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| Project Structure | ||||
| ================= | ||||
| 
 | ||||
| .. currentmodule:: telethon | ||||
| 
 | ||||
| The repository contains several folders, each with their own "package". | ||||
| 
 | ||||
| 
 | ||||
| benches/ | ||||
| -------- | ||||
| 
 | ||||
| This folder contains different benchmarks. | ||||
| Pretty straightforward. | ||||
| 
 | ||||
| 
 | ||||
| stubs/ | ||||
| ------ | ||||
| 
 | ||||
| If a dependency doesn't support typing, files here must work around that. | ||||
| 
 | ||||
| 
 | ||||
| tools/ | ||||
| ------ | ||||
| 
 | ||||
| Various utility scripts. | ||||
| Each script should have a "comment" at the top explaining what they are for. | ||||
| 
 | ||||
| See ``DEVELOPING.md`` in the repository root to learn how to use some of the tools. | ||||
| 
 | ||||
| 
 | ||||
| generator/ | ||||
| ---------- | ||||
| 
 | ||||
| A package that should not be published and is only used when developing the library. | ||||
| The implementation is private and exists under the ``src/*/_impl/`` folder. | ||||
| Only select parts are exported under public modules. | ||||
| Tests live under ``tests/``. | ||||
| 
 | ||||
| The implementation consists of a parser and a code generator. | ||||
| 
 | ||||
| The parser is able to read parse ``.tl`` files (Type-Language definition files). | ||||
| It doesn't do anything with the files other than to represent the content as Python objects. | ||||
| 
 | ||||
| The code generator uses the parsed definitions to generate Python code. | ||||
| Most of the code to serialize and deserialize objects lives under ``serde/``. | ||||
| 
 | ||||
| An in-memory "filesystem" structure is kept before writing all files to disk. | ||||
| This makes it possible to execute most of the process in a sans-io manner. | ||||
| Once the code generation finishes, all files are written to disk at once. | ||||
| 
 | ||||
| See ``DEVELOPING.md`` in the repository root to learn how to generate code. | ||||
| 
 | ||||
| 
 | ||||
| client/ | ||||
| ------- | ||||
| 
 | ||||
| The Telethon client library and documentation lives here. | ||||
| This is the package that gets published. | ||||
| The implementation is private and exists under the ``src/*/_impl/`` folder. | ||||
| Only select parts are exported under public modules. | ||||
| Tests live under ``tests/``. | ||||
| 
 | ||||
| The client implementation consists of several subpackages. | ||||
| 
 | ||||
| The ``tl`` package sits at the bottom. | ||||
| It is where the generated code is placed. | ||||
| It also contains some of the definitions needed for the generated code to work. | ||||
| Even though all the :term:`RPC` live here, this package can't do anything by itself. | ||||
| 
 | ||||
| The ``crypto`` package implements all the encryption and decryption rules used by Telegram. | ||||
| Details concerning the :term:`MTProto` are mostly avoided, so the package can be generally useful. | ||||
| 
 | ||||
| The ``mtproto`` package implements the logic required to talk to Telegram. | ||||
| It is implemented in a sans-io manner. | ||||
| This package is responsible for generating an authorization key and serializing packets. | ||||
| It also contains some optimizations which are not strictly necessary when implementing the library. | ||||
| 
 | ||||
| The ``mtsender`` package simply adds IO to ``mtproto``. | ||||
| It is responsible for driving the network, enqueuing requests, and waiting for results. | ||||
| 
 | ||||
| The ``session`` crate implements what's needed to manage the :term:`session` state. | ||||
| The logic to handle and correctly order updates also lives here, in a sans-io manner. | ||||
| 
 | ||||
| The ``client`` ties everything together. | ||||
| This is what defines the Pythonic API to interact with Telegram. | ||||
| Custom object and event types also live here. | ||||
| 
 | ||||
| Even though only common methods are implemented, the code is still huge. | ||||
| For this reason, the :class:`Client` implementation is separated from the class definition. | ||||
| The class definition only contains documentation and calls functions defined in other files. | ||||
| A tool under ``tools/`` exists to make it easy to keep these two in sync. | ||||
| 
 | ||||
| If you plan to port the library to a different language, good luck! | ||||
| You will need a code generator, the ``crypto``, ``mtproto`` and ``mtsender`` packages to have an initial working version. | ||||
| The tests are your friend, write them too! | ||||
|  | @ -1,15 +1,126 @@ | |||
| Telethon's documentation | ||||
| ======================== | ||||
| .. |svglogo| image:: ../../logo.svg | ||||
|     :width: 24pt | ||||
|     :height: 24pt | ||||
| 
 | ||||
| .. only:: html | ||||
| 
 | ||||
|     .. highlights:: |svglogo| **Welcome to Telethon's documentation!** | ||||
| 
 | ||||
| .. only:: not html | ||||
| 
 | ||||
|     .. highlights:: **Welcome to Telethon's documentation!** | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|     import asyncio | ||||
|     from telethon import Client, events | ||||
|     from telethon.events import filters | ||||
| 
 | ||||
|     async def main(): | ||||
|         async with Client('name', api_id, api_hash) as client: | ||||
|             me = await client.interactive_login() | ||||
|             await client.send_message(me, f'Hello, {me.full_name}!') | ||||
| 
 | ||||
|             @client.on(events.NewMessage, filters.Text(r'(?i)hello')) | ||||
|             async def handler(event): | ||||
|                 await event.reply('Hey!') | ||||
| 
 | ||||
|             await client.run_until_disconnected() | ||||
| 
 | ||||
|     asyncio.run(main()) | ||||
| 
 | ||||
| * Are you new here? Jump straight into :doc:`basic/installation`! | ||||
| * Looking for the Client API reference? See :doc:`modules/client`. | ||||
| * Did you upgrade the library? Please read :doc:`developing/changelog`. | ||||
| * Coming from Bot API or want to create new bots? See :doc:`concepts/botapi-vs-mtproto`. | ||||
| * Used Telethon before v2.0? See :doc:`developing/migration-guide`. | ||||
| * Want to hack away with the raw API? Search in `Telethon Raw API <https://tl.telethon.dev/>`_. | ||||
| 
 | ||||
| 
 | ||||
| Preface | ||||
| ======= | ||||
| 
 | ||||
| .. rubric:: What is this? | ||||
| 
 | ||||
| Telegram is a popular messaging application. | ||||
| This library is meant to make it easy for you to write Python programs that can interact with Telegram. | ||||
| Think of it as a wrapper that has already done the hard work for you, so you can focus on developing an application. | ||||
| 
 | ||||
| 
 | ||||
| .. rubric:: How should I use the documentation? | ||||
| 
 | ||||
| This documentation is divided in multiple sections. The first few sections are a guide, while others contain the API reference or a glossary of terms. | ||||
| The documentation assumes some familiarity with Python. | ||||
| 
 | ||||
| If you are getting started with the library, you should follow the documentation in order by pressing the "Next" button at the bottom-right of every page. | ||||
| 
 | ||||
| You can also use the menu on the left to quickly skip over sections if you're looking for something in particular or want to continue where you left off. | ||||
| 
 | ||||
| 
 | ||||
| First steps | ||||
| =========== | ||||
| 
 | ||||
| In this section you will learn how to install the library and login to your Telegram account. | ||||
| 
 | ||||
| :doc:`‣ Start reading Installation <basic/installation>` | ||||
| 
 | ||||
| .. toctree:: | ||||
|    :maxdepth: 2 | ||||
|    :caption: Contents: | ||||
|     :hidden: | ||||
|     :caption: First steps | ||||
| 
 | ||||
|     basic/installation | ||||
|     basic/signing-in | ||||
|     basic/next-steps | ||||
| 
 | ||||
| 
 | ||||
| API reference | ||||
| ============= | ||||
| 
 | ||||
| Indices and tables | ||||
| ================== | ||||
| This section contains all the functions and types offered by the library. | ||||
| 
 | ||||
| * :ref:`genindex` | ||||
| * :ref:`modindex` | ||||
| * :ref:`search` | ||||
| :doc:`‣ Start reading Client API <modules/client>` | ||||
| 
 | ||||
| .. toctree:: | ||||
|     :hidden: | ||||
|     :caption: API reference | ||||
| 
 | ||||
|     modules/client | ||||
|     modules/events | ||||
|     modules/types | ||||
|     modules/sessions | ||||
| 
 | ||||
| Concepts | ||||
| ======== | ||||
| 
 | ||||
| A more in-depth explanation of some of the concepts and words used in Telethon. | ||||
| 
 | ||||
| :doc:`‣ Start reading Chat concept <concepts/chats>` | ||||
| 
 | ||||
| .. toctree:: | ||||
|     :hidden: | ||||
|     :caption: Concepts | ||||
| 
 | ||||
|     concepts/chats | ||||
|     concepts/updates | ||||
|     concepts/sessions | ||||
|     concepts/errors | ||||
|     concepts/botapi-vs-mtproto | ||||
|     concepts/full-api | ||||
|     concepts/glossary | ||||
| 
 | ||||
| Developing | ||||
| ========== | ||||
| 
 | ||||
| Tips and tricks to develop both with the library and for the library. | ||||
| 
 | ||||
| :doc:`‣ Start reading Changelog <developing/changelog>` | ||||
| 
 | ||||
| .. toctree:: | ||||
|     :hidden: | ||||
|     :caption: Developing | ||||
| 
 | ||||
|     developing/changelog | ||||
|     developing/migration-guide | ||||
|     developing/philosophy.rst | ||||
|     developing/coding-style.rst | ||||
|     developing/project-structure.rst | ||||
|  |  | |||
							
								
								
									
										4
									
								
								client/doc/modules/client.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								client/doc/modules/client.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| Client | ||||
| ====== | ||||
| 
 | ||||
| .. autoclass:: telethon.Client | ||||
							
								
								
									
										12
									
								
								client/doc/modules/events.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								client/doc/modules/events.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| Events and filters | ||||
| ================== | ||||
| 
 | ||||
| Events | ||||
| ------ | ||||
| 
 | ||||
| .. automodule:: telethon.events | ||||
| 
 | ||||
| Filters | ||||
| ------- | ||||
| 
 | ||||
| .. automodule:: telethon.events.filters | ||||
							
								
								
									
										4
									
								
								client/doc/modules/sessions.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								client/doc/modules/sessions.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| Session storages | ||||
| ================ | ||||
| 
 | ||||
| .. automodule:: telethon.session | ||||
							
								
								
									
										6
									
								
								client/doc/modules/types.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								client/doc/modules/types.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| Types | ||||
| ===== | ||||
| 
 | ||||
| .. automodule:: telethon.types | ||||
| 
 | ||||
| .. autoclass:: telethon.RpcError | ||||
							
								
								
									
										34
									
								
								client/doc/roles/tl.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								client/doc/roles/tl.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| from docutils import nodes, utils | ||||
| from docutils.parsers.rst.roles import set_classes | ||||
| 
 | ||||
| 
 | ||||
| def make_link_node(rawtext, app, name, options): | ||||
|     try: | ||||
|         base = app.config.tl_ref_url | ||||
|         if not base: | ||||
|             raise AttributeError | ||||
|     except AttributeError as e: | ||||
|         raise ValueError("tl_ref_url config value is not set") from e | ||||
| 
 | ||||
|     if base[-1] != "/": | ||||
|         base += "/" | ||||
| 
 | ||||
|     set_classes(options) | ||||
|     node = nodes.reference( | ||||
|         rawtext, utils.unescape(name), refuri="{}?q={}".format(base, name), **options | ||||
|     ) | ||||
|     return node | ||||
| 
 | ||||
| 
 | ||||
| def tl_role(name, rawtext, text, lineno, inliner, options=None, content=None): | ||||
|     if options is None: | ||||
|         options = {} | ||||
| 
 | ||||
|     app = inliner.document.settings.env.app | ||||
|     node = make_link_node(rawtext, app, text, options) | ||||
|     return [node], [] | ||||
| 
 | ||||
| 
 | ||||
| def setup(app): | ||||
|     app.add_role("tl", tl_role) | ||||
|     app.add_config_value("tl_ref_url", None, "env") | ||||
|  | @ -28,9 +28,16 @@ dynamic = ["version"] | |||
| [project.optional-dependencies] | ||||
| cryptg = ["cryptg~=0.4"] | ||||
| dev = [ | ||||
|   "isort~=5.12", | ||||
|   "black~=23.3.0", | ||||
|   "mypy~=1.3", | ||||
|   "pytest~=7.3", | ||||
|   "pytest-asyncio~=0.21", | ||||
| ] | ||||
| doc = [ | ||||
|   "sphinx_rtd_theme~=1.2", | ||||
|   "types-docutils~=0.20", | ||||
| ] | ||||
| 
 | ||||
| [project.urls] | ||||
| "Homepage" = "https://telethon.dev/" | ||||
|  | @ -43,4 +50,4 @@ requires = ["setuptools>=61.0"] | |||
| build-backend = "setuptools.build_meta" | ||||
| 
 | ||||
| [tool.setuptools.dynamic] | ||||
| version = {attr = "telethon.__version__"} | ||||
| version = {attr = "telethon.version.__version__"} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user