### Install python-telegram Library
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
Use this command to install the python-telegram library.
```bash
python3 -m pip install python-telegram
```
--------------------------------
### Install tdlib
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tdlib.md
Install the tdlib library after building it. This command is typically run after a successful build process.
```bash
make install
```
--------------------------------
### Install python-telegram
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/README.md
Install the library using pip. Requires Python 3.9+ and Linux or MacOS.
```shell
pip install python-telegram
```
--------------------------------
### Run All Tests with Tox
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CONTRIBUTING.md
Execute all defined test environments using tox. Ensure tox is installed before running.
```shell
tox
```
--------------------------------
### Initialize and Connect Telegram Client
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Instantiate a Telegram client for user or bot accounts. The client starts background threads immediately. Ensure you have your API ID and hash from my.telegram.org.
```python
from telegram.client import Telegram
# User account login
tg = Telegram(
api_id=12345678, # from https://my.telegram.org/apps
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="my-secret-key",
files_directory="/tmp/.tdlib_files/", # optional; defaults to /tmp/.tdlib_files/
use_test_dc=False,
use_message_database=True,
use_secret_chats=True,
tdlib_verbosity=1, # 0=minimal, 5=verbose TDLib logs
login=True, # call login() automatically
)
tg.stop()
# Bot account login
tg_bot = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
bot_token="110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw",
database_encryption_key="my-secret-key",
login=True,
)
tg_bot.stop()
```
--------------------------------
### Run python-telegram examples via Docker
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Shows how to execute python-telegram scripts, such as sending a message or running the echo bot, within an isolated Docker container. This requires mounting a volume for temporary data.
```sh
# Send a message via Docker
docker run -i -t --rm \
-v /tmp/docker-python-telegram/:/tmp/ \
akhmetov/python-telegram \
python3 /app/examples/send_message.py \
12345678 \
"0123456789abcdef0123456789abcdef" \
"+15551234567" \
"-1001234567890" \
"Hello from Docker!"
# Run the echo bot via Docker
docker run -i -t --rm \
-v /tmp/docker-python-telegram/:/tmp/ \
akhmetov/python-telegram \
python3 /app/examples/echo_bot.py \
12345678 \
"0123456789abcdef0123456789abcdef" \
"+15551234567"
```
--------------------------------
### Telegram.__init__
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Initializes a Telegram client instance and connects to the TDLib JSON interface. It can optionally perform the full login flow upon instantiation. Requires either a phone number or a bot token for authentication. The client starts background threads immediately.
```APIDOC
## Telegram.__init__ — Initialize and connect the client
Creates a `Telegram` client instance, initializes the TDLib JSON interface, and optionally performs the full login flow in one step. Either `phone` or `bot_token` must be provided. The client starts background threads immediately upon instantiation.
```python
from telegram.client import Telegram
# User account login
tg = Telegram(
api_id=12345678, # from https://my.telegram.org/apps
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="my-secret-key",
files_directory="/tmp/.tdlib_files/", # optional; defaults to /tmp/.tdlib_files/
use_test_dc=False,
use_message_database=True,
use_secret_chats=True,
tdlib_verbosity=1, # 0=minimal, 5=verbose TDLib logs
login=True, # call login() automatically
)
tg.stop()
# Bot account login
tg_bot = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
bot_token="110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw",
database_encryption_key="my-secret-key",
login=True,
)
tg_bot.stop()
```
```
--------------------------------
### Login to Telegram
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
Call the login method to authenticate your Telegram client. This example uses a blocking login. You will receive a code via SMS or Telegram message, and potentially be asked for a 2FA password.
```python
tg.login()
```
--------------------------------
### Get Supergroup Full Info and Create Basic Group Chat
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Retrieves extended information about a supergroup, including its basic group predecessor. If a basic group ID is found, a chat object is created from it to access its history.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
SUPERGROUP_ID = 1234567890
r = tg.get_supergroup_full_info(SUPERGROUP_ID)
r.wait(raise_exc=True)
basic_group_id = r.update.get("upgraded_from_basic_group_id", 0)
print(f"Supergroup full info: member_count={r.update['member_count']}")
if basic_group_id:
r2 = tg.create_basic_group_chat(basic_group_id)
r2.wait(raise_exc=True)
print(f"Basic group chat ID: {r2.update['id']}")
tg.stop()
```
--------------------------------
### Telegram.get_chat_history
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Fetches a batch of messages from a chat in reverse chronological order. Use `from_message_id=0` to start from the latest and paginate using the last received message ID.
```APIDOC
## Telegram.get_chat_history — Fetch messages from a chat
Retrieves a batch of messages from a chat in reverse chronological order. Use `from_message_id=0` to start from the latest, then paginate using the last received message ID.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
CHAT_ID = -1001234567890
from_msg_id = 0
# Paginate through entire chat history
while True:
result = tg.get_chat_history(
chat_id=CHAT_ID,
limit=100,
from_message_id=from_msg_id,
offset=0,
only_local=False,
)
result.wait(raise_exc=True)
messages = result.update.get("messages", [])
if not messages:
break
for msg in messages:
if msg["content"]["@type"] == "messageText":
print(msg["id"], msg["content"]["text"]["text"])
from_msg_id = messages[-1]["id"]
tg.stop()
```
```
--------------------------------
### Fetch Chat History with Telegram Client
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Use `get_chat_history` to retrieve messages in reverse chronological order. Set `from_message_id=0` to start from the latest message and paginate using the last received message ID.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
CHAT_ID = -1001234567890
from_msg_id = 0
# Paginate through entire chat history
while True:
result = tg.get_chat_history(
chat_id=CHAT_ID,
limit=100,
from_message_id=from_msg_id,
offset=0,
only_local=False,
)
result.wait(raise_exc=True)
messages = result.update.get("messages", [])
if not messages:
break
for msg in messages:
if msg["content"]["@type"] == "messageText":
print(msg["id"], msg["content"]["text"]["text"])
from_msg_id = messages[-1]["id"]
tg.stop()
```
--------------------------------
### Build Docker Image
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Build the Docker image for the project. This command assumes a `Makefile` with a `docker/build` target is present.
```bash
make docker/build
```
--------------------------------
### Initialize Telegram Client
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
Initialize a new Telegram client with your API credentials and phone number. Ensure you replace the placeholder values with your actual information.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=123456,
api_hash='api_hash',
phone='+31611111111',
database_encryption_key='changeme1234',
)
```
--------------------------------
### Fetch Telegram Instant View for a URL
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Requests an Instant View preview of a webpage. Returns a 404 error if the page has no Instant View template. The `force_full` parameter can be used to attempt fetching the full content.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result = tg.get_web_page_instant_view(
url="https://telegram.org/blog/100-million",
force_full=True,
)
result.wait()
if result.error:
print(f"Error: {result.error_info}")
else:
title_block = result.update["page_blocks"][0]
print(title_block["title"]["text"])
tg.stop()
```
--------------------------------
### Telegram.get_web_page_instant_view
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Requests an Instant View preview of a webpage via Telegram's servers. Returns a 404 error if the page has no Instant View template.
```APIDOC
## `Telegram.get_web_page_instant_view` — Fetch Telegram Instant View for a URL
Requests an Instant View preview of a webpage via Telegram's servers. Returns `404` if the page has no Instant View template.
### Parameters
#### Query Parameters
- **url** (string) - Required - The URL of the webpage to fetch the Instant View for.
- **force_full** (boolean) - Optional - If true, attempts to fetch the full Instant View even if a preview is available.
### Request Example
```python
tg.get_web_page_instant_view(
url="https://telegram.org/blog/100-million",
force_full=True,
)
```
### Response
#### Success Response (200)
- **page_blocks** (list) - A list of blocks representing the content of the Instant View.
- **title** (dict) - Contains the title of the page.
- **text** (string) - The title text.
### Response Example
```json
{
"page_blocks": [
{
"title": {
"text": "100 Million Active Users!"
}
}
]
}
```
```
--------------------------------
### Build PyPI Package
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Build the Python package for distribution on PyPI. This command relies on a `Makefile` with a `build-pypi` target.
```bash
make build-pypi
```
--------------------------------
### Initialize Telegram Client
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/non_blocking_login.md
Initialize the Telegram client with your API credentials and phone number. This sets up the client for non-blocking operations.
```python
from telegram.client import Telegram, AuthorizationState
tg = Telegram(
api_id='api_id',
api_hash='api_hash',
phone='+31611111111',
database_encryption_key='changeme1234',
)
```
--------------------------------
### Basic Telegram Client Usage
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/README.md
Initialize the Telegram client, log in, preload chats, send a message with spoiler text, and wait for the result. Ensure to call `tg.stop()` at the end.
```python
from telegram.client import Telegram
from telegram.text import Spoiler
tg = Telegram(
api_id='api_id',
api_hash='api_hash',
phone='+31611111111', # you can pass 'bot_token' instead
database_encryption_key='changekey123',
files_directory='/tmp/.tdlib_files/',
)
tg.login()
# If this is the first run, the library needs to preload all chats.
# Otherwise, the message will not be sent.
result = tg.get_chats()
result.wait()
chat_id: int
result = tg.send_message(chat_id, Spoiler('Hello world!'))
# `tdlib` is asynchronous, so `python-telegram` always returns an `AsyncResult` object.
# You can receive a result with the `wait` method of this object.
result.wait()
print(result.update)
tg.stop() # You must call `stop` at the end of the script.
```
--------------------------------
### Run Format Check with Tox
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Check code formatting using Tox. This command verifies if the code adheres to the project's formatting standards, usually managed by Ruff.
```bash
tox -e ruff-format
```
--------------------------------
### Fetch User Information with Telegram Client
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Use `get_user` for basic info or `get_user_full_info` for extended details like bio. Ensure the client is logged in before calling.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
USER_ID = 123456789
result = tg.get_user(USER_ID)
result.wait(raise_exc=True)
print(result.update["first_name"], result.update["username"])
result_full = tg.get_user_full_info(USER_ID)
result_full.wait(raise_exc=True)
print(result_full.update)
# {'@type': 'userFullInfo', 'bio': {'@type': 'formattedText', 'text': '...', ...}, ...}
tg.stop()
```
--------------------------------
### Configure Proxy for Telegram Client
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/proxy.md
Define proxy parameters and pass them to the Telegram class constructor to establish a proxied connection. Supports MTProto, SOCKS5, and HTTP proxies.
```python
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,
)
```
--------------------------------
### Run Linting with Tox
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Perform linting checks using Tox. This command runs the configured linter, typically Ruff.
```bash
tox -e ruff
```
--------------------------------
### Configure Proxy Connection
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Proxy settings are passed to the Telegram constructor before authentication. Supports MTProto, SOCKS5, and HTTP proxy types. Ensure the correct proxy type and credentials are provided for a successful connection.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
proxy_server="proxy.example.com",
proxy_port=1080,
proxy_type={"@type": "proxyTypeSocks5", "username": "user", "password": "pass"},
login=True,
)
result = tg.get_me()
result.wait(raise_exc=True)
print(result.update["username"])
tg.stop()
# MTProto proxy (no username/password)
tg_mtproto = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
proxy_server="mtproto.example.com",
proxy_port=443,
proxy_type={"@type": "proxyTypeMtproto"},
)
```
--------------------------------
### Full Echo Bot Code
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
This is the complete code for the simple echo-bot, combining client initialization, login, message handling for 'ping'/'pong', and the idle call to keep the bot running.
```python
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()
is_outgoing = update['message']['is_outgoing']
if not is_outgoing and 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()
```
--------------------------------
### Retrieve Current User Profile Information
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Fetches information about the authenticated user or bot account by mapping to TDLib's `getMe` method. Requires successful login.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result = tg.get_me()
result.wait(raise_exc=True)
print(result.update)
# {
# '@type': 'user',
# 'id': 987654321,
```
--------------------------------
### Run Single Test with Tox
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Execute a specific test case within a given Python environment using Tox. Use the `-k` flag followed by the test name or pattern.
```bash
tox -e py312 -- -k test_send_message
```
--------------------------------
### Proxy Configuration
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Configures network connections to use a proxy server. Supported proxy types include MTProto, SOCKS5, and HTTP. Proxy settings are applied during the `Telegram` client initialization.
```APIDOC
## Proxy configuration — Connect through MTProto, SOCKS5, or HTTP proxy
Proxy settings are passed to the `Telegram` constructor and applied before authentication. Supported types are `proxyTypeMtproto`, `proxyTypeSocks5`, and `proxyTypeHttp`.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
proxy_server="proxy.example.com",
proxy_port=1080,
proxy_type={
"@type": "proxyTypeSocks5",
"username": "user",
"password": "pass"
},
login=True,
)
result = tg.get_me()
result.wait(raise_exc=True)
print(result.update["username"])
tg.stop()
# MTProto proxy (no username/password)
tg_mtproto = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
proxy_server="mtproto.example.com",
proxy_port=443,
proxy_type={
"@type": "proxyTypeMtproto"
},
)
```
```
--------------------------------
### Run python-telegram via Docker
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/README.md
Execute a Python script using the python-telegram Docker image. Mounts a volume for temporary files and passes necessary arguments.
```sh
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)
```
--------------------------------
### Authenticate with Telegram using Login Flow
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Handles the TDLib authorization state machine. In blocking mode, it prompts for credentials via stdin. In non-blocking mode, it returns the current state for programmatic credential supply.
```python
from telegram.client import Telegram, AuthorizationState
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
)
# Non-blocking login — useful for web apps or custom UI flows
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_CODE:
code = input("Enter the Telegram code you received: ")
tg.send_code(code)
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_PASSWORD:
import getpass
pwd = getpass.getpass("Enter your 2FA password: ")
tg.send_password(pwd)
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_REGISTRATION:
tg.register_user("Jane", "Doe")
state = tg.login(blocking=False)
assert state == AuthorizationState.READY
print("Logged in successfully")
tg.stop()
```
--------------------------------
### Run Type Checking with Tox
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Perform strict type checking using Tox and Mypy. Ensure Mypy is configured in your `tox.ini`.
```bash
tox -e mypy
```
--------------------------------
### Telegram.get_user / get_user_full_info
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Fetches user information. `get_user` retrieves basic details by ID, while `get_user_full_info` provides extended profile information.
```APIDOC
## Telegram.get_user / get_user_full_info — Fetch user information
`get_user` returns basic info for a user by ID; `get_user_full_info` returns extended profile details including bio, linked chat, etc.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
USER_ID = 123456789
result = tg.get_user(USER_ID)
result.wait(raise_exc=True)
print(result.update["first_name"], result.update["username"])
result_full = tg.get_user_full_info(USER_ID)
result_full.wait(raise_exc=True)
print(result_full.update)
# {'@type': 'userFullInfo', 'bio': {'@type': 'formattedText', 'text': '...', ...}, ...}
tg.stop()
```
```
--------------------------------
### Call tdlib Method
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/README.md
Use `call_method` to invoke any tdlib function with specified parameters. Refer to tdlib documentation for available functions and parameters.
```python
tg.call_method('getUser', params={'user_id': user_id})
```
--------------------------------
### Telegram.login
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Authenticates the client with Telegram by running the TDLib authorization state machine. In blocking mode, it interactively prompts for the SMS code and 2FA password. In non-blocking mode, it returns the current `AuthorizationState` for programmatic credential supply.
```APIDOC
## Telegram.login — Authenticate with Telegram
Runs the full TDLib authorization state machine. In blocking mode (default), prompts interactively for SMS code and 2FA password via stdin. In non-blocking mode, returns the current `AuthorizationState` so the caller can supply credentials programmatically.
```python
from telegram.client import Telegram, AuthorizationState
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
)
# Non-blocking login — useful for web apps or custom UI flows
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_CODE:
code = input("Enter the Telegram code you received: ")
tg.send_code(code)
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_PASSWORD:
import getpass
pwd = getpass.getpass("Enter your 2FA password: ")
tg.send_password(pwd)
state = tg.login(blocking=False)
if state == AuthorizationState.WAIT_REGISTRATION:
tg.register_user("Jane", "Doe")
state = tg.login(blocking=False)
assert state == AuthorizationState.READY
print("Logged in successfully")
tg.stop()
```
```
--------------------------------
### Call Any TDLib Method Directly
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
A low-level method to invoke any TDLib function by name. The `params` argument accepts a dictionary of parameters for the TDLib function. An optional `block=True` parameter can be used to wait synchronously for the result.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
# Search for public chats
result = tg.call_method("searchPublicChat", params={"username": "telegram"})
result.wait(raise_exc=True)
print(result.update["title"])
# Get current network type
result = tg.call_method("getNetworkStatistics", block=True)
print(result.update)
# Forward a message
result = tg.call_method("forwardMessages", params={
"chat_id": -1001111111111,
"from_chat_id": -1001234567890,
"message_ids": [1234567890123],
"send_copy": False,
"remove_caption": False,
})
result.wait(raise_exc=True)
tg.stop()
```
--------------------------------
### Auto-fix Linting and Formatting
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Automatically fix linting and formatting issues in the codebase. This command uses Ruff to check and fix code style problems.
```bash
ruff check --fix && ruff format
```
--------------------------------
### Non-blocking Login Flow
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/non_blocking_login.md
Perform a non-blocking login by checking the authorization state and providing the necessary code or password when prompted. This method allows the application to continue running while waiting for user input.
```python
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.
```
--------------------------------
### Send Rich Text Messages with python-telegram
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Demonstrates how to compose and send messages with rich text formatting using the `telegram.text` module. Ensure you have initialized the `Telegram` client and have a valid `CHAT_ID`.
```python
from telegram.client import Telegram
from telegram.text import (
Bold, Italic, Underline, Strikethrough, Spoiler,
Code, InlineCode, Link, Chain, PlainText,
OrderedList, UnorderedList,
)
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
CHAT_ID = -1001234567890
# Compose a mixed-format message
message = Chain(
Bold("Status Update\n"),
PlainText("Server "),
Code("prod-01"),
PlainText(" is "),
Italic("currently "),
Spoiler("offline"),
PlainText(". See "),
Link("dashboard", "https://example.com/dashboard"),
PlainText(" for details."),
)
tg.send_message(chat_id=CHAT_ID, text=message).wait(raise_exc=True)
# Ordered list
todo = OrderedList([
PlainText("Deploy hotfix"),
PlainText("Notify on-call team"),
PlainText("Update status page"),
])
tg.send_message(chat_id=CHAT_ID, text=todo).wait(raise_exc=True)
tg.stop()
```
--------------------------------
### Run Specific Test with Tox (Python 3.12)
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CONTRIBUTING.md
Run a specific test case, identified by '-k test_add_message_handler', within the Python 3.12 tox environment. This is useful for targeted testing.
```shell
tox -e py312 -- -k test_add_message_handler
```
--------------------------------
### Run Tox Tests for Specific Python Version
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/CLAUDE.md
Execute Tox tests for a particular Python version. Replace `py312` with the desired Python environment name.
```bash
tox -e py312
```
--------------------------------
### Keep Client Alive and Clean Shutdown
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
The idle() method blocks until a POSIX signal is received, then calls stop(). The stop() method ensures a clean shutdown by sending TDLib's close command and joining background threads. This is crucial for proper resource management before the process exits.
```python
import signal
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
def on_message(update):
print("New message:", update["message"]["content"])
tg.add_message_handler(on_message)
# Block until Ctrl-C or kill signal; handles shutdown automatically
tg.idle(stop_signals=(signal.SIGINT, signal.SIGTERM))
# For script-style usage without idle():
# result = tg.get_me()
# result.wait()
# tg.stop()
```
--------------------------------
### Send Text Messages with Formatting
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Sends messages to a chat using either plain text or rich-text elements from `telegram.text`. The chat must exist in TDLib's local database. Use `get_chats()` first for new sessions.
```python
from telegram.client import Telegram
from telegram.text import Bold, Italic, Spoiler, Chain, Link
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
CHAT_ID = -1001234567890
# Plain text
result = tg.send_message(chat_id=CHAT_ID, text="Hello, world!")
result.wait(raise_exc=True)
print(result.update)
# {'@type': 'message', 'id': 123456, 'chat_id': -1001234567890, ...}
# Rich text using telegram.text elements
formatted = Chain(Bold("Alert: "), Italic("server is "), Spoiler("down"))
result = tg.send_message(chat_id=CHAT_ID, text=formatted)
result.wait(raise_exc=True)
# Link
result = tg.send_message(chat_id=CHAT_ID, text=Link("Click here", "https://example.com"))
result.wait(raise_exc=True)
tg.stop()
```
--------------------------------
### Call tdlib Method with python-telegram
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tdlib.md
Use the call_method function from the python-telegram library to interact with tdlib. This requires initializing a Telegram object and providing the method name and parameters.
```python
tg = Telegram(...)
params = {'user_id': 1}
result = tg.call_method('getUser', params)
```
--------------------------------
### AsyncResult
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Handles asynchronous responses from TDLib methods. Each method call returns an `AsyncResult` object, which allows blocking until a result is available using `.wait()`, inspecting the response via `.update`, and checking for errors using `.error` or `.error_info`. Timeouts are supported.
```APIDOC
## `AsyncResult` — Handle asynchronous TDLib responses
Every `Telegram` method returns an `AsyncResult`. Call `.wait()` to block until the result arrives, inspect `.update` for the response dict, and check `.error` / `.error_info` for failures. Supports an optional timeout.
```python
from telegram.client import Telegram
from telegram.utils import AsyncResult
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result: AsyncResult = tg.get_me()
try:
result.wait(timeout=10, raise_exc=True) # raises RuntimeError on TDLib error
except TimeoutError:
print("Request timed out")
except RuntimeError as e:
print(f"TDLib error: {e}")
else:
if result.error:
print("Error:", result.error_info)
else:
print("Success:", result.update)
tg.stop()
```
```
--------------------------------
### Import Contacts by Phone Number
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Adds or updates contacts in the user's address book using their phone numbers. The result contains a list of Telegram user IDs matched to the provided numbers. A user ID of 0 indicates the phone number is not registered on Telegram.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
contacts = [
{"phone_number": "+15559876543", "first_name": "Alice", "last_name": "Smith"},
{"phone_number": "+15551112222", "first_name": "Bob", "last_name": "Jones"},
]
result = tg.import_contacts(contacts)
result.wait(raise_exc=True)
print(result.update)
# {'@type': 'importedContacts', 'user_ids': [111111111, 0], 'importer_count': [3, 0]}
# user_id == 0 means that phone number is not registered on Telegram
tg.stop()
```
--------------------------------
### Telegram.idle / stop
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Manages the client's lifecycle by blocking the main thread until a termination signal is received (using `idle()`) and then performing a clean shutdown (using `stop()`). `stop()` ensures all pending operations are completed and the TDLib client is properly closed.
```APIDOC
## `Telegram.idle` / `stop` — Keep alive and clean shutdown
`idle()` blocks the calling thread until a POSIX signal (SIGINT, SIGTERM, or SIGABRT) is received, then calls `stop()`. `stop()` sends TDLib's `close` command, waits for the `CLOSED` authorization state, joins background threads, and destroys the TDLib client. Always call `stop()` before the process exits.
```python
import signal
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
def on_message(update):
print("New message:", update["message"]["content"])
tg.add_message_handler(on_message)
# Block until Ctrl-C or kill signal; handles shutdown automatically
tg.idle(stop_signals=(signal.SIGINT, signal.SIGTERM))
# For script-style usage without idle():
# result = tg.get_me()
# result.wait()
# tg.stop()
```
```
--------------------------------
### Add Message Handler and Idle
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
Add a message handler function to process incoming messages and then call tg.idle() to keep the bot running and responsive. tg.idle() is a blocking call that waits for an exit signal (e.g., CTRL+C).
```python
# 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.
```
--------------------------------
### Track Message Confirmation with Event
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Use threading.Event to wait for server confirmation of a sent message. Remove the handler when no longer needed. Blocks until SIGINT/SIGTERM/SIGABRT is received.
```python
import threading
# Track when a sent message is confirmed by the server
sent_event = threading.Event()
def on_send_succeeded(update):
print(f"Message confirmed. New ID: {update['message']['id']}")
sent_event.set()
tg.add_update_handler("updateMessageSendSucceeded", on_send_succeeded)
result = tg.send_message(chat_id=-1001234567890, text="Hello")
result.wait()
sent_event.wait(timeout=30)
# Remove a handler when no longer needed
tg.remove_update_handler("updateMessageSendSucceeded", on_send_succeeded)
tg.idle() # blocks until SIGINT/SIGTERM/SIGABRT
tg.stop()
```
--------------------------------
### Retrieve Chat List with Telegram Client
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Call `get_chats` to fetch a page of chat IDs. This populates the local cache, which is necessary before sending messages. Use `get_chat` to fetch details for a specific chat.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
# Fetch up to 200 chats from the beginning of the list
result = tg.get_chats(offset_order=9223372036854775807, offset_chat_id=0, limit=200)
result.wait(raise_exc=True)
print(result.update)
# {'@type': 'chats', 'chat_ids': [-1001234567890, 987654321, ...], '@extra': {...}}
# Then fetch details for a specific chat
chat_result = tg.get_chat(-1001234567890)
chat_result.wait(raise_exc=True)
print(chat_result.update["title"])
tg.stop()
```
--------------------------------
### Register Update Callbacks
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Registers a callback function to be executed when a specific TDLib update type is received. `add_message_handler` is a shortcut for `add_update_handler('updateNewMessage', func)`. Handlers are processed in a worker thread with a default queue size of 1000.
```python
import threading
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
# Echo bot: reply "pong" to every "ping"
def on_message(update):
content = update["message"]["content"]
if content["@type"] != "messageText":
return
text = content["text"]["text"].strip().lower()
if not update["message"]["is_outgoing"] and text == "ping":
tg.send_message(chat_id=update["message"]["chat_id"], text="pong")
tg.add_message_handler(on_message)
```
--------------------------------
### Telegram.get_me
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Retrieves profile information for the currently authenticated user or bot. This method corresponds to TDLib's `getMe` function.
```APIDOC
## Telegram.get_me — Get the current user's profile
Returns information about the authenticated account (user or bot). Maps to TDLib's `getMe` method.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result = tg.get_me()
result.wait(raise_exc=True)
print(result.update)
# {
# '@type': 'user',
# 'id': 987654321,
```
--------------------------------
### Telegram.get_supergroup_full_info / Telegram.create_basic_group_chat
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Retrieves extended information about a supergroup, including its basic group predecessor. `create_basic_group_chat` opens or creates a chat object from a basic group ID for accessing its history.
```APIDOC
## `Telegram.get_supergroup_full_info` / `create_basic_group_chat` — Supergroup and group utilities
`get_supergroup_full_info` retrieves extended information about a supergroup including its basic group predecessor. `create_basic_group_chat` opens/creates a chat object from a basic group ID so its history can be accessed.
### Parameters
#### `get_supergroup_full_info`
- **supergroup_id** (int) - Required - The ID of the supergroup.
#### `create_basic_group_chat`
- **basic_group_id** (int) - Required - The ID of the basic group.
### Request Example
```python
SUPERGROUP_ID = 1234567890
r = tg.get_supergroup_full_info(SUPERGROUP_ID)
r.wait(raise_exc=True)
basic_group_id = r.update.get("upgraded_from_basic_group_id", 0)
if basic_group_id:
r2 = tg.create_basic_group_chat(basic_group_id)
r2.wait(raise_exc=True)
```
### Response
#### `get_supergroup_full_info` Success Response (200)
- **member_count** (int) - The number of members in the supergroup.
- **upgraded_from_basic_group_id** (int) - The ID of the basic group from which this supergroup was upgraded, if applicable.
#### `create_basic_group_chat` Success Response (200)
- **id** (int) - The ID of the created basic group chat.
```
--------------------------------
### Echo Ping Pong Logic
Source: https://github.com/alexander-akhmetov/python-telegram/blob/main/docs/source/tutorial.md
Enhance the message handler to specifically respond to 'ping' messages with 'pong'. This code checks if the message is not outgoing and its text content is 'ping', then sends 'pong' back to the same chat.
```python
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()
is_outgoing = update['message']['is_outgoing']
if not is_outgoing and 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',
)
```
--------------------------------
### Telegram.call_method
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
A low-level method to invoke any TDLib function directly by its name. Supports an optional `block` parameter for synchronous waiting.
```APIDOC
## `Telegram.call_method` — Call any TDLib method directly
Low-level escape hatch to invoke any [TDLib function](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html) by name. Supports an optional `block=True` parameter to wait synchronously for the result.
### Parameters
- **method_name** (string) - Required - The name of the TDLib function to call.
- **params** (dict) - Optional - A dictionary of parameters for the TDLib function.
- **block** (boolean) - Optional - If true, waits synchronously for the result. Defaults to false.
### Request Example
```python
# Search for public chats
result = tg.call_method("searchPublicChat", params={"username": "telegram"})
result.wait(raise_exc=True)
# Get current network type (synchronously)
result = tg.call_method("getNetworkStatistics", block=True)
# Forward a message
result = tg.call_method("forwardMessages", params={
"chat_id": -1001111111111,
"from_chat_id": -1001234567890,
"message_ids": [1234567890123],
"send_copy": False,
"remove_caption": False,
})
result.wait(raise_exc=True)
```
### Response
#### Success Response (200)
- **update** (dict) - The result of the TDLib function call. The structure depends on the specific function invoked.
### Response Example
```json
{
"update": {
"@type": "chat",
"id": 123456789012345,
"title": "Telegram"
}
}
```
```
--------------------------------
### Handle Asynchronous TDLib Responses
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Every Telegram method returns an AsyncResult. Use .wait() to block for the result, inspect .update for the response, and check .error/.error_info for failures. Supports optional timeouts and exception raising for TDLib errors.
```python
from telegram.client import Telegram
from telegram.utils import AsyncResult
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result: AsyncResult = tg.get_me()
try:
result.wait(timeout=10, raise_exc=True) # raises RuntimeError on TDLib error
except TimeoutError:
print("Request timed out")
except RuntimeError as e:
print(f"TDLib error: {e}")
else:
if result.error:
print("Error:", result.error_info)
else:
print("Success:", result.update)
tg.stop()
```
--------------------------------
### Fetch Single Message by ID with Telegram Client
Source: https://context7.com/alexander-akhmetov/python-telegram/llms.txt
Use `get_message` to retrieve a specific message using its `chat_id` and `message_id`. This is useful for looking up a known message after receiving a notification.
```python
from telegram.client import Telegram
tg = Telegram(
api_id=12345678,
api_hash="0123456789abcdef0123456789abcdef",
phone="+15551234567",
database_encryption_key="changeme1234",
login=True,
)
result = tg.get_message(chat_id=-1001234567890, message_id=1234567890123)
result.wait(raise_exc=True)
print(result.update)
# {
# '@type': 'message',
# 'id': 1234567890123,
# 'sender_user_id': 987654321,
# 'chat_id': -1001234567890,
# 'content': {'@type': 'messageText', 'text': {'text': 'Hello'}},
# ...
# }
tg.stop()
```