Metadata-Version: 2.4
Name: ScoloTeleuser
Version: 0.1.0
Summary: Typed asynchronous TDLib client for Telegram user accounts.
Author: G3tFun
License-Expression: MIT
Project-URL: Homepage, https://github.com/G3tFun/ScoloTeleuser
Project-URL: Repository, https://github.com/G3tFun/ScoloTeleuser
Project-URL: Issues, https://github.com/G3tFun/ScoloTeleuser/issues
Keywords: telegram,tdlib,mtproto,asyncio,client
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: tdjson
Requires-Dist: tdjson<2,>=1.8.66; extra == "tdjson"
Provides-Extra: logging
Requires-Dist: ScoloLogger>=0.1.0; extra == "logging"
Dynamic: license-file

# ScoloTeleuser

ScoloTeleuser is a typed asynchronous Python client for a **Telegram user account**. It uses TDLib’s official JSON interface for MTProto networking, encryption, local storage, reconnection and ordered updates, while exposing a concise `asyncio` API for authorization, chats, messages and updates.[1] [2]

The package is intended for transparent personal-account integrations. It does not provide bulk messaging, data extraction, artificial counter manipulation, ghost-mode behaviour, bypasses for disappearing content, or AI dataset features. Telegram requires third-party clients to act with the user’s knowledge and consent, preserve normal Telegram behaviour, and not use platform data for AI/ML development.[3]

## Installation

The base package has no mandatory Python dependencies:

```bash
pip install ScoloTeleuser
```

For the default prebuilt TDLib runtime on supported Linux, macOS and Windows systems:

```bash
pip install "ScoloTeleuser[tdjson]"
```

You may instead build TDLib yourself and set `TDJSON_LIBRARY_PATH` to `libtdjson` (`tdjson.dll` on Windows), or pass `tdjson_library_path=` to `Client`.[2]

## Credentials and session storage

Create an application at [my.telegram.org/apps](https://my.telegram.org/apps) and provide **your own** `api_id` and `api_hash`. Telegram requires application-specific credentials and monitors unofficial clients for abuse.[4]

The session configuration requires a non-empty local database encryption key. Store `api_hash` and this key in a secret manager or environment variables; do not commit them, print them, or place them in a public session file. On POSIX systems ScoloTeleuser creates the session directories with `0700` permissions and tightens created database-file permissions to `0600`.

```python
import os
from pathlib import Path

from scoloteleuser import SessionConfig

config = SessionConfig(
    api_id=int(os.environ["TELEGRAM_API_ID"]),
    api_hash=os.environ["TELEGRAM_API_HASH"],
    database_directory=Path.home() / ".local" / "share" / "my-app" / "telegram",
    database_encryption_key=os.environ["TELEGRAM_DATABASE_KEY"],
)
```

## Interactive login

ScoloTeleuser never reads a login code or 2FA password by itself. The application presents the current authorization state and obtains each value directly from the account owner.

```python
from scoloteleuser import Client

async with Client(config) as telegram:
    state = telegram.authorization_state

    if state and state.kind == "WaitPhoneNumber":
        state = await telegram.send_phone_number("+15551234567")

    if state and state.kind == "WaitCode":
        state = await telegram.check_code(input("Telegram code: "))

    if state and state.kind == "WaitPassword":
        state = await telegram.check_password(input("2FA password: "))

    await telegram.wait_until_ready()
    me = await telegram.get_me()
    print(me.first_name)
```

TDLib’s authorization flow can also request email verification or registration. These states remain visible through `authorization_state`; call the corresponding TDLib method via `invoke()` until a typed helper is added.

> Do not reuse the sample API ID embedded in Telegram’s open-source applications. Telegram documents that it is not suitable for released end-user applications.[4]

## Chats and messages

Use a long-lived client and close it through the async context manager. `send_text` sends one ordinary message to a chat that the application has explicitly selected.

```python
async with Client(config) as telegram:
    await telegram.wait_until_ready()

    chat = await telegram.search_public_chat("telegram")
    message = await telegram.send_text(chat.id, "Hello from my account")
    print(message.id)

    history = await telegram.get_chat_history(chat.id, limit=20)
    for item in history:
        print(item.date, item.text)
```

The client exposes `get_me`, `get_chat`, `search_public_chat`, `get_chat_history`, `send_text`, `delete_messages`, and `mark_chat_read`. Each helper checks that TDLib is authorized before sending the request.

## Updates and handlers

TDLib receives responses and updates asynchronously. ScoloTeleuser serializes them through one receiver task, preserves TDLib receive order, correlates method responses with private `@extra` IDs, and delivers all other objects as `Update` instances.[1]

```python
from scoloteleuser import Update

async def observe(update: Update) -> None:
    if update.kind == "updateNewMessage":
        print(update.raw)

async with Client(config) as telegram:
    telegram.add_handler(observe)
    await telegram.wait_until_ready()

    async for update in telegram.updates():
        if update.kind == "updateNewMessage":
            break
```

Handler exceptions are isolated and written through Python logging; they do not stop TDLib’s receive loop. Never log `update.raw` blindly in production because it can contain private message content and metadata.

## Raw TDLib methods

`invoke()` supports current TDLib schema methods that do not yet have typed helpers. It requires a non-empty `@type` and owns `@extra` internally.

```python
async with Client(config) as telegram:
    await telegram.wait_until_ready()
    result = await telegram.invoke({"@type": "getOption", "name": "version"})
```

Use raw methods only after consulting the [current TDLib API documentation](https://core.telegram.org/tdlib/docs/). ScoloTeleuser validates lifecycle and errors but cannot make an arbitrary raw method safe for a particular product.

## Safety boundaries

| Included | Deliberately excluded |
|---|---|
| Explicit account login, chats, normal read state, messages, events, encrypted local session storage. | Bulk messaging, spam/flood automation, scraping/export API, automatic group joining, counter manipulation, ghost mode, typing/read-state bypasses, disappearing-message circumvention, AI dataset collection. |

Telegram states that flooding, spam, and fake subscriber or channel-view counters can result in permanent bans.[4] Treat the account session like a password: anyone with access to it can act as the account owner.

## Compatibility

ScoloTeleuser requires Python 3.10+ and TDLib major version 1. The `tdjson` extra currently pins a compatible prebuilt runtime range; use `await client.tdlib_version()` for an explicit runtime check.

## License

MIT.

## References

[1]: https://core.telegram.org/tdlib/getting-started "Telegram: Getting started with TDLib"
[2]: https://core.telegram.org/tdlib "Telegram Database Library"
[3]: https://core.telegram.org/api/terms "Telegram API Terms of Service"
[4]: https://core.telegram.org/api/obtaining_api_id "Telegram: Creating your Telegram Application"
