Revisit documentation, cross-references and unnecessary indents

This commit is contained in:
Lonami Exo 2018-06-20 11:05:33 +02:00
parent 1b7e7320a4
commit c85ba4accc
20 changed files with 651 additions and 522 deletions

View File

@ -11,11 +11,11 @@ Accessing the Full API
reason not to, like a method not existing or you wanting more control. reason not to, like a method not existing or you wanting more control.
The `telethon.telegram_client.TelegramClient` doesn't offer a method for every The :ref:`TelegramClient <telethon-client>` doesn't offer a method for
single request the Telegram API supports. However, it's very simple to *call* every single request the Telegram API supports. However, it's very simple to
or *invoke* any request. Whenever you need something, don't forget to `check *call* or *invoke* any request. Whenever you need something, don't forget to
the documentation`__ and look for the `method you need`__. There you can go `check the documentation`__ and look for the `method you need`__. There you
through a sorted list of everything you can do. can go through a sorted list of everything you can do.
.. note:: .. note::
@ -30,7 +30,8 @@ You should also refer to the documentation to see what the objects
(constructors) Telegram returns look like. Every constructor inherits (constructors) Telegram returns look like. Every constructor inherits
from a common type, and that's the reason for this distinction. from a common type, and that's the reason for this distinction.
Say `telethon.telegram_client.TelegramClient.send_message` didn't exist, Say `client.send_message
<telethon.client.messages.MessageMethods.send_message>` didn't exist,
we could use the `search`__ to look for "message". There we would find we could use the `search`__ to look for "message". There we would find
:tl:`SendMessageRequest`, which we can work with. :tl:`SendMessageRequest`, which we can work with.
@ -63,7 +64,8 @@ construct one, for instance:
peer = InputPeerUser(user_id, user_hash) peer = InputPeerUser(user_id, user_hash)
Or we call `telethon.telegram_client.TelegramClient.get_input_entity()`: Or we call `client.get_input_entity
<telethon.client.users.UserMethods.get_input_entity>`:
.. code-block:: python .. code-block:: python
@ -71,10 +73,11 @@ Or we call `telethon.telegram_client.TelegramClient.get_input_entity()`:
When you're going to invoke an API method, most require you to pass an When you're going to invoke an API method, most require you to pass an
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using :tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
``.get_input_entity()`` is more straightforward (and often `client.get_input_entity <telethon.client.users.UserMethods.get_input_entity>`
immediate, if you've seen the user before, know their ID, etc.). is more straightforward (and often immediate, if you've seen the user before,
If you also need to have information about the whole user, use know their ID, etc.). If you also **need** to have information about the whole
`telethon.telegram_client.TelegramClient.get_entity()` instead: user, use `client.get_entity <telethon.client.users.UserMethods.get_entity>`
instead:
.. code-block:: python .. code-block:: python
@ -94,12 +97,15 @@ every time its used, simply call `telethon.utils.get_input_peer`:
.. note:: .. note::
Since ``v0.16.2`` this is further simplified. The ``Request`` itself Since ``v0.16.2`` this is further simplified. The ``Request`` itself
will call ``client.get_input_entity()`` for you when required, but will call `client.get_input_entity <
it's good to remember what's happening. telethon.client.users.UserMethods.get_input_entity>` for you when required,
but it's good to remember what's happening.
After this small parenthesis about ``.get_entity`` versus After this small parenthesis about `client.get_entity
``.get_input_entity``, we have everything we need. To ``.invoke()`` our <telethon.client.users.UserMethods.get_entity>` versus
`client.get_input_entity <telethon.client.users.UserMethods.get_input_entity>`,
we have everything we need. To invoke our
request we do: request we do:
.. code-block:: python .. code-block:: python

View File

@ -4,7 +4,8 @@
Session Files Session Files
============== ==============
The first parameter you pass to the constructor of the ``TelegramClient`` is The first parameter you pass to the constructor of the
:ref:`TelegramClient <telethon-client>` is
the ``session``, and defaults to be the session name (or full path). That is, the ``session``, and defaults to be the session name (or full path). That is,
if you create a ``TelegramClient('anon')`` instance and connect, an if you create a ``TelegramClient('anon')`` instance and connect, an
``anon.session`` file will be created in the working directory. ``anon.session`` file will be created in the working directory.
@ -42,7 +43,8 @@ If you don't want to use the default SQLite session storage, you can also use
one of the other implementations or implement your own storage. one of the other implementations or implement your own storage.
To use a custom session storage, simply pass the custom session instance to To use a custom session storage, simply pass the custom session instance to
``TelegramClient`` instead of the session name. :ref:`TelegramClient <telethon-client>` instead of
the session name.
Telethon contains two implementations of the abstract ``Session`` class: Telethon contains two implementations of the abstract ``Session`` class:

View File

@ -46,17 +46,35 @@ your disk. This is by default a database file using Python's ``sqlite3``.
creates the file in your working directory, but absolute paths work too. creates the file in your working directory, but absolute paths work too.
.. important::
The process shown here shows how to sign in *manually*. You **should**
use `client.start() <telethon.client.auth.AuthMethods.start>` instead
unless you have a better reason not to (e.g. you need more control):
.. code-block:: python
client.start()
This is explained after going through the manual process.
Before using the client, you must be connected to Telegram. Before using the client, you must be connected to Telegram.
Doing so is very easy: Doing so is very easy:
``client.connect() # Must return True, otherwise, try again`` .. code-block:: python
client.connect() # Must return True, otherwise, try again
You may or may not be authorized yet. You must be authorized You may or may not be authorized yet. You must be authorized
before you're able to send any request: before you're able to send any request:
``client.is_user_authorized() # Returns True if you can send requests`` .. code-block:: python
If you're not authorized, you need to ``.sign_in()``: client.is_user_authorized() # Returns True if you can send requests
If you're not authorized, you need to `.sign_in
<telethon.client.auth.AuthMethods.sign_in>`:
.. code-block:: python .. code-block:: python
@ -91,7 +109,8 @@ As a full example:
me = client.sign_in(phone_number, input('Enter code: ')) me = client.sign_in(phone_number, input('Enter code: '))
All of this, however, can be done through a call to ``.start()``: All of this, however, can be done through a call to `.start()
<telethon.client.auth.AuthMethods.start>`:
.. code-block:: python .. code-block:: python
@ -99,7 +118,8 @@ All of this, however, can be done through a call to ``.start()``:
client.start() client.start()
The code shown is just what ``.start()`` will be doing behind the scenes The code shown is just what `.start()
<telethon.client.auth.AuthMethods.start>` will be doing behind the scenes
(with a few extra checks), so that you know how to sign in case you want (with a few extra checks), so that you know how to sign in case you want
to avoid using ``input()`` (the default) for whatever reason. If no phone to avoid using ``input()`` (the default) for whatever reason. If no phone
or bot token is provided, you will be asked one through ``input()``. The or bot token is provided, you will be asked one through ``input()``. The
@ -108,13 +128,15 @@ method also accepts a ``phone=`` and ``bot_token`` parameters.
You can use either, as both will work. Determining which You can use either, as both will work. Determining which
is just a matter of taste, and how much control you need. is just a matter of taste, and how much control you need.
Remember that you can get yourself at any time with ``client.get_me()``. Remember that you can get yourself at any time with `client.get_me()
<telethon.client.users.UserMethods.get_me>`.
.. warning:: .. warning::
Please note that if you fail to login around 5 times (or change the first Please note that if you fail to login around 5 times (or change the first
parameter of the ``TelegramClient``, which is the session name) you will parameter of the :ref:`TelegramClient <telethon-client>`, which is the session
receive a ``FloodWaitError`` of around 22 hours, so be careful not to mess name) you will receive a ``FloodWaitError`` of around 22 hours, so be
this up! This shouldn't happen if you're doing things as explained, though. careful not to mess this up! This shouldn't happen if you're doing things
as explained, though.
.. note:: .. note::
If you want to use a **proxy**, you have to `install PySocks`__ If you want to use a **proxy**, you have to `install PySocks`__
@ -137,9 +159,10 @@ Two Factor Authorization (2FA)
****************************** ******************************
If you have Two Factor Authorization (from now on, 2FA) enabled on your If you have Two Factor Authorization (from now on, 2FA) enabled on your
account, calling :meth:`telethon.TelegramClient.sign_in` will raise a account, calling `.sign_in()
``SessionPasswordNeededError``. When this happens, just <telethon.client.auth.AuthMethods.sign_in>` will raise a
:meth:`telethon.TelegramClient.sign_in` again with a ``password=``: ``SessionPasswordNeededError``. When this happens, just use the method
again with a ``password=``:
.. code-block:: python .. code-block:: python
@ -153,15 +176,19 @@ account, calling :meth:`telethon.TelegramClient.sign_in` will raise a
client.sign_in(password=getpass.getpass()) client.sign_in(password=getpass.getpass())
The mentioned ``.start()`` method will handle this for you as well, but The mentioned `.start()
you must set the ``password=`` parameter beforehand (it won't be asked). <telethon.client.auth.AuthMethods.start>` method will handle this for you as
well, but you must set the ``password=`` parameter beforehand (it won't be
asked).
If you don't have 2FA enabled, but you would like to do so through the
library, use `client.edit_2fa()
<telethon.client.auth.AuthMethods.edit_2fa>`.
If you don't have 2FA enabled, but you would like to do so through the library,
use ``client.edit_2fa()``.
Be sure to know what you're doing when using this function and Be sure to know what you're doing when using this function and
you won't run into any problems. you won't run into any problems. Take note that if you want to
Take note that if you want to set only the email/hint and leave set only the email/hint and leave the current password unchanged,
the current password unchanged, you need to "redo" the 2fa. you need to "redo" the 2fa.
See the examples below: See the examples below:

View File

@ -22,9 +22,9 @@ in response to certain methods, such as :tl:`GetUsersRequest`.
To "encounter" an ID, you would have to "find it" like you would in the To "encounter" an ID, you would have to "find it" like you would in the
normal app. If the peer is in your dialogs, you would need to normal app. If the peer is in your dialogs, you would need to
`client.get_dialogs() <telethon.telegram_client.TelegramClient.get_dialogs>`. `client.get_dialogs() <telethon.client.dialogs.DialogMethods.get_dialogs>`.
If the peer is someone in a group, you would similarly If the peer is someone in a group, you would similarly
`client.get_participants(group) <telethon.telegram_client.TelegramClient.get_participants>`. `client.get_participants(group) <telethon.client.chats.ChatMethods.get_participants>`.
Once you have encountered an ID, the library will (by default) have saved Once you have encountered an ID, the library will (by default) have saved
their ``access_hash`` for you, which is needed to invoke most methods. their ``access_hash`` for you, which is needed to invoke most methods.
@ -69,9 +69,11 @@ you're able to just do this:
my_channel = client.get_entity(PeerChannel(some_id)) my_channel = client.get_entity(PeerChannel(some_id))
All methods in the :ref:`telegram-client` call ``.get_input_entity()`` prior All methods in the :ref:`telegram-client` call `.get_input_entity()
<telethon.client.users.UserMethods.get_input_entity>` prior
to sending the requst to save you from the hassle of doing so manually. to sending the requst to save you from the hassle of doing so manually.
That way, convenience calls such as ``client.send_message('lonami', 'hi!')`` That way, convenience calls such as `client.send_message('lonami', 'hi!')
<telethon.client.messages.MessageMethods.send_message>`
become possible. become possible.
Every entity the library encounters (in any response to any call) will by Every entity the library encounters (in any response to any call) will by
@ -88,8 +90,10 @@ Entities vs. Input Entities
Don't worry if you don't understand this section, just remember some Don't worry if you don't understand this section, just remember some
of the details listed here are important. When you're calling a method, of the details listed here are important. When you're calling a method,
don't call ``.get_entity()`` beforehand, just use the username or phone, don't call `client.get_entity() <telethon.client.users.UserMethods.get_entity>`
or the entity retrieved by other means like ``.get_dialogs()``. beforehand, just use the username or phone, or the entity retrieved by
other means like `client.get_dialogs()
<telethon.client.dialogs.DialogMethods.get_dialogs>`.
On top of the normal types, the API also make use of what they call their On top of the normal types, the API also make use of what they call their
@ -108,21 +112,27 @@ before you can "use them".
As we just mentioned, API calls don't need to know the whole information As we just mentioned, API calls don't need to know the whole information
about the entities, only their ID and hash. For this reason, another method, about the entities, only their ID and hash. For this reason, another method,
``.get_input_entity()`` is available. This will always use the cache while `client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
possible, making zero API calls most of the time. When a request is made, is available. This will always use the cache while possible, making zero API
if you provided the full entity, e.g. an :tl:`User`, the library will convert calls most of the time. When a request is made, if you provided the full
it to the required :tl:`InputPeer` automatically for you. entity, e.g. an :tl:`User`, the library will convert it to the required
:tl:`InputPeer` automatically for you.
**You should always favour** ``.get_input_entity()`` **over** ``.get_entity()`` **You should always favour**
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
**over**
`client.get_entity() <telethon.client.users.UserMethods.get_entity>`
for this reason! Calling the latter will always make an API call to get for this reason! Calling the latter will always make an API call to get
the most recent information about said entity, but invoking requests don't the most recent information about said entity, but invoking requests don't
need this information, just the ``InputPeer``. Only use ``.get_entity()`` need this information, just the :tl:`InputPeer`. Only use
`client.get_entity() <telethon.client.users.UserMethods.get_entity>`
if you need to get actual information, like the username, name, title, etc. if you need to get actual information, like the username, name, title, etc.
of the entity. of the entity.
To further simplify the workflow, since the version ``0.16.2`` of the To further simplify the workflow, since the version ``0.16.2`` of the
library, the raw requests you make to the API are also able to call library, the raw requests you make to the API are also able to call
``.get_input_entity`` wherever needed, so you can even do things like: `client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
wherever needed, so you can even do things like:
.. code-block:: python .. code-block:: python

View File

@ -9,7 +9,9 @@ Getting Started
Simple Installation Simple Installation
******************* *******************
``pip3 install telethon`` .. code-block:: sh
pip3 install telethon
**More details**: :ref:`installation` **More details**: :ref:`installation`

View File

@ -10,14 +10,18 @@ Automatic Installation
To install Telethon, simply do: To install Telethon, simply do:
``pip3 install telethon`` .. code-block:: sh
pip3 install telethon
Needless to say, you must have Python 3 and PyPi installed in your system. Needless to say, you must have Python 3 and PyPi installed in your system.
See https://python.org and https://pypi.python.org/pypi/pip for more. See https://python.org and https://pypi.python.org/pypi/pip for more.
If you already have the library installed, upgrade with: If you already have the library installed, upgrade with:
``pip3 install --upgrade telethon`` .. code-block:: sh
pip3 install --upgrade telethon
You can also install the library directly from GitHub or a fork: You can also install the library directly from GitHub or a fork:
@ -38,7 +42,9 @@ which can be really slow when uploading or downloading files. If you don't
mind using a C extension, install `cryptg <https://github.com/Lonami/cryptg>`__ mind using a C extension, install `cryptg <https://github.com/Lonami/cryptg>`__
via ``pip`` or as an extra: via ``pip`` or as an extra:
``pip3 install telethon[cryptg]`` .. code-block:: sh
pip3 install telethon[cryptg]
Manual Installation Manual Installation
@ -47,14 +53,27 @@ Manual Installation
1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and 1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and
``rsa`` (`GitHub`__ | `PyPi`__) modules: ``rsa`` (`GitHub`__ | `PyPi`__) modules:
``sudo -H pip3 install pyaes rsa`` .. code-block:: sh
pip3 install pyaes rsa
2. Clone Telethon's GitHub repository: 2. Clone Telethon's GitHub repository:
``git clone https://github.com/LonamiWebs/Telethon.git``
3. Enter the cloned repository: ``cd Telethon`` .. code-block:: sh
4. Run the code generator: ``python3 setup.py gen tl errors`` git clone https://github.com/LonamiWebs/Telethon.git
3. Enter the cloned repository:
.. code-block:: sh
cd Telethon
4. Run the code generator:
.. code-block:: sh
python3 setup.py gen
5. Done! 5. Done!

View File

@ -15,9 +15,9 @@ Introduction
available methods are in the :ref:`telethon-client` reference, including available methods are in the :ref:`telethon-client` reference, including
detailed descriptions to what they do. detailed descriptions to what they do.
The ``TelegramClient`` is the central class of the library, the one The :ref:`TelegramClient <telethon-client>` is the
you will be using most of the time. For this reason, it's important central class of the library, the one you will be using most of the time. For
to know what it offers. this reason, it's important to know what it offers.
Since we're working with Python, one must not forget that we can do Since we're working with Python, one must not forget that we can do
``help(client)`` or ``help(TelegramClient)`` at any time for a more ``help(client)`` or ``help(TelegramClient)`` at any time for a more
@ -27,12 +27,14 @@ methods for any object, even yours!
Interacting with the Telegram API is done through sending **requests**, Interacting with the Telegram API is done through sending **requests**,
this is, any "method" listed on the API. There are a few methods (and this is, any "method" listed on the API. There are a few methods (and
growing!) on the ``TelegramClient`` class that abstract you from the growing!) on the :ref:`TelegramClient <telethon-client>` class that abstract
need of manually importing the requests you need. you from the need of manually importing the requests you need.
For instance, retrieving your own user can be done in a single line: For instance, retrieving your own user can be done in a single line:
``myself = client.get_me()`` .. code-block:: python
myself = client.get_me()
Internally, this method has sent a request to Telegram, who replied with Internally, this method has sent a request to Telegram, who replied with
the information about your own user, and then the desired information the information about your own user, and then the desired information
@ -91,9 +93,9 @@ Available methods
***************** *****************
The :ref:`reference <telethon-package>` lists all the "handy" methods The :ref:`reference <telethon-package>` lists all the "handy" methods
available for you to use in the ``TelegramClient`` class. These are simply available for you to use in the :ref:`TelegramClient <telethon-client>` class.
wrappers around the "raw" Telegram API, making it much more manageable and These are simply wrappers around the "raw" Telegram API, making it much more
easier to work with. manageable and easier to work with.
Please refer to :ref:`accessing-the-full-api` if these aren't enough, Please refer to :ref:`accessing-the-full-api` if these aren't enough,
and don't be afraid to read the source code of the InteractiveTelegramClient_ and don't be afraid to read the source code of the InteractiveTelegramClient_

View File

@ -5,21 +5,27 @@ Working with Updates
==================== ====================
The library comes with the :mod:`events` module. *Events* are an abstraction The library comes with the `telethon.events` module. *Events* are an abstraction
over what Telegram calls `updates`__, and are meant to ease simple and common over what Telegram calls `updates`__, and are meant to ease simple and common
usage when dealing with them, since there are many updates. If you're looking usage when dealing with them, since there are many updates. If you're looking
for the method reference, check :ref:`telethon-events-package`, otherwise, for the method reference, check :ref:`telethon-events-package`, otherwise,
let's dive in! let's dive in!
.. note:: .. important::
The library logs by default no output, and any exception that occurs The library logs by default no output, and any exception that occurs
inside your handlers will be "hidden" from you to prevent the thread inside your handlers will be "hidden" from you to prevent the thread
from terminating (so it can still deliver events). You should enable from terminating (so it can still deliver events). You should enable
logging (``import logging; logging.basicConfig(level=logging.ERROR)``) logging when working with events, at least the error level, to see if
when working with events, at least the error level, to see if this is this is happening so you can debug the error.
happening so you can debug the error.
**When using updates, please enable logging:**
.. code-block:: python
import logging
logging.basicConfig(level=logging.ERROR)
.. contents:: .. contents::
@ -62,7 +68,8 @@ Nothing we don't know already.
This Python decorator will attach itself to the ``my_event_handler`` This Python decorator will attach itself to the ``my_event_handler``
definition, and basically means that *on* a ``NewMessage`` *event*, definition, and basically means that *on* a `NewMessage
<telethon.events.newmessage.NewMessage>` *event*,
the callback function you're about to define will be called: the callback function you're about to define will be called:
.. code-block:: python .. code-block:: python
@ -72,8 +79,10 @@ the callback function you're about to define will be called:
event.reply('hi!') event.reply('hi!')
If a ``NewMessage`` event occurs, and ``'hello'`` is in the text of the If a `NewMessage
message, we ``reply`` to the event with a ``'hi!'`` message. <telethon.events.newmessage.NewMessage>` event occurs,
and ``'hello'`` is in the text of the message, we ``reply`` to the event
with a ``'hi!'`` message.
.. code-block:: python .. code-block:: python
@ -88,10 +97,11 @@ do other things instead idling. For this refer to :ref:`update-modes`.
More on events More on events
************** **************
The ``NewMessage`` event has much more than what was shown. You can access The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
the ``.sender`` of the message through that member, or even see if the message more than what was shown. You can access the ``.sender`` of the message
had ``.media``, a ``.photo`` or a ``.document`` (which you could download with through that member, or even see if the message had ``.media``, a ``.photo``
for example ``client.download_media(event.photo)``. or a ``.document`` (which you could download with for example
`client.download_media(event.photo) <telethon.client.downloads.DownloadMethods.download_media>`.
If you don't want to ``.reply`` as a reply, you can use the ``.respond()`` If you don't want to ``.reply`` as a reply, you can use the ``.respond()``
method instead. Of course, there are more events such as ``ChatAction`` or method instead. Of course, there are more events such as ``ChatAction`` or
@ -102,8 +112,9 @@ instance, ``NewMessage.Event``), except for the ``Raw`` event which just
passes the ``Update`` object. passes the ``Update`` object.
Note that ``.reply()`` and ``.respond()`` are just wrappers around the Note that ``.reply()`` and ``.respond()`` are just wrappers around the
``client.send_message()`` method which supports the ``file=`` parameter. `client.send_message() <telethon.client.messages.MessageMethods.send_message>`
This means you can reply with a photo if you do ``client.reply(file=photo)``. method which supports the ``file=`` parameter.
This means you can reply with a photo if you do ``event.reply(file=photo)``.
You can put the same event on many handlers, and even different events on You can put the same event on many handlers, and even different events on
the same handler. You can also have a handler work on only specific chats, the same handler. You can also have a handler work on only specific chats,
@ -143,15 +154,20 @@ solution. Try it!
Events without decorators Events without decorators
************************* *************************
If for any reason you can't use the ``@client.on`` syntax, don't worry. If for any reason you can't use the `@client.on
You can call ``client.add_event_handler(callback, event)`` to achieve <telethon.client.updates.UpdateMethods.on>` syntax, don't worry.
You can call `client.add_event_handler(callback, event)
<telethon.client.updates.UpdateMethods.add_event_handler>` to achieve
the same effect. the same effect.
Similar to that method, you also have :meth:`client.remove_event_handler` Similarly, you also have `client.remove_event_handler
and :meth:`client.list_event_handlers` which do as they names indicate. <telethon.client.updates.UpdateMethods.remove_event_handler>`
and `client.list_event_handlers
<telethon.client.updates.UpdateMethods.list_event_handlers>`.
The ``event`` type is optional in all methods and defaults to ``events.Raw`` The ``event`` type is optional in all methods and defaults to
for adding, and ``None`` when removing (so all callbacks would be removed). `events.Raw <telethon.events.raw.Raw>` for adding, and ``None`` when
removing (so all callbacks would be removed).
Stopping propagation of Updates Stopping propagation of Updates
@ -159,8 +175,8 @@ Stopping propagation of Updates
There might be cases when an event handler is supposed to be used solitary and There might be cases when an event handler is supposed to be used solitary and
it makes no sense to process any other handlers in the chain. For this case, it makes no sense to process any other handlers in the chain. For this case,
it is possible to raise a ``StopPropagation`` exception which will cause the it is possible to raise a `telethon.events.StopPropagation` exception which
propagation of the update through your handlers to stop: will cause the propagation of the update through your handlers to stop:
.. code-block:: python .. code-block:: python

View File

@ -12,27 +12,32 @@ that servers as a nice interface with the most commonly used methods on
Telegram such as sending messages, retrieving the message history, Telegram such as sending messages, retrieving the message history,
handling updates, etc. handling updates, etc.
The ``TelegramClient`` inherits the ``TelegramBareClient``. The later is The ``TelegramClient`` inherits from several mixing ``Method`` classes,
basically a pruned version of the ``TelegramClient``, which knows basic since there are so many methods that having them in a single file would
stuff like ``.invoke()``\ 'ing requests, downloading files, or switching make maintenance painful (it was three thousand lines before this separation
between data centers. This is primary to keep the method count per class happened!). It's a "god object", but there is only a way to interact with
and file low and manageable. Telegram really.
Both clients make use of the ``network/mtproto_sender.py``. The The ``TelegramBaseClient`` is an ABC which will support all of these mixins
``MtProtoSender`` class handles packing requests with the ``salt``, so they can work together nicely. It doesn't even know how to invoke things
``id``, ``sequence``, etc., and also handles how to process responses because they need to be resolved with user information first (to work with
(i.e. pong, RPC errors). This class communicates through Telegram via input entities comfortably).
its ``.connection`` member.
The ``Connection`` class uses a ``extensions/tcp_client``, a C#-like The client makes use of the ``network/mtprotosender.py``. The
``TcpClient`` to ease working with sockets in Python. All the ``MTProtoSender`` is responsible for connecting, reconnecting,
packing, unpacking, sending and receiving items from the network.
Basically, the low-level communication with Telegram, and handling
MTProto-related functions and types such as ``BadSalt``.
The sender makes use of a ``Connection`` class which knows the format in
which outgoing messages should be sent (how to encode their length and
their body, if they're further encrypted).
For now, all connection modes make use of the ``extensions/tcpclient``,
a C#-like ``TcpClient`` to ease working with sockets in Python. All the
``TcpClient`` know is how to connect through TCP and writing/reading ``TcpClient`` know is how to connect through TCP and writing/reading
from the socket with optional cancel. from the socket with optional cancel.
The ``Connection`` class bundles up all the connections modes and sends
and receives the messages accordingly (TCP full, obfuscated,
intermediate…).
Auto-generated code Auto-generated code
******************* *******************

View File

@ -8,7 +8,7 @@ be kind and don't forget to mention it helped you!
You should start by reading the source code on the `first You should start by reading the source code on the `first
release <https://github.com/LonamiWebs/Telethon/releases/tag/v0.1>`__ of release <https://github.com/LonamiWebs/Telethon/releases/tag/v0.1>`__ of
the project, and start creating a ``MtProtoSender``. Once this is made, the project, and start creating a ``MTProtoSender``. Once this is made,
you should write by hand the code to authenticate on the Telegram's you should write by hand the code to authenticate on the Telegram's
server, which are some steps required to get the key required to talk to server, which are some steps required to get the key required to talk to
them. Save it somewhere! Then, simply mimic, or reinvent other parts of them. Save it somewhere! Then, simply mimic, or reinvent other parts of

View File

@ -31,7 +31,16 @@ class UpdateMethods(UserMethods):
def on(self, event): def on(self, event):
""" """
Decorator helper method around add_event_handler(). Decorator helper method around `add_event_handler`. Example:
>>> from telethon import TelegramClient, events
>>> client = TelegramClient(...)
>>>
>>> @client.on(events.NewMessage)
... async def handler(event):
... ...
...
>>>
Args: Args:
event (`_EventBuilder` | `type`): event (`_EventBuilder` | `type`):

View File

@ -82,7 +82,29 @@ class EventBuilder(abc.ABC):
class EventCommon(abc.ABC): class EventCommon(abc.ABC):
"""Intermediate class with common things to all events""" """
Intermediate class with common things to all events.
Attributes:
pattern_match (`obj`):
The resulting object from calling the passed ``pattern`` function.
Here's an example using a string (defaults to regex match):
>>> from telethon import TelegramClient, events
>>> client = TelegramClient(...)
>>>
>>> @client.on(events.NewMessage(pattern=r'hi (\w+)!'))
... def handler(event):
... # In this case, the result is a ``Match`` object
... # since the ``str`` pattern was converted into
... # the ``re.compile(pattern).match`` function.
... print('Welcomed', event.pattern_match.group(1))
...
>>>
original_update (:tl:`Update`):
The original Telegram update object that caused this event.
"""
_event_name = 'Event' _event_name = 'Event'
def __init__(self, chat_peer=None, msg_id=None, broadcast=False): def __init__(self, chat_peer=None, msg_id=None, broadcast=False):
@ -146,6 +168,9 @@ class EventCommon(abc.ABC):
@property @property
def client(self): def client(self):
"""
The `telethon.TelegramClient` that created this event.
"""
return self._client return self._client
@property @property

View File

@ -177,6 +177,12 @@ class Message:
@property @property
async def chat(self): async def chat(self):
"""
The (:tl:`User` | :tl:`Chat` | :tl:`Channel`, optional) on which
the event occurred. This property may make an API call the first time
to get the most up to date version of the chat (mostly when the event
doesn't belong to a channel), so keep that in mind.
"""
if self._chat is None: if self._chat is None:
try: try:
self._chat =\ self._chat =\