Welcome to python-telegram’s documentation

build-status Documentation Status pypi package

Tutorial

How to build a simple echo-bot with python-telegram

Install the library:

python3 -m pip install python-telegram

Let’s create a simple echo-bot, which sends “pong” when it receives “ping”.

Initialize a new telegram client with your credentials:

from telegram.client import Telegram

tg = Telegram(
    api_id=123456,
    api_hash='api_hash',
    phone='+31611111111',
    database_encryption_key='changeme1234',
)

Note

The library (actually tdlib) stores messages database and received files in the /tmp/.tdlib_files/{phone_number}/. You can change this behaviour with the files_directory parameter.

Note

You can use bot tokens: just pass bot_token instead of phone.

After that, you have to login:

tg.login()

In this example we use a blocking version of the login function. You can find an example for non-blocking usage here: Non blocking login. Telegram will send you a code in an SMS or as a Telegram message. If you have enabled 2FA, you will be asked for your password too. After successful login you can start using the library:

# this function will be called
# for each received message
def new_message_handler(update):
    print('New message!')

tg.add_message_handler(new_message_handler)
tg.idle()  # blocking waiting for CTRL+C

This code adds a new message handler which prints a simple text every time it receives a new message. tg.idle() is neccessary to block your script and wait for an exit shortcut (CTRL+C).

If you run this code, you will see something like that:

New message!
New message!

Let’s add more logic to the message handler:

def new_message_handler(update):
    # we want to process only text messages
    message_content = update['message']['content'].get('text', {})
    message_text = message_content.get('text', '').lower()

    if message_text == 'ping':
        chat_id = update['message']['chat_id']
        print(f'Ping has been received from {chat_id}')
        tg.send_message(
            chat_id=chat_id,
            text='pong',
        )

Full code of our new bot:

from telegram.client import Telegram

tg = Telegram(
    api_id=123456,
    api_hash='api_hash',
    phone='+31611111111',
    database_encryption_key='changeme1234',
)
tg.login()

def new_message_handler(update):
    # we want to process only text messages
    message_content = update['message']['content'].get('text', {})
    message_text = message_content.get('text', '').lower()

    if message_text == 'ping':
        chat_id = update['message']['chat_id']
        print(f'Ping has been received from {chat_id}')
        tg.send_message(
            chat_id=chat_id,
            text='pong',
        )

tg.add_message_handler(new_message_handler)
tg.idle()

Done! You have created your first client for the Telegram Messenger.

idle and stop

You must call stop to properly stop python-telegram and tdlib. It calls tdlib’s close method and waits until it’s finished.

When you use idle, it automatically waits until you call stop in another thread, or one of the stop signals is received.

Non blocking login

By default python-telegram uses blocking login method. It presents a prompt to the user for password and code. It makes it hard to use python-telegram as a web app. In this case you might want non blocking login.

telegram.client.Telegram instance keeps current authoriaztion state in authorization_state property. You can also request it from tdlib by calling get_authorization_state() method. login(blocking=False) tries to login, but when Telegram needs a password or a code, it returns current authorization state and gives you ability to provide it manually. When the code is sent (using send_code method), you can call login(bloking=False) again to continue the process. When the user logged it, login returns AuthorizationState.READY.

Let’s have a look at the example.

  1. Initialize the client:
from telegram.client import Telegram, AuthorizationState

tg = Telegram(
    api_id='api_id',
    api_hash='api_hash',
    phone='+31611111111',
    database_encryption_key='changeme1234',
)
  1. Call tg.login(blocking=False). It returns a new AuthorizationState:
code = 'some-code'
password = 'secret-password'

state = tg.login(blocking=False)

if state == AuthorizationState.WAIT_CODE:
    # Telegram expects a pin code
    tg.send_code(code)
    state = tg.login(blocking=False)  # continue the login process

if state == AuthorizationState.WAIT_PASSWORD:
    tg.send_password(password)
    state = tg.login(blocking=False)  # continue the login process

# Logged in.
# You can also check that tg.authorization state is AuthorizationState.READY.

We analyze the authorization state, send code or password and continue the login process after. Currently you can expect only two blocking authorization states: AuthorizationState.WAIT_CODE and AuthorizationState.WAIT_PASSWORD.

You can find the full example in the repository, examples/get_me_non_blocking_login.py.

telegram package

Submodules

telegram.client module

telegram.tdjson module

class telegram.tdjson.TDJson(library_path: Optional[str] = None, verbosity: int = 2)

Bases: object

receive() → Union[None, Dict[Any, Any]]
send(query: Dict[Any, Any]) → None
stop() → None
td_execute(query: Dict[Any, Any]) → Union[Dict[Any, Any], Any]

telegram.utils module

class telegram.utils.AsyncResult(client: Telegram, result_id: Optional[str] = None)

Bases: object

tdlib is asynchronous, and this class helps you get results back. After each API call, you receive AsyncResult object, which you can use to get results back.

parse_update(update: Dict[Any, Any]) → bool
wait(timeout: Optional[int] = None, raise_exc: bool = False) → None

Blocking method to wait for the result

telegram.worker module

class telegram.worker.BaseWorker(queue: queue.Queue)

Bases: object

Base worker class. Each worker must implement the run method to start listening to the queue and calling handler functions

run() → None
stop() → None
class telegram.worker.SimpleWorker(queue: queue.Queue)

Bases: telegram.worker.BaseWorker

Simple one-thread worker

run() → None
stop() → None

Module contents

tdlib

How to build tdlib

Official documentation

Do not forget install the library after:

make install

Also, you can use it with Docker:

You can call any method of tdlib with python-telegram using call_method:

tg = Telegram(...)
params = {'user_id': 1}
result = tg.call_method('getUser', params)

Proxy

How to use a proxy with tdlib

Define proxy parameters and pass them to Telegram:

from telegram.client import Telegram

proxy_type = {
   '@type': 'proxyTypeMtproto',  # 'proxyTypeSocks5', 'proxyTypeHttp'
}
proxy_port = 1234
proxy_server = 'localhost'


tg = Telegram(
    api_id='api_id',
    api_hash='api_hash',
    phone='+31611111111',
    database_encryption_key='changeme1234',
    proxy_server=proxy_server,
    proxy_port=proxy_port,
    proxy_type=proxy_type,
)

Changelog

[0.18.0] - 2023-03-13

  • Added support for tdlib > 1.8.5. (thanks to @JleMyP)

[0.17.0] - 2023-01-25

  • Added import_contacts method. (thanks to @vlad-lf)
  • Added markup support. It is now possible to send formatted text (html/markdown and telegram-specific formats, for example hidden spoiler styling) (thanks to @SKY-ALIN)

[0.16.0] - 2022-08-18

  • Search for the system library first, and fallback to the embedded one if the system was not found.
  • Fixed the finding system library mechanism (thanks to @weirdo-neutrino)
  • tdlib v1.8.5

[0.15.0] - 2021-12-03

  • tdlib v1.7.9. Fixes UPDATE_APP_TO_LOGIN errors.

[0.14.0] - 2020-12-17

  • tdlib v1.7.0

[0.13.0] - 2020-11-16

  • Non-blocking login, see examples/get_me_non_blocking_login.py (thanks to @melfnt).
  • Better stop. python-teleram calls close and waits until tdlib is closed.

[0.12.0] - 2020-03-29

  • New example: examples/clear_group_messages.py (thanks to @h4x3rotab)
  • Proxy support (thanks to @h4x3rotab)
  • New methods: delete_messages, get_supergroup_full_info, create_basic_group_chat. (thanks to @h4x3rotab)
  • Fix #67: fixed infinite waiting for a result during login or for an ok result type.
  • New Telegram initialization parameter: use_secret_chats (True by default) (thanks to @DopeforHope)
  • Fix #81: encryption_key for tdlib database encryption is now being sent to tdlib as a base64 encoded string.

[0.11.0] - 2020-02-15

  • tdlib upgraded to v1.6.0 (from this repository)
  • Added a new parameter to the call_method: block=False. If it is set to True, the method waits for the result from tdlib.
  • Added Telegram.get_message method (thanks to @ali-shokoohi)
  • Fixed a race condition when in some cases AsyncResult.wait() could raise TimeoutError or end up in an endless loop. (thanks to @akamaus)
  • Added a new method: get_user.
  • Added Telegram.remove_update_handler function to remove update handlers.

[0.10.0] - 2019-04-10

  • Incompatible Linux library has been changed, now it’s compiled on Ubuntu with libc.

[0.9.0] - 2019-04-05

  • Incompatible default path for files is changed. Now the library uses an md5 hash of the phone number or bot token instead of just a phone number. It should not be noticeable for most cases, but if you rely on locally saved files or database, you need to pass the files_directory parameter to the telegram.client.Telegram.
  • Fixed problem with randomly raised “Database encryption key is needed” errors during login process. (#12)
  • Fixed stop method execution. (#8)
  • Added examples/bot_login.py example.

[0.8.0] - 2019-03-17

  • telegram.client.Telegram now supports any update type with a new method add_update_handler(handler_type, func)
  • tdlib v 1.3.0
  • Fixed problem with openssl in Dockerfile (#4)

[0.7.0]

  • New method getMe with an example.

[0.6.1] - 2018-05-01

  • Fixes for the Linux pre-compiled tdlib library.

[0.6.0] - 2018-05-01

  • Fixes for the Linux pre-compiled tdlib library.

[0.5.0] - 2018-05-01

  • New required parameter in the telegram.client.Telegram: database_encryption_key.

  • Compiled tdlib files now are in the pypi package (Linux and MacOS).

  • Default location of the tdlib’s files changed to /tmp/.tdlib_files/{phone_number}.

  • Now you can define additional optional params:

    • use_test_dc (default False)
    • device_model
    • system_version
    • system_language_code
    • application_version
    • use_message_database (default True)
  • Added new example: chat_stats.py.

[0.4.0] - 2018-04-29

Added two new methods:

  • get_instant_view - get instant view of a web page
  • call_method - call any method with any params

New example: get_instant_view.py

[0.3.1] - 2018-04-29

  • Logging level in the examples changed to INFO.
  • Added new Makefile command: docker-echo-bot.
  • All docker- commands in the Makefile now mount /tmp/ from a host machine to store tdlib’s files.

[0.3.0] - 2018-04-28

  • Added Dockerfile and Makefile with some examples.
  • Changed directory for tdlib files to /tmp/.tdlib_files_{self.phone}/.

Client for the tdlib library (at very early stage :) ).

Installation

At first you must install tdlib.

How to build tdlib

Official documentation

Do not forget install it after:

make install

Library installation

This library works with Python 3.6+ only.

python3 -m pip install python-telegram

After you must register a new Telegram application.

Now you can start using the library: Tutorial.

Note

You can find more examples here.

Note

The tdlib binary for Linux provided by python-shortcuts is built on Ubuntu with libc since version 0.10.0. Before 0.10.0, Alpine Linux was used with musl.

Docker

This library has a docker image

docker run -i -t --rm \
            -v /tmp/docker-python-telegram/:/tmp/ \
            akhmetov/python-telegram \
            python3 /app/examples/send_message.py $(API_ID) $(API_HASH) $(PHONE) $(CHAT_ID) $(TEXT)