Metadata-Version: 2.4
Name: Scolocrizm
Version: 0.1.0
Summary: A forward-compatible async and sync framework for the Telegram Bot API.
Author: G3tFun
License-Expression: MIT
Project-URL: Homepage, https://github.com/G3tFun/Scolocrizm
Project-URL: Repository, https://github.com/G3tFun/Scolocrizm
Project-URL: Documentation, https://github.com/G3tFun/Scolocrizm#readme
Project-URL: Issues, https://github.com/G3tFun/Scolocrizm/issues
Project-URL: TelegramBotAPI, https://core.telegram.org/bots/api
Keywords: telegram,telegram-bot,bot-api,asyncio,webhook
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
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

# Scolocrizm

Scolocrizm is a Python framework for the Telegram Bot API. It provides asynchronous and synchronous clients, lossless models, file uploads, long polling, webhooks, routing, and a small FSM layer.

The bundled schema is based on Telegram Bot API 10.2. It includes 185 API methods and 387 documented object names. New optional fields are preserved instead of discarded.

## Installation

```bash
pip install Scolocrizm
```

For local development:

```bash
pip install -e '.[dev]'
```

## Quick start

```python
import asyncio
from scolocrizm import Bot

async def main() -> None:
    bot = Bot('123456:BOT_TOKEN')
    me = await bot.get_me()
    print(me.username)

    await bot.send_message(chat_id=123456789, text='Hello')

asyncio.run(main())
```

Every Bot API method is available in `snake_case`:

```python
await bot.send_rich_message(chat_id=123456789, rich_message={'markdown': '# Hello'})
await bot.edit_ephemeral_message_text(chat_id=123456789, ephemeral_message_id=1, text='Updated')
await bot.post_story(chat_id=123456789, content={'type': 'photo', 'photo': 'FILE_ID'})
```

## Routing and polling

```python
import asyncio
from scolocrizm import Bot, Command, Dispatcher, F

router = Dispatcher()

@router.message(Command('start') & F.text.startswith('/start'))
async def start(message, bot):
    await bot.send_message(chat_id=message.chat.id, text='Ready.')

async def main() -> None:
    bot = Bot('123456:BOT_TOKEN')
    await router.run_polling(bot, allowed_updates=['message'])

asyncio.run(main())
```

Use `router.on()` for any `Update` field:

```python
@router.on('subscription')
async def subscription_changed(subscription):
    print(subscription.raw)
```

## Files

Use `InputFile` for bytes, paths, or binary streams. File references returned by Telegram remain ordinary strings.

```python
from scolocrizm import Bot, InputFile
from scolocrizm.types import InputMediaPhoto

bot = Bot('123456:BOT_TOKEN')

await bot.send_photo(
    chat_id=123456789,
    photo=InputFile('cover.png'),
    caption='Cover',
)

await bot.send_media_group(
    chat_id=123456789,
    media=[InputMediaPhoto(media=InputFile('one.jpg'))],
)
```

Nested `InputFile` instances are converted to multipart attachments automatically.

## Webhooks

`asgi_app()` returns a dependency-free ASGI application. Set the same secret with `set_webhook(secret_token=...)` and in the application.

```python
from scolocrizm import asgi_app

async def handle(update):
    print(update.raw)

app = asgi_app(handle, secret_token='long-random-secret', path='/telegram')
```

The webhook handler checks `X-Telegram-Bot-Api-Secret-Token` with a constant-time comparison.

## Callback data

```python
from scolocrizm import CallbackCodec

codec = CallbackCodec('separate-random-secret')
data = codec.pack('order', id=42, action='pay')
assert codec.unpack(data, namespace='order').data['id'] == 42
```

The codec signs payloads and enforces Telegram's 64-byte callback-data limit.

## State

```python
from scolocrizm import FSMMiddleware

router.middleware(FSMMiddleware())

@router.message(Command('name'))
async def ask_name(message, state, bot):
    await state.set_state('awaiting_name')
    await bot.send_message(chat_id=message.chat.id, text='What is your name?')
```

`MemoryStorage` is suitable for a single process. Multi-worker deployments should provide a shared implementation of the `StateStorage` protocol.

## Sync client

```python
from scolocrizm import SyncBot

bot = SyncBot('123456:BOT_TOKEN')
bot.send_message(chat_id=123456789, text='Sent from a script')
```

`SyncBot` cannot run inside an active event loop. Use `Bot` in asynchronous applications.

## Compatibility

The client preserves unknown response fields and accepts direct calls to methods that may be added after a package release:

```python
result = await bot.call('futureMethod', chat_id=123456789)
print(result.raw)
```

Scolocrizm retries rate-limited requests after Telegram's `retry_after` delay. Calls that could create a duplicate message are not retried after an ambiguous transport error unless `retry_unsafe=True` is explicitly requested.

## Development

```bash
PYTHONPATH=src pytest -q
ruff check src tests tools
python tools/audit_bot_api.py
python tools/generate_manifest.py
python -m build
```

The API audit and release verification are documented in [`reports/BOT_API_COVERAGE_REPORT.md`](reports/BOT_API_COVERAGE_REPORT.md).

## License

MIT. Scolocrizm is an independent project and is not affiliated with Telegram.
