Several documentation enhancements and build warnings fixes

- Made the documentation even more friendly towards newbies.
- Eased the usage of methods like get history which now set
  a default empty message for message actions and vice versa.
- Fixed some docstring documentations too.
- Updated the old normal docs/ to link back and forth RTD.
- Fixed the version of the documentation, now auto-loaded.
This commit is contained in:
Lonami Exo 2018-01-20 11:47:17 +01:00
parent 4d4e81e609
commit b716c4fe67
18 changed files with 180 additions and 141 deletions

View File

@ -44,8 +44,15 @@
page aims to provide easy access to all the available methods, their page aims to provide easy access to all the available methods, their
definition and parameters.</p> definition and parameters.</p>
<p>Although this documentation was generated for <i>Telethon</i>, it may <p>Please note that when you see this:</p>
be useful for any other Telegram library out there.</p> <pre>---functions---
users.getUsers#0d91a548 id:Vector&lt;InputUser&gt; = Vector&lt;User&gt;</pre>
<p>This is <b>not</b> Python code. It's the "TL definition". It's
an easy-to-read line that gives a quick overview on the parameters
and its result. You don't need to worry about this. See
<a href="http://telethon.readthedocs.io/en/latest/extra/developing/understanding-the-type-language.html">here</a>
for more details on it.</p>
<h3>Index</h3> <h3>Index</h3>
<ul> <ul>
@ -69,12 +76,12 @@
<p>Currently there are <b>{method_count} methods</b> available for the layer <p>Currently there are <b>{method_count} methods</b> available for the layer
{layer}. The complete list can be seen <a href="methods/index.html">here</a>. {layer}. The complete list can be seen <a href="methods/index.html">here</a>.
<br /><br /> <br /><br />
Methods, also known as <i>requests</i>, are used to interact with Methods, also known as <i>requests</i>, are used to interact with the
the Telegram API itself and are invoked with a call to <code>.invoke()</code>. Telegram API itself and are invoked through <code>client(Request(...))</code>.
<b>Only these</b> can be passed to <code>.invoke()</code>! You cannot <b>Only these</b> can be used like that! You cannot invoke types or
<code>.invoke()</code> types or constructors, only requests. After this, constructors, only requests. After this, Telegram will return a
Telegram will return a <code>result</code>, which may be, for instance, <code>result</code>, which may be, for instance, a bunch of messages,
a bunch of messages, some dialogs, users, etc.</p> some dialogs, users, etc.</p>
<h3 id="types">Types</h3> <h3 id="types">Types</h3>
<p>Currently there are <b>{type_count} types</b>. You can see the full <p>Currently there are <b>{type_count} types</b>. You can see the full
@ -151,58 +158,9 @@
</ul> </ul>
<h3 id="example">Full example</h3> <h3 id="example">Full example</h3>
<p>The following example demonstrates:</p> <p>Documentation for this is now
<ol> <a href="http://telethon.readthedocs.io/en/latest/extra/advanced-usage/accessing-the-full-api.html">here</a>.
<li>How to create a <code>TelegramClient</code>.</li> </p>
<li>Connecting to the Telegram servers and authorizing an user.</li>
<li>Retrieving a list of chats (<i>dialogs</i>).</li>
<li>Invoking a request without the built-in methods.</li>
</ol>
<pre><span class="sh3">#!/usr/bin/python3</span>
<span class="sh4">from</span> telethon <span class="sh4">import</span> TelegramClient
<span class="sh4">from</span> telethon.tl.functions.messages <span class="sh4">import</span> GetHistoryRequest
<span class="sh3"># <b>(1)</b> Use your own values here</span>
api_id = <span class="sh1">12345</span>
api_hash = <span class="sh2">'0123456789abcdef0123456789abcdef'</span>
phone = <span class="sh2">'+34600000000'</span>
<span class="sh3"># <b>(2)</b> Create the client and connect</span>
client = TelegramClient(<span class="sh2">'username'</span>, api_id, api_hash)
client.connect()
<span class="sh3"># Ensure you're authorized</span>
if not client.is_user_authorized():
client.send_code_request(phone)
client.sign_in(phone, input(<span class="sh2">'Enter the code: '</span>))
<span class="sh3"># <b>(3)</b> Using built-in methods</span>
dialogs, entities = client.get_dialogs(<span class="sh1">10</span>)
entity = entities[<span class="sh1">0</span>]
<span class="sh3"># <b>(4)</b> !! Invoking a request manually !!</span>
result = <b>client</b>(GetHistoryRequest(
entity,
limit=<span class="sh1">20</span>,
offset_date=<span class="sh1">None</span>,
offset_id=<span class="sh1">0</span>,
max_id=<span class="sh1">0</span>,
min_id=<span class="sh1">0</span>,
add_offset=<span class="sh1">0</span>
))
<span class="sh3"># Now you have access to the first 20 messages</span>
messages = result.messages</pre>
<p>As it can be seen, manually calling requests with
<code>client(request)</code> (or using the old way, by calling
<code>client.invoke(request)</code>) is way more verbose than using the
built-in methods (such as <code>client.get_dialogs()</code>).</p>
<p>However, and
given that there are so many methods available, it's impossible to provide
a nice interface to things that may change over time. To get full access,
however, you're still able to invoke these methods manually.</p>
</div> </div>
</div> </div>

View File

@ -20,6 +20,11 @@
# import os # import os
# import sys # import sys
# sys.path.insert(0, os.path.abspath('.')) # sys.path.insert(0, os.path.abspath('.'))
import os
import re
root = os.path.abspath(os.path.join(__file__, os.path.pardir, os.path.pardir))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -55,9 +60,12 @@ author = 'Lonami'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.15' with open(os.path.join(root, 'telethon', 'version.py')) as f:
version = re.search(r"^__version__\s+=\s+'(.*)'$",
f.read(), flags=re.MULTILINE).group(1)
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.15.5' release = version
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -14,8 +14,10 @@ through a sorted list of everything you can do.
.. note:: .. note::
Removing the hand crafted documentation for methods is still The reason to keep both https://lonamiwebs.github.io/Telethon and this
a work in progress! documentation alive is that the former allows instant search results
as you type, and a "Copy import" button. If you like namespaces, you
can also do ``from telethon.tl import types, functions``. Both work.
You should also refer to the documentation to see what the objects You should also refer to the documentation to see what the objects
@ -39,8 +41,8 @@ If you're going to use a lot of these, you may do:
.. code-block:: python .. code-block:: python
import telethon.tl.functions as tl from telethon.tl import types, functions
# We now have access to 'tl.messages.SendMessageRequest' # We now have access to 'functions.messages.SendMessageRequest'
We see that this request must take at least two parameters, a ``peer`` We see that this request must take at least two parameters, a ``peer``
of type `InputPeer`__, and a ``message`` which is just a Python of type `InputPeer`__, and a ``message`` which is just a Python
@ -82,6 +84,14 @@ every time its used, simply call ``.get_input_peer``:
from telethon import utils from telethon import utils
peer = utils.get_input_user(entity) peer = utils.get_input_user(entity)
.. note::
Since ``v0.16.2`` this is further simplified. The ``Request`` itself
will call ``client.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 ``.get_entity`` versus
``.get_input_entity``, we have everything we need. To ``.invoke()`` our ``.get_input_entity``, we have everything we need. To ``.invoke()`` our
request we do: request we do:

View File

@ -93,6 +93,8 @@ 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()``.
.. 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`__

View File

@ -10,21 +10,6 @@ The library widely uses the concept of "entities". An entity will refer
to any ``User``, ``Chat`` or ``Channel`` object that the API may return to any ``User``, ``Chat`` or ``Channel`` object that the API may return
in response to certain methods, such as ``GetUsersRequest``. in response to certain methods, such as ``GetUsersRequest``.
To save bandwidth, the API also makes use of their "input" versions.
The input version of an entity (e.g. ``InputPeerUser``, ``InputChat``,
etc.) only contains the minimum required information that's required
for Telegram to be able to identify who you're referring to: their ID
and hash. This ID/hash pair is unique per user, so if you use the pair
given by another user **or bot** it will **not** work.
To save *even more* bandwidth, the API also makes use of the ``Peer``
versions, which just have an ID. This serves to identify them, but
peers alone are not enough to use them. You need to know their hash
before you can "use them".
Luckily, the library tries to simplify this mess the best it can.
Getting entities Getting entities
**************** ****************
@ -58,8 +43,8 @@ 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_entity()`` to further All methods in the :ref:`telegram-client` call ``.get_input_entity()`` to
save you from the hassle of doing so manually, so doing things like further save you from the hassle of doing so manually, so doing things like
``client.send_message('lonami', 'hi!')`` is possible. ``client.send_message('lonami', 'hi!')`` is possible.
Every entity the library "sees" (in any response to any call) will by Every entity the library "sees" (in any response to any call) will by
@ -72,7 +57,27 @@ made to obtain the required information.
Entities vs. Input Entities Entities vs. Input Entities
*************************** ***************************
As we mentioned before, API calls don't need to know the whole information .. note::
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,
don't call ``.get_entity()`` before, just use the username or phone,
or the entity retrieved by other means like ``.get_dialogs()``.
To save bandwidth, the API also makes use of their "input" versions.
The input version of an entity (e.g. ``InputPeerUser``, ``InputChat``,
etc.) only contains the minimum required information that's required
for Telegram to be able to identify who you're referring to: their ID
and hash. This ID/hash pair is unique per user, so if you use the pair
given by another user **or bot** it will **not** work.
To save *even more* bandwidth, the API also makes use of the ``Peer``
versions, which just have an ID. This serves to identify them, but
peers alone are not enough to use them. You need to know their hash
before you can "use them".
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 ``.get_input_entity()`` is available. This will always use the cache while
possible, making zero API calls most of the time. When a request is made, possible, making zero API calls most of the time. When a request is made,
@ -85,3 +90,15 @@ 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 ``InputPeer``. Only use ``.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
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:
.. code-block:: python
client(SendMessageRequest('username', 'hello'))
The library will call the ``.resolve()`` method of the request, which will
resolve ``'username'`` with the appropriated ``InputPeer``. Don't worry if
you don't get this yet, but remember some of the details here are important.

View File

@ -1,7 +1,5 @@
.. Telethon documentation master file, created by .. _getting-started:
sphinx-quickstart on Fri Nov 17 15:36:11 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
=============== ===============
Getting Started Getting Started
@ -39,13 +37,36 @@ Basic Usage
.. code-block:: python .. code-block:: python
print(me.stringify()) # Getting information about yourself
print(client.get_me().stringify())
client.send_message('username', 'Hello! Talking to you from Telethon') # Sending a message (you can use 'me' or 'self' to message yourself)
client.send_message('username', 'Hello World from Telethon!')
# Sending a file
client.send_file('username', '/home/myself/Pictures/holidays.jpg') client.send_file('username', '/home/myself/Pictures/holidays.jpg')
client.download_profile_photo(me) # Retrieving messages from a chat
from telethon import utils
for message in client.get_message_history('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Listing all the dialogs (conversations you have open)
for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.message)
# Downloading profile photos (default path is the working directory)
client.download_profile_photo('username')
# Once you have a message with .media (if message.media)
# you can download it using client.download_media():
messages = client.get_message_history('username') messages = client.get_message_history('username')
client.download_media(messages[0]) client.download_media(messages[0])
**More details**: :ref:`telegram-client` **More details**: :ref:`telegram-client`
----------
You can continue by clicking on the "More details" link below each
snippet of code or the "Next" button at the bottom of the page.

View File

@ -29,7 +29,9 @@ You can also install the library directly from GitHub or a fork:
$ cd Telethon/ $ cd Telethon/
# pip install -Ue . # pip install -Ue .
If you don't have root access, simply pass the ``--user`` flag to the pip command. If you don't have root access, simply pass the ``--user`` flag to the pip
command. If you want to install a specific branch, append ``@branch`` to
the end of the first install command.
Manual Installation Manual Installation
@ -49,7 +51,8 @@ Manual Installation
5. Done! 5. Done!
To generate the documentation, ``cd docs`` and then ``python3 generate.py``. To generate the `method documentation`__, ``cd docs`` and then
``python3 generate.py`` (if some pages render bad do it twice).
Optional dependencies Optional dependencies
@ -62,5 +65,6 @@ will also work without it.
__ https://github.com/ricmoo/pyaes __ https://github.com/ricmoo/pyaes
__ https://pypi.python.org/pypi/pyaes __ https://pypi.python.org/pypi/pyaes
__ https://github.com/sybrenstuvel/python-rsa/ __ https://github.com/sybrenstuvel/python-rsa
__ https://pypi.python.org/pypi/rsa/3.4.2 __ https://pypi.python.org/pypi/rsa/3.4.2
__ https://lonamiwebs.github.io/Telethon

View File

@ -43,30 +43,29 @@ how the library refers to either of these:
lonami = client.get_entity('lonami') lonami = client.get_entity('lonami')
The so called "entities" are another important whole concept on its own, The so called "entities" are another important whole concept on its own,
and you should but for now you don't need to worry about it. Simply know that they are
Note that saving and using these entities will be more important when a good way to get information about an user, chat or channel.
Accessing the Full API. For now, this is a good way to get information
about an user or chat.
Other common methods for quick scripts are also available: Many other common methods for quick scripts are also available:
.. code-block:: python .. code-block:: python
# Sending a message (use an entity/username/etc) # Note that you can use 'me' or 'self' to message yourself
client.send_message('TheAyyBot', 'ayy') client.send_message('username', 'Hello World from Telethon!')
# Sending a photo, or a file client.send_file('username', '/home/myself/Pictures/holidays.jpg')
client.send_file(myself, '/path/to/the/file.jpg', force_document=True)
# Downloading someone's profile photo. File is saved to 'where' # The utils package has some goodies, like .get_display_name()
where = client.download_profile_photo(someone) from telethon import utils
for message in client.get_message_history('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Retrieving the message history # Dialogs are the conversations you have open
messages = client.get_message_history(someone) for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.message)
# Downloading the media from a specific message # Default path is the working directory
# You can specify either a directory, a filename, or nothing at all client.download_profile_photo('username')
where = client.download_media(message, '/path/to/output')
# Call .disconnect() when you're done # Call .disconnect() when you're done
client.disconnect() client.disconnect()

View File

@ -4,6 +4,12 @@
Working with Updates Working with Updates
==================== ====================
.. note::
There are plans to make working with updates more friendly. Stay tuned!
.. contents:: .. contents::

View File

@ -3,6 +3,11 @@ Bots
==== ====
.. note::
These examples assume you have read :ref:`accessing-the-full-api`.
Talking to Inline Bots Talking to Inline Bots
********************** **********************

View File

@ -3,6 +3,11 @@ Working with Chats and Channels
=============================== ===============================
.. note::
These examples assume you have read :ref:`accessing-the-full-api`.
Joining a chat or channel Joining a chat or channel
************************* *************************

View File

@ -3,6 +3,11 @@ Working with messages
===================== =====================
.. note::
These examples assume you have read :ref:`accessing-the-full-api`.
Forwarding messages Forwarding messages
******************* *******************

View File

@ -10,8 +10,12 @@ Welcome to Telethon's documentation!
Pure Python 3 Telegram client library. Pure Python 3 Telegram client library.
Official Site `here <https://lonamiwebs.github.io/Telethon>`_. Official Site `here <https://lonamiwebs.github.io/Telethon>`_.
Please follow the links below to get you started, and remember Please follow the links on the index below to navigate from here,
to read the :ref:`changelog` when you upgrade! or use the menu on the left. Remember to read the :ref:`changelog`
when you upgrade!
.. important::
If you're new here, you want to read :ref:`getting-started`.
What is this? What is this?
@ -85,19 +89,20 @@ heavy job for you, so you can focus on developing an application.
extra/developing/telegram-api-in-other-languages.rst extra/developing/telegram-api-in-other-languages.rst
.. _Wall-of-shame: .. _More:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Wall of Shame :caption: More
extra/changelog
extra/wall-of-shame.rst extra/wall-of-shame.rst
.. toctree:: .. toctree::
:caption: Telethon modules :caption: Telethon modules
telethon modules
Indices and tables Indices and tables

View File

@ -42,6 +42,13 @@ telethon\.utils module
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
telethon\.session module
------------------------
.. automodule:: telethon.session
:members:
:undoc-members:
:show-inheritance:
telethon\.cryto package telethon\.cryto package
------------------------ ------------------------
@ -58,21 +65,21 @@ telethon\.errors package
telethon.errors telethon.errors
telethon\.extensions package telethon\.extensions package
------------------------ ----------------------------
.. toctree:: .. toctree::
telethon.extensions telethon.extensions
telethon\.network package telethon\.network package
------------------------ -------------------------
.. toctree:: .. toctree::
telethon.network telethon.network
telethon\.tl package telethon\.tl package
------------------------ --------------------
.. toctree:: .. toctree::

View File

@ -7,14 +7,6 @@ telethon\.tl package
telethon.tl.custom telethon.tl.custom
telethon\.tl\.entity\_database module
-------------------------------------
.. automodule:: telethon.tl.entity_database
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.gzip\_packed module telethon\.tl\.gzip\_packed module
--------------------------------- ---------------------------------
@ -31,14 +23,6 @@ telethon\.tl\.message\_container module
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
telethon\.tl\.session module
----------------------------
.. automodule:: telethon.tl.session
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.tl\_message module telethon\.tl\.tl\_message module
-------------------------------- --------------------------------

View File

@ -406,7 +406,7 @@ class TelegramClient(TelegramBareClient):
def log_out(self): def log_out(self):
""" """
Logs out Telegram and deletes the current *.session file. Logs out Telegram and deletes the current ``*.session`` file.
Returns: Returns:
True if the operation was successful. True if the operation was successful.
@ -742,6 +742,10 @@ class TelegramClient(TelegramBareClient):
# Add a few extra attributes to the Message to make it friendlier. # Add a few extra attributes to the Message to make it friendlier.
messages.total = total_messages messages.total = total_messages
for m in messages: for m in messages:
# To make messages more friendly, always add message
# to service messages, and action to normal messages.
m.message = getattr(m, 'message', None)
m.action = getattr(m, 'action', None)
m.sender = (None if not m.from_id else m.sender = (None if not m.from_id else
entities[utils.get_peer_id(m.from_id)]) entities[utils.get_peer_id(m.from_id)])

View File

@ -24,10 +24,7 @@ class Dialog:
self.unread_count = dialog.unread_count self.unread_count = dialog.unread_count
self.unread_mentions_count = dialog.unread_mentions_count self.unread_mentions_count = dialog.unread_mentions_count
if dialog.draft:
self.draft = Draft(client, dialog.peer, dialog.draft) self.draft = Draft(client, dialog.peer, dialog.draft)
else:
self.draft = None
def send_message(self, *args, **kwargs): def send_message(self, *args, **kwargs):
""" """

View File

@ -1,16 +1,18 @@
from ..functions.messages import SaveDraftRequest from ..functions.messages import SaveDraftRequest
from ..types import UpdateDraftMessage from ..types import UpdateDraftMessage, DraftMessage
class Draft: class Draft:
""" """
Custom class that encapsulates a draft on the Telegram servers, providing Custom class that encapsulates a draft on the Telegram servers, providing
an abstraction to change the message conveniently. The library will return an abstraction to change the message conveniently. The library will return
instances of this class when calling `client.get_drafts()`. instances of this class when calling ``client.get_drafts()``.
""" """
def __init__(self, client, peer, draft): def __init__(self, client, peer, draft):
self._client = client self._client = client
self._peer = peer self._peer = peer
if not draft:
draft = DraftMessage('', None, None, None, None)
self.text = draft.message self.text = draft.message
self.date = draft.date self.date = draft.date