Metadata-Version: 2.4
Name: teledev
Version: 0.1.0
Summary: Telegram Bot API framework, 1-to-1 style compatible with pyTelegramBotAPI (telebot), plus built-in DB and HTTP helpers
Author: XNar
License: MIT
Project-URL: Homepage, https://github.com/XNar/teledev
Project-URL: Documentation, https://github.com/XNar/teledev/tree/main/docs
Project-URL: Issues, https://github.com/XNar/teledev/issues
Keywords: telegram,bot,telebot,api,teledev,async,fsm
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Provides-Extra: db
Provides-Extra: http
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# TeleDev

**TeleDev** — фреймворк для Telegram-ботов на Python, максимально близкий по стилю
и API к [pyTelegramBotAPI (telebot)](https://github.com/eternnoir/pyTelegramBotAPI),
но с рядом встроенных «фишек», которых в оригинале нет, плюс два спутника:

- **teledevdb** — простое хранилище данных (JSON / SQLite) с единым интерфейсом.
- **teledevhttp** — HTTP-клиент для похода во внешние API из хендлеров бота.

> Версия: `0.1.0` (alpha). API близко к стабильному, но до `1.0` возможны правки.

---

## Установка

```bash
pip install teledev
```

Пакет ставит `requests` как единственную обязательную зависимость. `teledevdb`
и `teledevhttp` идут в комплекте — отдельно ставить их не нужно.

---

## Быстрый старт (как в telebot, но с плюшками)

```python
import os
from teledev import TeleDev, types

bot = TeleDev(os.environ["TELEGRAM_TOKEN"], parse_mode="HTML")

@bot.command("start")
def send_welcome(message):
    kb = types.InlineKeyboardMarkup()
    kb.add(types.InlineKeyboardButton("Нажми меня", callback_data="hello"))
    bot.send_message(message.chat_id, "Привет! Я бот на TeleDev 🚀", reply_markup=kb)

@bot.callback_query_handler(func=lambda c: c.data == "hello")
def handle_hello(call):
    bot.answer_callback_query(call.id, text="Привет в ответ!")
    bot.send_message(call.message.chat_id, "Ты нажал на кнопку!")

@bot.message_handler(func=lambda m: True, content_types=["text"])
def echo_all(message):
    bot.send_message(message.chat_id, message.text)

bot.infinity_polling()
```

Если вы раньше писали на `telebot`, то заметите: `TeleBot` — это просто alias
на `TeleDev`, а декораторы (`message_handler`, `callback_query_handler`,
`send_message`, `register_next_step_handler`...) называются так же.

```python
import teledev as telebot  # да, так тоже можно
bot = telebot.TeleBot(TOKEN)
```

---

## Чем TeleDev отличается от telebot

| Фишка | telebot | TeleDev |
|---|---|---|
| Автоповтор при сетевых сбоях | нет | ✅ есть (backoff) |
| Автообработка flood control (HTTP 429) | частично | ✅ по `retry_after` |
| Middleware pipeline (`pre_process`/`post_process`) | нет | ✅ есть |
| Встроенный FSM (`StatesGroup`, `State`) | нет (только `next_step_handler`) | ✅ есть, со своим хранилищем |
| Персистентность состояний из коробки | нет | ✅ через `teledevdb` |
| Ограниченный worker pool для threaded-режима | простой Thread на апдейт | ✅ пул с очередью и backpressure |
| Встроенный HTTP-клиент для внешних API | нет | ✅ `teledevhttp` |

---

## Middleware

```python
from teledev import BaseMiddleware

class LoggingMiddleware(BaseMiddleware):
    def pre_process(self, message, data):
        print("Входящее сообщение:", getattr(message, "text", message))
        return True  # False — оборвать обработку

    def post_process(self, message, data, exception=None):
        if exception:
            print("Ошибка при обработке:", exception)

bot.add_middleware(LoggingMiddleware())
```

---

## FSM (машина состояний)

```python
from teledev.states import StatesGroup, State

class Registration(StatesGroup):
    waiting_name = State()
    waiting_age = State()

@bot.command("register")
def start(message):
    bot.set_state(message.chat_id, message.from_user.id, Registration.waiting_name)
    bot.send_message(message.chat_id, "Как тебя зовут?")

@bot.message_handler(func=lambda m: bot.get_state(m.chat_id, m.from_user.id) == str(Registration.waiting_name))
def name_step(message):
    bot.set_data(message.chat_id, message.from_user.id, name=message.text)
    bot.set_state(message.chat_id, message.from_user.id, Registration.waiting_age)
    bot.send_message(message.chat_id, "Сколько тебе лет?")
```

По умолчанию состояния хранятся в памяти (`MemoryStateStorage`). Чтобы они
переживали перезапуск бота — передайте `teledevdb`-хранилище:

```python
from teledev import TeleDev
from teledev.states import DBStateStorage
from teledevdb import SQLiteStorage

bot = TeleDev(TOKEN, state_storage=DBStateStorage(SQLiteStorage("fsm.db")))
```

---

## teledevdb — работа с данными

```python
from teledevdb import JSONStorage, SQLiteStorage

db = SQLiteStorage("bot.db")   # или JSONStorage("bot.json")

db.set("user:123:name", "Иван")
print(db.get("user:123:name"))          # "Иван"
db.increment("user:123:messages")       # атомарный счётчик
db.delete("user:123:name")
print(db.all())                         # весь словарь целиком
```

`JSONStorage` и `SQLiteStorage` реализуют один и тот же интерфейс
(`get/set/delete/all/increment`), поэтому взаимозаменяемы, а `SQLiteStorage`
дополнительно даёт `execute()`/`query()` для произвольного SQL, если
понадобится что-то сложнее ключ-значение.

---

## teledevhttp — запросы к внешним API

```python
from teledevhttp import HttpClient, HttpError

api = HttpClient(base_url="https://api.example.com", timeout=5, max_retries=3)

@bot.command("status")
def status(message):
    try:
        data = api.get_json("status")
        bot.send_message(message.chat_id, f"Статус: {data['status']}")
    except HttpError as e:
        bot.send_message(message.chat_id, f"Ошибка запроса: {e}")
```

`HttpClient` держит один `requests.Session` (переиспользование соединений),
сам делает retry с экспоненциальным backoff на сетевых ошибках, 5xx и 429
(с уважением к заголовку `Retry-After`).

---

## Структура проекта

```
teledev/         # ядро фреймворка (бот, типы, хендлеры, FSM, middleware)
teledevdb/        # JSON / SQLite хранилища
teledevhttp/       # HTTP-клиент для внешних API
examples/         # готовые примеры (echo-бот, FSM, БД, HTTP)
docs/             # документация
tests/            # unit-тесты
```

Больше примеров — в папке [`examples/`](examples), подробная документация —
в [`docs/`](docs).

## Лицензия

MIT — см. [LICENSE](LICENSE).
