Metadata-Version: 2.4
Name: neogram
Version: 10.1.5
Summary: Telegram Bot API library
Author-email: SiriLV <siriteamrs@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/SiriLV/neogram
Project-URL: Documentation, https://github.com/SiriLV/neogram#readme
Project-URL: Repository, https://github.com/SiriLV/neogram
Project-URL: Issues, https://github.com/SiriLV/neogram/issues
Keywords: telegram,bot,api,telegram-bot,curl_cffi
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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 :: Communications :: Chat
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: curl_cffi>=0.5.0
Requires-Dist: bs4>=0.0.2
Dynamic: license-file

# neogram

**neogram** — минималистичная Python-библиотека для Telegram Bot API и набора дополнительных AI/utility-клиентов.

Библиотека ориентирована на простой прямой доступ к Telegram Bot API без лишней магии
Текущая версия поддерживает **Telegram Bot API 10.1**.

---

## Возможности

- Полный клиент Telegram Bot API на основе `curl_cffi`.
- Синхронный клиент `Bot`.
- Асинхронный клиент `AsyncBot`.
- Автоматически сгенерированные методы Bot API.
- Автоматически сгенерированные типы Telegram API.
- Десериализация ответов Telegram в Python-объекты.
- Сериализация объектов обратно в `dict`.
- Загрузка файлов через `InputFile`.
- Скачивание файлов Telegram через `bot.download_file(...)`.
- Декораторная система обработчиков сообщений и обновлений.
- Polling и обработка webhook-обновлений.
- Автоповторы при сетевых ошибках, 5xx и Flood Wait.
- Дополнительные клиенты из `ii.py`: `OnlySQ`, `Deef`, `Qwen`, `ChatGPT`, `OpenAI`.

---

## Установка

```bash
pip install neogram
```

Зависимости:

```bash
pip install curl_cffi beautifulsoup4
```

`curl_cffi` используется как основной HTTP-клиент. `beautifulsoup4` нужен для некоторых функций из `Deef`.

---

## Быстрый старт

### Синхронный бот

```python
from neogram import Bot

bot = Bot("YOUR_BOT_TOKEN", parse_mode="HTML")

@bot.message_handler(commands=["start"])
def start(message):
    bot.send_message(chat_id=message.chat.id, text="Привет! Я работаю на neogram.")

@bot.message_handler(content_types=["text"])
def text(message):
    bot.send_message(chat_id=message.chat.id, text=f"Ты написал: {message.text}")

bot.infinity_polling()
```

### Асинхронный бот

```python
import asyncio
from neogram import AsyncBot

bot = AsyncBot("YOUR_BOT_TOKEN", parse_mode="HTML")

@bot.message_handler(commands=["start"])
async def start(message):
    await bot.send_message(chat_id=message.chat.id, text="Привет из AsyncBot!")

async def main():
    async with bot:
        await bot.infinity_polling()

asyncio.run(main())
```

---

## Bot

`Bot` — синхронный клиент Telegram Bot API.

```python
from neogram import Bot

bot = Bot(token="YOUR_BOT_TOKEN", api_url="https://api.telegram.org", timeout=60, impersonate="chrome", parse_mode=None, proxies=None, max_retries=3, retry_on_flood=True)
```

### Параметры конструктора

| Параметр | Тип | По умолчанию | Описание |
|---|---:|---:|---|
| `token` | `str` | — | Токен бота от BotFather. |
| `api_url` | `str` | `https://api.telegram.org` | Базовый URL Telegram Bot API. |
| `timeout` | `int` | `60` | Таймаут HTTP-запросов в секундах. |
| `impersonate` | `str` | `chrome` | TLS fingerprint для `curl_cffi`. |
| `parse_mode` | `Optional[str]` | `None` | Форматирование по умолчанию: `HTML`, `MarkdownV2` и т.д. |
| `proxies` | `Optional[dict]` | `None` | Прокси для `curl_cffi`. |
| `max_retries` | `int` | `3` | Количество повторов при сетевых/серверных ошибках. |
| `retry_on_flood` | `bool` | `True` | Автоповтор при 429 Flood Wait. |

### Закрытие сессии

```python
bot.close()
```

Или через context manager:

```python
from neogram import Bot

with Bot("YOUR_BOT_TOKEN") as bot:
    print(bot.get_me())
```

---

## Методы Telegram Bot API

Все методы Telegram Bot API доступны у `Bot` и `AsyncBot` в `snake_case`.

Примеры соответствия:

| Telegram Bot API | neogram |
|---|---|
| `getMe` | `bot.get_me()` |
| `sendMessage` | `bot.send_message(...)` |
| `sendPhoto` | `bot.send_photo(...)` |
| `getUpdates` | `bot.get_updates(...)` |
| `setWebhook` | `bot.set_webhook(...)` |
| `answerCallbackQuery` | `bot.answer_callback_query(...)` |
| `sendRichMessage` | `bot.send_rich_message(...)` |
| `sendRichMessageDraft` | `bot.send_rich_message_draft(...)` |

### Отправка сообщения

```python
bot.send_message(chat_id=123456789, text="<b>Привет</b>", parse_mode="HTML")
```

Если `parse_mode` задан в `Bot(...)`, его можно не передавать каждый раз:

```python
bot = Bot("YOUR_BOT_TOKEN", parse_mode="HTML")
bot.send_message(chat_id=123456789, text="<b>Привет</b>")
```

### Отправка фото

```python
from neogram import InputFile

bot.send_photo(chat_id=123456789, photo=InputFile("photo.jpg"), caption="Фото из файла")
```

Можно передавать URL или уже существующий `file_id`:

```python
bot.send_photo(chat_id=123456789, photo="https://example.com/photo.jpg")
bot.send_photo(chat_id=123456789, photo="AgACAgIAAxkBAA...")
```

### Отправка документа

```python
from neogram import InputFile

bot.send_document(chat_id=123456789, document=InputFile("report.pdf"), caption="Документ")
```

### Новые rich message методы Bot API 10.1

```python
from neogram import InputRichMessage

bot.send_rich_message(chat_id=123456789, rich_message=InputRichMessage(...))
```

Для потокового черновика rich message:

```python
bot.send_rich_message_draft(chat_id=123456789, draft_id=1, rich_message=InputRichMessage(...))
```

---

## Типы Telegram API

Все типы Telegram Bot API представлены Python-классами. Например:

```python
from neogram import Message, User, Chat, InlineKeyboardMarkup, InlineKeyboardButton
```

Типы наследуются от `TelegramObject` и поддерживают:

- `from_dict(...)` — создание объекта из словаря;
- `to_dict()` — преобразование объекта обратно в словарь;
- автоматическую обработку переименованных Python-полей (`from` → `from_user`, `type` → `type_val`).

Пример:

```python
from neogram import Message

message = Message.from_dict(update_data["message"])
print(message.chat.id)
print(message.to_dict())
```

---

## InputFile

`InputFile` используется для загрузки файлов в Telegram.

```python
from neogram import InputFile

photo = InputFile("photo.jpg")
bot.send_photo(chat_id=123456789, photo=photo)
```

Можно передать bytes:

```python
from neogram import InputFile

with open("photo.jpg", "rb") as f:
    data = f.read()

bot.send_photo(chat_id=123456789, photo=InputFile(data, filename="photo.jpg"))
```

Или file-like объект:

```python
with open("document.pdf", "rb") as f:
    bot.send_document(chat_id=123456789, document=InputFile(f, filename="document.pdf"))
```

---

## Скачивание файлов Telegram

`download_file` принимает `file_id`, вызывает `getFile`, получает `file_path` и скачивает файл.

Вернуть bytes:

```python
data = bot.download_file(file_id="FILE_ID")

if data:
    print(len(data))
```

Сохранить на диск:

```python
path = bot.download_file(file_id="FILE_ID", save_path="downloaded_file.bin")

print(path)
```

Пример скачивания документа из сообщения:

```python
@bot.message_handler(content_types=["document"])
def on_document(message):
    file_id = message.document.file_id
    saved = bot.download_file(file_id, save_path=message.document.file_name)
    bot.send_message(message.chat.id, f"Файл сохранён: {saved}")
```

---

## Handlers

neogram поддерживает регистрацию обработчиков через декораторы.

### message_handler

```python
@bot.message_handler(commands=["start", "help"])
def commands(message):
    bot.send_message(message.chat.id, "Команда получена")
```

```python
@bot.message_handler(content_types=["text"])
def text(message):
    bot.send_message(message.chat.id, message.text)
```

```python
@bot.message_handler(regexp=r"^/echo\s+(.+)")
def echo(message):
    text = message.text.split(maxsplit=1)[1]
    bot.send_message(message.chat.id, text)
```

```python
@bot.message_handler(func=lambda m: m.chat.type_val == "private")
def private_only(message):
    bot.send_message(message.chat.id, "Это личный чат")
```

### Фильтры message_handler

| Фильтр | Описание |
|---|---|
| `commands` | Список команд без `/` или с `/`: `['start']`, `['/start']`. |
| `content_types` | Список типов контента: `text`, `photo`, `document`, `sticker`, `voice`, `rich_message` и т.д. |
| `regexp` | Регулярное выражение по `message.text` или `message.caption`. |
| `func` | Пользовательская функция-предикат. |
| `chat_types` | Ограничение по типу чата: `private`, `group`, `supergroup`, `channel`. |
| `user_ids` | Белый список ID пользователей. |
| `chat_ids` | Белый список ID чатов. |

### callback_query_handler

```python
@bot.callback_query_handler(data="open_menu")
def open_menu(call):
    bot.answer_callback_query(call.id)
    bot.send_message(call.message.chat.id, "Меню открыто")
```

Можно использовать функцию:

```python
@bot.callback_query_handler(func=lambda c: c.data.startswith("user:"))
def user_callback(call):
    user_id = call.data.split(":", 1)[1]
    bot.answer_callback_query(call.id, f"User ID: {user_id}")
```

### Остальные обработчики

| Декоратор | Update field |
|---|---|
| `edited_message_handler` | `edited_message` |
| `channel_post_handler` | `channel_post` |
| `edited_channel_post_handler` | `edited_channel_post` |
| `callback_query_handler` | `callback_query` |
| `inline_handler` | `inline_query` |
| `chosen_inline_result_handler` | `chosen_inline_result` |
| `poll_handler` | `poll` |
| `poll_answer_handler` | `poll_answer` |
| `my_chat_member_handler` | `my_chat_member` |
| `chat_member_handler` | `chat_member` |
| `chat_join_request_handler` | `chat_join_request` |
| `pre_checkout_query_handler` | `pre_checkout_query` |
| `shipping_query_handler` | `shipping_query` |
| `business_message_handler` | `business_message` |
| `edited_business_message_handler` | `edited_business_message` |
| `deleted_business_messages_handler` | `deleted_business_messages` |
| `message_reaction_handler` | `message_reaction` |
| `message_reaction_count_handler` | `message_reaction_count` |
| `chat_boost_handler` | `chat_boost` |
| `removed_chat_boost_handler` | `removed_chat_boost` |
| `purchased_paid_media_handler` | `purchased_paid_media` |

### StopPropagation

`StopPropagation` можно выбросить внутри обработчика, чтобы остановить дальнейшую обработку текущего update.

```python
from neogram import StopPropagation

@bot.message_handler(commands=["stop"])
def stop(message):
    bot.send_message(message.chat.id, "Остановлено")
    raise StopPropagation
```

### Обработчик ошибок

```python
@bot.error_handler
def errors(update, exception):
    print("Ошибка в обработчике:", exception)
```

---

## Polling

Запуск polling:

```python
bot.polling(timeout=30, allowed_updates=None, none_stop=True, interval=0.0)
```

Бесконечный polling:

```python
bot.infinity_polling()
```

Остановка polling:

```python
bot.stop_polling()
```

### allowed_updates

Можно указать список типов обновлений:

```python
bot.infinity_polling(allowed_updates=["message", "callback_query", "my_chat_member"])
```

---

## Webhook

Для webhook можно передать входящий JSON в `process_update`.

Пример с Flask:

```python
from flask import Flask, request
from neogram import Bot

app = Flask(__name__)
bot = Bot("YOUR_BOT_TOKEN")

@app.post("/webhook")
def webhook():
    bot.process_update(request.json)
    return "ok"
```

Для `AsyncBot`:

```python
await bot.process_update(update_dict)
```

---

## AsyncBot

`AsyncBot` имеет те же API-методы, но все они являются корутинами.

```python
from neogram import AsyncBot

async with AsyncBot("YOUR_BOT_TOKEN") as bot:
    me = await bot.get_me()
    await bot.send_message(me.id, "Проверка")
```

Асинхронные обработчики:

```python
@bot.message_handler(content_types=["text"])
async def text(message):
    await bot.send_message(message.chat.id, message.text)
```

Синхронные обработчики в `AsyncBot` тоже допустимы: диспетчер проверяет результат и делает `await`, если обработчик вернул awaitable.

---

## Исключения

### TelegramAPIError

Выбрасывается, если Telegram API вернул ошибку.

```python
from neogram import TelegramAPIError

try:
    bot.send_message(chat_id=123, text="test")
except TelegramAPIError as e:
    print(e.error_code)
    print(e.description)
    print(e.parameters)
    print(e.retry_after)
```

### StopPropagation

Служебное исключение для остановки обработки update внутри handler.

---

## Retry-логика

`Bot` и `AsyncBot` автоматически повторяют запросы:

- при сетевых ошибках;
- при серверных ошибках `5xx`;
- при `429 Flood Wait`, если `retry_on_flood=True`.

Настройки:

```python
bot = Bot("YOUR_BOT_TOKEN", max_retries=3, retry_on_flood=True)
```

---

## Клавиатуры

### Inline keyboard

```python
from neogram import InlineKeyboardMarkup, InlineKeyboardButton

keyboard = InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="Открыть", callback_data="open_menu")]])

bot.send_message(chat_id=123456789, text="Выбери действие:", reply_markup=keyboard)
```

### Reply keyboard

```python
from neogram import ReplyKeyboardMarkup, KeyboardButton

keyboard = ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text="Профиль")]], resize_keyboard=True)

bot.send_message(chat_id=123456789, text="Меню:", reply_markup=keyboard)
```

---

## Команды бота

```python
from neogram import BotCommand

bot.set_my_commands([BotCommand(command="start", description="Запустить бота"), BotCommand(command="help", description="Помощь")])
```

---

## Работа с update вручную

```python
update = bot.get_updates(limit=1)[0]

if update.message:
    print(update.message.text)
```

---

## OnlySQ

`OnlySQ` — клиент OnlySQ API для генерации текста и изображений.

```python
from neogram import OnlySQ

ai = OnlySQ(key="ONLYSQ_API_KEY")
```

### Получение моделей

```python
models = ai.get_models(modality="text")
print(models)
```

Фильтрация:

```python
models = ai.get_models(modality=["text", "image"], can_tools=True, can_stream=True, max_cost=5, hidden_models=["gpt-5.5", "claude-opus-*", "Grok 4.3"], sort_by="cost")
```

Вернуть полный список с данными моделей:

```python
models = ai.get_models(return_full=True)
```

### Генерация текста

```python
answer = ai.generate_answer(model="gemini-3.5-flash", messages=[{"role": "user", "content": "Напиши короткое приветствие"}])

print(answer)
```

### Генерация изображения

```python
ok = ai.generate_image(model="flux", prompt="Кот-программист за ноутбуком", ratio="16:9", filename="cat.png")

print(ok)
```

---

## Deef

`Deef` — набор утилит.

```python
from neogram import Deef

deef = Deef()
```

### Перевод текста

```python
translated = deef.translate("Hello world", lang="ru")
print(translated)
```

### Скачивание файла по URL

```python
data = deef.download_file("https://example.com/file.png")
```

Сохранение на диск:

```python
path = deef.download_file("https://example.com/file.png", save_path="file.png")
```

### Сокращение ссылки

```python
short = deef.short_url("https://example.com/very/long/url")
print(short)
```

### Запуск функции в фоне

```python
def work(x, y):
    print(x + y)

thread = deef.run_in_bg(work, 2, 3)
```

### Base64

```python
encoded = deef.encode_base64("image.png")
```

### Perplexity

```python
answer = deef.perplexity_ask(prompt="Что такое Python?", model="auto")
```

### Toolbaz

```python
answer = deef.toolchat(prompt="Напиши идею для бота", model="toolbaz-v4.5-fast")
```

---

## Qwen

`Qwen` — клиент для `chat.qwen.ai`.

```python
from neogram import Qwen

qwen = Qwen()
```

### Получение моделей

```python
models = qwen.fetch_models()
print(models)
```

### Чат

```python
result = qwen.chat(model="qwen3.7-plus", messages=[{"role": "user", "content": "Привет!"}], ctype="t2t", think=True)

print(result)
```

### Типы чата

Поддерживаемые типы зависят от текущей реализации `Qwen` и доступности сервиса. Обычно используются:

- `t2t` — обычный текстовый чат;
- `search` — чат с поиском;
- `t2i` — генерация изображения;
- `deep_research` — глубокое исследование;
- `artifacts` — работа с артефактами;
- `learn` — обучающий режим;
- `image_edit` — редактирование изображения, если доступно.

---

## ChatGPT / OpenAI

`ChatGPT` — универсальный клиент для OpenAI-совместимых API. `OpenAI` является алиасом `ChatGPT`.

```python
from neogram import ChatGPT, OpenAI

client = ChatGPT(url="https://api.openai.com/v1", headers={"Authorization": "Bearer YOUR_API_KEY"})
```

### Chat Completions

```python
response = client.generate_chat_completion(model="gpt-4o-mini", messages=[{"role": "user", "content": "Привет!"}])

print(response)
```

### Images

```python
image = client.generate_image(prompt="A small robot in cyberpunk style", n=1, size="1024x1024")
```

### Embeddings

```python
embedding = client.generate_embedding(model="text-embedding-3-small", input_data="Hello world")
```

### Audio transcription

```python
with open("audio.mp3", "rb") as f:
    result = client.generate_transcription(file=f, model="whisper-1", language="ru")
```

### Audio translation

```python
with open("audio.mp3", "rb") as f:
    result = client.generate_translation(file=f, model="whisper-1")
```

### Models

```python
models = client.get_models()
```

### Закрытие клиента

```python
client.close()
```

Или:

```python
with ChatGPT(url="https://api.example.com/v1", headers={}) as client:
    print(client.get_models())
```

---

## Именование полей

Некоторые поля Telegram имеют имена, конфликтующие с Python. neogram переименовывает их:

| Telegram field | Python field |
|---|---|
| `from` | `from_user` |
| `type` | `type_val` |
| `filter` | `filter_val` |
| `class` | `class_val` |

Пример:

```python
@bot.message_handler(content_types=["text"])
def handle(message):
    user = message.from_user
    chat_type = message.chat.type_val
```

---

## Логирование

neogram использует стандартный `logging`.

```python
import logging

logging.basicConfig(level=logging.INFO)
logging.getLogger("neogram").setLevel(logging.DEBUG)
```

---

## Советы по использованию

1. Для простых ботов используйте `Bot` и `infinity_polling()`.
2. Для высоконагруженных приложений используйте `AsyncBot` или webhook.
3. Для файлов используйте `InputFile`, если нужно загрузить локальный файл.
4. Для скачивания файлов Telegram используйте `bot.download_file(file_id, save_path=...)`.
5. Не храните токены и API-ключи прямо в коде — используйте переменные окружения.
6. Для больших проектов разделяйте обработчики по файлам и регистрируйте их через функции.

---

## Минимальный шаблон проекта

```text
my_bot/
├── main.py
├── handlers.py
└── config.py
```

`config.py`:

```python
import os

BOT_TOKEN = os.getenv("BOT_TOKEN")
```

`handlers.py`:

```python
def setup_handlers(bot):
    @bot.message_handler(commands=["start"])
    def start(message):
        bot.send_message(message.chat.id, "Привет!")
```

`main.py`:

```python
from neogram import Bot
from config import BOT_TOKEN
from handlers import setup_handlers

bot = Bot(BOT_TOKEN, parse_mode="HTML")
setup_handlers(bot)
bot.infinity_polling()
```

---

## Лицензия
MIT 2026 by SiriLV
