Merge pull request #448 from jeffffc/master

Add readthedocs, transfer tutorials from wiki to there too
This commit is contained in:
Lonami 2017-11-21 12:53:58 +01:00 committed by GitHub
commit 4e5dede7fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1834 additions and 0 deletions

20
readthedocs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = Telethon
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

174
readthedocs/conf.py Normal file
View File

@ -0,0 +1,174 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Telethon documentation build configuration file, created by
# sphinx-quickstart on Fri Nov 17 15:36:11 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Telethon'
copyright = '2017, Lonami'
author = 'Lonami'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.15'
# The full version, including alpha/beta/rc tags.
release = '0.15.5'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'collapse_navigation': True,
'display_version': True,
'navigation_depth': 3,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'globaltoc.html',
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
]
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Telethondoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Telethon.tex', 'Telethon Documentation',
'Jeff', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'telethon', 'Telethon Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Telethon', 'Telethon Documentation',
author, 'Telethon', 'One line description of project.',
'Miscellaneous'),
]

View File

@ -0,0 +1,59 @@
======
Bots
======
Talking to Inline Bots
^^^^^^^^^^^^^^^^^^^^^^
You can query an inline bot, such as `@VoteBot`__
(note, *query*, not *interact* with a voting message), by making use of
the `GetInlineBotResultsRequest`__ request:
.. code-block:: python
from telethon.tl.functions.messages import GetInlineBotResultsRequest
bot_results = client(GetInlineBotResultsRequest(
bot, user_or_chat, 'query', ''
))
And you can select any of their results by using
`SendInlineBotResultRequest`__:
.. code-block:: python
from telethon.tl.functions.messages import SendInlineBotResultRequest
client(SendInlineBotResultRequest(
get_input_peer(user_or_chat),
obtained_query_id,
obtained_str_id
))
Talking to Bots with special reply markup
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To interact with a message that has a special reply markup, such as
`@VoteBot`__ polls, you would use
`GetBotCallbackAnswerRequest`__:
.. code-block:: python
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
client(GetBotCallbackAnswerRequest(
user_or_chat,
msg.id,
data=msg.reply_markup.rows[wanted_row].buttons[wanted_button].data
))
Its a bit verbose, but it has all the information you would need to
show it visually (button rows, and buttons within each row, each with
its own data).
__ https://t.me/vote
__ https://lonamiwebs.github.io/Telethon/methods/messages/get_inline_bot_results.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/send_inline_bot_result.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/get_bot_callback_answer.html
__ https://t.me/vote

View File

@ -0,0 +1,58 @@
=========================
Signing In
=========================
.. note::
Make sure you have gone through :ref:`prelude` already!
Two Factor Authorization (2FA)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have Two Factor Authorization (from now on, 2FA) enabled on your account, calling
:meth:`telethon.TelegramClient.sign_in` will raise a `SessionPasswordNeededError`.
When this happens, just :meth:`telethon.TelegramClient.sign_in` again with a ``password=``:
.. code-block:: python
import getpass
from telethon.errors import SessionPasswordNeededError
client.sign_in(phone)
try:
client.sign_in(code=input('Enter code: '))
except SessionPasswordNeededError:
client.sign_in(password=getpass.getpass())
Enabling 2FA
*************
If you don't have 2FA enabled, but you would like to do so through Telethon, take as example the following code snippet:
.. code-block:: python
import os
from hashlib import sha256
from telethon.tl.functions import account
from telethon.tl.types.account import PasswordInputSettings
new_salt = client(account.GetPasswordRequest()).new_salt
salt = new_salt + os.urandom(8) # new random salt
pw = 'secret'.encode('utf-8') # type your new password here
hint = 'hint'
pw_salted = salt + pw + salt
pw_hash = sha256(pw_salted).digest()
result = client(account.UpdatePasswordSettingsRequest(
current_password_hash=salt,
new_settings=PasswordInputSettings(
new_salt=salt,
new_password_hash=pw_hash,
hint=hint
)
))
Thanks to `Issue 259 <https://github.com/LonamiWebs/Telethon/issues/259>`_ for the tip!

View File

@ -0,0 +1,324 @@
=========================
Users and Chats
=========================
.. note::
Make sure you have gone through :ref:`prelude` already!
.. contents::
:depth: 2
.. _retrieving-an-entity:
Retrieving an entity (user or group)
**************************************
An “entity” is used to refer to either an `User`__ or a `Chat`__
(which includes a `Channel`__). The most straightforward way to get
an entity is to use ``TelegramClient.get_entity()``. This method accepts
either a string, which can be a username, phone number or `t.me`__-like
link, or an integer that will be the ID of an **user**. You can use it
like so:
.. code-block:: python
# all of these work
lonami = client.get_entity('lonami')
lonami = client.get_entity('t.me/lonami')
lonami = client.get_entity('https://telegram.dog/lonami')
# other kind of entities
channel = client.get_entity('telegram.me/joinchat/AAAAAEkk2WdoDrB4-Q8-gg')
contact = client.get_entity('+34xxxxxxxxx')
friend = client.get_entity(friend_id)
For the last one to work, the library must have “seen” the user at least
once. The library will “see” the user as long as any request contains
them, so if youve called ``.get_dialogs()`` for instance, and your
friend was there, the library will know about them. For more, read about
the :ref:`sessions`.
If you want to get a channel or chat by ID, you need to specify that
they are a channel or a chat. The library cant infer what they are by
just their ID (unless the ID is marked, but this is only done
internally), so you need to wrap the ID around a `Peer`__ object:
.. code-block:: python
from telethon.tl.types import PeerUser, PeerChat, PeerChannel
my_user = client.get_entity(PeerUser(some_id))
my_chat = client.get_entity(PeerChat(some_id))
my_channel = client.get_entity(PeerChannel(some_id))
**Note** that most requests dont ask for an ``User``, or a ``Chat``,
but rather for ``InputUser``, ``InputChat``, and so on. If this is the
case, you should prefer ``.get_input_entity()`` over ``.get_entity()``,
as it will be immediate if you provide an ID (whereas ``.get_entity()``
may need to find who the entity is first).
Via your open “chats” (dialogs)
-------------------------------
.. note::
Please read here: :ref:`retrieving-all-dialogs`.
Via ResolveUsernameRequest
--------------------------
This is the request used by ``.get_entity`` internally, but you can also
use it by hand:
.. code-block:: python
from telethon.tl.functions.contacts import ResolveUsernameRequest
result = client(ResolveUsernameRequest('username'))
found_chats = result.chats
found_users = result.users
# result.peer may be a PeerUser, PeerChat or PeerChannel
See `Peer`__ for more information about this result.
Via MessageFwdHeader
--------------------
If all you have is a `MessageFwdHeader`__ after you retrieved a bunch
of messages, this gives you access to the ``from_id`` (if forwarded from
an user) and ``channel_id`` (if forwarded from a channel). Invoking
`GetMessagesRequest`__ also returns a list of ``chats`` and
``users``, and you can find the desired entity there:
.. code-block:: python
# Logic to retrieve messages with `GetMessagesRequest´
messages = foo()
fwd_header = bar()
user = next(u for u in messages.users if u.id == fwd_header.from_id)
channel = next(c for c in messages.chats if c.id == fwd_header.channel_id)
Or you can just call ``.get_entity()`` with the ID, as you should have
seen that user or channel before. A call to ``GetMessagesRequest`` may
still be neeed.
Via GetContactsRequest
----------------------
The library will call this for you if you pass a phone number to
``.get_entity``, but again, it can be done manually. If the user you
want to talk to is a contact, you can use `GetContactsRequest`__:
.. code-block:: python
from telethon.tl.functions.contacts import GetContactsRequest
from telethon.tl.types.contacts import Contacts
contacts = client(GetContactsRequest(0))
if isinstance(contacts, Contacts):
users = contacts.users
contacts = contacts.contacts
__ https://lonamiwebs.github.io/Telethon/types/user.html
__ https://lonamiwebs.github.io/Telethon/types/chat.html
__ https://lonamiwebs.github.io/Telethon/constructors/channel.html
__ https://t.me
__ https://lonamiwebs.github.io/Telethon/types/peer.html
__ https://lonamiwebs.github.io/Telethon/types/peer.html
__ https://lonamiwebs.github.io/Telethon/constructors/message_fwd_header.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/get_messages.html
__ https://lonamiwebs.github.io/Telethon/methods/contacts/get_contacts.html
.. _retrieving-all-dialogs:
Retrieving all dialogs
***********************
There are several ``offset_xyz=`` parameters that have no effect at all,
but there's not much one can do since this is something the server should handle.
Currently, the only way to get all dialogs
(open chats, conversations, etc.) is by using the ``offset_date``:
.. code-block:: python
from telethon.tl.functions.messages import GetDialogsRequest
from telethon.tl.types import InputPeerEmpty
from time import sleep
dialogs = []
users = []
chats = []
last_date = None
chunk_size = 20
while True:
result = client(GetDialogsRequest(
offset_date=last_date,
offset_id=0,
offset_peer=InputPeerEmpty(),
limit=chunk_size
))
dialogs.extend(result.dialogs)
users.extend(result.users)
chats.extend(result.chats)
if not result.messages:
break
last_date = min(msg.date for msg in result.messages)
sleep(2)
Joining a chat or channel
*******************************
Note that `Chat`__\ s are normal groups, and `Channel`__\ s are a
special form of `Chat`__\ s,
which can also be super-groups if their ``megagroup`` member is
``True``.
Joining a public channel
------------------------
Once you have the :ref:`entity <retrieving-an-entity>`
of the channel you want to join to, you can
make use of the `JoinChannelRequest`__ to join such channel:
.. code-block:: python
from telethon.tl.functions.channels import JoinChannelRequest
client(JoinChannelRequest(channel))
# In the same way, you can also leave such channel
from telethon.tl.functions.channels import LeaveChannelRequest
client(LeaveChannelRequest(input_channel))
For more on channels, check the `channels namespace`__.
Joining a private chat or channel
---------------------------------
If all you have is a link like this one:
``https://t.me/joinchat/AAAAAFFszQPyPEZ7wgxLtd``, you already have
enough information to join! The part after the
``https://t.me/joinchat/``, this is, ``AAAAAFFszQPyPEZ7wgxLtd`` on this
example, is the ``hash`` of the chat or channel. Now you can use
`ImportChatInviteRequest`__ as follows:
.. -block:: python
from telethon.tl.functions.messages import ImportChatInviteRequest
updates = client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
Adding someone else to such chat or channel
-------------------------------------------
If you dont want to add yourself, maybe because youre already in, you
can always add someone else with the `AddChatUserRequest`__, which
use is very straightforward:
.. code-block:: python
from telethon.tl.functions.messages import AddChatUserRequest
client(AddChatUserRequest(
chat_id,
user_to_add,
fwd_limit=10 # allow the user to see the 10 last messages
))
Checking a link without joining
-------------------------------
If you dont need to join but rather check whether its a group or a
channel, you can use the `CheckChatInviteRequest`__, which takes in
the `hash`__ of said channel or group.
__ https://lonamiwebs.github.io/Telethon/constructors/chat.html
__ https://lonamiwebs.github.io/Telethon/constructors/channel.html
__ https://lonamiwebs.github.io/Telethon/types/chat.html
__ https://lonamiwebs.github.io/Telethon/methods/channels/join_channel.html
__ https://lonamiwebs.github.io/Telethon/methods/channels/index.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/import_chat_invite.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/add_chat_user.html
__ https://lonamiwebs.github.io/Telethon/methods/messages/check_chat_invite.html
__ https://github.com/LonamiWebs/Telethon/wiki/Joining-a-chat-or-channel#joining-a-private-chat-or-channel
Retrieving all chat members (channels too)
******************************************
In order to get all the members from a mega-group or channel, you need
to use `GetParticipantsRequest`__. As we can see it needs an
`InputChannel`__, (passing the mega-group or channel youre going to
use will work), and a mandatory `ChannelParticipantsFilter`__. The
closest thing to “no filter” is to simply use
`ChannelParticipantsSearch`__ with an empty ``'q'`` string.
If we want to get *all* the members, we need to use a moving offset and
a fixed limit:
.. code-block:: python
from telethon.tl.functions.channels import GetParticipantsRequest
from telethon.tl.types import ChannelParticipantsSearch
from time import sleep
offset = 0
limit = 100
all_participants = []
while True:
participants = client.invoke(GetParticipantsRequest(
channel, ChannelParticipantsSearch(''), offset, limit
))
if not participants.users:
break
all_participants.extend(participants.users)
offset += len(participants.users)
# sleep(1) # This line seems to be optional, no guarantees!
Note that ``GetParticipantsRequest`` returns `ChannelParticipants`__,
which may have more information you need (like the role of the
participants, total count of members, etc.)
__ https://lonamiwebs.github.io/Telethon/methods/channels/get_participants.html
__ https://lonamiwebs.github.io/Telethon/methods/channels/get_participants.html
__ https://lonamiwebs.github.io/Telethon/types/channel_participants_filter.html
__ https://lonamiwebs.github.io/Telethon/constructors/channel_participants_search.html
__ https://lonamiwebs.github.io/Telethon/constructors/channels/channel_participants.html
Recent Actions
********************
“Recent actions” is simply the name official applications have given to
the “admin log”. Simply use `GetAdminLogRequest`__ for that, and
youll get AdminLogResults.events in return which in turn has the final
`.action`__.
__ https://lonamiwebs.github.io/Telethon/methods/channels/get_admin_log.html
__ https://lonamiwebs.github.io/Telethon/types/channel_admin_log_event_action.html
Increasing View Count in a Channel
****************************************
It has been asked `quite`__ `a few`__ `times`__ (really, `many`__), and
while I dont understand why so many people ask this, the solution is to
use `GetMessagesViewsRequest`__, setting ``increment=True``:
.. code-block:: python
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
# Obtain `msg_ids' through `.get_message_history()` or anyhow. Must be a list.
client(GetMessagesViewsRequest(
peer=channel,
id=msg_ids,
increment=True
))
__ https://github.com/LonamiWebs/Telethon/issues/233
__ https://github.com/LonamiWebs/Telethon/issues/305
__ https://github.com/LonamiWebs/Telethon/issues/409
__ https://github.com/LonamiWebs/Telethon/issues/447
__ https://lonamiwebs.github.io/Telethon/methods/messages/get_messages_views.html

View File

@ -0,0 +1,103 @@
=========================
Working with messages
=========================
.. note::
Make sure you have gone through :ref:`prelude` already!
Forwarding messages
*******************
Note that ForwardMessageRequest_ (note it's Message, singular) will *not* work if channels are involved.
This is because channel (and megagroups) IDs are not unique, so you also need to know who the sender is
(a parameter this request doesn't have).
Either way, you are encouraged to use ForwardMessagesRequest_ (note it's Message*s*, plural) *always*,
since it is more powerful, as follows:
.. code-block:: python
from telethon.tl.functions.messages import ForwardMessagesRequest
# note the s ^
messages = foo() # retrieve a few messages (or even one, in a list)
from_entity = bar()
to_entity = baz()
client(ForwardMessagesRequest(
from_peer=from_entity, # who sent these messages?
id=[msg.id for msg in messages], # which are the messages?
to_peer=to_entity # who are we forwarding them to?
))
The named arguments are there for clarity, although they're not needed because they appear in order.
You can obviously just wrap a single message on the list too, if that's all you have.
Searching Messages
*******************
Messages are searched through the obvious SearchRequest_, but you may run into issues_. A valid example would be:
.. code-block:: python
result = client(SearchRequest(
entity, 'query', InputMessagesFilterEmpty(), None, None, 0, 0, 100
))
It's important to note that the optional parameter ``from_id`` has been left omitted and thus defaults to ``None``.
Changing it to InputUserEmpty_, as one could think to specify "no user", won't work because this parameter is a flag,
and it being unspecified has a different meaning.
If one were to set ``from_id=InputUserEmpty()``, it would filter messages from "empty" senders,
which would likely match no users.
If you get a ``ChatAdminRequiredError`` on a channel, it's probably because you tried setting the ``from_id`` filter,
and as the error says, you can't do that. Leave it set to ``None`` and it should work.
As with every method, make sure you use the right ID/hash combination for your ``InputUser`` or ``InputChat``,
or you'll likely run into errors like ``UserIdInvalidError``.
Sending stickers
*****************
Stickers are nothing else than ``files``, and when you successfully retrieve the stickers for a certain sticker set,
all you will have are ``handles`` to these files. Remember, the files Telegram holds on their servers can be referenced
through this pair of ID/hash (unique per user), and you need to use this handle when sending a "document" message.
This working example will send yourself the very first sticker you have:
.. code-block:: python
# Get all the sticker sets this user has
sticker_sets = client(GetAllStickersRequest(0))
# Choose a sticker set
sticker_set = sticker_sets.sets[0]
# Get the stickers for this sticker set
stickers = client(GetStickerSetRequest(
stickerset=InputStickerSetID(
id=sticker_set.id, access_hash=sticker_set.access_hash
)
))
# Stickers are nothing more than files, so send that
client(SendMediaRequest(
peer=client.get_me(),
media=InputMediaDocument(
id=InputDocument(
id=stickers.documents[0].id,
access_hash=stickers.documents[0].access_hash
),
caption=''
)
))
.. _ForwardMessageRequest: https://lonamiwebs.github.io/Telethon/methods/messages/forward_message.html
.. _ForwardMessagesRequest: https://lonamiwebs.github.io/Telethon/methods/messages/forward_messages.html
.. _SearchRequest: https://lonamiwebs.github.io/Telethon/methods/messages/search.html
.. _issues: https://github.com/LonamiWebs/Telethon/issues/215
.. _InputUserEmpty: https://lonamiwebs.github.io/Telethon/constructors/input_user_empty.html

View File

@ -0,0 +1,48 @@
.. _prelude:
Prelude
---------
Before reading any specific example, make sure to read the following common steps:
All the examples assume that you have successfully created a client and you're authorized as follows:
.. code-block:: python
from telethon import TelegramClient
# Use your own values here
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
phone_number = '+34600000000'
client = TelegramClient('some_name', api_id, api_hash)
client.connect() # Must return True, otherwise, try again
if not client.is_user_authorized():
client.send_code_request(phone_number)
# .sign_in() may raise PhoneNumberUnoccupiedError
# In that case, you need to call .sign_up() to get a new account
client.sign_in(phone_number, input('Enter code: '))
# The `client´ is now ready
Although Python will probably clean up the resources used by the ``TelegramClient``,
you should always ``.disconnect()`` it once you're done:
.. code-block:: python
try:
# Code using the client goes here
except:
# No matter what happens, always disconnect in the end
client.disconnect()
If the examples aren't enough, you're strongly advised to read the source code
for the InteractiveTelegramClient_ for an overview on how you could build your next script.
This example shows a basic usage more than enough in most cases. Even reading the source
for the TelegramClient_ may help a lot!
.. _InteractiveTelegramClient: https://github.com/LonamiWebs/Telethon/blob/master/telethon_examples/interactive_telegram_client.py
.. _TelegramClient: https://github.com/LonamiWebs/Telethon/blob/master/telethon/telegram_client.py

View File

@ -0,0 +1,117 @@
.. _accessing-the-full-api:
==========================
Accessing the Full API
==========================
The ``TelegramClient`` doesnt offer a method for every single request
the Telegram API supports. However, its very simple to ``.invoke()``
any request. Whenever you need something, dont forget to `check the
documentation`__ and look for the `method you need`__. There you can go
through a sorted list of everything you can do.
You should also refer to the documentation to see what the objects
(constructors) Telegram returns look like. Every constructor inherits
from a common type, and thats the reason for this distinction.
Say ``client.send_message()`` didnt exist, we could use the `search`__
to look for “message”. There we would find `SendMessageRequest`__,
which we can work with.
Every request is a Python class, and has the parameters needed for you
to invoke it. You can also call ``help(request)`` for information on
what input parameters it takes. Remember to “Copy import to the
clipboard”, or your script wont be aware of this class! Now we have:
.. code-block:: python
from telethon.tl.functions.messages import SendMessageRequest
If youre going to use a lot of these, you may do:
.. code-block:: python
import telethon.tl.functions as tl
# We now have access to 'tl.messages.SendMessageRequest'
We see that this request must take at least two parameters, a ``peer``
of type `InputPeer`__, and a ``message`` which is just a Python
``str``\ ing.
How can we retrieve this ``InputPeer``? We have two options. We manually
`construct one`__, for instance:
.. code-block:: python
from telethon.tl.types import InputPeerUser
peer = InputPeerUser(user_id, user_hash)
Or we call ``.get_input_entity()``:
.. code-block:: python
peer = client.get_input_entity('someone')
When youre going to invoke an API method, most require you to pass an
``InputUser``, ``InputChat``, or so on, this is why using
``.get_input_entity()`` is more straightforward (and sometimes
immediate, if you know the ID of the user for instance). If you also
need to have information about the whole user, use ``.get_entity()``
instead:
.. code-block:: python
entity = client.get_entity('someone')
In the later case, when you use the entity, the library will cast it to
its “input” version for you. If you already have the complete user and
want to cache its input version so the library doesnt have to do this
every time its used, simply call ``.get_input_peer``:
.. code-block:: python
from telethon import utils
peer = utils.get_input_user(entity)
After this small parenthesis about ``.get_entity`` versus
``.get_input_entity``, we have everything we need. To ``.invoke()`` our
request we do:
.. code-block:: python
result = client(SendMessageRequest(peer, 'Hello there!'))
# __call__ is an alias for client.invoke(request). Both will work
Message sent! Of course, this is only an example.
There are nearly 250 methods available as of layer 73,
and you can use every single of them as you wish.
Remember to use the right types! To sum up:
.. code-block:: python
result = client(SendMessageRequest(
client.get_input_entity('username'), 'Hello there!'
))
.. note::
Note that some requests have a "hash" parameter. This is **not** your ``api_hash``!
It likely isn't your self-user ``.access_hash`` either.
It's a special hash used by Telegram to only send a difference of new data
that you don't already have with that request,
so you can leave it to 0, and it should work (which means no hash is known yet).
For those requests having a "limit" parameter,
you can often set it to zero to signify "return as many items as possible".
This won't work for all of them though,
for instance, in "messages.search" it will actually return 0 items.
__ https://lonamiwebs.github.io/Telethon
__ https://lonamiwebs.github.io/Telethon/methods/index.html
__ https://lonamiwebs.github.io/Telethon/?q=message
__ https://lonamiwebs.github.io/Telethon/methods/messages/send_message.html
__ https://lonamiwebs.github.io/Telethon/types/input_peer.html
__ https://lonamiwebs.github.io/Telethon/constructors/input_peer_user.html

View File

@ -0,0 +1,76 @@
.. _creating-a-client:
===================
Creating a Client
===================
Before working with Telegram's API, you need to get your own API ID and hash:
1. Follow `this link <https://my.telegram.org/>`_ and login with your phone number.
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 be changed later as far as I'm aware.
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!
Once that's ready, the next step is to create a ``TelegramClient``.
This class will be your main interface with Telegram's API, and creating one is very simple:
.. code-block:: python
from telethon import TelegramClient
# Use your own values here
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
phone_number = '+34600000000'
client = TelegramClient('some_name', api_id, api_hash)
Note that ``'some_name'`` will be used to save your session (persistent information such as access key and others)
as ``'some_name.session'`` in your disk. This is simply a JSON file which you can (but shouldn't) modify.
Before using the client, you must be connected to Telegram. Doing so is very easy:
``client.connect() # Must return True, otherwise, try again``
You may or may not be authorized yet. You must be authorized before you're able to send any request:
``client.is_user_authorized() # Returns True if you can send requests``
If you're not authorized, you need to ``.sign_in()``:
.. code-block:: python
client.send_code_request(phone_number)
myself = client.sign_in(phone_number, input('Enter code: '))
# If .sign_in raises PhoneNumberUnoccupiedError, use .sign_up instead
# If .sign_in raises SessionPasswordNeeded error, call .sign_in(password=...)
# You can import both exceptions from telethon.errors.
``myself`` is your Telegram user.
You can view all the information about yourself by doing ``print(myself.stringify())``.
You're now ready to use the client as you wish!
.. note::
If you want to use a **proxy**, you have to `install PySocks`__ (via pip or manual)
and then set the appropriated parameters:
.. code-block:: python
import socks
client = TelegramClient('session_id',
api_id=12345, api_hash='0123456789abcdef0123456789abcdef',
proxy=(socks.SOCKS5, 'localhost', 4444)
)
The ``proxy=`` argument should be a tuple, a list or a dict,
consisting of parameters described `here`__.
__ https://github.com/Anorov/PySocks#installation
__ https://github.com/Anorov/PySocks#usage-1%3E

View File

@ -0,0 +1,54 @@
.. Telethon documentation master file, created by
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!
=================
Simple Installation
*********************
``pip install telethon``
**More details**: :ref:`installation`
Creating a client
**************
.. code-block:: python
from telethon import TelegramClient
# These example values won't work. You must get your own api_id and
# api_hash from https://my.telegram.org, under API Development.
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
phone = '+34600000000'
client = TelegramClient('session_name', api_id, api_hash)
client.connect()
# If you already have a previous 'session_name.session' file, skip this.
client.sign_in(phone=phone)
me = client.sign_in(code=77777) # Put whatever code you received here.
**More details**: :ref:`creating-a-client`
Simple Stuff
**************
.. code-block:: python
print(me.stringify())
client.send_message('username', 'Hello! Talking to you from Telethon')
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
client.download_profile_photo(me)
total, messages, senders = client.get_message_history('username')
client.download_media(messages[0])

View File

@ -0,0 +1,71 @@
.. _installation:
=================
Installation
=================
Automatic Installation
^^^^^^^^^^^^^^^^^^^^^^^
To install Telethon, simply do:
``pip install telethon``
If you get something like ``"SyntaxError: invalid syntax"`` or any other error while installing,
it's probably because ``pip`` defaults to Python 2, which is not supported. Use ``pip3`` instead.
If you already have the library installed, upgrade with:
``pip install --upgrade telethon``
You can also install the library directly from GitHub or a fork:
.. code-block:: python
# pip install git+https://github.com/LonamiWebs/Telethon.git
or
$ git clone https://github.com/LonamiWebs/Telethon.git
$ cd Telethon/
# pip install -Ue .
If you don't have root access, simply pass the ``--user`` flag to the pip command.
Manual Installation
^^^^^^^^^^^^^^^^^^^^
1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and ``rsa`` (`GitHub`__ | `PyPi`__) modules:
``sudo -H pip install pyaes rsa``
2. Clone Telethon's GitHub repository: ``git clone https://github.com/LonamiWebs/Telethon.git``
3. Enter the cloned repository: ``cd Telethon``
4. Run the code generator: ``python3 setup.py gen_tl``
5. Done!
To generate the documentation, ``cd docs`` and then ``python3 generate.py``.
Optional dependencies
^^^^^^^^^^^^^^^^^^^^^^^^
If you're using the library under ARM (or even if you aren't),
you may want to install ``sympy`` through ``pip`` for a substantial speed-up
when generating the keys required to connect to Telegram
(you can of course do this on desktop too). See `issue #199`__ for more.
If ``libssl`` is available on your system, it will also be used wherever encryption is needed.
If neither of these are available, a pure Python callback will be used instead,
so you can still run the library wherever Python is available!
__ https://github.com/ricmoo/pyaes
__ https://pypi.python.org/pypi/pyaes
__ https://github.com/sybrenstuvel/python-rsa/
__ https://pypi.python.org/pypi/rsa/3.4.2
__ https://github.com/LonamiWebs/Telethon/issues/199

View File

@ -0,0 +1,55 @@
.. _sending-requests:
==================
Sending Requests
==================
Since we're working with Python, one must not forget that they can do ``help(client)`` or ``help(TelegramClient)``
at any time for a more detailed description and a list of all the available methods.
Calling ``help()`` from an interactive Python session will always list all the methods for any object, even yours!
Interacting with the Telegram API is done through sending **requests**,
this is, any "method" listed on the API. There are a few methods on the ``TelegramClient`` class
that abstract you from the need of manually importing the requests you need.
For instance, retrieving your own user can be done in a single line:
``myself = client.get_me()``
Internally, this method has sent a request to Telegram, who replied with the information about your own user.
If you want to retrieve any other user, chat or channel (channels are a special subset of chats),
you want to retrieve their "entity". This is how the library refers to either of these:
.. code-block:: python
# The method will infer that you've passed an username
# It also accepts phone numbers, and will get the user
# from your contact list.
lonami = client.get_entity('lonami')
Note that saving and using these entities will be more important when 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:
.. code-block:: python
# Sending a message (use an entity/username/etc)
client.send_message('TheAyyBot', 'ayy')
# Sending a photo, or a file
client.send_file(myself, '/path/to/the/file.jpg', force_document=True)
# Downloading someone's profile photo. File is saved to 'where'
where = client.download_profile_photo(someone)
# Retrieving the message history
total, messages, senders = client.get_message_history(someone)
# Downloading the media from a specific message
# You can specify either a directory, a filename, or nothing at all
where = client.download_media(message, '/path/to/output')
Remember that you can call ``.stringify()`` to any object Telegram returns to pretty print it.
Calling ``str(result)`` does the same operation, but on a single line.

View File

@ -0,0 +1,48 @@
.. _sessions:
==============
Session Files
==============
The first parameter you pass the the constructor of the
``TelegramClient`` 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 ``anon.session`` file will be created on the
working directory.
These JSON session files contain the required information to talk to the
Telegram servers, such as to which IP the client should connect, port,
authorization key so that messages can be encrypted, and so on.
These files will by default also save all the input entities that youve
seen, so that you can get information about an user or channel by just
their ID. Telegram will **not** send their ``access_hash`` required to
retrieve more information about them, if it thinks you have already seem
them. For this reason, the library needs to store this information
offline.
The library will by default too save all the entities (users with their
name, username, chats and so on) **in memory**, not to disk, so that you
can quickly access them by username or phone number. This can be
disabled too. Run ``help(client.session.entities)`` to see the available
methods (or ``help(EntityDatabase)``).
If youre not going to work without updates, or dont need to cache the
``access_hash`` associated with the entities ID, you can disable this
by setting ``client.session.save_entities = False``.
If you dont want to save the files as JSON, you can also create your
custom ``Session`` subclass and override the ``.save()`` and ``.load()``
methods. For example, you could save it on a database:
.. code-block:: python
class DatabaseSession(Session):
def save():
# serialize relevant data to the database
def load():
# load relevant data to the database
You should read the ``session.py`` source file to know what “relevant
data” you need to keep track of.

View File

@ -0,0 +1,135 @@
.. _working-with-updates:
====================
Working with Updates
====================
.. contents::
The library can run in four distinguishable modes:
- With no extra threads at all.
- With an extra thread that receives everything as soon as possible (default).
- With several worker threads that run your update handlers.
- A mix of the above.
Since this section is about updates, we'll describe the simplest way to work with them.
.. warning::
Remember that you should always call ``client.disconnect()`` once you're done.
Using multiple workers
^^^^^^^^^^^^^^^^^^^^^^^
When you create your client, simply pass a number to the ``update_workers`` parameter:
``client = TelegramClient('session', api_id, api_hash, update_workers=4)``
4 workers should suffice for most cases (this is also the default on `Python Telegram Bot`__).
You can set this value to more, or even less if you need.
The next thing you want to do is to add a method that will be called when an `Update`__ arrives:
.. code-block:: python
def callback(update):
print('I received', update)
client.add_update_handler(callback)
# do more work here, or simply sleep!
That's it! Now let's do something more interesting.
Every time an user talks to use, let's reply to them with the same text reversed:
.. code-block:: python
from telethon.tl.types import UpdateShortMessage, PeerUser
def replier(update):
if isinstance(update, UpdateShortMessage) and not update.out:
client.send_message(PeerUser(update.user_id), update.message[::-1])
client.add_update_handler(replier)
input('Press enter to stop this!')
client.disconnect()
We only ask you one thing: don't keep this running for too long, or your contacts will go mad.
Spawning no worker at all
^^^^^^^^^^^^^^^^^^^^^^^^^^
All the workers do is loop forever and poll updates from a queue that is filled from the ``ReadThread``,
responsible for reading every item off the network.
If you only need a worker and the ``MainThread`` would be doing no other job,
this is the preferred way. You can easily do the same as the workers like so:
.. code-block:: python
while True:
try:
update = client.updates.poll()
if not update:
continue
print('I received', update)
except KeyboardInterrupt:
break
client.disconnect()
Note that ``poll`` accepts a ``timeout=`` parameter,
and it will return ``None`` if other thread got the update before you could or if the timeout expired,
so it's important to check ``if not update``.
This can coexist with the rest of ``N`` workers, or you can set it to ``0`` additional workers:
``client = TelegramClient('session', api_id, api_hash, update_workers=0)``
You **must** set it to ``0`` (or other number), as it defaults to ``None`` and there is a different.
``None`` workers means updates won't be processed *at all*,
so you must set it to some value (0 or greater) if you want ``client.updates.poll()`` to work.
Using the main thread instead the ``ReadThread``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have no work to do on the ``MainThread`` and you were planning to have a ``while True: sleep(1)``,
don't do that. Instead, don't spawn the secondary ``ReadThread`` at all like so:
.. code-block:: python
client = TelegramClient(
...
spawn_read_thread=False
)
And then ``.idle()`` from the ``MainThread``:
``client.idle()``
You can stop it with :kbd:`Control+C`,
and you can configure the signals to be used in a similar fashion to `Python Telegram Bot`__.
As a complete example:
.. code-block:: python
def callback(update):
print('I received', update)
client = TelegramClient('session', api_id, api_hash,
update_workers=1, spawn_read_thread=False)
client.connect()
client.add_update_handler(callback)
client.idle() # ends with Ctrl+C
client.disconnect()
__ https://python-telegram-bot.org/
__ https://lonamiwebs.github.io/Telethon/types/update.html
__ https://github.com/python-telegram-bot/python-telegram-bot/blob/4b3315db6feebafb94edcaa803df52bb49999ced/telegram/ext/updater.py#L460

View File

@ -0,0 +1,26 @@
=========================================
Deleted, Limited or Deactivated Accounts
=========================================
If you're from Iran or Russian, we have bad news for you.
Telegram is much more likely to ban these numbers,
as they are often used to spam other accounts,
likely through the use of libraries like this one.
The best advice we can give you is to not abuse the API,
like calling many requests really quickly,
and to sign up with these phones through an official application.
Telegram may also ban virtual (VoIP) phone numbers,
as again, they're likely to be used for spam.
If you want to check if your account has been limited,
simply send a private message to `@SpamBot`__ through Telegram itself.
You should notice this by getting errors like ``PeerFloodError``,
which means you're limited, for instance,
when sending a message to some accounts but not others.
For more discussion, please see `issue 297`__.
__ https://t.me/SpamBot
__ https://github.com/LonamiWebs/Telethon/issues/297

View File

@ -0,0 +1,24 @@
================
Enable Logging
================
Telethon makes use of the `logging`__ module, and you can enable it as follows:
.. code-block:: python
import logging
logging.basicConfig(level=logging.DEBUG)
You can also use it in your own project very easily:
.. code-block:: python
import logging
logger = logging.getLogger(__name__)
logger.debug('Debug messages')
logger.info('Useful information')
logger.warning('This is a warning!')
__ https://docs.python.org/3/library/logging.html

View File

@ -0,0 +1,27 @@
==========
RPC Errors
==========
RPC stands for Remote Procedure Call, and when Telethon raises an
``RPCError``, its most likely because you have invoked some of the API
methods incorrectly (wrong parameters, wrong permissions, or even
something went wrong on Telegrams server). The most common are:
- ``FloodError`` (420), the same request was repeated many times. Must
wait ``.seconds``.
- ``SessionPasswordNeededError``, if you have setup two-steps
verification on Telegram.
- ``CdnFileTamperedError``, if the media you were trying to download
from a CDN has been altered.
- ``ChatAdminRequiredError``, you dont have permissions to perform
said operation on a chat or channel. Try avoiding filters, i.e. when
searching messages.
The generic classes for different error codes are: \* ``InvalidDCError``
(303), the request must be repeated on another DC. \*
``BadRequestError`` (400), the request contained errors. \*
``UnauthorizedError`` (401), the user is not authorized yet. \*
``ForbiddenError`` (403), privacy violation error. \* ``NotFoundError``
(404), make sure youre invoking ``Request``\ s!
If the error is not recognised, it will only be an ``RPCError``.

65
readthedocs/index.rst Normal file
View File

@ -0,0 +1,65 @@
.. Telethon documentation master file, created by
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.
Welcome to Telethon's documentation!
====================================
Pure Python 3 Telegram client library. Official Site `here <https://lonamiwebs.github.io/Telethon>`_.
.. _installation-and-usage:
.. toctree::
:maxdepth: 2
:caption: Installation and Simple Usage
extra/basic/getting-started
extra/basic/installation
extra/basic/creating-a-client
extra/basic/sessions
extra/basic/sending-requests
extra/basic/working-with-updates
extra/basic/accessing-the-full-api
.. _Advanced-usage:
.. toctree::
:maxdepth: 2
:caption: Advanced Usage
extra/advanced
extra/advanced-usage/signing-in
extra/advanced-usage/working-with-messages
extra/advanced-usage/users-and-chats
extra/advanced-usage/bots
.. _Troubleshooting:
.. toctree::
:maxdepth: 2
:caption: Troubleshooting
extra/troubleshooting/enable-logging
extra/troubleshooting/deleted-limited-or-deactivated-accounts
extra/troubleshooting/rpc-errors
.. toctree::
:caption: Telethon modules
telethon
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

36
readthedocs/make.bat Normal file
View File

@ -0,0 +1,36 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=Telethon
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

7
readthedocs/modules.rst Normal file
View File

@ -0,0 +1,7 @@
telethon
========
.. toctree::
:maxdepth: 3
telethon

View File

@ -0,0 +1 @@
telethon

View File

@ -0,0 +1,61 @@
telethon\.crypto package
========================
telethon\.crypto\.aes module
----------------------------
.. automodule:: telethon.crypto.aes
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.aes\_ctr module
---------------------------------
.. automodule:: telethon.crypto.aes_ctr
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.auth\_key module
----------------------------------
.. automodule:: telethon.crypto.auth_key
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.cdn\_decrypter module
---------------------------------------
.. automodule:: telethon.crypto.cdn_decrypter
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.factorization module
--------------------------------------
.. automodule:: telethon.crypto.factorization
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.libssl module
-------------------------------
.. automodule:: telethon.crypto.libssl
:members:
:undoc-members:
:show-inheritance:
telethon\.crypto\.rsa module
----------------------------
.. automodule:: telethon.crypto.rsa
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,21 @@
telethon\.errors package
========================
telethon\.errors\.common module
-------------------------------
.. automodule:: telethon.errors.common
:members:
:undoc-members:
:show-inheritance:
telethon\.errors\.rpc\_base\_errors module
------------------------------------------
.. automodule:: telethon.errors.rpc_base_errors
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
telethon\.extensions package
============================
telethon\.extensions\.binary\_reader module
-------------------------------------------
.. automodule:: telethon.extensions.binary_reader
:members:
:undoc-members:
:show-inheritance:
telethon\.extensions\.markdown module
-------------------------------------
.. automodule:: telethon.extensions.markdown
:members:
:undoc-members:
:show-inheritance:
telethon\.extensions\.tcp\_client module
----------------------------------------
.. automodule:: telethon.extensions.tcp_client
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,37 @@
telethon\.network package
=========================
telethon\.network\.authenticator module
---------------------------------------
.. automodule:: telethon.network.authenticator
:members:
:undoc-members:
:show-inheritance:
telethon\.network\.connection module
------------------------------------
.. automodule:: telethon.network.connection
:members:
:undoc-members:
:show-inheritance:
telethon\.network\.mtproto\_plain\_sender module
------------------------------------------------
.. automodule:: telethon.network.mtproto_plain_sender
:members:
:undoc-members:
:show-inheritance:
telethon\.network\.mtproto\_sender module
-----------------------------------------
.. automodule:: telethon.network.mtproto_sender
:members:
:undoc-members:
:show-inheritance:

89
readthedocs/telethon.rst Normal file
View File

@ -0,0 +1,89 @@
telethon package
================
telethon\.helpers module
------------------------
.. automodule:: telethon.helpers
:members:
:undoc-members:
:show-inheritance:
telethon\.telegram\_bare\_client module
---------------------------------------
.. automodule:: telethon.telegram_bare_client
:members:
:undoc-members:
:show-inheritance:
telethon\.telegram\_client module
---------------------------------
.. automodule:: telethon.telegram_client
:members:
:undoc-members:
:show-inheritance:
telethon\.update\_state module
------------------------------
.. automodule:: telethon.update_state
:members:
:undoc-members:
:show-inheritance:
telethon\.utils module
----------------------
.. automodule:: telethon.utils
:members:
:undoc-members:
:show-inheritance:
telethon\.cryto package
------------------------
.. toctree::
telethon.crypto
telethon\.errors package
------------------------
.. toctree::
telethon.errors
telethon\.extensions package
------------------------
.. toctree::
telethon.extensions
telethon\.network package
------------------------
.. toctree::
telethon.network
telethon\.tl package
------------------------
.. toctree::
telethon.tl
Module contents
---------------
.. automodule:: telethon
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,12 @@
telethon\.tl\.custom package
============================
telethon\.tl\.custom\.draft module
----------------------------------
.. automodule:: telethon.tl.custom.draft
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,57 @@
telethon\.tl package
====================
.. toctree::
telethon.tl.custom
telethon\.tl\.entity\_database module
-------------------------------------
.. automodule:: telethon.tl.entity_database
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.gzip\_packed module
---------------------------------
.. automodule:: telethon.tl.gzip_packed
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.message\_container module
---------------------------------------
.. automodule:: telethon.tl.message_container
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.session module
----------------------------
.. automodule:: telethon.tl.session
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.tl\_message module
--------------------------------
.. automodule:: telethon.tl.tl_message
:members:
:undoc-members:
:show-inheritance:
telethon\.tl\.tlobject module
-----------------------------
.. automodule:: telethon.tl.tlobject
:members:
:undoc-members:
:show-inheritance: